@typespec/tspd 0.70.0-dev.2 → 0.70.0
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/dist/src/cli.js +85 -103
- package/dist/src/gen-extern-signatures/components/decorator-signature-tests.d.ts +8 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-tests.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-tests.js +16 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-tests.jsx +12 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-tests.jsx.map +1 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-type.d.ts +16 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-type.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-type.js +404 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-type.jsx +316 -0
- package/dist/src/gen-extern-signatures/components/decorator-signature-type.jsx.map +1 -0
- package/dist/src/gen-extern-signatures/components/decorators-signatures.d.ts +12 -0
- package/dist/src/gen-extern-signatures/components/decorators-signatures.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/components/decorators-signatures.js +107 -0
- package/dist/src/gen-extern-signatures/components/decorators-signatures.jsx +60 -0
- package/dist/src/gen-extern-signatures/components/decorators-signatures.jsx.map +1 -0
- package/dist/src/gen-extern-signatures/components/dollar-decorators-type.d.ts +10 -0
- package/dist/src/gen-extern-signatures/components/dollar-decorators-type.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/components/dollar-decorators-type.js +39 -0
- package/dist/src/gen-extern-signatures/components/dollar-decorators-type.jsx +18 -0
- package/dist/src/gen-extern-signatures/components/dollar-decorators-type.jsx.map +1 -0
- package/dist/src/gen-extern-signatures/components/tspd-context.d.ts +10 -0
- package/dist/src/gen-extern-signatures/components/tspd-context.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/components/tspd-context.js +22 -0
- package/dist/src/gen-extern-signatures/components/tspd-context.js.map +1 -0
- package/dist/src/gen-extern-signatures/doc-builder.js +10 -12
- package/dist/src/gen-extern-signatures/external-packages/compiler.d.ts +17 -0
- package/dist/src/gen-extern-signatures/external-packages/compiler.d.ts.map +1 -0
- package/dist/src/gen-extern-signatures/external-packages/compiler.js +10 -0
- package/dist/src/gen-extern-signatures/external-packages/compiler.js.map +1 -0
- package/dist/src/gen-extern-signatures/gen-extern-signatures.d.ts.map +1 -1
- package/dist/src/gen-extern-signatures/gen-extern-signatures.js +109 -102
- package/dist/src/gen-extern-signatures/gen-extern-signatures.js.map +1 -1
- package/dist/src/gen-extern-signatures/types.js +1 -2
- package/dist/src/ref-doc/api-docs.js +56 -56
- package/dist/src/ref-doc/emitters/docusaurus.js +156 -209
- package/dist/src/ref-doc/emitters/markdown.js +278 -327
- package/dist/src/ref-doc/emitters/starlight.js +154 -190
- package/dist/src/ref-doc/experimental.js +48 -45
- package/dist/src/ref-doc/extractor.js +486 -449
- package/dist/src/ref-doc/index.js +1 -2
- package/dist/src/ref-doc/lib.js +29 -26
- package/dist/src/ref-doc/types.js +1 -2
- package/dist/src/ref-doc/utils/markdown.js +37 -44
- package/dist/src/ref-doc/utils/type-signature.js +89 -98
- package/package.json +12 -9
- package/dist/src/gen-extern-signatures/decorators-signatures.d.ts +0 -5
- package/dist/src/gen-extern-signatures/decorators-signatures.d.ts.map +0 -1
- package/dist/src/gen-extern-signatures/decorators-signatures.js +0 -338
- package/dist/src/gen-extern-signatures/decorators-signatures.js.map +0 -1
package/dist/src/cli.js
CHANGED
|
@@ -5,114 +5,96 @@ import yargs from "yargs";
|
|
|
5
5
|
import { generateExternSignatures } from "./gen-extern-signatures/gen-extern-signatures.js";
|
|
6
6
|
import { generateLibraryDocs } from "./ref-doc/experimental.js";
|
|
7
7
|
try {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// package only present in dev.
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
await import("source-map-support/register.js");
|
|
11
|
+
} catch {
|
|
12
|
+
// package only present in dev.
|
|
14
13
|
}
|
|
15
14
|
function logExperimentalWarning(type) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
log(`
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
log("-".repeat(100));
|
|
15
|
+
const log = type === "error" ? message => console.error(pc.red(message)) : message => console.log(pc.yellow(message));
|
|
16
|
+
log("-".repeat(100));
|
|
17
|
+
log(`tspd (TypeSpec Library Developer Cli) is experimental and might be ${pc.bold("BREAKING")} between versions.`);
|
|
18
|
+
if (type === "error") {
|
|
19
|
+
log(`Add "--enable-experimental" flag to acknowledge this and continue.`);
|
|
20
|
+
}
|
|
21
|
+
log("-".repeat(100));
|
|
25
22
|
}
|
|
26
23
|
async function main() {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
.command("gen-extern-signature <entrypoint>", "Format given list of TypeSpec files.", (cmd) => {
|
|
87
|
-
return cmd.positional("entrypoint", {
|
|
88
|
-
description: "Path to the library entrypoint.",
|
|
89
|
-
type: "string",
|
|
90
|
-
demandOption: true,
|
|
91
|
-
});
|
|
92
|
-
}, async (args) => {
|
|
93
|
-
const resolvedRoot = resolvePath(process.cwd(), args.entrypoint);
|
|
94
|
-
const host = NodeHost;
|
|
95
|
-
const diagnostics = await generateExternSignatures(host, resolvedRoot);
|
|
96
|
-
if (diagnostics.length > 0) {
|
|
97
|
-
logDiagnostics(diagnostics, host.logSink);
|
|
98
|
-
}
|
|
99
|
-
})
|
|
100
|
-
.demandCommand(1, "You must use one of the supported commands.").argv;
|
|
24
|
+
console.log(`TypeSpec Developer Tools\n`);
|
|
25
|
+
await yargs(process.argv.slice(2)).scriptName("tspd").help().strict().parserConfiguration({
|
|
26
|
+
"greedy-arrays": false,
|
|
27
|
+
"boolean-negation": false
|
|
28
|
+
}).option("debug", {
|
|
29
|
+
type: "boolean",
|
|
30
|
+
description: "Output debug log messages.",
|
|
31
|
+
default: false
|
|
32
|
+
}).option("pretty", {
|
|
33
|
+
type: "boolean",
|
|
34
|
+
description: "Enable color and formatting in TypeSpec's output to make compiler errors easier to read.",
|
|
35
|
+
default: true
|
|
36
|
+
}).option("enable-experimental", {
|
|
37
|
+
type: "boolean",
|
|
38
|
+
description: "Acknowledge that the tspd command line is experiemental.",
|
|
39
|
+
default: false
|
|
40
|
+
}).check(args => {
|
|
41
|
+
if (args["enable-experimental"]) {
|
|
42
|
+
logExperimentalWarning("log");
|
|
43
|
+
return true;
|
|
44
|
+
} else {
|
|
45
|
+
logExperimentalWarning("error");
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}).command("doc <entrypoint>", "Generate documentation for a TypeSpec library.", cmd => {
|
|
49
|
+
return cmd.positional("entrypoint", {
|
|
50
|
+
description: "Path to the library entrypoint.",
|
|
51
|
+
type: "string",
|
|
52
|
+
demandOption: true
|
|
53
|
+
}).option("output-dir", {
|
|
54
|
+
type: "string"
|
|
55
|
+
}).positional("skip-js", {
|
|
56
|
+
description: "Skip generating JS API docs.",
|
|
57
|
+
type: "boolean"
|
|
58
|
+
});
|
|
59
|
+
}, async args => {
|
|
60
|
+
const resolvedRoot = resolvePath(process.cwd(), args.entrypoint);
|
|
61
|
+
const host = NodeHost;
|
|
62
|
+
const diagnostics = await generateLibraryDocs(resolvedRoot, args["output-dir"] ?? resolvePath(resolvedRoot, "docs"), {
|
|
63
|
+
skipJSApi: args["skip-js"]
|
|
64
|
+
});
|
|
65
|
+
// const diagnostics = await generateExternSignatures(host, resolvedRoot);
|
|
66
|
+
if (diagnostics.length > 0) {
|
|
67
|
+
logDiagnostics(diagnostics, host.logSink);
|
|
68
|
+
}
|
|
69
|
+
}).command("gen-extern-signature <entrypoint>", "Format given list of TypeSpec files.", cmd => {
|
|
70
|
+
return cmd.positional("entrypoint", {
|
|
71
|
+
description: "Path to the library entrypoint.",
|
|
72
|
+
type: "string",
|
|
73
|
+
demandOption: true
|
|
74
|
+
});
|
|
75
|
+
}, async args => {
|
|
76
|
+
const resolvedRoot = resolvePath(process.cwd(), args.entrypoint);
|
|
77
|
+
const host = NodeHost;
|
|
78
|
+
const diagnostics = await generateExternSignatures(host, resolvedRoot);
|
|
79
|
+
if (diagnostics.length > 0) {
|
|
80
|
+
logDiagnostics(diagnostics, host.logSink);
|
|
81
|
+
}
|
|
82
|
+
}).demandCommand(1, "You must use one of the supported commands.").argv;
|
|
101
83
|
}
|
|
102
84
|
function internalError(error) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
85
|
+
// NOTE: An expected error, like one thrown for bad input, shouldn't reach
|
|
86
|
+
// here, but be handled somewhere else. If we reach here, it should be
|
|
87
|
+
// considered a bug and therefore we should not suppress the stack trace as
|
|
88
|
+
// that risks losing it in the case of a bug that does not repro easily.
|
|
89
|
+
|
|
90
|
+
console.error("Internal error!");
|
|
91
|
+
console.error("File issue at https://github.com/microsoft/typespec");
|
|
92
|
+
console.error();
|
|
93
|
+
console.error(error);
|
|
94
|
+
process.exit(1);
|
|
112
95
|
}
|
|
113
|
-
process.on("unhandledRejection",
|
|
114
|
-
|
|
115
|
-
|
|
96
|
+
process.on("unhandledRejection", error => {
|
|
97
|
+
console.error("Unhandled promise rejection!");
|
|
98
|
+
internalError(error);
|
|
116
99
|
});
|
|
117
|
-
main().catch(internalError);
|
|
118
|
-
//# sourceMappingURL=cli.js.map
|
|
100
|
+
main().catch(internalError);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as ay from "@alloy-js/core";
|
|
2
|
+
export interface DecoratorSignatureTests {
|
|
3
|
+
namespaceName: string;
|
|
4
|
+
dollarDecoratorRefKey: ay.Refkey;
|
|
5
|
+
dollarDecoratorsTypeRefKey: ay.Refkey;
|
|
6
|
+
}
|
|
7
|
+
export declare function DecoratorSignatureTests({ namespaceName, dollarDecoratorRefKey, dollarDecoratorsTypeRefKey, }: Readonly<DecoratorSignatureTests>): ay.Children;
|
|
8
|
+
//# sourceMappingURL=decorator-signature-tests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorator-signature-tests.d.ts","sourceRoot":"","sources":["../../../../src/gen-extern-signatures/components/decorator-signature-tests.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGrC,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,EAAE,CAAC,MAAM,CAAC;IACjC,0BAA0B,EAAE,EAAE,CAAC,MAAM,CAAC;CACvC;AAED,wBAAgB,uBAAuB,CAAC,EACtC,aAAa,EACb,qBAAqB,EACrB,0BAA0B,GAC3B,EAAE,QAAQ,CAAC,uBAAuB,CAAC,eAenC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createIntrinsic as _$createIntrinsic, createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import * as ts from "@alloy-js/typescript";
|
|
3
|
+
export function DecoratorSignatureTests({
|
|
4
|
+
namespaceName,
|
|
5
|
+
dollarDecoratorRefKey,
|
|
6
|
+
dollarDecoratorsTypeRefKey
|
|
7
|
+
}) {
|
|
8
|
+
return [_$createIntrinsic("hbr", {}), _$createIntrinsic("hbr", {}), _$createComponent(ts.VarDeclaration, {
|
|
9
|
+
name: "_",
|
|
10
|
+
type: dollarDecoratorsTypeRefKey,
|
|
11
|
+
doc: "An error here would mean that the exported decorator is not using the same signature. Make sure to have export const $decName: DecNameDecorator = (...) => ...",
|
|
12
|
+
get children() {
|
|
13
|
+
return [dollarDecoratorRefKey, `["${namespaceName}"]`];
|
|
14
|
+
}
|
|
15
|
+
})];
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as ts from "@alloy-js/typescript";
|
|
2
|
+
export function DecoratorSignatureTests({ namespaceName, dollarDecoratorRefKey, dollarDecoratorsTypeRefKey, }) {
|
|
3
|
+
return (<>
|
|
4
|
+
<hbr />
|
|
5
|
+
<hbr />
|
|
6
|
+
<ts.VarDeclaration name="_" type={dollarDecoratorsTypeRefKey} doc="An error here would mean that the exported decorator is not using the same signature. Make sure to have export const $decName: DecNameDecorator = (...) => ...">
|
|
7
|
+
{dollarDecoratorRefKey}
|
|
8
|
+
{`["${namespaceName}"]`}
|
|
9
|
+
</ts.VarDeclaration>
|
|
10
|
+
</>);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=decorator-signature-tests.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorator-signature-tests.jsx","sourceRoot":"","sources":["../../../../src/gen-extern-signatures/components/decorator-signature-tests.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAQ3C,MAAM,UAAU,uBAAuB,CAAC,EACtC,aAAa,EACb,qBAAqB,EACrB,0BAA0B,GACQ;IAClC,OAAO,CACL,EACE;MAAA,CAAC,GAAG,CAAC,AAAD,EACJ;MAAA,CAAC,GAAG,CAAC,AAAD,EACJ;MAAA,CAAC,EAAE,CAAC,cAAc,CAChB,IAAI,CAAC,GAAG,CACR,IAAI,CAAC,CAAC,0BAA0B,CAAC,CACjC,GAAG,CAAC,gKAAgK,CAEpK;QAAA,CAAC,qBAAqB,CACtB;QAAA,CAAC,KAAK,aAAa,IAAI,CACzB;MAAA,EAAE,EAAE,CAAC,cAAc,CACrB;IAAA,GAAG,CACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as ay from "@alloy-js/core";
|
|
2
|
+
import { MixedParameterConstraint, Model } from "@typespec/compiler";
|
|
3
|
+
import { DecoratorSignature } from "../types.js";
|
|
4
|
+
export interface DecoratorSignatureProps {
|
|
5
|
+
signature: DecoratorSignature;
|
|
6
|
+
}
|
|
7
|
+
/** Render the type of decorator implementation function */
|
|
8
|
+
export declare function DecoratorSignatureType(props: Readonly<DecoratorSignatureProps>): ay.Children;
|
|
9
|
+
export interface ParameterTsTypeProps {
|
|
10
|
+
constraint: MixedParameterConstraint;
|
|
11
|
+
}
|
|
12
|
+
export declare function ParameterTsType({ constraint }: ParameterTsTypeProps): ay.Children;
|
|
13
|
+
export declare function ValueOfModelTsInterfaceBody({ model }: {
|
|
14
|
+
model: Model;
|
|
15
|
+
}): ay.Children;
|
|
16
|
+
//# sourceMappingURL=decorator-signature-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorator-signature-type.d.ts","sourceRoot":"","sources":["../../../../src/gen-extern-signatures/components/decorator-signature-type.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,EAEL,wBAAwB,EACxB,KAAK,EAON,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAED,4DAA4D;AAC5D,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC,uBAAuB,CAAC,eAwC9E;AA+BD,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,wBAAwB,CAAC;CACtC;AACD,wBAAgB,eAAe,CAAC,EAAE,UAAU,EAAE,EAAE,oBAAoB,eAiBnE;AAkHD,wBAAgB,2BAA2B,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,eAsBtE"}
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import { createComponent as _$createComponent, memo as _$memo } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import * as ay from "@alloy-js/core";
|
|
3
|
+
import * as ts from "@alloy-js/typescript";
|
|
4
|
+
import { getSourceLocation, isArrayModelType, isUnknownType } from "@typespec/compiler";
|
|
5
|
+
import { SyntaxKind } from "@typespec/compiler/ast";
|
|
6
|
+
import { typespecCompiler } from "../external-packages/compiler.js";
|
|
7
|
+
import { useTspd } from "./tspd-context.js";
|
|
8
|
+
/** Render the type of decorator implementation function */
|
|
9
|
+
export function DecoratorSignatureType(props) {
|
|
10
|
+
const {
|
|
11
|
+
program
|
|
12
|
+
} = useTspd();
|
|
13
|
+
const decorator = props.signature.decorator;
|
|
14
|
+
const parameters = [{
|
|
15
|
+
name: "context",
|
|
16
|
+
type: typespecCompiler.DecoratorContext
|
|
17
|
+
}, {
|
|
18
|
+
name: decorator.target.name,
|
|
19
|
+
type: _$createComponent(TargetParameterTsType, {
|
|
20
|
+
get type() {
|
|
21
|
+
return decorator.target.type.type;
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
}, ...decorator.parameters.map(param => ({
|
|
25
|
+
// https://github.com/alloy-framework/alloy/issues/144
|
|
26
|
+
name: param.rest ? `...${param.name}` : param.name,
|
|
27
|
+
type: param.rest ? ["(", _$memo(() => _$memo(() => !!param.type)() ? _$createComponent(ParameterTsType, {
|
|
28
|
+
get constraint() {
|
|
29
|
+
return extractRestParamConstraint(program, param.type);
|
|
30
|
+
}
|
|
31
|
+
}) : undefined), ")[]"] : _$createComponent(ParameterTsType, {
|
|
32
|
+
get constraint() {
|
|
33
|
+
return param.type;
|
|
34
|
+
}
|
|
35
|
+
}),
|
|
36
|
+
optional: param.optional
|
|
37
|
+
}))];
|
|
38
|
+
return _$createComponent(ts.TypeDeclaration, {
|
|
39
|
+
"export": true,
|
|
40
|
+
get name() {
|
|
41
|
+
return props.signature.typeName;
|
|
42
|
+
},
|
|
43
|
+
get doc() {
|
|
44
|
+
return getDocComment(props.signature.decorator);
|
|
45
|
+
},
|
|
46
|
+
get children() {
|
|
47
|
+
return _$createComponent(ts.FunctionType, {
|
|
48
|
+
parameters: parameters
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** For a rest param of constraint T[] or valueof T[] return the T or valueof T */
|
|
55
|
+
function extractRestParamConstraint(program, constraint) {
|
|
56
|
+
let valueType;
|
|
57
|
+
let type;
|
|
58
|
+
if (constraint.valueType) {
|
|
59
|
+
if (constraint.valueType.kind === "Model" && isArrayModelType(program, constraint.valueType)) {
|
|
60
|
+
valueType = constraint.valueType.indexer.value;
|
|
61
|
+
} else {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (constraint.type) {
|
|
66
|
+
if (constraint.type.kind === "Model" && isArrayModelType(program, constraint.type)) {
|
|
67
|
+
type = constraint.type.indexer.value;
|
|
68
|
+
} else {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
entityKind: "MixedParameterConstraint",
|
|
74
|
+
type,
|
|
75
|
+
valueType
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export function ParameterTsType({
|
|
79
|
+
constraint
|
|
80
|
+
}) {
|
|
81
|
+
if (constraint.type && constraint.valueType) {
|
|
82
|
+
return [_$createComponent(TypeConstraintTSType, {
|
|
83
|
+
get type() {
|
|
84
|
+
return constraint.type;
|
|
85
|
+
}
|
|
86
|
+
}), " | ", _$createComponent(ValueTsType, {
|
|
87
|
+
get type() {
|
|
88
|
+
return constraint.valueType;
|
|
89
|
+
}
|
|
90
|
+
})];
|
|
91
|
+
}
|
|
92
|
+
if (constraint.valueType) {
|
|
93
|
+
return _$createComponent(ValueTsType, {
|
|
94
|
+
get type() {
|
|
95
|
+
return constraint.valueType;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
} else if (constraint.type) {
|
|
99
|
+
return _$createComponent(TypeConstraintTSType, {
|
|
100
|
+
get type() {
|
|
101
|
+
return constraint.type;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return typespecCompiler.Type;
|
|
106
|
+
}
|
|
107
|
+
function TargetParameterTsType(props) {
|
|
108
|
+
const type = props.type;
|
|
109
|
+
if (type === undefined) {
|
|
110
|
+
return typespecCompiler.Type;
|
|
111
|
+
}
|
|
112
|
+
if (type.kind === "Union") {
|
|
113
|
+
const variants = [...type.variants.values()].map(x => x.type).map(getTargetType);
|
|
114
|
+
return ay.join(new Set(variants).values(), {
|
|
115
|
+
joiner: " | "
|
|
116
|
+
});
|
|
117
|
+
} else {
|
|
118
|
+
return getTargetType(type);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function getTargetType(type) {
|
|
122
|
+
if (type === undefined || isUnknownType(type)) {
|
|
123
|
+
return typespecCompiler.Type;
|
|
124
|
+
} else if (type.kind === "Model" && isReflectionType(type)) {
|
|
125
|
+
return typespecCompiler[type.name];
|
|
126
|
+
} else if (type.kind === "Scalar") {
|
|
127
|
+
// Special case for target type if it is a scalar type(e.g. `string`) then it can only be a Scalar.
|
|
128
|
+
// In the case of regular parameter it could also be a union of the scalar, or a literal matching the scalar or union of both,
|
|
129
|
+
// so we only change that when isTarget is true.
|
|
130
|
+
return typespecCompiler.Scalar;
|
|
131
|
+
} else {
|
|
132
|
+
return typespecCompiler.Type;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function TypeConstraintTSType({
|
|
136
|
+
type
|
|
137
|
+
}) {
|
|
138
|
+
if (type.kind === "Model" && isReflectionType(type)) {
|
|
139
|
+
return typespecCompiler[type.name];
|
|
140
|
+
} else if (type.kind === "Union") {
|
|
141
|
+
const variants = [...type.variants.values()].map(x => x.type);
|
|
142
|
+
if (variants.every(x => isReflectionType(x))) {
|
|
143
|
+
return ay.join([...new Set(variants)].map(x => getCompilerType(x.name)), {
|
|
144
|
+
joiner: " | "
|
|
145
|
+
});
|
|
146
|
+
} else {
|
|
147
|
+
return typespecCompiler.Type;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return typespecCompiler.Type;
|
|
151
|
+
}
|
|
152
|
+
function getCompilerType(name) {
|
|
153
|
+
return typespecCompiler[name];
|
|
154
|
+
}
|
|
155
|
+
function ValueTsType({
|
|
156
|
+
type
|
|
157
|
+
}) {
|
|
158
|
+
const {
|
|
159
|
+
program
|
|
160
|
+
} = useTspd();
|
|
161
|
+
switch (type.kind) {
|
|
162
|
+
case "Boolean":
|
|
163
|
+
return `${type.value}`;
|
|
164
|
+
case "String":
|
|
165
|
+
return `"${type.value}"`;
|
|
166
|
+
case "Number":
|
|
167
|
+
return `${type.value}`;
|
|
168
|
+
case "Scalar":
|
|
169
|
+
return _$createComponent(ScalarTsType, {
|
|
170
|
+
scalar: type
|
|
171
|
+
});
|
|
172
|
+
case "Union":
|
|
173
|
+
return ay.join([...type.variants.values()].map(x => _$createComponent(ValueTsType, {
|
|
174
|
+
get type() {
|
|
175
|
+
return x.type;
|
|
176
|
+
}
|
|
177
|
+
})), {
|
|
178
|
+
joiner: " | "
|
|
179
|
+
});
|
|
180
|
+
case "Model":
|
|
181
|
+
if (isArrayModelType(program, type)) {
|
|
182
|
+
return ["readonly (", _$createComponent(ValueTsType, {
|
|
183
|
+
get type() {
|
|
184
|
+
return type.indexer.value;
|
|
185
|
+
}
|
|
186
|
+
}), ")[]"];
|
|
187
|
+
} else if (isReflectionType(type)) {
|
|
188
|
+
return getValueOfReflectionType(type);
|
|
189
|
+
} else {
|
|
190
|
+
// If its exactly the record type use Record<string, T> instead of the model name.
|
|
191
|
+
if (type.indexer && type.name === "Record" && type.namespace?.name === "TypeSpec") {
|
|
192
|
+
return ["Record", "<string, ", _$createComponent(ValueTsType, {
|
|
193
|
+
get type() {
|
|
194
|
+
return type.indexer.value;
|
|
195
|
+
}
|
|
196
|
+
}), ">"];
|
|
197
|
+
}
|
|
198
|
+
if (type.name) {
|
|
199
|
+
return _$createComponent(LocalTypeReference, {
|
|
200
|
+
type: type
|
|
201
|
+
});
|
|
202
|
+
} else {
|
|
203
|
+
return _$createComponent(ValueOfModelTsType, {
|
|
204
|
+
model: type
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return "unknown";
|
|
210
|
+
}
|
|
211
|
+
function LocalTypeReference({
|
|
212
|
+
type
|
|
213
|
+
}) {
|
|
214
|
+
const {
|
|
215
|
+
addLocalType
|
|
216
|
+
} = useTspd();
|
|
217
|
+
addLocalType(type);
|
|
218
|
+
return _$createComponent(ts.Reference, {
|
|
219
|
+
get refkey() {
|
|
220
|
+
return ay.refkey(type);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
function ValueOfModelTsType({
|
|
225
|
+
model
|
|
226
|
+
}) {
|
|
227
|
+
return _$createComponent(ts.InterfaceExpression, {
|
|
228
|
+
get children() {
|
|
229
|
+
return _$createComponent(ValueOfModelTsInterfaceBody, {
|
|
230
|
+
model: model
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
export function ValueOfModelTsInterfaceBody({
|
|
236
|
+
model
|
|
237
|
+
}) {
|
|
238
|
+
return _$createComponent(ay.List, {
|
|
239
|
+
joiner: ";",
|
|
240
|
+
enderPunctuation: true,
|
|
241
|
+
get children() {
|
|
242
|
+
return [_$memo(() => _$memo(() => !!model.indexer?.value)() && _$createComponent(ts.InterfaceMember, {
|
|
243
|
+
readonly: true,
|
|
244
|
+
indexer: "key: string",
|
|
245
|
+
get type() {
|
|
246
|
+
return _$createComponent(ValueTsType, {
|
|
247
|
+
get type() {
|
|
248
|
+
return model.indexer.value;
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
})), _$createComponent(ay.For, {
|
|
253
|
+
get each() {
|
|
254
|
+
return model.properties.values();
|
|
255
|
+
},
|
|
256
|
+
children: x => _$createComponent(ts.InterfaceMember, {
|
|
257
|
+
readonly: true,
|
|
258
|
+
get name() {
|
|
259
|
+
return x.name;
|
|
260
|
+
},
|
|
261
|
+
get optional() {
|
|
262
|
+
return x.optional;
|
|
263
|
+
},
|
|
264
|
+
get type() {
|
|
265
|
+
return _$createComponent(ValueTsType, {
|
|
266
|
+
get type() {
|
|
267
|
+
return x.type;
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
})
|
|
272
|
+
})];
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
function ScalarTsType({
|
|
277
|
+
scalar
|
|
278
|
+
}) {
|
|
279
|
+
const {
|
|
280
|
+
program
|
|
281
|
+
} = useTspd();
|
|
282
|
+
const isStd = program.checker.isStdType(scalar);
|
|
283
|
+
if (isStd) {
|
|
284
|
+
return getStdScalarTSType(scalar);
|
|
285
|
+
} else if (scalar.baseScalar) {
|
|
286
|
+
return _$createComponent(ScalarTsType, {
|
|
287
|
+
get scalar() {
|
|
288
|
+
return scalar.baseScalar;
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
} else {
|
|
292
|
+
return "unknown";
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function getStdScalarTSType(scalar) {
|
|
296
|
+
switch (scalar.name) {
|
|
297
|
+
case "numeric":
|
|
298
|
+
case "decimal":
|
|
299
|
+
case "decimal128":
|
|
300
|
+
case "float":
|
|
301
|
+
case "integer":
|
|
302
|
+
case "int64":
|
|
303
|
+
case "uint64":
|
|
304
|
+
return typespecCompiler.Numeric;
|
|
305
|
+
case "int8":
|
|
306
|
+
case "int16":
|
|
307
|
+
case "int32":
|
|
308
|
+
case "safeint":
|
|
309
|
+
case "uint8":
|
|
310
|
+
case "uint16":
|
|
311
|
+
case "uint32":
|
|
312
|
+
case "float64":
|
|
313
|
+
case "float32":
|
|
314
|
+
return "number";
|
|
315
|
+
case "string":
|
|
316
|
+
case "url":
|
|
317
|
+
return "string";
|
|
318
|
+
case "boolean":
|
|
319
|
+
return "boolean";
|
|
320
|
+
case "plainDate":
|
|
321
|
+
case "utcDateTime":
|
|
322
|
+
case "offsetDateTime":
|
|
323
|
+
case "plainTime":
|
|
324
|
+
case "duration":
|
|
325
|
+
case "bytes":
|
|
326
|
+
return "unknown";
|
|
327
|
+
default:
|
|
328
|
+
const _assertNever = scalar.name;
|
|
329
|
+
return "unknown";
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
function isReflectionType(type) {
|
|
333
|
+
return type.kind === "Model" && type.namespace?.name === "Reflection" && type.namespace?.namespace?.name === "TypeSpec";
|
|
334
|
+
}
|
|
335
|
+
function getValueOfReflectionType(type) {
|
|
336
|
+
switch (type.name) {
|
|
337
|
+
case "EnumMember":
|
|
338
|
+
case "Enum":
|
|
339
|
+
return typespecCompiler.EnumValue;
|
|
340
|
+
case "Model":
|
|
341
|
+
return "Record<string, unknown>";
|
|
342
|
+
default:
|
|
343
|
+
return "unknown";
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
function getDocComment(type) {
|
|
347
|
+
const docs = type.node?.docs;
|
|
348
|
+
if (docs === undefined || docs.length === 0) {
|
|
349
|
+
return "";
|
|
350
|
+
}
|
|
351
|
+
const mainContentLines = [];
|
|
352
|
+
const tagLines = [];
|
|
353
|
+
for (const doc of docs) {
|
|
354
|
+
for (const content of doc.content) {
|
|
355
|
+
for (const line of content.text.split("\n")) {
|
|
356
|
+
mainContentLines.push(line);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
for (const tag of doc.tags) {
|
|
360
|
+
tagLines.push();
|
|
361
|
+
let first = true;
|
|
362
|
+
const hasContentFirstLine = checkIfTagHasDocOnSameLine(tag);
|
|
363
|
+
const tagStart = tag.kind === SyntaxKind.DocParamTag || tag.kind === SyntaxKind.DocTemplateTag ? `@${tag.tagName.sv} ${tag.paramName.sv}` : `@${tag.tagName.sv}`;
|
|
364
|
+
for (const content of tag.content) {
|
|
365
|
+
for (const line of content.text.split("\n")) {
|
|
366
|
+
const cleaned = sanitizeDocComment(line);
|
|
367
|
+
if (first) {
|
|
368
|
+
if (hasContentFirstLine) {
|
|
369
|
+
tagLines.push(`${tagStart} ${cleaned}`);
|
|
370
|
+
} else {
|
|
371
|
+
tagLines.push(tagStart, cleaned);
|
|
372
|
+
}
|
|
373
|
+
first = false;
|
|
374
|
+
} else {
|
|
375
|
+
tagLines.push(cleaned);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const docLines = [...mainContentLines, ...(tagLines.length > 0 ? [""] : []), ...tagLines];
|
|
382
|
+
return docLines.join("\n");
|
|
383
|
+
}
|
|
384
|
+
function sanitizeDocComment(doc) {
|
|
385
|
+
// Issue to escape @internal and other tsdoc tags https://github.com/microsoft/TypeScript/issues/47679
|
|
386
|
+
return doc.replaceAll("@internal", `@_internal`);
|
|
387
|
+
}
|
|
388
|
+
function checkIfTagHasDocOnSameLine(tag) {
|
|
389
|
+
const start = tag.content[0]?.pos;
|
|
390
|
+
const end = tag.content[0]?.end;
|
|
391
|
+
const file = getSourceLocation(tag.content[0]).file;
|
|
392
|
+
let hasFirstLine = false;
|
|
393
|
+
for (let i = start; i < end; i++) {
|
|
394
|
+
const ch = file.text[i];
|
|
395
|
+
if (ch === "\n") {
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
398
|
+
// Todo reuse compiler whitespace logic or have a way to get this info from the parser.
|
|
399
|
+
if (ch !== " ") {
|
|
400
|
+
hasFirstLine = true;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return hasFirstLine;
|
|
404
|
+
}
|