@nestia/sdk 3.1.0-dev.20240426 → 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 (58) 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/SwaggerGenerator.js +1 -1
  5. package/lib/generates/SwaggerGenerator.js.map +1 -1
  6. package/lib/generates/internal/SdkHttpFunctionProgrammer.js +18 -20
  7. package/lib/generates/internal/SdkHttpFunctionProgrammer.js.map +1 -1
  8. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js +30 -1
  9. package/lib/generates/internal/SdkWebSocketRouteProgrammer.js.map +1 -1
  10. package/lib/structures/ITypedWebSocketRoute.d.ts +1 -0
  11. package/package.json +4 -4
  12. package/src/NestiaSdkApplication.ts +257 -257
  13. package/src/analyses/AccessorAnalyzer.ts +67 -67
  14. package/src/analyses/ConfigAnalyzer.ts +147 -147
  15. package/src/analyses/GenericAnalyzer.ts +51 -51
  16. package/src/analyses/PathAnalyzer.ts +69 -69
  17. package/src/analyses/SecurityAnalyzer.ts +25 -25
  18. package/src/analyses/TypedWebSocketOperationAnalyzer.ts +1 -0
  19. package/src/executable/internal/CommandParser.ts +15 -15
  20. package/src/executable/internal/NestiaConfigLoader.ts +67 -67
  21. package/src/executable/internal/NestiaSdkCommand.ts +60 -60
  22. package/src/executable/sdk.ts +73 -73
  23. package/src/generates/CloneGenerator.ts +64 -64
  24. package/src/generates/E2eGenerator.ts +64 -64
  25. package/src/generates/SdkGenerator.ts +91 -91
  26. package/src/generates/SwaggerGenerator.ts +1 -1
  27. package/src/generates/internal/E2eFileProgrammer.ts +178 -178
  28. package/src/generates/internal/FilePrinter.ts +53 -53
  29. package/src/generates/internal/SdkAliasCollection.ts +157 -157
  30. package/src/generates/internal/SdkDistributionComposer.ts +100 -100
  31. package/src/generates/internal/SdkFileProgrammer.ts +119 -119
  32. package/src/generates/internal/SdkHttpCloneProgrammer.ts +154 -154
  33. package/src/generates/internal/SdkHttpFunctionProgrammer.ts +298 -299
  34. package/src/generates/internal/SdkHttpNamespaceProgrammer.ts +505 -505
  35. package/src/generates/internal/SdkHttpRouteProgrammer.ts +82 -82
  36. package/src/generates/internal/SdkHttpSimulationProgrammer.ts +363 -363
  37. package/src/generates/internal/SdkImportWizard.ts +55 -55
  38. package/src/generates/internal/SdkRouteDirectory.ts +18 -18
  39. package/src/generates/internal/SdkWebSocketRouteProgrammer.ts +42 -1
  40. package/src/generates/internal/SwaggerSchemaValidator.ts +198 -198
  41. package/src/index.ts +4 -4
  42. package/src/module.ts +2 -2
  43. package/src/structures/IErrorReport.ts +6 -6
  44. package/src/structures/INestiaProject.ts +13 -13
  45. package/src/structures/INormalizedInput.ts +20 -20
  46. package/src/structures/IReflectController.ts +17 -17
  47. package/src/structures/ITypeTuple.ts +6 -6
  48. package/src/structures/ITypedHttpRoute.ts +55 -55
  49. package/src/structures/ITypedWebSocketRoute.ts +1 -0
  50. package/src/structures/MethodType.ts +5 -5
  51. package/src/structures/ParamCategory.ts +1 -1
  52. package/src/utils/ArrayUtil.ts +26 -26
  53. package/src/utils/FileRetriever.ts +22 -22
  54. package/src/utils/MapUtil.ts +14 -14
  55. package/src/utils/PathUtil.ts +10 -10
  56. package/src/utils/SourceFinder.ts +66 -66
  57. package/src/utils/StringUtil.ts +6 -6
  58. 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
+ };
@@ -123,7 +123,7 @@ export namespace SwaggerGenerator {
123
123
  if (errors.length) {
124
124
  for (const e of errors)
125
125
  console.error(
126
- `${path.relative(e.route.location, process.cwd())}:${
126
+ `${path.relative(process.cwd(), e.route.location)}:${
127
127
  e.route.controller.name
128
128
  }.${e.route.name}:${
129
129
  e.from
@@ -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
+ }