зеркало из https://github.com/microsoft/ts-gyb.git
Rename ts-codegen to ts-gyb (#57)
* Rename ts-codegen to ts-gyb * Drop @microsoft prefix * GYB and features
This commit is contained in:
Родитель
f9026f0b1b
Коммит
a9b296304e
32
README.md
32
README.md
|
@ -1,21 +1,27 @@
|
|||
# ts-codegen
|
||||
# ts-gyb
|
||||
|
||||
ts-codegen is a multi-purpose code generation tool based on TypeScript interfaces. It was initially designed for generating boilerplate interfacing code between web and mobile platforms in hybrid apps. With custom templates, it can generate code for any use from TypeScript.
|
||||
ts-gyb is a multi-purpose code generation tool based on TypeScript interfaces. It was initially designed for generating boilerplate interfacing code between web and mobile platforms in hybrid apps. With custom templates, it can generate code for any use from TypeScript.
|
||||
|
||||
GYB: Generate Your Boilerplate. Inspired by [swift/gyb.py](https://github.com/apple/swift/blob/main/utils/gyb.py).
|
||||
|
||||
## Features
|
||||
|
||||
- Generate production ready and well documented code from TypeScript code
|
||||
- Support most of TypeScript syntax
|
||||
- Fully customizable template makes the generated code fit perfectly into any project
|
||||
|
||||
## Installation
|
||||
|
||||
To use ts-codegen with an existing project managed by npm, it is recommended to install ts-codegen as a dev dependency:
|
||||
To use ts-gyb with an existing project managed by npm, it is recommended to install ts-gyb as a dev dependency:
|
||||
|
||||
```shell
|
||||
npm install --save-dev @microsoft/ts-codegen
|
||||
npm install --save-dev ts-gyb
|
||||
```
|
||||
|
||||
You can also install ts-codegen globally:
|
||||
You can also install ts-gyb globally:
|
||||
|
||||
```shell
|
||||
npm install --global @microsoft/ts-codegen
|
||||
npm install --global ts-gyb
|
||||
```
|
||||
|
||||
## Get Started
|
||||
|
@ -39,11 +45,11 @@ interface EditorSelection {
|
|||
}
|
||||
```
|
||||
|
||||
ts-codegen only handles method members like `methodName(): ReturnType;`. If a method needs to take in parameters, it must define one object argument. The type of this object can either be an interface or an object literal. For more information on how to write interfaces for ts-codegen, please refer to [TypeScript Interface Guide](documentation/interface-guide.md).
|
||||
ts-gyb only handles method members like `methodName(): ReturnType;`. If a method needs to take in parameters, it must define one object argument. The type of this object can either be an interface or an object literal. For more information on how to write interfaces for ts-gyb, please refer to [TypeScript Interface Guide](documentation/interface-guide.md).
|
||||
|
||||
### 2. Provide templates
|
||||
|
||||
ts-codegen generates code from [mustache](http://mustache.github.io) templates. At least two templates are needed:
|
||||
ts-gyb generates code from [mustache](http://mustache.github.io) templates. At least two templates are needed:
|
||||
|
||||
- **Module template**: used to generate a file for every TypeScript interface
|
||||
- **Custom type template**: used to generate the file that hosts all TypeScript types found in method parameters or return types
|
||||
|
@ -80,16 +86,16 @@ Create a json configuration file in your project:
|
|||
|
||||
All paths are relative to the configuration file. For all supported options in the configuration file, please refer to [Configuration Reference](documentation/generated/interfaces/Configuration.md).
|
||||
|
||||
### 4. Run ts-codegen
|
||||
### 4. Run ts-gyb
|
||||
|
||||
```shell
|
||||
npx ts-codegen --config path/to/config.json
|
||||
npx ts-gyb --config path/to/config.json
|
||||
```
|
||||
|
||||
Or if ts-codegen is installed globally:
|
||||
Or if ts-gyb is installed globally:
|
||||
|
||||
```shell
|
||||
ts-codegen --config path/to/config.json
|
||||
ts-gyb --config path/to/config.json
|
||||
```
|
||||
|
||||
Generated code can be found at the output directory specified in the configuration file.
|
||||
|
@ -98,7 +104,7 @@ Generated code can be found at the output directory specified in the configurati
|
|||
|
||||
[mini-editor](demo/mini-editor) contains an iOS and an Android rich text editing app. Their editors are powered by the same TypeScript web project.
|
||||
|
||||
The web part provides some rich text formatting operations that can be invoked from native code (Kotlin/Swift). The operations are defined in [IEditor.ts](demo/mini-editor/web/src/editor/IEditor.ts). ts-codegen generates [EditorBridge.swift](demo/mini-editor/apple/MiniEditor/Generated/EditorBridge.swift) from that TypeScript interface.
|
||||
The web part provides some rich text formatting operations that can be invoked from native code (Kotlin/Swift). The operations are defined in [IEditor.ts](demo/mini-editor/web/src/editor/IEditor.ts). ts-gyb generates [EditorBridge.swift](demo/mini-editor/apple/MiniEditor/Generated/EditorBridge.swift) from that TypeScript interface.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
fun onInsertContentButtonClick(view: View) {
|
||||
bridge.insertContent("[inserted content]", true) { result ->
|
||||
println("[ts-codegen] result: $result")
|
||||
println("[ts-gyb] result: $result")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,33 +23,33 @@ open class EditorBridge(private val webView: WebView, private val gson: Gson) :
|
|||
|
||||
override fun toggleBold() {
|
||||
val javascriptString = "editor.toggleBold()"
|
||||
println("[ts-codegen] evaluating JavaScript: $javascriptString")
|
||||
println("[ts-gyb] evaluating JavaScript: $javascriptString")
|
||||
webView.evaluateJavascript(javascriptString){ evaluationResult ->
|
||||
println("[ts-codegen] JavaScript result: $evaluationResult")
|
||||
println("[ts-gyb] JavaScript result: $evaluationResult")
|
||||
}
|
||||
}
|
||||
|
||||
override fun toggleItalic() {
|
||||
val javascriptString = "editor.toggleItalic()"
|
||||
println("[ts-codegen] evaluating JavaScript: $javascriptString")
|
||||
println("[ts-gyb] evaluating JavaScript: $javascriptString")
|
||||
webView.evaluateJavascript(javascriptString){ evaluationResult ->
|
||||
println("[ts-codegen] JavaScript result: $evaluationResult")
|
||||
println("[ts-gyb] JavaScript result: $evaluationResult")
|
||||
}
|
||||
}
|
||||
|
||||
override fun toggleUnderline() {
|
||||
val javascriptString = "editor.toggleUnderline()"
|
||||
println("[ts-codegen] evaluating JavaScript: $javascriptString")
|
||||
println("[ts-gyb] evaluating JavaScript: $javascriptString")
|
||||
webView.evaluateJavascript(javascriptString){ evaluationResult ->
|
||||
println("[ts-codegen] JavaScript result: $evaluationResult")
|
||||
println("[ts-gyb] JavaScript result: $evaluationResult")
|
||||
}
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
val javascriptString = "editor.clear()"
|
||||
println("[ts-codegen] evaluating JavaScript: $javascriptString")
|
||||
println("[ts-gyb] evaluating JavaScript: $javascriptString")
|
||||
webView.evaluateJavascript(javascriptString){ evaluationResult ->
|
||||
println("[ts-codegen] JavaScript result: $evaluationResult")
|
||||
println("[ts-gyb] JavaScript result: $evaluationResult")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ open class EditorBridge(private val webView: WebView, private val gson: Gson) :
|
|||
)
|
||||
val jsonString = gson.toJson(args, Args_insertContent::class.java)
|
||||
val javascriptString = "editor.insertContent($jsonString)"
|
||||
println("[ts-codegen] evaluating JavaScript: $javascriptString")
|
||||
println("[ts-gyb] evaluating JavaScript: $javascriptString")
|
||||
webView.evaluateJavascript(javascriptString){ evaluationResult ->
|
||||
val result = gson.fromJson(evaluationResult, InsertContentResult::class.java)
|
||||
callback(result)
|
||||
|
|
|
@ -20,7 +20,7 @@ public class EditorBridge {
|
|||
public func toggleBold(completion: ((Result<Void, Error>) -> Void)? = nil) {
|
||||
let javaScriptString = "editor.toggleBold" + "(" + ")"
|
||||
|
||||
print("[ts-codegen] evaluating: \(javaScriptString)")
|
||||
print("[ts-gyb] evaluating: \(javaScriptString)")
|
||||
|
||||
webView?.evaluateJavaScript(javaScriptString) { evaluationResult, error in
|
||||
guard let completion = completion else { return }
|
||||
|
@ -35,7 +35,7 @@ public class EditorBridge {
|
|||
public func toggleItalic(completion: ((Result<Void, Error>) -> Void)? = nil) {
|
||||
let javaScriptString = "editor.toggleItalic" + "(" + ")"
|
||||
|
||||
print("[ts-codegen] evaluating: \(javaScriptString)")
|
||||
print("[ts-gyb] evaluating: \(javaScriptString)")
|
||||
|
||||
webView?.evaluateJavaScript(javaScriptString) { evaluationResult, error in
|
||||
guard let completion = completion else { return }
|
||||
|
@ -50,7 +50,7 @@ public class EditorBridge {
|
|||
public func toggleUnderline(completion: ((Result<Void, Error>) -> Void)? = nil) {
|
||||
let javaScriptString = "editor.toggleUnderline" + "(" + ")"
|
||||
|
||||
print("[ts-codegen] evaluating: \(javaScriptString)")
|
||||
print("[ts-gyb] evaluating: \(javaScriptString)")
|
||||
|
||||
webView?.evaluateJavaScript(javaScriptString) { evaluationResult, error in
|
||||
guard let completion = completion else { return }
|
||||
|
@ -65,7 +65,7 @@ public class EditorBridge {
|
|||
public func clear(completion: ((Result<Void, Error>) -> Void)? = nil) {
|
||||
let javaScriptString = "editor.clear" + "(" + ")"
|
||||
|
||||
print("[ts-codegen] evaluating: \(javaScriptString)")
|
||||
print("[ts-gyb] evaluating: \(javaScriptString)")
|
||||
|
||||
webView?.evaluateJavaScript(javaScriptString) { evaluationResult, error in
|
||||
guard let completion = completion else { return }
|
||||
|
@ -89,7 +89,7 @@ public class EditorBridge {
|
|||
let argsString = String(data: try! jsonEncoder.encode(args), encoding: .utf8)!
|
||||
let javaScriptString = "editor.insertContent" + "(" + "\(argsString)" + ")"
|
||||
|
||||
print("[ts-codegen] evaluating: \(javaScriptString)")
|
||||
print("[ts-gyb] evaluating: \(javaScriptString)")
|
||||
|
||||
webView?.evaluateJavaScript(javaScriptString) { [unowned self]evaluationResult, error in
|
||||
if let error = error {
|
||||
|
|
|
@ -65,7 +65,7 @@ extension ViewController: ToolbarDelegate {
|
|||
) { result in
|
||||
switch result {
|
||||
case .success(let contentString):
|
||||
print("[ts-codegen] contentString after insertContent(): \(contentString)")
|
||||
print("[ts-gyb] contentString after insertContent(): \(contentString)")
|
||||
case .failure(let error):
|
||||
assertionFailure("\(error)")
|
||||
}
|
||||
|
|
|
@ -37,14 +37,14 @@ open class {{moduleName}}(private val webView: WebView, private val gson: Gson)
|
|||
val jsonString = gson.toJson(args, Args_{{methodName}}::class.java)
|
||||
{{/parameters.length}}
|
||||
val javascriptString = "{{customTags.invokePath}}.{{methodName}}({{#parameters.length}}$jsonString{{/parameters.length}})"
|
||||
println("[ts-codegen] evaluating JavaScript: $javascriptString")
|
||||
println("[ts-gyb] evaluating JavaScript: $javascriptString")
|
||||
webView.evaluateJavascript(javascriptString){ evaluationResult ->
|
||||
{{#returnType}}
|
||||
val result = gson.fromJson(evaluationResult, {{{returnType}}}::class.java)
|
||||
callback(result)
|
||||
{{/returnType}}
|
||||
{{^returnType}}
|
||||
println("[ts-codegen] JavaScript result: $evaluationResult")
|
||||
println("[ts-gyb] JavaScript result: $evaluationResult")
|
||||
{{/returnType}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public class {{moduleName}} {
|
|||
{{/parameters.length}}
|
||||
let javaScriptString = "{{customTags.invokePath}}.{{methodName}}" + "(" {{#parameters.length}}+ "\(argsString)"{{/parameters.length}} + ")"
|
||||
|
||||
print("[ts-codegen] evaluating: \(javaScriptString)")
|
||||
print("[ts-gyb] evaluating: \(javaScriptString)")
|
||||
|
||||
webView?.evaluateJavaScript(javaScriptString) { {{#returnType}}[unowned self]{{/returnType}}evaluationResult, error in
|
||||
{{^returnType}}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "mini-editor-web",
|
||||
"version": "0.0.1",
|
||||
"description": "An end-to-end example of ts-codegen",
|
||||
"description": "An end-to-end example of ts-gyb",
|
||||
"main": "src/main.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Method definition
|
||||
|
||||
ts-codegen only recognizes interface members defined as methods.
|
||||
ts-gyb only recognizes interface members defined as methods.
|
||||
|
||||
```typescript
|
||||
/**
|
||||
|
@ -51,7 +51,7 @@ Refer to [Value types](#value-types) for allowed parameter types.
|
|||
|
||||
## Return type
|
||||
|
||||
Return type must be explicitly specified. When not provided, TypeScript would use `any` which is not supported by ts-codegen. Use `void` when the method does not return a value.
|
||||
Return type must be explicitly specified. When not provided, TypeScript would use `any` which is not supported by ts-gyb. Use `void` when the method does not return a value.
|
||||
|
||||
Return type can be a `Promise`.
|
||||
|
||||
|
@ -65,7 +65,7 @@ Refer to [Value types](#value-types) for allowed types as return type.
|
|||
- `number`
|
||||
- `boolean`
|
||||
|
||||
> Tips: TypeScript does not distinguish integer from float point number, and ts-codegen would map `number` to the default float point type in the target language. To map a value to integer, refer to the guide in [Integer type](#integer-type).
|
||||
> Tips: TypeScript does not distinguish integer from float point number, and ts-gyb would map `number` to the default float point type in the target language. To map a value to integer, refer to the guide in [Integer type](#integer-type).
|
||||
|
||||
### `interface` and object literal
|
||||
|
||||
|
@ -79,7 +79,7 @@ When an interface extends another interface, all members of the parent interface
|
|||
|
||||
#### Indexable types
|
||||
|
||||
When an interface or an object literal contains an index member, it would be parsed as [index signature](https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures) and be mapped to dictionary. ts-codegen only recognizes indexable types with only one index member. Currently the index type can only be `string`. The type of the value can be any type specified in [Value types](#value-types).
|
||||
When an interface or an object literal contains an index member, it would be parsed as [index signature](https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures) and be mapped to dictionary. ts-gyb only recognizes indexable types with only one index member. Currently the index type can only be `string`. The type of the value can be any type specified in [Value types](#value-types).
|
||||
|
||||
```typescript
|
||||
// allowed: indexable interface
|
||||
|
@ -186,20 +186,20 @@ type AliasDefinedInterface = { stringField: string }
|
|||
|
||||
### Predefined type
|
||||
|
||||
You can define some types as predefined. ts-codegen would treat these as known types and would assume they exist in the generated code. You must ensure these types can be correctly referenced in your project when using generated code.
|
||||
You can define some types as predefined. ts-gyb would treat these as known types and would assume they exist in the generated code. You must ensure these types can be correctly referenced in your project when using generated code.
|
||||
|
||||
This is helpful for working around types that not supported by TypeScript or ts-codegen. [Workarounds](#workarounds) section introduces some use cases for this type.
|
||||
This is helpful for working around types that not supported by TypeScript or ts-gyb. [Workarounds](#workarounds) section introduces some use cases for this type.
|
||||
|
||||
Refer to [Predefined Type](./predefined-type.md) for how to configure predefined types.
|
||||
|
||||
## Tags
|
||||
|
||||
ts-codegen parses tags in [JSDoc](https://jsdoc.app) documentation.
|
||||
ts-gyb parses tags in [JSDoc](https://jsdoc.app) documentation.
|
||||
|
||||
### Built-in tags
|
||||
|
||||
- `@shouldExport`: Specify whether an `interface` should be exported. Set it to `true` to export.
|
||||
- `@overrideModuleName`: Change the name of the interface for ts-codegen. This is helpful for dropping the `I` prefix in TypeScript interface name.
|
||||
- `@overrideModuleName`: Change the name of the interface for ts-gyb. This is helpful for dropping the `I` prefix in TypeScript interface name.
|
||||
- `@overrideTypeName`: Similar to `@overrideModuleName`, this is used to override the name of custom types used in method parameters or return values.
|
||||
|
||||
```typescript
|
||||
|
@ -217,7 +217,7 @@ interface InterfaceWithTags {
|
|||
|
||||
You can also define custom tags and use them in templates. Refer to [module in template](template-guide.md#module) for how to use them.
|
||||
|
||||
ts-codegen would try to parse the value of custom tags via `JSON.parse()`. If failed, it would be passed as string.
|
||||
ts-gyb would try to parse the value of custom tags via `JSON.parse()`. If failed, it would be passed as string.
|
||||
|
||||
```typescript
|
||||
/**
|
||||
|
@ -233,7 +233,7 @@ interface InterfaceWithTags {
|
|||
|
||||
## JSDoc documentation
|
||||
|
||||
ts-codegen would read the documentation comment from `interface` and `enum`, and their members. Documentation comment must be placed above all tags.
|
||||
ts-gyb would read the documentation comment from `interface` and `enum`, and their members. Documentation comment must be placed above all tags.
|
||||
|
||||
```typescript
|
||||
/**
|
||||
|
@ -254,7 +254,7 @@ interface InterfaceWithTags {
|
|||
|
||||
TypeScript does not have an integer type. To generate methods with an integer as a parameter or return value, you can use the combination of [Type alias](#type-alias) and [Predefined type](#predefined-type).
|
||||
|
||||
First, define an integer type as an alias to `number`. For basic types like `number`, `string` and `boolean`, the type alias must be branded. This is because [TypeScript interns certain types](https://github.com/microsoft/TypeScript/issues/28197#issuecomment-434027046), and ts-codegen cannot distinguish these types from the target types. Learn more about TypeScript type branding [here](https://medium.com/@KevinBGreene/surviving-the-typescript-ecosystem-branding-and-type-tagging-6cf6e516523d).
|
||||
First, define an integer type as an alias to `number`. For basic types like `number`, `string` and `boolean`, the type alias must be branded. This is because [TypeScript interns certain types](https://github.com/microsoft/TypeScript/issues/28197#issuecomment-434027046), and ts-gyb cannot distinguish these types from the target types. Learn more about TypeScript type branding [here](https://medium.com/@KevinBGreene/surviving-the-typescript-ecosystem-branding-and-type-tagging-6cf6e516523d).
|
||||
|
||||
```typescript
|
||||
type CodeGen_Int = number & { _intBrand: never }
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
# Template Guide
|
||||
|
||||
ts-codegen uses [mustache](http://mustache.github.io) template to generate code. Refer to [mustache Manul](http://mustache.github.io/mustache.5.html) for supported syntax.
|
||||
ts-gyb uses [mustache](http://mustache.github.io) template to generate code. Refer to [mustache Manul](http://mustache.github.io/mustache.5.html) for supported syntax.
|
||||
|
||||
## Required templates
|
||||
|
||||
ts-codegen needs two templates: module template and named type template.
|
||||
ts-gyb needs two templates: module template and named type template.
|
||||
|
||||
### Module template
|
||||
|
||||
ts-codegen uses this template to generate a file for every module. Typically, generated file includes a module class and all types used in the method parameters and return values of the module.
|
||||
ts-gyb uses this template to generate a file for every module. Typically, generated file includes a module class and all types used in the method parameters and return values of the module.
|
||||
|
||||
### Named type template
|
||||
|
||||
When a TypeScript `interface` or an `enum` is used by more than one module, it is not suitable to place the generated type in any module file. ts-codegen uses this template to generate a single file that hosts all shared TypeScript types found in method parameters and return types.
|
||||
When a TypeScript `interface` or an `enum` is used by more than one module, it is not suitable to place the generated type in any module file. ts-gyb uses this template to generate a single file that hosts all shared TypeScript types found in method parameters and return types.
|
||||
|
||||
## Variables
|
||||
|
||||
ts-codegen defines some variables that can be directly used in templates.
|
||||
ts-gyb defines some variables that can be directly used in templates.
|
||||
|
||||
### Variables in templates
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@olm/ts-codegen",
|
||||
"name": "ts-gyb",
|
||||
"version": "0.3.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@olm/ts-codegen",
|
||||
"name": "ts-gyb",
|
||||
"version": "0.3.0",
|
||||
"description": "Generate Native API based on TS interface",
|
||||
"scripts": {
|
||||
|
@ -18,7 +18,7 @@
|
|||
},
|
||||
"main": "dist/index.js",
|
||||
"bin": {
|
||||
"ts-codegen": "bin/ts-codegen"
|
||||
"ts-gyb": "bin/ts-gyb"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*.js",
|
||||
|
|
|
@ -14,11 +14,6 @@
|
|||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"paths": {
|
||||
"@olm/ts-codegen-basic-type": [
|
||||
"src/basic-types/types.ts"
|
||||
]
|
||||
},
|
||||
"baseUrl": ""
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче