@nestia/sdk 12.0.0-dev.20260612.2 → 12.0.0-rc.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/assets/bundle/distribute/package.json +1 -1
- package/lib/analyses/AccessorAnalyzer.js +33 -10
- package/lib/analyses/AccessorAnalyzer.js.map +1 -1
- package/lib/analyses/ConfigAnalyzer.js +11 -37
- package/lib/analyses/ConfigAnalyzer.js.map +1 -1
- package/lib/factories/ExpressionFactory.d.ts +9 -0
- package/lib/factories/ExpressionFactory.js +16 -0
- package/lib/factories/ExpressionFactory.js.map +1 -0
- package/lib/factories/IdentifierFactory.d.ts +22 -0
- package/lib/factories/IdentifierFactory.js +50 -0
- package/lib/factories/IdentifierFactory.js.map +1 -0
- package/lib/factories/LiteralFactory.d.ts +9 -0
- package/lib/factories/LiteralFactory.js +48 -0
- package/lib/factories/LiteralFactory.js.map +1 -0
- package/lib/factories/StatementFactory.d.ts +14 -0
- package/lib/factories/StatementFactory.js +20 -0
- package/lib/factories/StatementFactory.js.map +1 -0
- package/lib/factories/TypeFactory.d.ts +24 -0
- package/lib/factories/TypeFactory.js +27 -0
- package/lib/factories/TypeFactory.js.map +1 -0
- package/lib/generates/CloneGenerator.js +2 -2
- package/lib/generates/CloneGenerator.js.map +1 -1
- package/lib/generates/internal/E2eFileProgrammer.js +30 -29
- package/lib/generates/internal/E2eFileProgrammer.js.map +1 -1
- package/lib/generates/internal/FilePrinter.d.ts +2 -2
- package/lib/generates/internal/FilePrinter.js +14 -25
- package/lib/generates/internal/FilePrinter.js.map +1 -1
- package/lib/generates/internal/ImportDictionary.d.ts +1 -1
- package/lib/generates/internal/ImportDictionary.js +10 -9
- package/lib/generates/internal/ImportDictionary.js.map +1 -1
- package/lib/generates/internal/SdkAliasCollection.d.ts +12 -12
- package/lib/generates/internal/SdkAliasCollection.js +23 -25
- package/lib/generates/internal/SdkAliasCollection.js.map +1 -1
- package/lib/generates/internal/SdkFileProgrammer.js +2 -2
- package/lib/generates/internal/SdkFileProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpCloneProgrammer.d.ts +1 -1
- package/lib/generates/internal/SdkHttpCloneProgrammer.js +3 -3
- package/lib/generates/internal/SdkHttpCloneProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpFunctionProgrammer.d.ts +1 -1
- package/lib/generates/internal/SdkHttpFunctionProgrammer.js +45 -48
- package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpNamespaceProgrammer.d.ts +1 -1
- package/lib/generates/internal/SdkHttpNamespaceProgrammer.js +61 -60
- package/lib/generates/internal/SdkHttpNamespaceProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpParameterProgrammer.d.ts +2 -2
- package/lib/generates/internal/SdkHttpParameterProgrammer.js +11 -13
- package/lib/generates/internal/SdkHttpParameterProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkHttpRouteProgrammer.d.ts +1 -1
- package/lib/generates/internal/SdkHttpSimulationProgrammer.d.ts +1 -1
- package/lib/generates/internal/SdkHttpSimulationProgrammer.js +50 -48
- package/lib/generates/internal/SdkHttpSimulationProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkMcpRouteProgrammer.d.ts +1 -1
- package/lib/generates/internal/SdkMcpRouteProgrammer.js +54 -53
- package/lib/generates/internal/SdkMcpRouteProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkTypeProgrammer.d.ts +3 -3
- package/lib/generates/internal/SdkTypeProgrammer.js +42 -43
- package/lib/generates/internal/SdkTypeProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkTypeTagProgrammer.d.ts +2 -1
- package/lib/generates/internal/SdkTypeTagProgrammer.js +7 -9
- package/lib/generates/internal/SdkTypeTagProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.d.ts +2 -2
- package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js +45 -47
- package/lib/generates/internal/SdkWebSocketNamespaceProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkWebSocketParameterProgrammer.d.ts +3 -3
- package/lib/generates/internal/SdkWebSocketParameterProgrammer.js +9 -9
- package/lib/generates/internal/SdkWebSocketParameterProgrammer.js.map +1 -1
- package/lib/generates/internal/SdkWebSocketRouteProgrammer.d.ts +2 -2
- package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +34 -40
- package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -1
- package/lib/transform.d.ts +5 -9
- package/lib/transform.js +8 -31
- package/lib/transform.js.map +1 -1
- package/lib/utils/SourceFinder.d.ts +1 -0
- package/lib/utils/SourceFinder.js +6 -3
- package/lib/utils/SourceFinder.js.map +1 -1
- package/package.json +11 -11
- package/src/analyses/AccessorAnalyzer.ts +39 -10
- package/src/analyses/ConfigAnalyzer.ts +19 -5
- package/src/factories/ExpressionFactory.ts +23 -0
- package/src/factories/IdentifierFactory.ts +84 -0
- package/src/factories/LiteralFactory.ts +54 -0
- package/src/factories/StatementFactory.ts +56 -0
- package/src/factories/TypeFactory.ts +27 -0
- package/src/generates/CloneGenerator.ts +8 -7
- package/src/generates/internal/E2eFileProgrammer.ts +59 -53
- package/src/generates/internal/FilePrinter.ts +28 -36
- package/src/generates/internal/ImportDictionary.ts +19 -21
- package/src/generates/internal/SdkAliasCollection.ts +55 -49
- package/src/generates/internal/SdkFileProgrammer.ts +4 -7
- package/src/generates/internal/SdkHttpCloneProgrammer.ts +11 -13
- package/src/generates/internal/SdkHttpFunctionProgrammer.ts +90 -101
- package/src/generates/internal/SdkHttpNamespaceProgrammer.ts +153 -166
- package/src/generates/internal/SdkHttpParameterProgrammer.ts +15 -17
- package/src/generates/internal/SdkHttpRouteProgrammer.ts +1 -1
- package/src/generates/internal/SdkHttpSimulationProgrammer.ts +121 -130
- package/src/generates/internal/SdkMcpRouteProgrammer.ts +135 -140
- package/src/generates/internal/SdkTypeProgrammer.ts +389 -382
- package/src/generates/internal/SdkTypeTagProgrammer.ts +13 -17
- package/src/generates/internal/SdkWebSocketNamespaceProgrammer.ts +124 -130
- package/src/generates/internal/SdkWebSocketParameterProgrammer.ts +17 -15
- package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +112 -139
- package/src/transform.ts +14 -45
- package/src/utils/SourceFinder.ts +9 -3
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Expression,
|
|
3
|
+
type Identifier,
|
|
4
|
+
type ParameterDeclaration,
|
|
5
|
+
type StringLiteral,
|
|
6
|
+
SyntaxKind,
|
|
7
|
+
type Token,
|
|
8
|
+
type TypeNode,
|
|
9
|
+
factory,
|
|
10
|
+
} from "@ttsc/factory";
|
|
11
|
+
|
|
12
|
+
import { TypeFactory } from "./TypeFactory";
|
|
13
|
+
|
|
14
|
+
// Conservative "is this string a syntactically valid JavaScript variable
|
|
15
|
+
// name?" test, inlined to avoid pulling in @typia/utils' full namespace.
|
|
16
|
+
const VARIABLE_REGEX = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
17
|
+
const isVariableName = (str: string): boolean => VARIABLE_REGEX.test(str);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Identifier and member-access helpers. The surface kept here is the subset
|
|
21
|
+
* nestia generators actually call (`identifier`, `access`, `parameter`).
|
|
22
|
+
*/
|
|
23
|
+
export namespace IdentifierFactory {
|
|
24
|
+
/**
|
|
25
|
+
* Build an identifier or string literal depending on whether `name` is a
|
|
26
|
+
* valid JavaScript identifier.
|
|
27
|
+
*/
|
|
28
|
+
export const identifier = (name: string): Identifier | StringLiteral =>
|
|
29
|
+
isVariableName(name)
|
|
30
|
+
? factory.createIdentifier(name)
|
|
31
|
+
: factory.createStringLiteral(name);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Member access on `input` by `key`. Falls back to element access when the
|
|
35
|
+
* key is not a valid identifier.
|
|
36
|
+
*/
|
|
37
|
+
export const access = (
|
|
38
|
+
input: Expression,
|
|
39
|
+
key: string,
|
|
40
|
+
chain?: boolean,
|
|
41
|
+
): Expression => {
|
|
42
|
+
const postfix = identifier(key);
|
|
43
|
+
if (postfix.kind === "StringLiteral")
|
|
44
|
+
return chain === true
|
|
45
|
+
? factory.createElementAccessChain(
|
|
46
|
+
input,
|
|
47
|
+
factory.createToken(SyntaxKind.QuestionDotToken),
|
|
48
|
+
postfix,
|
|
49
|
+
)
|
|
50
|
+
: factory.createElementAccessExpression(input, postfix);
|
|
51
|
+
return chain === true
|
|
52
|
+
? factory.createPropertyAccessChain(
|
|
53
|
+
input,
|
|
54
|
+
factory.createToken(SyntaxKind.QuestionDotToken),
|
|
55
|
+
postfix,
|
|
56
|
+
)
|
|
57
|
+
: factory.createPropertyAccessExpression(input, postfix);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Parameter declaration with default `any` type when the caller omits one.
|
|
62
|
+
* Passing a `QuestionToken` as `init` marks the parameter optional.
|
|
63
|
+
*/
|
|
64
|
+
export const parameter = (
|
|
65
|
+
name: string | Identifier,
|
|
66
|
+
type?: TypeNode,
|
|
67
|
+
init?: Expression | Token,
|
|
68
|
+
): ParameterDeclaration => {
|
|
69
|
+
const isQuestionToken =
|
|
70
|
+
!!init &&
|
|
71
|
+
init.kind === "Token" &&
|
|
72
|
+
(init as Token).token === SyntaxKind.QuestionToken;
|
|
73
|
+
return factory.createParameterDeclaration(
|
|
74
|
+
undefined,
|
|
75
|
+
undefined,
|
|
76
|
+
name,
|
|
77
|
+
isQuestionToken
|
|
78
|
+
? factory.createToken(SyntaxKind.QuestionToken)
|
|
79
|
+
: undefined,
|
|
80
|
+
type ?? TypeFactory.keyword("any"),
|
|
81
|
+
isQuestionToken ? undefined : (init as Expression | undefined),
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type Expression, factory } from "@ttsc/factory";
|
|
2
|
+
|
|
3
|
+
import { ExpressionFactory } from "./ExpressionFactory";
|
|
4
|
+
import { IdentifierFactory } from "./IdentifierFactory";
|
|
5
|
+
|
|
6
|
+
const PASSTHROUGH_KINDS = new Set<string>([
|
|
7
|
+
"ArrowFunction",
|
|
8
|
+
"CallExpression",
|
|
9
|
+
"Identifier",
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
const isNode = (value: unknown): value is Expression =>
|
|
13
|
+
typeof value === "object" &&
|
|
14
|
+
value !== null &&
|
|
15
|
+
typeof (value as { kind?: unknown }).kind === "string";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Recursive value-to-AST-literal builder. Hands back already-AST inputs
|
|
19
|
+
* unchanged (so callers can mix factory output with raw JS values inside the
|
|
20
|
+
* same object/array), and emits the appropriate literal node otherwise.
|
|
21
|
+
*/
|
|
22
|
+
export namespace LiteralFactory {
|
|
23
|
+
export const write = (input: any): Expression => {
|
|
24
|
+
if (input === null) return factory.createNull();
|
|
25
|
+
if (isNode(input) && PASSTHROUGH_KINDS.has(input.kind)) return input;
|
|
26
|
+
if (Array.isArray(input)) return writeArray(input);
|
|
27
|
+
if (typeof input === "object") return writeObject(input as object);
|
|
28
|
+
if (typeof input === "boolean")
|
|
29
|
+
return input ? factory.createTrue() : factory.createFalse();
|
|
30
|
+
if (typeof input === "number") return ExpressionFactory.number(input);
|
|
31
|
+
if (typeof input === "string") return factory.createStringLiteral(input);
|
|
32
|
+
if (typeof input === "bigint")
|
|
33
|
+
return factory.createStringLiteral(input.toString());
|
|
34
|
+
if (typeof input === "function")
|
|
35
|
+
return factory.createIdentifier("undefined");
|
|
36
|
+
throw new TypeError("LiteralFactory.write: unsupported input type.");
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const writeObject = (obj: object): Expression =>
|
|
40
|
+
factory.createObjectLiteralExpression(
|
|
41
|
+
Object.entries(obj)
|
|
42
|
+
.filter(([, value]) => value !== undefined)
|
|
43
|
+
.map(([key, value]) =>
|
|
44
|
+
factory.createPropertyAssignment(
|
|
45
|
+
IdentifierFactory.identifier(key),
|
|
46
|
+
write(value),
|
|
47
|
+
),
|
|
48
|
+
),
|
|
49
|
+
true,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const writeArray = (array: readonly any[]): Expression =>
|
|
53
|
+
factory.createArrayLiteralExpression(array.map(write), true);
|
|
54
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Expression,
|
|
3
|
+
NodeFlags,
|
|
4
|
+
type TypeNode,
|
|
5
|
+
type VariableStatement,
|
|
6
|
+
factory,
|
|
7
|
+
} from "@ttsc/factory";
|
|
8
|
+
|
|
9
|
+
import { TypeFactory } from "./TypeFactory";
|
|
10
|
+
|
|
11
|
+
/** Variable-statement helpers. `constant` emits `const`, `mut` emits `let`. */
|
|
12
|
+
export namespace StatementFactory {
|
|
13
|
+
export const mut = (props: {
|
|
14
|
+
name: string;
|
|
15
|
+
type?: TypeNode | undefined;
|
|
16
|
+
initializer?: Expression | undefined;
|
|
17
|
+
}): VariableStatement =>
|
|
18
|
+
factory.createVariableStatement(
|
|
19
|
+
undefined,
|
|
20
|
+
factory.createVariableDeclarationList(
|
|
21
|
+
[
|
|
22
|
+
factory.createVariableDeclaration(
|
|
23
|
+
props.name,
|
|
24
|
+
undefined,
|
|
25
|
+
props.type !== undefined
|
|
26
|
+
? props.type
|
|
27
|
+
: props.initializer === undefined
|
|
28
|
+
? TypeFactory.keyword("any")
|
|
29
|
+
: undefined,
|
|
30
|
+
props.initializer,
|
|
31
|
+
),
|
|
32
|
+
],
|
|
33
|
+
NodeFlags.Let,
|
|
34
|
+
),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
export const constant = (props: {
|
|
38
|
+
name: string;
|
|
39
|
+
type?: TypeNode | undefined;
|
|
40
|
+
value?: Expression | undefined;
|
|
41
|
+
}): VariableStatement =>
|
|
42
|
+
factory.createVariableStatement(
|
|
43
|
+
undefined,
|
|
44
|
+
factory.createVariableDeclarationList(
|
|
45
|
+
[
|
|
46
|
+
factory.createVariableDeclaration(
|
|
47
|
+
props.name,
|
|
48
|
+
undefined,
|
|
49
|
+
props.type,
|
|
50
|
+
props.value,
|
|
51
|
+
),
|
|
52
|
+
],
|
|
53
|
+
NodeFlags.Const,
|
|
54
|
+
),
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type KeywordTypeNode, SyntaxKind, factory } from "@ttsc/factory";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Higher-level type-keyword factory.
|
|
5
|
+
*
|
|
6
|
+
* Wraps {@link factory.createKeywordTypeNode} with a name-based interface so
|
|
7
|
+
* generator code reads as `TypeFactory.keyword("any")` instead of selecting the
|
|
8
|
+
* `SyntaxKind.AnyKeyword` token by hand.
|
|
9
|
+
*/
|
|
10
|
+
export namespace TypeFactory {
|
|
11
|
+
const KEYWORDS = {
|
|
12
|
+
void: SyntaxKind.VoidKeyword,
|
|
13
|
+
any: SyntaxKind.AnyKeyword,
|
|
14
|
+
unknown: SyntaxKind.UnknownKeyword,
|
|
15
|
+
boolean: SyntaxKind.BooleanKeyword,
|
|
16
|
+
number: SyntaxKind.NumberKeyword,
|
|
17
|
+
bigint: SyntaxKind.BigIntKeyword,
|
|
18
|
+
string: SyntaxKind.StringKeyword,
|
|
19
|
+
never: SyntaxKind.NeverKeyword,
|
|
20
|
+
undefined: SyntaxKind.UndefinedKeyword,
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
export type Keyword = keyof typeof KEYWORDS;
|
|
24
|
+
|
|
25
|
+
export const keyword = (type: Keyword): KeywordTypeNode =>
|
|
26
|
+
factory.createKeywordTypeNode(KEYWORDS[type]);
|
|
27
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Node,
|
|
2
|
+
type Node,
|
|
3
3
|
NodeFlags,
|
|
4
|
+
type Statement,
|
|
4
5
|
SyntaxKind,
|
|
5
|
-
|
|
6
|
-
} from "@
|
|
6
|
+
factory,
|
|
7
|
+
} from "@ttsc/factory";
|
|
7
8
|
import fs from "fs";
|
|
8
9
|
|
|
9
10
|
import { INestiaProject } from "../structures/INestiaProject";
|
|
@@ -60,10 +61,10 @@ export namespace CloneGenerator {
|
|
|
60
61
|
for (const child of modulo.children.values())
|
|
61
62
|
internal.push(...iterate(importer)(child));
|
|
62
63
|
output.push(
|
|
63
|
-
|
|
64
|
-
[
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
factory.createModuleDeclaration(
|
|
65
|
+
[factory.createModifier(SyntaxKind.ExportKeyword)],
|
|
66
|
+
factory.createIdentifier(modulo.name),
|
|
67
|
+
factory.createModuleBlock(internal as Statement[]),
|
|
67
68
|
NodeFlags.Namespace,
|
|
68
69
|
),
|
|
69
70
|
);
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Node,
|
|
2
|
+
type Node,
|
|
3
3
|
NodeFlags,
|
|
4
|
+
type NumericLiteral,
|
|
4
5
|
SyntaxKind,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
type TypeNode,
|
|
7
|
+
factory,
|
|
8
|
+
} from "@ttsc/factory";
|
|
8
9
|
|
|
10
|
+
import { IdentifierFactory } from "../../factories/IdentifierFactory";
|
|
11
|
+
import { LiteralFactory } from "../../factories/LiteralFactory";
|
|
9
12
|
import { INestiaProject } from "../../structures/INestiaProject";
|
|
10
13
|
import { ITypedHttpRoute } from "../../structures/ITypedHttpRoute";
|
|
11
14
|
import { FilePrinter } from "./FilePrinter";
|
|
@@ -44,12 +47,12 @@ export namespace E2eFileProgrammer {
|
|
|
44
47
|
(project: INestiaProject) =>
|
|
45
48
|
(importer: ImportDictionary) =>
|
|
46
49
|
(route: ITypedHttpRoute): Node =>
|
|
47
|
-
|
|
48
|
-
[
|
|
49
|
-
|
|
50
|
+
factory.createVariableStatement(
|
|
51
|
+
[factory.createModifier(SyntaxKind.ExportKeyword)],
|
|
52
|
+
factory.createVariableDeclarationList(
|
|
50
53
|
[
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
factory.createVariableDeclaration(
|
|
55
|
+
factory.createIdentifier(getFunctionName(route)),
|
|
53
56
|
undefined,
|
|
54
57
|
undefined,
|
|
55
58
|
generateArrow(project)(importer)(route),
|
|
@@ -64,34 +67,36 @@ export namespace E2eFileProgrammer {
|
|
|
64
67
|
(importer: ImportDictionary) =>
|
|
65
68
|
(route: ITypedHttpRoute) => {
|
|
66
69
|
const random = IdentifierFactory.access(
|
|
67
|
-
|
|
70
|
+
factory.createIdentifier(SdkImportWizard.typia(importer)),
|
|
68
71
|
"random",
|
|
69
72
|
);
|
|
70
73
|
const connection = route.headerObject
|
|
71
|
-
?
|
|
74
|
+
? factory.createObjectLiteralExpression(
|
|
72
75
|
[
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
factory.createSpreadAssignment(
|
|
77
|
+
factory.createIdentifier("connection"),
|
|
75
78
|
),
|
|
76
|
-
|
|
79
|
+
factory.createPropertyAssignment(
|
|
77
80
|
"headers",
|
|
78
|
-
|
|
81
|
+
factory.createObjectLiteralExpression(
|
|
79
82
|
[
|
|
80
|
-
|
|
83
|
+
factory.createSpreadAssignment(
|
|
81
84
|
IdentifierFactory.access(
|
|
82
|
-
|
|
85
|
+
factory.createIdentifier("connection"),
|
|
83
86
|
"headers",
|
|
84
87
|
),
|
|
85
88
|
),
|
|
86
|
-
|
|
87
|
-
|
|
89
|
+
factory.createSpreadAssignment(
|
|
90
|
+
factory.createCallExpression(
|
|
88
91
|
random,
|
|
89
92
|
[
|
|
90
|
-
project.config.clone === true
|
|
93
|
+
(project.config.clone === true
|
|
91
94
|
? SdkAliasCollection.from(project)(importer)(
|
|
92
95
|
route.headerObject.metadata,
|
|
93
96
|
)
|
|
94
|
-
: SdkAliasCollection.name(
|
|
97
|
+
: SdkAliasCollection.name(
|
|
98
|
+
route.headerObject,
|
|
99
|
+
)) as TypeNode,
|
|
95
100
|
],
|
|
96
101
|
undefined,
|
|
97
102
|
),
|
|
@@ -103,7 +108,7 @@ export namespace E2eFileProgrammer {
|
|
|
103
108
|
],
|
|
104
109
|
true,
|
|
105
110
|
)
|
|
106
|
-
:
|
|
111
|
+
: factory.createIdentifier("connection");
|
|
107
112
|
const entries = SdkHttpParameterProgrammer.getEntries({
|
|
108
113
|
project,
|
|
109
114
|
importer,
|
|
@@ -112,8 +117,8 @@ export namespace E2eFileProgrammer {
|
|
|
112
117
|
e2e: true,
|
|
113
118
|
prefix: ["api", "functional", ...route.accessor].join(".") + ".",
|
|
114
119
|
});
|
|
115
|
-
const fetch =
|
|
116
|
-
|
|
120
|
+
const fetch = factory.createCallExpression(
|
|
121
|
+
factory.createIdentifier(
|
|
117
122
|
["api", "functional", ...route.accessor].join("."),
|
|
118
123
|
),
|
|
119
124
|
undefined,
|
|
@@ -125,9 +130,9 @@ export namespace E2eFileProgrammer {
|
|
|
125
130
|
Object.fromEntries(
|
|
126
131
|
entries.map((e) => [
|
|
127
132
|
e.key,
|
|
128
|
-
|
|
133
|
+
factory.createCallExpression(
|
|
129
134
|
IdentifierFactory.access(
|
|
130
|
-
|
|
135
|
+
factory.createIdentifier(
|
|
131
136
|
SdkImportWizard.typia(importer),
|
|
132
137
|
),
|
|
133
138
|
"random",
|
|
@@ -140,11 +145,9 @@ export namespace E2eFileProgrammer {
|
|
|
140
145
|
),
|
|
141
146
|
]
|
|
142
147
|
: entries.map((e) =>
|
|
143
|
-
|
|
148
|
+
factory.createCallExpression(
|
|
144
149
|
IdentifierFactory.access(
|
|
145
|
-
|
|
146
|
-
SdkImportWizard.typia(importer),
|
|
147
|
-
),
|
|
150
|
+
factory.createIdentifier(SdkImportWizard.typia(importer)),
|
|
148
151
|
"random",
|
|
149
152
|
),
|
|
150
153
|
[getRandomType(importer)(e)],
|
|
@@ -153,39 +156,41 @@ export namespace E2eFileProgrammer {
|
|
|
153
156
|
)),
|
|
154
157
|
],
|
|
155
158
|
);
|
|
156
|
-
const assert =
|
|
159
|
+
const assert = factory.createCallExpression(
|
|
157
160
|
IdentifierFactory.access(
|
|
158
|
-
|
|
161
|
+
factory.createIdentifier(SdkImportWizard.typia(importer)),
|
|
159
162
|
"assert",
|
|
160
163
|
),
|
|
161
164
|
undefined,
|
|
162
|
-
[
|
|
165
|
+
[factory.createIdentifier("output")],
|
|
163
166
|
);
|
|
164
167
|
|
|
165
|
-
return
|
|
166
|
-
[
|
|
168
|
+
return factory.createArrowFunction(
|
|
169
|
+
[factory.createModifier(SyntaxKind.AsyncKeyword)],
|
|
167
170
|
undefined,
|
|
168
171
|
[
|
|
169
172
|
IdentifierFactory.parameter(
|
|
170
173
|
"connection",
|
|
171
|
-
|
|
174
|
+
factory.createTypeReferenceNode("api.IConnection"),
|
|
172
175
|
),
|
|
173
176
|
],
|
|
174
177
|
undefined,
|
|
175
178
|
undefined,
|
|
176
|
-
|
|
177
|
-
|
|
179
|
+
factory.createBlock([
|
|
180
|
+
factory.createVariableStatement(
|
|
178
181
|
[],
|
|
179
|
-
|
|
182
|
+
factory.createVariableDeclarationList(
|
|
180
183
|
[
|
|
181
|
-
|
|
184
|
+
factory.createVariableDeclaration(
|
|
182
185
|
"output",
|
|
183
186
|
undefined,
|
|
184
187
|
project.config.propagate !== true &&
|
|
185
188
|
route.success.type!.name === "void"
|
|
186
189
|
? undefined
|
|
187
|
-
: SdkAliasCollection.response(project)(importer)(
|
|
188
|
-
|
|
190
|
+
: (SdkAliasCollection.response(project)(importer)(
|
|
191
|
+
route,
|
|
192
|
+
) as TypeNode),
|
|
193
|
+
factory.createAwaitExpression(fetch),
|
|
189
194
|
),
|
|
190
195
|
],
|
|
191
196
|
NodeFlags.Const,
|
|
@@ -193,7 +198,7 @@ export namespace E2eFileProgrammer {
|
|
|
193
198
|
),
|
|
194
199
|
...(route.success.binary === true
|
|
195
200
|
? []
|
|
196
|
-
: [
|
|
201
|
+
: [factory.createExpressionStatement(assert)]),
|
|
197
202
|
]),
|
|
198
203
|
);
|
|
199
204
|
};
|
|
@@ -201,13 +206,14 @@ export namespace E2eFileProgrammer {
|
|
|
201
206
|
|
|
202
207
|
const getRandomType =
|
|
203
208
|
(importer: ImportDictionary) =>
|
|
204
|
-
(entry: SdkHttpParameterProgrammer.IEntry):
|
|
205
|
-
if (isPlainStringPathParameter(entry) === false)
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
(entry: SdkHttpParameterProgrammer.IEntry): TypeNode => {
|
|
210
|
+
if (isPlainStringPathParameter(entry) === false)
|
|
211
|
+
return entry.type as TypeNode;
|
|
212
|
+
return factory.createIntersectionTypeNode([
|
|
213
|
+
entry.type as TypeNode,
|
|
214
|
+
factory.createTypeReferenceNode(
|
|
215
|
+
factory.createQualifiedName(
|
|
216
|
+
factory.createIdentifier(
|
|
211
217
|
importer.external({
|
|
212
218
|
declaration: true,
|
|
213
219
|
file: "typia",
|
|
@@ -215,11 +221,11 @@ const getRandomType =
|
|
|
215
221
|
name: "tags",
|
|
216
222
|
}),
|
|
217
223
|
),
|
|
218
|
-
|
|
224
|
+
factory.createIdentifier("MinLength"),
|
|
219
225
|
),
|
|
220
226
|
[
|
|
221
|
-
|
|
222
|
-
LiteralFactory.write(1) as
|
|
227
|
+
factory.createLiteralTypeNode(
|
|
228
|
+
LiteralFactory.write(1) as NumericLiteral,
|
|
223
229
|
),
|
|
224
230
|
],
|
|
225
231
|
),
|
|
@@ -1,55 +1,47 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Node,
|
|
2
|
+
type Node,
|
|
3
|
+
type Statement,
|
|
3
4
|
SyntaxKind,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
TsPrinter,
|
|
6
|
+
addSyntheticLeadingComment,
|
|
7
|
+
factory,
|
|
8
|
+
} from "@ttsc/factory";
|
|
7
9
|
import fs from "fs";
|
|
8
10
|
import { format } from "prettier";
|
|
9
11
|
|
|
10
12
|
export namespace FilePrinter {
|
|
11
|
-
export const description = <T extends Node>(
|
|
12
|
-
node: T,
|
|
13
|
-
comment: string,
|
|
14
|
-
): T => {
|
|
13
|
+
export const description = <T extends Node>(node: T, comment: string): T => {
|
|
15
14
|
if (comment.length === 0) return node;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
hasTrailingNewLine: true,
|
|
34
|
-
},
|
|
35
|
-
];
|
|
36
|
-
return node;
|
|
15
|
+
return addSyntheticLeadingComment(
|
|
16
|
+
node,
|
|
17
|
+
SyntaxKind.MultiLineCommentTrivia,
|
|
18
|
+
[
|
|
19
|
+
"*",
|
|
20
|
+
...comment
|
|
21
|
+
.split("\r\n")
|
|
22
|
+
.join("\n")
|
|
23
|
+
.split("\n")
|
|
24
|
+
.map(
|
|
25
|
+
(str) =>
|
|
26
|
+
` * ${str.split("*/").join("*\\\\/").split("*\\/").join("*\\\\/")}`,
|
|
27
|
+
),
|
|
28
|
+
"",
|
|
29
|
+
].join("\n"),
|
|
30
|
+
true,
|
|
31
|
+
);
|
|
37
32
|
};
|
|
38
33
|
|
|
39
34
|
export const enter = () =>
|
|
40
|
-
|
|
41
|
-
TypeScriptFactory.createIdentifier("\n"),
|
|
42
|
-
);
|
|
35
|
+
factory.createExpressionStatement(factory.createIdentifier("\n"));
|
|
43
36
|
|
|
44
37
|
export const write = async (props: {
|
|
45
38
|
location: string;
|
|
46
39
|
statements: Node[];
|
|
47
40
|
top?: string;
|
|
48
41
|
}): Promise<void> => {
|
|
49
|
-
const script: string =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
});
|
|
42
|
+
const script: string =
|
|
43
|
+
(props.top ?? "") +
|
|
44
|
+
new TsPrinter().printFile(undefined, props.statements as Statement[]);
|
|
53
45
|
await fs.promises.writeFile(props.location, await beautify(script), "utf8");
|
|
54
46
|
};
|
|
55
47
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Node,
|
|
1
|
+
import { type ImportClause, type Node, factory } from "@ttsc/factory";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { HashMap, TreeMap, hash } from "tstl";
|
|
4
4
|
|
|
@@ -109,11 +109,10 @@ export class ImportDictionary {
|
|
|
109
109
|
.sort((a, b) => a.file.localeCompare(b.file));
|
|
110
110
|
for (const c of compositions)
|
|
111
111
|
container.push(
|
|
112
|
-
|
|
112
|
+
factory.createImportDeclaration(
|
|
113
113
|
undefined,
|
|
114
114
|
this.toImportClaude(c),
|
|
115
|
-
|
|
116
|
-
undefined,
|
|
115
|
+
factory.createStringLiteral(c.file),
|
|
117
116
|
),
|
|
118
117
|
);
|
|
119
118
|
};
|
|
@@ -127,29 +126,28 @@ export class ImportDictionary {
|
|
|
127
126
|
];
|
|
128
127
|
}
|
|
129
128
|
|
|
130
|
-
private toImportClaude(c: ICompositeValue):
|
|
129
|
+
private toImportClaude(c: ICompositeValue): ImportClause {
|
|
130
|
+
// A namespace import cannot carry a per-binding `type` modifier, so the
|
|
131
|
+
// type-only flag stays off here (a value namespace import resolves type
|
|
132
|
+
// members fine), matching the legacy printer output `import * as X`.
|
|
131
133
|
if (c.asterisk !== null)
|
|
132
|
-
return
|
|
133
|
-
|
|
134
|
+
return factory.createImportClause(
|
|
135
|
+
false,
|
|
134
136
|
undefined,
|
|
135
|
-
|
|
136
|
-
TypeScriptFactory.createIdentifier(c.asterisk),
|
|
137
|
-
),
|
|
137
|
+
factory.createNamespaceImport(factory.createIdentifier(c.asterisk)),
|
|
138
138
|
);
|
|
139
|
-
|
|
139
|
+
// `c.declaration` (type-only) belongs on the import clause, not on each
|
|
140
|
+
// specifier — emitting both produces the invalid `import type { type X }`.
|
|
141
|
+
return factory.createImportClause(
|
|
140
142
|
c.declaration,
|
|
141
|
-
c.default !== null
|
|
142
|
-
? TypeScriptFactory.createIdentifier(c.default)
|
|
143
|
-
: undefined,
|
|
143
|
+
c.default !== null ? factory.createIdentifier(c.default) : undefined,
|
|
144
144
|
c.elements.size() !== 0
|
|
145
|
-
?
|
|
145
|
+
? factory.createNamedImports(
|
|
146
146
|
Array.from(c.elements).map(({ first: name, second: alias }) =>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
alias !== null
|
|
150
|
-
|
|
151
|
-
: undefined,
|
|
152
|
-
TypeScriptFactory.createIdentifier(alias ?? name),
|
|
147
|
+
factory.createImportSpecifier(
|
|
148
|
+
false,
|
|
149
|
+
alias !== null ? factory.createIdentifier(name) : undefined,
|
|
150
|
+
factory.createIdentifier(alias ?? name),
|
|
153
151
|
),
|
|
154
152
|
),
|
|
155
153
|
)
|