@nestia/sdk 3.1.0-dev.20240429 → 3.1.0-dev.20240430

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 (55) hide show
  1. package/lib/analyses/TypedWebSocketOperationAnalyzer.js +1 -1
  2. package/lib/analyses/TypedWebSocketOperationAnalyzer.js.map +1 -1
  3. package/lib/executable/sdk.js +11 -11
  4. package/lib/generates/internal/SdkHttpFunctionProgrammer.js +18 -20
  5. package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -1
  6. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +30 -1
  7. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -1
  8. package/lib/structures/ITypedWebSocketRoute.d.ts +1 -0
  9. package/package.json +3 -3
  10. package/src/NestiaSdkApplication.ts +257 -257
  11. package/src/analyses/AccessorAnalyzer.ts +67 -67
  12. package/src/analyses/ConfigAnalyzer.ts +147 -147
  13. package/src/analyses/GenericAnalyzer.ts +51 -51
  14. package/src/analyses/PathAnalyzer.ts +69 -69
  15. package/src/analyses/SecurityAnalyzer.ts +25 -25
  16. package/src/analyses/TypedWebSocketOperationAnalyzer.ts +1 -0
  17. package/src/executable/internal/CommandParser.ts +15 -15
  18. package/src/executable/internal/NestiaConfigLoader.ts +67 -67
  19. package/src/executable/internal/NestiaSdkCommand.ts +60 -60
  20. package/src/executable/sdk.ts +73 -73
  21. package/src/generates/CloneGenerator.ts +64 -64
  22. package/src/generates/E2eGenerator.ts +64 -64
  23. package/src/generates/SdkGenerator.ts +91 -91
  24. package/src/generates/internal/E2eFileProgrammer.ts +178 -178
  25. package/src/generates/internal/FilePrinter.ts +53 -53
  26. package/src/generates/internal/SdkAliasCollection.ts +157 -157
  27. package/src/generates/internal/SdkDistributionComposer.ts +100 -100
  28. package/src/generates/internal/SdkFileProgrammer.ts +119 -119
  29. package/src/generates/internal/SdkHttpCloneProgrammer.ts +154 -154
  30. package/src/generates/internal/SdkHttpFunctionProgrammer.ts +298 -299
  31. package/src/generates/internal/SdkHttpNamespaceProgrammer.ts +505 -505
  32. package/src/generates/internal/SdkHttpRouteProgrammer.ts +82 -82
  33. package/src/generates/internal/SdkHttpSimulationProgrammer.ts +363 -363
  34. package/src/generates/internal/SdkImportWizard.ts +55 -55
  35. package/src/generates/internal/SdkRouteDirectory.ts +18 -18
  36. package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +42 -1
  37. package/src/generates/internal/SwaggerSchemaValidator.ts +198 -198
  38. package/src/index.ts +4 -4
  39. package/src/module.ts +2 -2
  40. package/src/structures/IErrorReport.ts +6 -6
  41. package/src/structures/INestiaProject.ts +13 -13
  42. package/src/structures/INormalizedInput.ts +20 -20
  43. package/src/structures/IReflectController.ts +17 -17
  44. package/src/structures/ITypeTuple.ts +6 -6
  45. package/src/structures/ITypedHttpRoute.ts +55 -55
  46. package/src/structures/ITypedWebSocketRoute.ts +1 -0
  47. package/src/structures/MethodType.ts +5 -5
  48. package/src/structures/ParamCategory.ts +1 -1
  49. package/src/utils/ArrayUtil.ts +26 -26
  50. package/src/utils/FileRetriever.ts +22 -22
  51. package/src/utils/MapUtil.ts +14 -14
  52. package/src/utils/PathUtil.ts +10 -10
  53. package/src/utils/SourceFinder.ts +66 -66
  54. package/src/utils/StringUtil.ts +6 -6
  55. package/src/utils/StripEnums.ts +5 -5
@@ -1,91 +1,91 @@
1
- import fs from "fs";
2
- import NodePath from "path";
3
- import { IPointer } from "tstl";
4
-
5
- import { INestiaProject } from "../structures/INestiaProject";
6
- import { ITypedHttpRoute } from "../structures/ITypedHttpRoute";
7
- import { ITypedWebSocketRoute } from "../structures/ITypedWebSocketRoute";
8
- import { CloneGenerator } from "./CloneGenerator";
9
- import { SdkDistributionComposer } from "./internal/SdkDistributionComposer";
10
- import { SdkFileProgrammer } from "./internal/SdkFileProgrammer";
11
-
12
- export namespace SdkGenerator {
13
- export const generate =
14
- (project: INestiaProject) =>
15
- async (
16
- routes: Array<ITypedHttpRoute | ITypedWebSocketRoute>,
17
- ): Promise<void> => {
18
- console.log("Generating SDK Library");
19
-
20
- // PREPARE NEW DIRECTORIES
21
- try {
22
- await fs.promises.mkdir(project.config.output!);
23
- } catch {}
24
-
25
- // BUNDLING
26
- const bundle: string[] = await fs.promises.readdir(BUNDLE_PATH);
27
- for (const file of bundle) {
28
- const current: string = `${BUNDLE_PATH}/${file}`;
29
- const target: string = `${project.config.output}/${file}`;
30
- const stats: fs.Stats = await fs.promises.stat(current);
31
-
32
- if (stats.isFile() === true) {
33
- const content: string = await fs.promises.readFile(current, "utf8");
34
- if (fs.existsSync(target) === false)
35
- await fs.promises.writeFile(target, content, "utf8");
36
- else if (BUNDLE_CHANGES[file] !== undefined) {
37
- const r: IPointer<string> = {
38
- value: await fs.promises.readFile(target, "utf8"),
39
- };
40
- for (const [before, after] of BUNDLE_CHANGES[file])
41
- r.value = r.value.replace(before, after);
42
- await fs.promises.writeFile(target, r.value, "utf8");
43
- }
44
- }
45
- }
46
-
47
- // STRUCTURES
48
- if (project.config.clone)
49
- await CloneGenerator.write(project)(
50
- routes.filter((r) => r.protocol === "http") as ITypedHttpRoute[],
51
- );
52
-
53
- // FUNCTIONAL
54
- await SdkFileProgrammer.generate(project)(routes);
55
-
56
- // DISTRIBUTION
57
- if (project.config.distribute !== undefined)
58
- await SdkDistributionComposer.compose(
59
- project.config,
60
- routes.some((r) => r.protocol === "websocket"),
61
- );
62
- };
63
-
64
- export const BUNDLE_PATH = NodePath.join(
65
- __dirname,
66
- "..",
67
- "..",
68
- "assets",
69
- "bundle",
70
- "api",
71
- );
72
- }
73
-
74
- const BUNDLE_CHANGES: Record<string, [string, string][]> = {
75
- "IConnection.ts": [
76
- [
77
- `export { IConnection } from "@nestia/fetcher"`,
78
- `export type { IConnection } from "@nestia/fetcher"`,
79
- ],
80
- ],
81
- "module.ts": [
82
- [`export * from "./IConnection"`, `export type * from "./IConnection"`],
83
- [`export * from "./Primitive"`, `export type * from "./Primitive"`],
84
- ],
85
- "Primitive.ts": [
86
- [
87
- `export { Primitive } from "@nestia/fetcher"`,
88
- `export type { Primitive } from "@nestia/fetcher"`,
89
- ],
90
- ],
91
- };
1
+ import fs from "fs";
2
+ import NodePath from "path";
3
+ import { IPointer } from "tstl";
4
+
5
+ import { INestiaProject } from "../structures/INestiaProject";
6
+ import { ITypedHttpRoute } from "../structures/ITypedHttpRoute";
7
+ import { ITypedWebSocketRoute } from "../structures/ITypedWebSocketRoute";
8
+ import { CloneGenerator } from "./CloneGenerator";
9
+ import { SdkDistributionComposer } from "./internal/SdkDistributionComposer";
10
+ import { SdkFileProgrammer } from "./internal/SdkFileProgrammer";
11
+
12
+ export namespace SdkGenerator {
13
+ export const generate =
14
+ (project: INestiaProject) =>
15
+ async (
16
+ routes: Array<ITypedHttpRoute | ITypedWebSocketRoute>,
17
+ ): Promise<void> => {
18
+ console.log("Generating SDK Library");
19
+
20
+ // PREPARE NEW DIRECTORIES
21
+ try {
22
+ await fs.promises.mkdir(project.config.output!);
23
+ } catch {}
24
+
25
+ // BUNDLING
26
+ const bundle: string[] = await fs.promises.readdir(BUNDLE_PATH);
27
+ for (const file of bundle) {
28
+ const current: string = `${BUNDLE_PATH}/${file}`;
29
+ const target: string = `${project.config.output}/${file}`;
30
+ const stats: fs.Stats = await fs.promises.stat(current);
31
+
32
+ if (stats.isFile() === true) {
33
+ const content: string = await fs.promises.readFile(current, "utf8");
34
+ if (fs.existsSync(target) === false)
35
+ await fs.promises.writeFile(target, content, "utf8");
36
+ else if (BUNDLE_CHANGES[file] !== undefined) {
37
+ const r: IPointer<string> = {
38
+ value: await fs.promises.readFile(target, "utf8"),
39
+ };
40
+ for (const [before, after] of BUNDLE_CHANGES[file])
41
+ r.value = r.value.replace(before, after);
42
+ await fs.promises.writeFile(target, r.value, "utf8");
43
+ }
44
+ }
45
+ }
46
+
47
+ // STRUCTURES
48
+ if (project.config.clone)
49
+ await CloneGenerator.write(project)(
50
+ routes.filter((r) => r.protocol === "http") as ITypedHttpRoute[],
51
+ );
52
+
53
+ // FUNCTIONAL
54
+ await SdkFileProgrammer.generate(project)(routes);
55
+
56
+ // DISTRIBUTION
57
+ if (project.config.distribute !== undefined)
58
+ await SdkDistributionComposer.compose(
59
+ project.config,
60
+ routes.some((r) => r.protocol === "websocket"),
61
+ );
62
+ };
63
+
64
+ export const BUNDLE_PATH = NodePath.join(
65
+ __dirname,
66
+ "..",
67
+ "..",
68
+ "assets",
69
+ "bundle",
70
+ "api",
71
+ );
72
+ }
73
+
74
+ const BUNDLE_CHANGES: Record<string, [string, string][]> = {
75
+ "IConnection.ts": [
76
+ [
77
+ `export { IConnection } from "@nestia/fetcher"`,
78
+ `export type { IConnection } from "@nestia/fetcher"`,
79
+ ],
80
+ ],
81
+ "module.ts": [
82
+ [`export * from "./IConnection"`, `export type * from "./IConnection"`],
83
+ [`export * from "./Primitive"`, `export type * from "./Primitive"`],
84
+ ],
85
+ "Primitive.ts": [
86
+ [
87
+ `export { Primitive } from "@nestia/fetcher"`,
88
+ `export type { Primitive } from "@nestia/fetcher"`,
89
+ ],
90
+ ],
91
+ };
@@ -1,178 +1,178 @@
1
- import ts from "typescript";
2
- import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
3
-
4
- import { INestiaProject } from "../../structures/INestiaProject";
5
- import { ITypedHttpRoute } from "../../structures/ITypedHttpRoute";
6
- import { FilePrinter } from "./FilePrinter";
7
- import { ImportDictionary } from "./ImportDictionary";
8
- import { SdkAliasCollection } from "./SdkAliasCollection";
9
- import { SdkImportWizard } from "./SdkImportWizard";
10
- import { SdkTypeProgrammer } from "./SdkTypeProgrammer";
11
-
12
- export namespace E2eFileProgrammer {
13
- export const generate =
14
- (project: INestiaProject) =>
15
- (props: { api: string; current: string }) =>
16
- async (route: ITypedHttpRoute): Promise<void> => {
17
- const importer: ImportDictionary = new ImportDictionary(
18
- `${props.current}/${getFunctionName(route)}.ts`,
19
- );
20
- if (project.config.clone !== true)
21
- for (const tuple of route.imports)
22
- for (const instance of tuple[1])
23
- importer.internal({
24
- file: tuple[0],
25
- type: true,
26
- instance,
27
- });
28
- importer.internal({
29
- type: false,
30
- file: props.api,
31
- instance: null,
32
- name: "api",
33
- });
34
-
35
- const functor = generate_function(project)(importer)(route);
36
- await FilePrinter.write({
37
- location: importer.file,
38
- statements: [
39
- ...importer.toStatements(props.current),
40
- FilePrinter.enter(),
41
- functor,
42
- ],
43
- });
44
- };
45
-
46
- const generate_function =
47
- (project: INestiaProject) =>
48
- (importer: ImportDictionary) =>
49
- (route: ITypedHttpRoute): ts.Statement =>
50
- ts.factory.createVariableStatement(
51
- [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
52
- ts.factory.createVariableDeclarationList(
53
- [
54
- ts.factory.createVariableDeclaration(
55
- ts.factory.createIdentifier(getFunctionName(route)),
56
- undefined,
57
- undefined,
58
- generate_arrow(project)(importer)(route),
59
- ),
60
- ],
61
- ts.NodeFlags.Const,
62
- ),
63
- );
64
-
65
- const generate_arrow =
66
- (project: INestiaProject) =>
67
- (importer: ImportDictionary) =>
68
- (route: ITypedHttpRoute) => {
69
- const headers = route.parameters.find(
70
- (p) => p.category === "headers" && p.field === undefined,
71
- );
72
- const connection = headers
73
- ? ts.factory.createObjectLiteralExpression(
74
- [
75
- ts.factory.createSpreadAssignment(
76
- ts.factory.createIdentifier("connection"),
77
- ),
78
- ts.factory.createPropertyAssignment(
79
- "headers",
80
- ts.factory.createObjectLiteralExpression(
81
- [
82
- ts.factory.createSpreadAssignment(
83
- IdentifierFactory.access(
84
- ts.factory.createIdentifier("connection"),
85
- )("headers"),
86
- ),
87
- ts.factory.createSpreadAssignment(
88
- ts.factory.createCallExpression(
89
- IdentifierFactory.access(
90
- ts.factory.createIdentifier(
91
- SdkImportWizard.typia(importer),
92
- ),
93
- )("random"),
94
- [getTypeName(project)(importer)(headers)],
95
- undefined,
96
- ),
97
- ),
98
- ],
99
- true,
100
- ),
101
- ),
102
- ],
103
- true,
104
- )
105
- : ts.factory.createIdentifier("connection");
106
- const caller = ts.factory.createCallExpression(
107
- ts.factory.createIdentifier(
108
- ["api", "functional", ...route.accessors].join("."),
109
- ),
110
- undefined,
111
- [
112
- connection,
113
- ...route.parameters
114
- .filter((p) => p.category !== "headers")
115
- .map((p) =>
116
- ts.factory.createCallExpression(
117
- IdentifierFactory.access(
118
- ts.factory.createIdentifier(SdkImportWizard.typia(importer)),
119
- )("random"),
120
- [getTypeName(project)(importer)(p)],
121
- undefined,
122
- ),
123
- ),
124
- ],
125
- );
126
- const assert = ts.factory.createCallExpression(
127
- IdentifierFactory.access(
128
- ts.factory.createIdentifier(SdkImportWizard.typia(importer)),
129
- )("assert"),
130
- undefined,
131
- [ts.factory.createIdentifier("output")],
132
- );
133
-
134
- return ts.factory.createArrowFunction(
135
- [ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword)],
136
- undefined,
137
- [
138
- IdentifierFactory.parameter(
139
- "connection",
140
- ts.factory.createTypeReferenceNode("api.IConnection"),
141
- ),
142
- ],
143
- undefined,
144
- undefined,
145
- ts.factory.createBlock([
146
- ts.factory.createVariableStatement(
147
- [],
148
- ts.factory.createVariableDeclarationList(
149
- [
150
- ts.factory.createVariableDeclaration(
151
- "output",
152
- undefined,
153
- project.config.propagate !== true &&
154
- route.output.typeName === "void"
155
- ? undefined
156
- : SdkAliasCollection.output(project)(importer)(route),
157
- ts.factory.createAwaitExpression(caller),
158
- ),
159
- ],
160
- ts.NodeFlags.Const,
161
- ),
162
- ),
163
- ts.factory.createExpressionStatement(assert),
164
- ]),
165
- );
166
- };
167
- }
168
-
169
- const getFunctionName = (route: ITypedHttpRoute): string =>
170
- ["test", "api", ...route.accessors].join("_");
171
-
172
- const getTypeName =
173
- (project: INestiaProject) =>
174
- (importer: ImportDictionary) =>
175
- (p: ITypedHttpRoute.IParameter | ITypedHttpRoute.IOutput) =>
176
- p.metadata
177
- ? SdkTypeProgrammer.write(project)(importer)(p.metadata)
178
- : ts.factory.createTypeReferenceNode(p.typeName);
1
+ import ts from "typescript";
2
+ import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
3
+
4
+ import { INestiaProject } from "../../structures/INestiaProject";
5
+ import { ITypedHttpRoute } from "../../structures/ITypedHttpRoute";
6
+ import { FilePrinter } from "./FilePrinter";
7
+ import { ImportDictionary } from "./ImportDictionary";
8
+ import { SdkAliasCollection } from "./SdkAliasCollection";
9
+ import { SdkImportWizard } from "./SdkImportWizard";
10
+ import { SdkTypeProgrammer } from "./SdkTypeProgrammer";
11
+
12
+ export namespace E2eFileProgrammer {
13
+ export const generate =
14
+ (project: INestiaProject) =>
15
+ (props: { api: string; current: string }) =>
16
+ async (route: ITypedHttpRoute): Promise<void> => {
17
+ const importer: ImportDictionary = new ImportDictionary(
18
+ `${props.current}/${getFunctionName(route)}.ts`,
19
+ );
20
+ if (project.config.clone !== true)
21
+ for (const tuple of route.imports)
22
+ for (const instance of tuple[1])
23
+ importer.internal({
24
+ file: tuple[0],
25
+ type: true,
26
+ instance,
27
+ });
28
+ importer.internal({
29
+ type: false,
30
+ file: props.api,
31
+ instance: null,
32
+ name: "api",
33
+ });
34
+
35
+ const functor = generate_function(project)(importer)(route);
36
+ await FilePrinter.write({
37
+ location: importer.file,
38
+ statements: [
39
+ ...importer.toStatements(props.current),
40
+ FilePrinter.enter(),
41
+ functor,
42
+ ],
43
+ });
44
+ };
45
+
46
+ const generate_function =
47
+ (project: INestiaProject) =>
48
+ (importer: ImportDictionary) =>
49
+ (route: ITypedHttpRoute): ts.Statement =>
50
+ ts.factory.createVariableStatement(
51
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
52
+ ts.factory.createVariableDeclarationList(
53
+ [
54
+ ts.factory.createVariableDeclaration(
55
+ ts.factory.createIdentifier(getFunctionName(route)),
56
+ undefined,
57
+ undefined,
58
+ generate_arrow(project)(importer)(route),
59
+ ),
60
+ ],
61
+ ts.NodeFlags.Const,
62
+ ),
63
+ );
64
+
65
+ const generate_arrow =
66
+ (project: INestiaProject) =>
67
+ (importer: ImportDictionary) =>
68
+ (route: ITypedHttpRoute) => {
69
+ const headers = route.parameters.find(
70
+ (p) => p.category === "headers" && p.field === undefined,
71
+ );
72
+ const connection = headers
73
+ ? ts.factory.createObjectLiteralExpression(
74
+ [
75
+ ts.factory.createSpreadAssignment(
76
+ ts.factory.createIdentifier("connection"),
77
+ ),
78
+ ts.factory.createPropertyAssignment(
79
+ "headers",
80
+ ts.factory.createObjectLiteralExpression(
81
+ [
82
+ ts.factory.createSpreadAssignment(
83
+ IdentifierFactory.access(
84
+ ts.factory.createIdentifier("connection"),
85
+ )("headers"),
86
+ ),
87
+ ts.factory.createSpreadAssignment(
88
+ ts.factory.createCallExpression(
89
+ IdentifierFactory.access(
90
+ ts.factory.createIdentifier(
91
+ SdkImportWizard.typia(importer),
92
+ ),
93
+ )("random"),
94
+ [getTypeName(project)(importer)(headers)],
95
+ undefined,
96
+ ),
97
+ ),
98
+ ],
99
+ true,
100
+ ),
101
+ ),
102
+ ],
103
+ true,
104
+ )
105
+ : ts.factory.createIdentifier("connection");
106
+ const caller = ts.factory.createCallExpression(
107
+ ts.factory.createIdentifier(
108
+ ["api", "functional", ...route.accessors].join("."),
109
+ ),
110
+ undefined,
111
+ [
112
+ connection,
113
+ ...route.parameters
114
+ .filter((p) => p.category !== "headers")
115
+ .map((p) =>
116
+ ts.factory.createCallExpression(
117
+ IdentifierFactory.access(
118
+ ts.factory.createIdentifier(SdkImportWizard.typia(importer)),
119
+ )("random"),
120
+ [getTypeName(project)(importer)(p)],
121
+ undefined,
122
+ ),
123
+ ),
124
+ ],
125
+ );
126
+ const assert = ts.factory.createCallExpression(
127
+ IdentifierFactory.access(
128
+ ts.factory.createIdentifier(SdkImportWizard.typia(importer)),
129
+ )("assert"),
130
+ undefined,
131
+ [ts.factory.createIdentifier("output")],
132
+ );
133
+
134
+ return ts.factory.createArrowFunction(
135
+ [ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword)],
136
+ undefined,
137
+ [
138
+ IdentifierFactory.parameter(
139
+ "connection",
140
+ ts.factory.createTypeReferenceNode("api.IConnection"),
141
+ ),
142
+ ],
143
+ undefined,
144
+ undefined,
145
+ ts.factory.createBlock([
146
+ ts.factory.createVariableStatement(
147
+ [],
148
+ ts.factory.createVariableDeclarationList(
149
+ [
150
+ ts.factory.createVariableDeclaration(
151
+ "output",
152
+ undefined,
153
+ project.config.propagate !== true &&
154
+ route.output.typeName === "void"
155
+ ? undefined
156
+ : SdkAliasCollection.output(project)(importer)(route),
157
+ ts.factory.createAwaitExpression(caller),
158
+ ),
159
+ ],
160
+ ts.NodeFlags.Const,
161
+ ),
162
+ ),
163
+ ts.factory.createExpressionStatement(assert),
164
+ ]),
165
+ );
166
+ };
167
+ }
168
+
169
+ const getFunctionName = (route: ITypedHttpRoute): string =>
170
+ ["test", "api", ...route.accessors].join("_");
171
+
172
+ const getTypeName =
173
+ (project: INestiaProject) =>
174
+ (importer: ImportDictionary) =>
175
+ (p: ITypedHttpRoute.IParameter | ITypedHttpRoute.IOutput) =>
176
+ p.metadata
177
+ ? SdkTypeProgrammer.write(project)(importer)(p.metadata)
178
+ : ts.factory.createTypeReferenceNode(p.typeName);
@@ -1,53 +1,53 @@
1
- import fs from "fs";
2
- import { format } from "prettier";
3
- import ts from "typescript";
4
-
5
- export namespace FilePrinter {
6
- export const description = <Node extends ts.Node>(
7
- node: Node,
8
- comment: string,
9
- ): Node => {
10
- if (comment.length === 0) return node;
11
- ts.addSyntheticLeadingComment(
12
- node,
13
- ts.SyntaxKind.MultiLineCommentTrivia,
14
- ["*", ...comment.split("\n").map((str) => ` * ${str}`), ""].join("\n"),
15
- true,
16
- );
17
- return node;
18
- };
19
-
20
- export const enter = () =>
21
- ts.factory.createExpressionStatement(ts.factory.createIdentifier("\n"));
22
-
23
- export const write = async (props: {
24
- location: string;
25
- statements: ts.Statement[];
26
- top?: string;
27
- }): Promise<void> => {
28
- const script: string = ts
29
- .createPrinter()
30
- .printFile(
31
- ts.factory.createSourceFile(
32
- props.statements,
33
- ts.factory.createToken(ts.SyntaxKind.EndOfFileToken),
34
- ts.NodeFlags.None,
35
- ),
36
- );
37
- await fs.promises.writeFile(
38
- props.location,
39
- await beautify((props.top ?? "") + script),
40
- "utf8",
41
- );
42
- };
43
-
44
- const beautify = async (script: string): Promise<string> => {
45
- try {
46
- return await format(script, {
47
- parser: "typescript",
48
- });
49
- } catch {
50
- return script;
51
- }
52
- };
53
- }
1
+ import fs from "fs";
2
+ import { format } from "prettier";
3
+ import ts from "typescript";
4
+
5
+ export namespace FilePrinter {
6
+ export const description = <Node extends ts.Node>(
7
+ node: Node,
8
+ comment: string,
9
+ ): Node => {
10
+ if (comment.length === 0) return node;
11
+ ts.addSyntheticLeadingComment(
12
+ node,
13
+ ts.SyntaxKind.MultiLineCommentTrivia,
14
+ ["*", ...comment.split("\n").map((str) => ` * ${str}`), ""].join("\n"),
15
+ true,
16
+ );
17
+ return node;
18
+ };
19
+
20
+ export const enter = () =>
21
+ ts.factory.createExpressionStatement(ts.factory.createIdentifier("\n"));
22
+
23
+ export const write = async (props: {
24
+ location: string;
25
+ statements: ts.Statement[];
26
+ top?: string;
27
+ }): Promise<void> => {
28
+ const script: string = ts
29
+ .createPrinter()
30
+ .printFile(
31
+ ts.factory.createSourceFile(
32
+ props.statements,
33
+ ts.factory.createToken(ts.SyntaxKind.EndOfFileToken),
34
+ ts.NodeFlags.None,
35
+ ),
36
+ );
37
+ await fs.promises.writeFile(
38
+ props.location,
39
+ await beautify((props.top ?? "") + script),
40
+ "utf8",
41
+ );
42
+ };
43
+
44
+ const beautify = async (script: string): Promise<string> => {
45
+ try {
46
+ return await format(script, {
47
+ parser: "typescript",
48
+ });
49
+ } catch {
50
+ return script;
51
+ }
52
+ };
53
+ }