@typespec/tspd 0.70.0-dev.1 → 0.70.0-dev.3

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.
Files changed (50) hide show
  1. package/dist/src/cli.js +85 -103
  2. package/dist/src/gen-extern-signatures/components/decorator-signature-tests.d.ts +8 -0
  3. package/dist/src/gen-extern-signatures/components/decorator-signature-tests.d.ts.map +1 -0
  4. package/dist/src/gen-extern-signatures/components/decorator-signature-tests.js +16 -0
  5. package/dist/src/gen-extern-signatures/components/decorator-signature-tests.jsx +12 -0
  6. package/dist/src/gen-extern-signatures/components/decorator-signature-tests.jsx.map +1 -0
  7. package/dist/src/gen-extern-signatures/components/decorator-signature-type.d.ts +16 -0
  8. package/dist/src/gen-extern-signatures/components/decorator-signature-type.d.ts.map +1 -0
  9. package/dist/src/gen-extern-signatures/components/decorator-signature-type.js +404 -0
  10. package/dist/src/gen-extern-signatures/components/decorator-signature-type.jsx +316 -0
  11. package/dist/src/gen-extern-signatures/components/decorator-signature-type.jsx.map +1 -0
  12. package/dist/src/gen-extern-signatures/components/decorators-signatures.d.ts +12 -0
  13. package/dist/src/gen-extern-signatures/components/decorators-signatures.d.ts.map +1 -0
  14. package/dist/src/gen-extern-signatures/components/decorators-signatures.js +107 -0
  15. package/dist/src/gen-extern-signatures/components/decorators-signatures.jsx +60 -0
  16. package/dist/src/gen-extern-signatures/components/decorators-signatures.jsx.map +1 -0
  17. package/dist/src/gen-extern-signatures/components/dollar-decorators-type.d.ts +10 -0
  18. package/dist/src/gen-extern-signatures/components/dollar-decorators-type.d.ts.map +1 -0
  19. package/dist/src/gen-extern-signatures/components/dollar-decorators-type.js +39 -0
  20. package/dist/src/gen-extern-signatures/components/dollar-decorators-type.jsx +18 -0
  21. package/dist/src/gen-extern-signatures/components/dollar-decorators-type.jsx.map +1 -0
  22. package/dist/src/gen-extern-signatures/components/tspd-context.d.ts +10 -0
  23. package/dist/src/gen-extern-signatures/components/tspd-context.d.ts.map +1 -0
  24. package/dist/src/gen-extern-signatures/components/tspd-context.js +22 -0
  25. package/dist/src/gen-extern-signatures/components/tspd-context.js.map +1 -0
  26. package/dist/src/gen-extern-signatures/doc-builder.js +10 -12
  27. package/dist/src/gen-extern-signatures/external-packages/compiler.d.ts +17 -0
  28. package/dist/src/gen-extern-signatures/external-packages/compiler.d.ts.map +1 -0
  29. package/dist/src/gen-extern-signatures/external-packages/compiler.js +10 -0
  30. package/dist/src/gen-extern-signatures/external-packages/compiler.js.map +1 -0
  31. package/dist/src/gen-extern-signatures/gen-extern-signatures.d.ts.map +1 -1
  32. package/dist/src/gen-extern-signatures/gen-extern-signatures.js +109 -102
  33. package/dist/src/gen-extern-signatures/gen-extern-signatures.js.map +1 -1
  34. package/dist/src/gen-extern-signatures/types.js +1 -2
  35. package/dist/src/ref-doc/api-docs.js +56 -56
  36. package/dist/src/ref-doc/emitters/docusaurus.js +156 -209
  37. package/dist/src/ref-doc/emitters/markdown.js +278 -327
  38. package/dist/src/ref-doc/emitters/starlight.js +154 -190
  39. package/dist/src/ref-doc/experimental.js +48 -45
  40. package/dist/src/ref-doc/extractor.js +486 -449
  41. package/dist/src/ref-doc/index.js +1 -2
  42. package/dist/src/ref-doc/lib.js +29 -26
  43. package/dist/src/ref-doc/types.js +1 -2
  44. package/dist/src/ref-doc/utils/markdown.js +37 -44
  45. package/dist/src/ref-doc/utils/type-signature.js +89 -98
  46. package/package.json +10 -6
  47. package/dist/src/gen-extern-signatures/decorators-signatures.d.ts +0 -5
  48. package/dist/src/gen-extern-signatures/decorators-signatures.d.ts.map +0 -1
  49. package/dist/src/gen-extern-signatures/decorators-signatures.js +0 -338
  50. 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
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
9
- // @ts-ignore
10
- await import("source-map-support/register.js");
11
- }
12
- catch {
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
- const log = type === "error"
17
- ? (message) => console.error(pc.red(message))
18
- : (message) => console.log(pc.yellow(message));
19
- log("-".repeat(100));
20
- log(`tspd (TypeSpec Library Developer Cli) is experimental and might be ${pc.bold("BREAKING")} between versions.`);
21
- if (type === "error") {
22
- log(`Add "--enable-experimental" flag to acknowledge this and continue.`);
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
- console.log(`TypeSpec Developer Tools\n`);
28
- await yargs(process.argv.slice(2))
29
- .scriptName("tspd")
30
- .help()
31
- .strict()
32
- .parserConfiguration({
33
- "greedy-arrays": false,
34
- "boolean-negation": false,
35
- })
36
- .option("debug", {
37
- type: "boolean",
38
- description: "Output debug log messages.",
39
- default: false,
40
- })
41
- .option("pretty", {
42
- type: "boolean",
43
- description: "Enable color and formatting in TypeSpec's output to make compiler errors easier to read.",
44
- default: true,
45
- })
46
- .option("enable-experimental", {
47
- type: "boolean",
48
- description: "Acknowledge that the tspd command line is experiemental.",
49
- default: false,
50
- })
51
- .check((args) => {
52
- if (args["enable-experimental"]) {
53
- logExperimentalWarning("log");
54
- return true;
55
- }
56
- else {
57
- logExperimentalWarning("error");
58
- process.exit(1);
59
- }
60
- })
61
- .command("doc <entrypoint>", "Generate documentation for a TypeSpec library.", (cmd) => {
62
- return cmd
63
- .positional("entrypoint", {
64
- description: "Path to the library entrypoint.",
65
- type: "string",
66
- demandOption: true,
67
- })
68
- .option("output-dir", {
69
- type: "string",
70
- })
71
- .positional("skip-js", {
72
- description: "Skip generating JS API docs.",
73
- type: "boolean",
74
- });
75
- }, async (args) => {
76
- const resolvedRoot = resolvePath(process.cwd(), args.entrypoint);
77
- const host = NodeHost;
78
- const diagnostics = await generateLibraryDocs(resolvedRoot, args["output-dir"] ?? resolvePath(resolvedRoot, "docs"), {
79
- skipJSApi: args["skip-js"],
80
- });
81
- // const diagnostics = await generateExternSignatures(host, resolvedRoot);
82
- if (diagnostics.length > 0) {
83
- logDiagnostics(diagnostics, host.logSink);
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
- // NOTE: An expected error, like one thrown for bad input, shouldn't reach
104
- // here, but be handled somewhere else. If we reach here, it should be
105
- // considered a bug and therefore we should not suppress the stack trace as
106
- // that risks losing it in the case of a bug that does not repro easily.
107
- console.error("Internal error!");
108
- console.error("File issue at https://github.com/microsoft/typespec");
109
- console.error();
110
- console.error(error);
111
- process.exit(1);
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", (error) => {
114
- console.error("Unhandled promise rejection!");
115
- internalError(error);
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
+ }