typespec-typescript-emitter 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/FUNDING.yml +1 -0
- package/LICENSE +21 -0
- package/README.md +203 -0
- package/dist/src/emit_routes.d.ts +3 -0
- package/dist/src/emit_routes.js +94 -0
- package/dist/src/emit_routes.js.map +1 -0
- package/dist/src/emit_types.d.ts +8 -0
- package/dist/src/emit_types.js +175 -0
- package/dist/src/emit_types.js.map +1 -0
- package/dist/src/emitter.d.ts +2 -0
- package/dist/src/emitter.js +54 -0
- package/dist/src/emitter.js.map +1 -0
- package/dist/src/helper_autogenerateWarning.d.ts +2 -0
- package/dist/src/helper_autogenerateWarning.js +12 -0
- package/dist/src/helper_autogenerateWarning.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib.d.ts +18 -0
- package/dist/src/lib.js +21 -0
- package/dist/src/lib.js.map +1 -0
- package/dist/src/testing/index.d.ts +2 -0
- package/dist/src/testing/index.js +8 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/test/hello.test.d.ts +1 -0
- package/dist/test/hello.test.js +10 -0
- package/dist/test/hello.test.js.map +1 -0
- package/dist/test/test-host.d.ts +5 -0
- package/dist/test/test-host.js +36 -0
- package/dist/test/test-host.js.map +1 -0
- package/eslint.config.js +11 -0
- package/package.json +48 -0
- package/prettierrc.yaml +8 -0
- package/src/emit_routes.ts +122 -0
- package/src/emit_types.ts +216 -0
- package/src/emitter.ts +72 -0
- package/src/helper_autogenerateWarning.ts +12 -0
- package/src/index.ts +2 -0
- package/src/lib.ts +30 -0
- package/src/testing/index.ts +12 -0
- package/test/hello.test.ts +10 -0
- package/test/test-host.ts +49 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ko_fi: crowbait
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Crowbait
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# typespec-typescript-emitter
|
|
2
|
+
|
|
3
|
+
This is a [TypeSpec](https://typespec.io) library aiming to provide
|
|
4
|
+
TypeScript output to a TypeSpec project.
|
|
5
|
+
|
|
6
|
+
Currently, this library is tailored to my specific use case, which is defining
|
|
7
|
+
an HTTP API. The 'routes'-emitter will only work on HTTP operations. **However**, exporting all models as types is independent of HTTP, and so may also benefit projects with a different usage scenario.
|
|
8
|
+
|
|
9
|
+
It can export two things:
|
|
10
|
+
|
|
11
|
+
- ts files exporting every model present in the spec
|
|
12
|
+
- 1 file for each (nested) namespace
|
|
13
|
+
- exports models, enums and unions
|
|
14
|
+
- does NOT export aliases (see below)
|
|
15
|
+
- for `TypeSpec.Http`: ts file containing a nested object containing information about every route
|
|
16
|
+
- this can be imported at runtime to provide a robust way of eg. accessing URLs
|
|
17
|
+
|
|
18
|
+
## Content
|
|
19
|
+
|
|
20
|
+
- [Installation](#installation)
|
|
21
|
+
- [Configuration](#configuration)
|
|
22
|
+
- [Types Emitter](#types-emitter)
|
|
23
|
+
- [Alias's](#aliass)
|
|
24
|
+
- [Routes Emitter](#routes-emitter)
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npm i -D typespec-typescript-emitter
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Configuration
|
|
33
|
+
|
|
34
|
+
This library is configured using TypeSpec's `tspconfig.yaml` file:
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
emit:
|
|
38
|
+
- "typespec-typescript-emitter"
|
|
39
|
+
options:
|
|
40
|
+
"typespec-typescript-emitter":
|
|
41
|
+
root-namespace: "string"
|
|
42
|
+
out-dir: "{cwd}/path"
|
|
43
|
+
enable-types: true
|
|
44
|
+
enable-routes: true
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The following options are available:
|
|
48
|
+
|
|
49
|
+
- `root-namespace` **(required)**: name of the most outer namespace. As the TypeSpec docs recommend, your project is expected to consist of one or more nested namespaces. Here, you need to specify the most outer / general namespace you want emitted.
|
|
50
|
+
- `out-dir`: output directory. Must be an absolute path; replacers like `{cwd}` are permitted.
|
|
51
|
+
- `enable-types` (default: true): enables output of TypeScript types.
|
|
52
|
+
- `enable-routes` (default: false): enables output of the HTTP-routes object.
|
|
53
|
+
|
|
54
|
+
## Types emitter
|
|
55
|
+
|
|
56
|
+
This emitter will traverse your configured root namespace and all nested namespaces, generating a `{namespace-name}.ts`-file.
|
|
57
|
+
|
|
58
|
+
The emitter can handle `Model`s, `Enum`s and `Union`s. ~~`Alias`'s~~ are _not_ emitted - more on that [later](#aliass). It will also preserve docs as JSDoc-style comments.
|
|
59
|
+
|
|
60
|
+
The emitter should be able to handle most basic TS contructs, like scalars, literals, object, arrays, tuples and intrinsics (eg. `null`).
|
|
61
|
+
|
|
62
|
+
Example:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
namespace myProject { // remember to set in config!
|
|
66
|
+
enum ReadStatus {
|
|
67
|
+
Never,
|
|
68
|
+
Once,
|
|
69
|
+
Often
|
|
70
|
+
}
|
|
71
|
+
union Author {"unknown" | string}
|
|
72
|
+
model Book {
|
|
73
|
+
author: Author,
|
|
74
|
+
title: string,
|
|
75
|
+
subtitle: null | string,
|
|
76
|
+
read: ReadStatus,
|
|
77
|
+
chapterTitles: string[]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// you can either nest namespaces like this:
|
|
81
|
+
namespace subNameSpace {/* ... */}
|
|
82
|
+
// ... or specify them in (and import from) external files:
|
|
83
|
+
namespace myProject.subNameSpace {/* ... */} // this is in another file
|
|
84
|
+
// The emitted file will always have the name of the namespace it's
|
|
85
|
+
// *currently* investigating, in this case:
|
|
86
|
+
// `SubNameSpace.ts`
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
...will be transformed into:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
/* /path/to/outdir/MyProject.ts */
|
|
94
|
+
export enum ReadStatus {
|
|
95
|
+
Never,
|
|
96
|
+
Once,
|
|
97
|
+
Often,
|
|
98
|
+
}
|
|
99
|
+
export type Author = "unknown" | string;
|
|
100
|
+
export interface Book {
|
|
101
|
+
author: Author;
|
|
102
|
+
title: string;
|
|
103
|
+
subtitile: null | string;
|
|
104
|
+
read: ReadStatus;
|
|
105
|
+
chapterTitles: string[];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// the other namespace will be emitted to `/path/to/outdir/SubNameSpace.ts`
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Alias's
|
|
112
|
+
|
|
113
|
+
There seems to be no way to extract aliases from TypeSpec's emitter framework. Because of that, `Alias`'s are ignored by the emitter (or, to be more precise: `Alias`'s reach the emitter already resolved. They won't be exported as their own type but directly substituted where they're needed).
|
|
114
|
+
|
|
115
|
+
That means, if you want something to be emitted, it can't be an alias:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
model Demo {
|
|
119
|
+
prop1: string,
|
|
120
|
+
prop2: int32
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// will not be emitted:
|
|
124
|
+
alias Derived1 = OmitProperties<Demo, "prop1">;
|
|
125
|
+
|
|
126
|
+
// will be emitted:
|
|
127
|
+
model Derived2 {...OmitProperties<Demo, "prop1">};
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Routes emitter
|
|
131
|
+
|
|
132
|
+
**This emitter depends on your use of the `TypeSpec.Http` library**.
|
|
133
|
+
|
|
134
|
+
If you're using `TypeSpec.Http` to define your API routes and endpoints, this library offers an emitter to export a `routes` object.
|
|
135
|
+
|
|
136
|
+
It is strongly advised to define a `server`, to make URL generation more meaningful. The way this is implemented however, will currently only work well for 'simpler' projects using one root domain.
|
|
137
|
+
|
|
138
|
+
Just as the types emitter, this emitter will also preserve docs as JSDoc-style comments.
|
|
139
|
+
|
|
140
|
+
Example:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
@server("https://api.example.com", "Server")
|
|
144
|
+
namespace myProject { // remember to set in config!
|
|
145
|
+
@get
|
|
146
|
+
op getSomething(): string;
|
|
147
|
+
|
|
148
|
+
@get
|
|
149
|
+
@route("{param}")
|
|
150
|
+
@useAuth(NoAuth | BasicAuth)
|
|
151
|
+
op getSmthElse(@path param: string): string;
|
|
152
|
+
|
|
153
|
+
@route("/subroute")
|
|
154
|
+
namespace sub {
|
|
155
|
+
@post
|
|
156
|
+
@route("post/{post_param}")
|
|
157
|
+
@useAuth(BasicAuth)
|
|
158
|
+
op postSomething(
|
|
159
|
+
@path post_param: int32,
|
|
160
|
+
@body body: string
|
|
161
|
+
): string;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
...will be transformed into:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
/* /path/to/outdir/routes_{root-namespace}.ts */
|
|
170
|
+
export interface IRoute {
|
|
171
|
+
method: string
|
|
172
|
+
getUrl: (p: any) => string
|
|
173
|
+
auth: boolean | 'varies'
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export const routes_myProject = {
|
|
177
|
+
getSomething: {
|
|
178
|
+
method: 'get',
|
|
179
|
+
getUrl: () => 'https://api.example.com/',
|
|
180
|
+
auth: false
|
|
181
|
+
},
|
|
182
|
+
getSmthElse: {
|
|
183
|
+
method: 'get',
|
|
184
|
+
getUrl: (p: {param: string}) => `https://api.example.com/${p.param}`,
|
|
185
|
+
auth: 'varies
|
|
186
|
+
},
|
|
187
|
+
sub: {
|
|
188
|
+
postSomething: {
|
|
189
|
+
method: 'post',
|
|
190
|
+
getUrl: (p: {post_param: string}) => `https://api.example.com/subroute/post/${p.post_param}`,
|
|
191
|
+
auth: true
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
} as const;
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The `IRoute` interface should be used sparsely. Consider the following:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
const foo: IRoute = routes_myProject.some.route;
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Now `foo.getUrl` will have lost its signature and your IDE can no longer suggest its parameters (if any).
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { getDoc } from "@typespec/compiler";
|
|
2
|
+
import { getAuthentication, getHttpOperation } from "@typespec/http";
|
|
3
|
+
import autogenerateWarning from "./helper_autogenerateWarning.js";
|
|
4
|
+
const emitRoutes = (context, namespace, rootServer) => {
|
|
5
|
+
const rootNode = `routes_${context.options["root-namespace"]}`;
|
|
6
|
+
let out = autogenerateWarning;
|
|
7
|
+
out +=
|
|
8
|
+
"/** This type is mostly meant for use in function signatures and `extends`' in generic functions.\n";
|
|
9
|
+
out += " * eg: `const callApi(route: IRoute) => fetch(route.getUrl(...))`\n";
|
|
10
|
+
out +=
|
|
11
|
+
" * It should not be used to type variables (eg.: `let x: IRoute`), because the resulting type\n";
|
|
12
|
+
out += " * loses it's information about the getUrl parameters.\n";
|
|
13
|
+
out += " */\n";
|
|
14
|
+
out += "export interface IRoute {\n";
|
|
15
|
+
out += " method: string\n";
|
|
16
|
+
/* The "getUrl" type should really be more specific; something that at least shows that it's a Record.
|
|
17
|
+
* However, doing that, Typescript always complains about the actual fields (of an implemented function in the output)
|
|
18
|
+
* is missing from the type. I think, it's a TS issue...
|
|
19
|
+
*/
|
|
20
|
+
out += " getUrl: (p: any) => string\n";
|
|
21
|
+
out += " auth: boolean | 'varies'\n";
|
|
22
|
+
out += "};\n\n";
|
|
23
|
+
out += `const ${rootNode} = {\n`;
|
|
24
|
+
const traverseNamespace = (n, nestLevel) => {
|
|
25
|
+
const line = (str, addLevels) => {
|
|
26
|
+
out += `${" ".repeat(nestLevel + 1 + (addLevels ?? 0))}${str}\n`;
|
|
27
|
+
};
|
|
28
|
+
// operations
|
|
29
|
+
let opNum = 0;
|
|
30
|
+
n.operations.forEach((op) => {
|
|
31
|
+
opNum++;
|
|
32
|
+
const httpOp = getHttpOperation(context.program, op);
|
|
33
|
+
// jsdoc comment
|
|
34
|
+
const doc = getDoc(context.program, op);
|
|
35
|
+
if (doc)
|
|
36
|
+
line(`/** ${doc} */`);
|
|
37
|
+
line(`${op.name}: {`);
|
|
38
|
+
// http method
|
|
39
|
+
line(`method: '${httpOp[0].verb}',`, 1);
|
|
40
|
+
// url parameters
|
|
41
|
+
const pathParams = httpOp[0].parameters.parameters.filter((p) => p.type === "path");
|
|
42
|
+
if (pathParams.length > 0) {
|
|
43
|
+
line("getUrl: (p: {", 1);
|
|
44
|
+
pathParams
|
|
45
|
+
.map((p) => `${p.name}: string`)
|
|
46
|
+
.forEach((p, i) => line(p, 2));
|
|
47
|
+
let fn = "}) => ";
|
|
48
|
+
fn += pathParams.reduce((sum, cur) => sum.replaceAll(`{${cur.name}}`, `${"$"}{p.${cur.name}}`), `\`${rootServer}${httpOp[0].path}\`,`);
|
|
49
|
+
line(fn, 1);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
line(`getUrl: () => '${rootServer}${httpOp[0].path}',`, 1);
|
|
53
|
+
}
|
|
54
|
+
// auth
|
|
55
|
+
let auth = false;
|
|
56
|
+
const opAuth = getAuthentication(context.program, op);
|
|
57
|
+
if (opAuth) {
|
|
58
|
+
let includesSome = false;
|
|
59
|
+
let includesNone = false;
|
|
60
|
+
opAuth.options.forEach((authOpt) => {
|
|
61
|
+
if (authOpt.schemes.some((scheme) => scheme.type !== "noAuth"))
|
|
62
|
+
includesSome = true;
|
|
63
|
+
if (authOpt.schemes.some((scheme) => scheme.type === "noAuth"))
|
|
64
|
+
includesNone = true;
|
|
65
|
+
});
|
|
66
|
+
auth =
|
|
67
|
+
includesSome && includesNone
|
|
68
|
+
? "varies"
|
|
69
|
+
: includesSome && !includesNone
|
|
70
|
+
? true
|
|
71
|
+
: false;
|
|
72
|
+
}
|
|
73
|
+
line(`auth: ${typeof auth === "string" ? `'${auth}'` : auth.toString()}`, 1);
|
|
74
|
+
line(`}${opNum < n.operations.size || n.namespaces.size > 0 ? "," : ""}`);
|
|
75
|
+
});
|
|
76
|
+
// namespaces
|
|
77
|
+
let nsNum = 0;
|
|
78
|
+
n.namespaces.forEach((ns) => {
|
|
79
|
+
nsNum++;
|
|
80
|
+
const doc = getDoc(context.program, ns);
|
|
81
|
+
if (doc)
|
|
82
|
+
line(`/** ${doc} */`);
|
|
83
|
+
line(`${ns.name}: {`);
|
|
84
|
+
traverseNamespace(ns, nestLevel + 1);
|
|
85
|
+
line(`}${nsNum < n.namespaces.size ? "," : ""}`);
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
traverseNamespace(namespace, 0);
|
|
89
|
+
out += "} as const;\n";
|
|
90
|
+
out += `export default ${rootNode};\n`;
|
|
91
|
+
return out;
|
|
92
|
+
};
|
|
93
|
+
export default emitRoutes;
|
|
94
|
+
//# sourceMappingURL=emit_routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit_routes.js","sourceRoot":"","sources":["../../src/emit_routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { EmitContext, Namespace } from "@typespec/compiler";
|
|
2
|
+
declare global {
|
|
3
|
+
interface String {
|
|
4
|
+
addLine(str: string, tabs?: number, continued?: boolean): string;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
declare const emitTypes: (context: EmitContext, namespace: Namespace) => Record<string, string>;
|
|
8
|
+
export default emitTypes;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { getDoc, } from "@typespec/compiler";
|
|
2
|
+
import autogenerateWarning from "./helper_autogenerateWarning.js";
|
|
3
|
+
String.prototype.addLine = function (str, tabs, continued) {
|
|
4
|
+
return `${this}${" ".repeat(tabs ?? 0)}${str}${continued ? "" : "\n"}`;
|
|
5
|
+
};
|
|
6
|
+
const emitTypes = (context, namespace) => {
|
|
7
|
+
const out = {};
|
|
8
|
+
const traverseNamespace = (n) => {
|
|
9
|
+
let file = autogenerateWarning;
|
|
10
|
+
const resolvedNames = {
|
|
11
|
+
enums: [],
|
|
12
|
+
unions: [],
|
|
13
|
+
models: [],
|
|
14
|
+
};
|
|
15
|
+
const resolveType = (t, nestlevel) => {
|
|
16
|
+
let typeStr = "unknown";
|
|
17
|
+
switch (t.kind) {
|
|
18
|
+
case "Model":
|
|
19
|
+
if (t.name === "Array") {
|
|
20
|
+
typeStr = resolveArray(t, nestlevel);
|
|
21
|
+
}
|
|
22
|
+
else
|
|
23
|
+
typeStr = resolveModel(t, nestlevel + 1);
|
|
24
|
+
break;
|
|
25
|
+
case "Boolean":
|
|
26
|
+
typeStr = "boolean";
|
|
27
|
+
break;
|
|
28
|
+
case "Enum":
|
|
29
|
+
typeStr = resolveEnum(t, nestlevel);
|
|
30
|
+
break;
|
|
31
|
+
case "Intrinsic":
|
|
32
|
+
typeStr = t.name;
|
|
33
|
+
break;
|
|
34
|
+
case "Number":
|
|
35
|
+
typeStr = t.valueAsString;
|
|
36
|
+
break;
|
|
37
|
+
case "Scalar":
|
|
38
|
+
typeStr = resolveScalar(t);
|
|
39
|
+
break;
|
|
40
|
+
case "String":
|
|
41
|
+
typeStr = `'${t.value}'`;
|
|
42
|
+
break;
|
|
43
|
+
case "Tuple":
|
|
44
|
+
typeStr = resolveTuple(t, nestlevel);
|
|
45
|
+
break;
|
|
46
|
+
case "Union":
|
|
47
|
+
typeStr = resolveUnion(t, nestlevel);
|
|
48
|
+
break;
|
|
49
|
+
default:
|
|
50
|
+
console.warn("Could not resolve type:", t.kind);
|
|
51
|
+
}
|
|
52
|
+
return typeStr;
|
|
53
|
+
};
|
|
54
|
+
const resolveArray = (a, nestlevel) => {
|
|
55
|
+
if (a.name !== "Array")
|
|
56
|
+
throw new Error(`Trying to parse model ${a.name} as Array`);
|
|
57
|
+
let ret = `${resolveType(a.indexer.value, nestlevel)}[]`;
|
|
58
|
+
return ret;
|
|
59
|
+
};
|
|
60
|
+
const resolveEnum = (e, nestlevel) => {
|
|
61
|
+
if (e.name && resolvedNames.enums.includes(e.name))
|
|
62
|
+
return e.name;
|
|
63
|
+
let ret = "{\n";
|
|
64
|
+
let i = 1;
|
|
65
|
+
e.members.forEach((p) => {
|
|
66
|
+
const val = p.value === undefined
|
|
67
|
+
? ""
|
|
68
|
+
: " = " +
|
|
69
|
+
(typeof p.value === "string"
|
|
70
|
+
? `'${p.value}'`
|
|
71
|
+
: p.value.toString());
|
|
72
|
+
ret = ret.addLine(`${p.name}${val}${i < e.members.size ? "," : ""}`, nestlevel + 1);
|
|
73
|
+
i++;
|
|
74
|
+
});
|
|
75
|
+
ret = ret.addLine("}", nestlevel, true);
|
|
76
|
+
resolvedNames.enums.push(e.name);
|
|
77
|
+
return ret;
|
|
78
|
+
};
|
|
79
|
+
const resolveTuple = (t, nestlevel) => {
|
|
80
|
+
return `[${t.values.map((v) => resolveType(v, nestlevel)).join(", ")}]`;
|
|
81
|
+
};
|
|
82
|
+
const resolveUnion = (u, nestlevel) => {
|
|
83
|
+
if (u.name && resolvedNames.unions.includes(u.name))
|
|
84
|
+
return u.name;
|
|
85
|
+
return Array.from(u.variants)
|
|
86
|
+
.map((v) => resolveType(v[1].type, nestlevel))
|
|
87
|
+
.join(" | ");
|
|
88
|
+
};
|
|
89
|
+
const resolveScalar = (s) => {
|
|
90
|
+
let ret = "unknown";
|
|
91
|
+
if (!s.baseScalar) {
|
|
92
|
+
switch (s.name) {
|
|
93
|
+
case "boolean":
|
|
94
|
+
ret = "boolean";
|
|
95
|
+
break;
|
|
96
|
+
case "bytes":
|
|
97
|
+
ret = "Uint8Array";
|
|
98
|
+
break;
|
|
99
|
+
case "duration":
|
|
100
|
+
case "numeric":
|
|
101
|
+
ret = "number";
|
|
102
|
+
break;
|
|
103
|
+
case "plainTime":
|
|
104
|
+
case "string":
|
|
105
|
+
case "url":
|
|
106
|
+
ret = "string";
|
|
107
|
+
break;
|
|
108
|
+
case "offsetDateTime":
|
|
109
|
+
case "plainDate":
|
|
110
|
+
case "unixTimestamp32":
|
|
111
|
+
case "utcDateTime":
|
|
112
|
+
ret = "Date";
|
|
113
|
+
break;
|
|
114
|
+
default:
|
|
115
|
+
console.warn("Could not resolve scalar:", s.name);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return s.baseScalar ? resolveScalar(s.baseScalar) : ret;
|
|
119
|
+
};
|
|
120
|
+
const resolveModel = (m, nestlevel = 0) => {
|
|
121
|
+
if (m.name && resolvedNames.models.includes(m.name))
|
|
122
|
+
return m.name;
|
|
123
|
+
let ret = "{\n";
|
|
124
|
+
let i = 1;
|
|
125
|
+
m.properties.forEach((p) => {
|
|
126
|
+
const doc = getDoc(context.program, p);
|
|
127
|
+
if (doc)
|
|
128
|
+
ret = ret.addLine(`/** ${doc} */`, nestlevel + 1);
|
|
129
|
+
const typeStr = resolveType(p.type, nestlevel);
|
|
130
|
+
if (typeStr.includes("unknown"))
|
|
131
|
+
console.warn(`Could not resolve property ${p.name} on ${m.name}`);
|
|
132
|
+
ret = ret.addLine(`${p.name}: ${typeStr}${i < m.properties.size ? "," : ""}`, nestlevel + 1);
|
|
133
|
+
i++;
|
|
134
|
+
});
|
|
135
|
+
ret = ret.addLine("}", nestlevel, true);
|
|
136
|
+
resolvedNames.models.push(m.name);
|
|
137
|
+
return ret;
|
|
138
|
+
};
|
|
139
|
+
n.enums.forEach((e) => {
|
|
140
|
+
const resolved = resolveEnum(e, 0);
|
|
141
|
+
if (resolved) {
|
|
142
|
+
const doc = getDoc(context.program, e);
|
|
143
|
+
if (doc)
|
|
144
|
+
file = file.addLine(`/** ${doc} */`);
|
|
145
|
+
file = file.addLine(`export enum ${e.name} ${resolved};\n`);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
n.unions.forEach((u) => {
|
|
149
|
+
const resolved = resolveUnion(u, 0);
|
|
150
|
+
if (resolved) {
|
|
151
|
+
const doc = getDoc(context.program, u);
|
|
152
|
+
if (doc)
|
|
153
|
+
file = file.addLine(`/** ${doc} */`);
|
|
154
|
+
file = file.addLine(`export type ${u.name} = ${resolved};\n`);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
n.models.forEach((m) => {
|
|
158
|
+
const resolved = resolveModel(m);
|
|
159
|
+
if (resolved) {
|
|
160
|
+
const doc = getDoc(context.program, m);
|
|
161
|
+
if (doc)
|
|
162
|
+
file = file.addLine(`/** ${doc} */`);
|
|
163
|
+
file = file.addLine(`export interface ${m.name} ${resolved};\n`);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
// set output for this namespace
|
|
167
|
+
out[n.name.charAt(0).toUpperCase() + n.name.slice(1)] = file;
|
|
168
|
+
// recursively iterate child namespaces
|
|
169
|
+
n.namespaces.forEach((ns) => traverseNamespace(ns));
|
|
170
|
+
};
|
|
171
|
+
traverseNamespace(namespace);
|
|
172
|
+
return out;
|
|
173
|
+
};
|
|
174
|
+
export default emitTypes;
|
|
175
|
+
//# sourceMappingURL=emit_types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit_types.js","sourceRoot":"","sources":["../../src/emit_types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { emitFile, navigateProgram, resolvePath, } from "@typespec/compiler";
|
|
2
|
+
import { getServers } from "@typespec/http";
|
|
3
|
+
import emitRoutes from "./emit_routes.js";
|
|
4
|
+
import emitTypes from "./emit_types.js";
|
|
5
|
+
export async function $onEmit(context) {
|
|
6
|
+
if (!context.program.compilerOptions.noEmit) {
|
|
7
|
+
const options = {
|
|
8
|
+
"root-namespace": context.options["root-namespace"],
|
|
9
|
+
"out-dir": context.options["out-dir"] ?? context.emitterOutputDir,
|
|
10
|
+
"enable-types": context.options["enable-types"] ?? true,
|
|
11
|
+
"enable-routes": context.options["enable-routes"] ?? false,
|
|
12
|
+
};
|
|
13
|
+
console.log(`Writing routes to ${options["out-dir"]}`);
|
|
14
|
+
let targetNamespaceFound = false;
|
|
15
|
+
let routesObject = "";
|
|
16
|
+
let typeFiles = {};
|
|
17
|
+
navigateProgram(context.program, {
|
|
18
|
+
namespace(n) {
|
|
19
|
+
if (!targetNamespaceFound &&
|
|
20
|
+
n.name === context.options["root-namespace"]) {
|
|
21
|
+
targetNamespaceFound = true;
|
|
22
|
+
if (options["enable-routes"]) {
|
|
23
|
+
const servers = getServers(context.program, n);
|
|
24
|
+
routesObject = emitRoutes(context, n, servers && servers[0] ? servers[0].url : "");
|
|
25
|
+
}
|
|
26
|
+
if (options["enable-types"])
|
|
27
|
+
typeFiles = emitTypes(context, n);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
if (!targetNamespaceFound)
|
|
32
|
+
throw new Error("Targeted root namespace not found.");
|
|
33
|
+
// routes object
|
|
34
|
+
if (options["enable-routes"]) {
|
|
35
|
+
if (!routesObject)
|
|
36
|
+
throw new Error("Routes object empty.");
|
|
37
|
+
await emitFile(context.program, {
|
|
38
|
+
path: resolvePath(options["out-dir"], `routes_${options["root-namespace"]}.ts`),
|
|
39
|
+
content: routesObject,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
// type files
|
|
43
|
+
if (options["enable-types"]) {
|
|
44
|
+
const typeFileArr = Object.entries(typeFiles);
|
|
45
|
+
for (let i = 0; i < typeFileArr.length; i++) {
|
|
46
|
+
await emitFile(context.program, {
|
|
47
|
+
path: resolvePath(options["out-dir"], `${typeFileArr[i][0]}.ts`),
|
|
48
|
+
content: typeFileArr[i][1],
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=emitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitter.js","sourceRoot":"","sources":["../../src/emitter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const autogenerateWarning = "\n/*\n * This file is automatically generated by typespec-typescript-emitter.\n * \n * You should not change or manipulate this file, as it will be overwritten.\n * Instead, change the underlying spec.\n */\n\n\n";
|
|
2
|
+
export default autogenerateWarning;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const autogenerateWarning = `
|
|
2
|
+
/*
|
|
3
|
+
* This file is automatically generated by typespec-typescript-emitter.
|
|
4
|
+
*
|
|
5
|
+
* You should not change or manipulate this file, as it will be overwritten.
|
|
6
|
+
* Instead, change the underlying spec.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
`;
|
|
11
|
+
export default autogenerateWarning;
|
|
12
|
+
//# sourceMappingURL=helper_autogenerateWarning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helper_autogenerateWarning.js","sourceRoot":"","sources":["../../src/helper_autogenerateWarning.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG;;;;;;;;;CAS3B,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface EmitterOptions {
|
|
2
|
+
"root-namespace": string;
|
|
3
|
+
"out-dir": string;
|
|
4
|
+
"enable-types": boolean;
|
|
5
|
+
"enable-routes": boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare const $lib: import("@typespec/compiler").TypeSpecLibrary<{
|
|
8
|
+
[code: string]: import("@typespec/compiler").DiagnosticMessages;
|
|
9
|
+
}, EmitterOptions, never>;
|
|
10
|
+
export declare const reportDiagnostic: <C extends string | number, M extends keyof {
|
|
11
|
+
[code: string]: import("@typespec/compiler").DiagnosticMessages;
|
|
12
|
+
}[C]>(program: import("@typespec/compiler").Program, diag: import("@typespec/compiler").DiagnosticReport<{
|
|
13
|
+
[code: string]: import("@typespec/compiler").DiagnosticMessages;
|
|
14
|
+
}, C, M>) => void, createDiagnostic: <C extends string | number, M extends keyof {
|
|
15
|
+
[code: string]: import("@typespec/compiler").DiagnosticMessages;
|
|
16
|
+
}[C]>(diag: import("@typespec/compiler").DiagnosticReport<{
|
|
17
|
+
[code: string]: import("@typespec/compiler").DiagnosticMessages;
|
|
18
|
+
}, C, M>) => import("@typespec/compiler").Diagnostic;
|