@nestia/sdk 2.6.3-dev.20240328 → 2.6.4-dev.20240401

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 (45) hide show
  1. package/lib/INestiaConfig.d.ts +14 -2
  2. package/lib/executable/internal/NestiaConfigLoader.js +31 -5
  3. package/lib/executable/internal/NestiaConfigLoader.js.map +1 -1
  4. package/lib/generates/SwaggerGenerator.d.ts +2 -0
  5. package/lib/generates/SwaggerGenerator.js +19 -3
  6. package/lib/generates/SwaggerGenerator.js.map +1 -1
  7. package/lib/structures/ISwagger.d.ts +5 -28
  8. package/lib/structures/ISwaggerServer.d.ts +15 -0
  9. package/lib/structures/ISwaggerServer.js +3 -0
  10. package/lib/structures/ISwaggerServer.js.map +1 -0
  11. package/lib/structures/ISwaggerTag.d.ts +9 -0
  12. package/lib/structures/ISwaggerTag.js +3 -0
  13. package/lib/structures/ISwaggerTag.js.map +1 -0
  14. package/package.json +3 -3
  15. package/src/INestiaConfig.ts +261 -248
  16. package/src/NestiaSdkApplication.ts +255 -255
  17. package/src/analyses/ExceptionAnalyzer.ts +148 -148
  18. package/src/analyses/ImportAnalyzer.ts +137 -137
  19. package/src/analyses/SecurityAnalyzer.ts +24 -24
  20. package/src/generates/CloneGenerator.ts +62 -62
  21. package/src/generates/E2eGenerator.ts +66 -66
  22. package/src/generates/SdkGenerator.ts +84 -84
  23. package/src/generates/SwaggerGenerator.ts +23 -3
  24. package/src/generates/internal/E2eFileProgrammer.ts +182 -182
  25. package/src/generates/internal/FilePrinter.ts +53 -53
  26. package/src/generates/internal/SdkAliasCollection.ts +152 -152
  27. package/src/generates/internal/SdkCloneProgrammer.ts +155 -155
  28. package/src/generates/internal/SdkFileProgrammer.ts +115 -115
  29. package/src/generates/internal/SdkFunctionProgrammer.ts +298 -298
  30. package/src/generates/internal/SdkImportWizard.ts +55 -55
  31. package/src/generates/internal/SdkNamespaceProgrammer.ts +510 -510
  32. package/src/generates/internal/SdkRouteProgrammer.ts +83 -83
  33. package/src/generates/internal/SdkSimulationProgrammer.ts +365 -365
  34. package/src/generates/internal/SdkTypeProgrammer.ts +385 -385
  35. package/src/generates/internal/SwaggerSchemaGenerator.ts +438 -438
  36. package/src/structures/IController.ts +94 -94
  37. package/src/structures/IRoute.ts +53 -53
  38. package/src/structures/ISwagger.ts +66 -91
  39. package/src/structures/ISwaggerRoute.ts +54 -54
  40. package/src/structures/ISwaggerSecurityScheme.ts +65 -65
  41. package/src/structures/ISwaggerServer.ts +16 -0
  42. package/src/structures/ISwaggerTag.ts +9 -0
  43. package/src/structures/ParamCategory.ts +1 -1
  44. package/src/structures/TypeEntry.ts +22 -22
  45. package/src/utils/StringUtil.ts +6 -6
@@ -1,152 +1,152 @@
1
- import ts from "typescript";
2
- import typia from "typia";
3
-
4
- import { INestiaConfig } from "../../INestiaConfig";
5
- import { IController } from "../../structures/IController";
6
- import { IRoute } from "../../structures/IRoute";
7
- import { ImportDictionary } from "./ImportDictionary";
8
- import { SdkTypeProgrammer } from "./SdkTypeProgrammer";
9
-
10
- export namespace SdkAliasCollection {
11
- export const name =
12
- (config: INestiaConfig) =>
13
- (importer: ImportDictionary) =>
14
- (p: IRoute.IParameter | IRoute.IOutput): ts.TypeNode =>
15
- p.metadata
16
- ? SdkTypeProgrammer.write(config)(importer)(p.metadata)
17
- : ts.factory.createTypeReferenceNode(p.typeName);
18
-
19
- export const headers =
20
- (config: INestiaConfig) =>
21
- (importer: ImportDictionary) =>
22
- (param: IRoute.IParameter): ts.TypeNode => {
23
- const type: ts.TypeNode = name(config)(importer)(param);
24
- if (config.primitive === false) return type;
25
- return ts.factory.createTypeReferenceNode(
26
- importer.external({
27
- type: true,
28
- library: "@nestia/fetcher",
29
- instance: "Resolved",
30
- }),
31
- [type],
32
- );
33
- };
34
-
35
- export const query =
36
- (config: INestiaConfig) =>
37
- (importer: ImportDictionary) =>
38
- (param: IRoute.IParameter): ts.TypeNode => {
39
- const type: ts.TypeNode = name(config)(importer)(param);
40
- if (config.primitive === false) return type;
41
- return ts.factory.createTypeReferenceNode(
42
- importer.external({
43
- type: true,
44
- library: "@nestia/fetcher",
45
- instance: "Resolved",
46
- }),
47
- [type],
48
- );
49
- };
50
-
51
- export const input =
52
- (config: INestiaConfig) =>
53
- (importer: ImportDictionary) =>
54
- (param: IRoute.IParameter): ts.TypeNode => {
55
- const type: ts.TypeNode = name(config)(importer)(param);
56
- if (config.clone === true || config.primitive === false) return type;
57
- return ts.factory.createTypeReferenceNode(
58
- importer.external({
59
- type: true,
60
- library: "@nestia/fetcher",
61
- instance:
62
- typia.is<IController.IBodyParameter>(param) &&
63
- param.contentType === "multipart/form-data"
64
- ? "Resolved"
65
- : "Primitive",
66
- }),
67
- [type],
68
- );
69
- };
70
-
71
- export const output =
72
- (checker: ts.TypeChecker) =>
73
- (config: INestiaConfig) =>
74
- (importer: ImportDictionary) =>
75
- (route: IRoute): ts.TypeNode => {
76
- if (config.propagate !== true) {
77
- const node: ts.TypeNode = name(config)(importer)(route.output);
78
- const type = checker.getTypeAtLocation(node);
79
- const filter = (flag: ts.TypeFlags) => (type.getFlags() & flag) !== 0;
80
-
81
- if (
82
- config.clone === true ||
83
- config.primitive === false ||
84
- filter(ts.TypeFlags.Undefined) ||
85
- filter(ts.TypeFlags.Never) ||
86
- filter(ts.TypeFlags.Void) ||
87
- filter(ts.TypeFlags.VoidLike)
88
- )
89
- return node;
90
- return ts.factory.createTypeReferenceNode(
91
- importer.external({
92
- type: true,
93
- library: "@nestia/fetcher",
94
- instance:
95
- route.output.contentType === "application/x-www-form-urlencoded"
96
- ? "Resolved"
97
- : "Primitive",
98
- }),
99
- [node],
100
- );
101
- }
102
-
103
- const branches: IBranch[] = [
104
- {
105
- status: String(route.status ?? (route.method === "POST" ? 201 : 200)),
106
- type: name(config)(importer)(route.output),
107
- },
108
- ...Object.entries(route.exceptions).map(([status, value]) => ({
109
- status,
110
- type: name(config)(importer)(value),
111
- })),
112
- ];
113
- return ts.factory.createTypeReferenceNode(
114
- importer.external({
115
- type: true,
116
- library: "@nestia/fetcher",
117
- instance: "IPropagation",
118
- }),
119
- [
120
- ts.factory.createTypeLiteralNode(
121
- branches.map((b) =>
122
- ts.factory.createPropertySignature(
123
- undefined,
124
- ts.factory.createNumericLiteral(b.status),
125
- undefined,
126
- b.type,
127
- ),
128
- ),
129
- ),
130
- ...(route.status
131
- ? [
132
- ts.factory.createLiteralTypeNode(
133
- ts.factory.createNumericLiteral(route.status),
134
- ),
135
- ]
136
- : []),
137
- ],
138
- );
139
- };
140
-
141
- export const responseBody =
142
- (checker: ts.TypeChecker) =>
143
- (config: INestiaConfig) =>
144
- (importer: ImportDictionary) =>
145
- (route: IRoute): ts.TypeNode =>
146
- output(checker)({ ...config, propagate: false })(importer)(route);
147
- }
148
-
149
- interface IBranch {
150
- status: string;
151
- type: ts.TypeNode;
152
- }
1
+ import ts from "typescript";
2
+ import typia from "typia";
3
+
4
+ import { INestiaConfig } from "../../INestiaConfig";
5
+ import { IController } from "../../structures/IController";
6
+ import { IRoute } from "../../structures/IRoute";
7
+ import { ImportDictionary } from "./ImportDictionary";
8
+ import { SdkTypeProgrammer } from "./SdkTypeProgrammer";
9
+
10
+ export namespace SdkAliasCollection {
11
+ export const name =
12
+ (config: INestiaConfig) =>
13
+ (importer: ImportDictionary) =>
14
+ (p: IRoute.IParameter | IRoute.IOutput): ts.TypeNode =>
15
+ p.metadata
16
+ ? SdkTypeProgrammer.write(config)(importer)(p.metadata)
17
+ : ts.factory.createTypeReferenceNode(p.typeName);
18
+
19
+ export const headers =
20
+ (config: INestiaConfig) =>
21
+ (importer: ImportDictionary) =>
22
+ (param: IRoute.IParameter): ts.TypeNode => {
23
+ const type: ts.TypeNode = name(config)(importer)(param);
24
+ if (config.primitive === false) return type;
25
+ return ts.factory.createTypeReferenceNode(
26
+ importer.external({
27
+ type: true,
28
+ library: "@nestia/fetcher",
29
+ instance: "Resolved",
30
+ }),
31
+ [type],
32
+ );
33
+ };
34
+
35
+ export const query =
36
+ (config: INestiaConfig) =>
37
+ (importer: ImportDictionary) =>
38
+ (param: IRoute.IParameter): ts.TypeNode => {
39
+ const type: ts.TypeNode = name(config)(importer)(param);
40
+ if (config.primitive === false) return type;
41
+ return ts.factory.createTypeReferenceNode(
42
+ importer.external({
43
+ type: true,
44
+ library: "@nestia/fetcher",
45
+ instance: "Resolved",
46
+ }),
47
+ [type],
48
+ );
49
+ };
50
+
51
+ export const input =
52
+ (config: INestiaConfig) =>
53
+ (importer: ImportDictionary) =>
54
+ (param: IRoute.IParameter): ts.TypeNode => {
55
+ const type: ts.TypeNode = name(config)(importer)(param);
56
+ if (config.clone === true || config.primitive === false) return type;
57
+ return ts.factory.createTypeReferenceNode(
58
+ importer.external({
59
+ type: true,
60
+ library: "@nestia/fetcher",
61
+ instance:
62
+ typia.is<IController.IBodyParameter>(param) &&
63
+ param.contentType === "multipart/form-data"
64
+ ? "Resolved"
65
+ : "Primitive",
66
+ }),
67
+ [type],
68
+ );
69
+ };
70
+
71
+ export const output =
72
+ (checker: ts.TypeChecker) =>
73
+ (config: INestiaConfig) =>
74
+ (importer: ImportDictionary) =>
75
+ (route: IRoute): ts.TypeNode => {
76
+ if (config.propagate !== true) {
77
+ const node: ts.TypeNode = name(config)(importer)(route.output);
78
+ const type = checker.getTypeAtLocation(node);
79
+ const filter = (flag: ts.TypeFlags) => (type.getFlags() & flag) !== 0;
80
+
81
+ if (
82
+ config.clone === true ||
83
+ config.primitive === false ||
84
+ filter(ts.TypeFlags.Undefined) ||
85
+ filter(ts.TypeFlags.Never) ||
86
+ filter(ts.TypeFlags.Void) ||
87
+ filter(ts.TypeFlags.VoidLike)
88
+ )
89
+ return node;
90
+ return ts.factory.createTypeReferenceNode(
91
+ importer.external({
92
+ type: true,
93
+ library: "@nestia/fetcher",
94
+ instance:
95
+ route.output.contentType === "application/x-www-form-urlencoded"
96
+ ? "Resolved"
97
+ : "Primitive",
98
+ }),
99
+ [node],
100
+ );
101
+ }
102
+
103
+ const branches: IBranch[] = [
104
+ {
105
+ status: String(route.status ?? (route.method === "POST" ? 201 : 200)),
106
+ type: name(config)(importer)(route.output),
107
+ },
108
+ ...Object.entries(route.exceptions).map(([status, value]) => ({
109
+ status,
110
+ type: name(config)(importer)(value),
111
+ })),
112
+ ];
113
+ return ts.factory.createTypeReferenceNode(
114
+ importer.external({
115
+ type: true,
116
+ library: "@nestia/fetcher",
117
+ instance: "IPropagation",
118
+ }),
119
+ [
120
+ ts.factory.createTypeLiteralNode(
121
+ branches.map((b) =>
122
+ ts.factory.createPropertySignature(
123
+ undefined,
124
+ ts.factory.createNumericLiteral(b.status),
125
+ undefined,
126
+ b.type,
127
+ ),
128
+ ),
129
+ ),
130
+ ...(route.status
131
+ ? [
132
+ ts.factory.createLiteralTypeNode(
133
+ ts.factory.createNumericLiteral(route.status),
134
+ ),
135
+ ]
136
+ : []),
137
+ ],
138
+ );
139
+ };
140
+
141
+ export const responseBody =
142
+ (checker: ts.TypeChecker) =>
143
+ (config: INestiaConfig) =>
144
+ (importer: ImportDictionary) =>
145
+ (route: IRoute): ts.TypeNode =>
146
+ output(checker)({ ...config, propagate: false })(importer)(route);
147
+ }
148
+
149
+ interface IBranch {
150
+ status: string;
151
+ type: ts.TypeNode;
152
+ }
@@ -1,155 +1,155 @@
1
- import { IPointer } from "tstl";
2
- import ts from "typescript";
3
- import { IJsDocTagInfo } from "typia";
4
- import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
5
- import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
6
- import { MetadataAlias } from "typia/lib/schemas/metadata/MetadataAlias";
7
- import { MetadataAtomic } from "typia/lib/schemas/metadata/MetadataAtomic";
8
- import { MetadataObject } from "typia/lib/schemas/metadata/MetadataObject";
9
-
10
- import { INestiaConfig } from "../../INestiaConfig";
11
- import { IRoute } from "../../structures/IRoute";
12
- import { MapUtil } from "../../utils/MapUtil";
13
- import { FilePrinter } from "./FilePrinter";
14
- import { ImportDictionary } from "./ImportDictionary";
15
- import { SdkTypeProgrammer } from "./SdkTypeProgrammer";
16
-
17
- export namespace SdkCloneProgrammer {
18
- export interface IModule {
19
- name: string;
20
- children: Map<string, IModule>;
21
- programmer:
22
- | null
23
- | ((importer: ImportDictionary) => ts.TypeAliasDeclaration);
24
- }
25
-
26
- export const write =
27
- (checker: ts.TypeChecker) =>
28
- (config: INestiaConfig) =>
29
- (routes: IRoute[]): Map<string, IModule> => {
30
- const collection = new MetadataCollection({
31
- replace: MetadataCollection.replace,
32
- });
33
- for (const r of routes) {
34
- for (const p of r.parameters) {
35
- const res = MetadataFactory.analyze(checker)({
36
- escape: false,
37
- constant: true,
38
- absorb: false,
39
- })(collection)(p.type);
40
- if (res.success) p.metadata = res.data;
41
- }
42
- for (const e of Object.values(r.exceptions)) {
43
- const res = MetadataFactory.analyze(checker)({
44
- escape: true,
45
- constant: true,
46
- absorb: false,
47
- })(collection)(e.type);
48
- if (res.success) e.metadata = res.data;
49
- }
50
- const res = MetadataFactory.analyze(checker)({
51
- escape: true,
52
- constant: true,
53
- absorb: false,
54
- })(collection)(r.output.type);
55
- if (res.success) r.output.metadata = res.data;
56
- }
57
-
58
- const dict: Map<string, IModule> = new Map();
59
- for (const alias of collection.aliases())
60
- if (isNamedDeclaration(alias.name))
61
- prepare(dict)(alias.name)((importer) =>
62
- write_alias(config)(importer)(alias),
63
- );
64
- for (const object of collection.objects())
65
- if (isNamedDeclaration(object.name))
66
- prepare(dict)(object.name)((importer) =>
67
- write_object(config)(importer)(object),
68
- );
69
- return dict;
70
- };
71
-
72
- const prepare =
73
- (dict: Map<string, IModule>) =>
74
- (name: string) =>
75
- (programmer: (importer: ImportDictionary) => ts.TypeAliasDeclaration) => {
76
- const accessors: string[] = name.split(".");
77
- const modulo: IPointer<IModule> = { value: null! };
78
-
79
- accessors.forEach((acc, i) => {
80
- modulo.value = MapUtil.take(dict, acc, () => ({
81
- name: acc,
82
- children: new Map(),
83
- programmer: null,
84
- }));
85
- if (i === accessors.length - 1) modulo.value.programmer = programmer;
86
- dict = modulo.value.children;
87
- });
88
- return modulo!;
89
- };
90
-
91
- const write_alias =
92
- (config: INestiaConfig) =>
93
- (importer: ImportDictionary) =>
94
- (alias: MetadataAlias): ts.TypeAliasDeclaration =>
95
- FilePrinter.description(
96
- ts.factory.createTypeAliasDeclaration(
97
- [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
98
- alias.name.split(".").at(-1)!,
99
- [],
100
- SdkTypeProgrammer.write(config)(importer)(alias.value),
101
- ),
102
- writeComment([])(alias.description, alias.jsDocTags),
103
- );
104
-
105
- const write_object =
106
- (config: INestiaConfig) =>
107
- (importer: ImportDictionary) =>
108
- (object: MetadataObject): ts.TypeAliasDeclaration => {
109
- return FilePrinter.description(
110
- ts.factory.createTypeAliasDeclaration(
111
- [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
112
- object.name.split(".").at(-1)!,
113
- [],
114
- SdkTypeProgrammer.write_object(config)(importer)(object),
115
- ),
116
- writeComment([])(object.description ?? null, object.jsDocTags),
117
- );
118
- };
119
- }
120
-
121
- const isNamedDeclaration = (name: string) =>
122
- name !== "object" &&
123
- name !== "__type" &&
124
- !name.startsWith("__type.") &&
125
- name !== "__object" &&
126
- !name.startsWith("__object.");
127
-
128
- const writeComment =
129
- (atomics: MetadataAtomic[]) =>
130
- (description: string | null, jsDocTags: IJsDocTagInfo[]): string => {
131
- const lines: string[] = [];
132
- if (description?.length)
133
- lines.push(...description.split("\n").map((s) => `${s}`));
134
-
135
- const filtered: IJsDocTagInfo[] =
136
- !!atomics.length && !!jsDocTags?.length
137
- ? jsDocTags.filter(
138
- (tag) =>
139
- !atomics.some((a) =>
140
- a.tags.some((r) => r.some((t) => t.kind === tag.name)),
141
- ),
142
- )
143
- : jsDocTags ?? [];
144
-
145
- if (description?.length && filtered.length) lines.push("");
146
- if (filtered.length)
147
- lines.push(
148
- ...filtered.map((t) =>
149
- t.text?.length
150
- ? `@${t.name} ${t.text.map((e) => e.text).join("")}`
151
- : `@${t.name}`,
152
- ),
153
- );
154
- return lines.join("\n");
155
- };
1
+ import { IPointer } from "tstl";
2
+ import ts from "typescript";
3
+ import { IJsDocTagInfo } from "typia";
4
+ import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
5
+ import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
6
+ import { MetadataAlias } from "typia/lib/schemas/metadata/MetadataAlias";
7
+ import { MetadataAtomic } from "typia/lib/schemas/metadata/MetadataAtomic";
8
+ import { MetadataObject } from "typia/lib/schemas/metadata/MetadataObject";
9
+
10
+ import { INestiaConfig } from "../../INestiaConfig";
11
+ import { IRoute } from "../../structures/IRoute";
12
+ import { MapUtil } from "../../utils/MapUtil";
13
+ import { FilePrinter } from "./FilePrinter";
14
+ import { ImportDictionary } from "./ImportDictionary";
15
+ import { SdkTypeProgrammer } from "./SdkTypeProgrammer";
16
+
17
+ export namespace SdkCloneProgrammer {
18
+ export interface IModule {
19
+ name: string;
20
+ children: Map<string, IModule>;
21
+ programmer:
22
+ | null
23
+ | ((importer: ImportDictionary) => ts.TypeAliasDeclaration);
24
+ }
25
+
26
+ export const write =
27
+ (checker: ts.TypeChecker) =>
28
+ (config: INestiaConfig) =>
29
+ (routes: IRoute[]): Map<string, IModule> => {
30
+ const collection = new MetadataCollection({
31
+ replace: MetadataCollection.replace,
32
+ });
33
+ for (const r of routes) {
34
+ for (const p of r.parameters) {
35
+ const res = MetadataFactory.analyze(checker)({
36
+ escape: false,
37
+ constant: true,
38
+ absorb: false,
39
+ })(collection)(p.type);
40
+ if (res.success) p.metadata = res.data;
41
+ }
42
+ for (const e of Object.values(r.exceptions)) {
43
+ const res = MetadataFactory.analyze(checker)({
44
+ escape: true,
45
+ constant: true,
46
+ absorb: false,
47
+ })(collection)(e.type);
48
+ if (res.success) e.metadata = res.data;
49
+ }
50
+ const res = MetadataFactory.analyze(checker)({
51
+ escape: true,
52
+ constant: true,
53
+ absorb: false,
54
+ })(collection)(r.output.type);
55
+ if (res.success) r.output.metadata = res.data;
56
+ }
57
+
58
+ const dict: Map<string, IModule> = new Map();
59
+ for (const alias of collection.aliases())
60
+ if (isNamedDeclaration(alias.name))
61
+ prepare(dict)(alias.name)((importer) =>
62
+ write_alias(config)(importer)(alias),
63
+ );
64
+ for (const object of collection.objects())
65
+ if (isNamedDeclaration(object.name))
66
+ prepare(dict)(object.name)((importer) =>
67
+ write_object(config)(importer)(object),
68
+ );
69
+ return dict;
70
+ };
71
+
72
+ const prepare =
73
+ (dict: Map<string, IModule>) =>
74
+ (name: string) =>
75
+ (programmer: (importer: ImportDictionary) => ts.TypeAliasDeclaration) => {
76
+ const accessors: string[] = name.split(".");
77
+ const modulo: IPointer<IModule> = { value: null! };
78
+
79
+ accessors.forEach((acc, i) => {
80
+ modulo.value = MapUtil.take(dict, acc, () => ({
81
+ name: acc,
82
+ children: new Map(),
83
+ programmer: null,
84
+ }));
85
+ if (i === accessors.length - 1) modulo.value.programmer = programmer;
86
+ dict = modulo.value.children;
87
+ });
88
+ return modulo!;
89
+ };
90
+
91
+ const write_alias =
92
+ (config: INestiaConfig) =>
93
+ (importer: ImportDictionary) =>
94
+ (alias: MetadataAlias): ts.TypeAliasDeclaration =>
95
+ FilePrinter.description(
96
+ ts.factory.createTypeAliasDeclaration(
97
+ [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
98
+ alias.name.split(".").at(-1)!,
99
+ [],
100
+ SdkTypeProgrammer.write(config)(importer)(alias.value),
101
+ ),
102
+ writeComment([])(alias.description, alias.jsDocTags),
103
+ );
104
+
105
+ const write_object =
106
+ (config: INestiaConfig) =>
107
+ (importer: ImportDictionary) =>
108
+ (object: MetadataObject): ts.TypeAliasDeclaration => {
109
+ return FilePrinter.description(
110
+ ts.factory.createTypeAliasDeclaration(
111
+ [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
112
+ object.name.split(".").at(-1)!,
113
+ [],
114
+ SdkTypeProgrammer.write_object(config)(importer)(object),
115
+ ),
116
+ writeComment([])(object.description ?? null, object.jsDocTags),
117
+ );
118
+ };
119
+ }
120
+
121
+ const isNamedDeclaration = (name: string) =>
122
+ name !== "object" &&
123
+ name !== "__type" &&
124
+ !name.startsWith("__type.") &&
125
+ name !== "__object" &&
126
+ !name.startsWith("__object.");
127
+
128
+ const writeComment =
129
+ (atomics: MetadataAtomic[]) =>
130
+ (description: string | null, jsDocTags: IJsDocTagInfo[]): string => {
131
+ const lines: string[] = [];
132
+ if (description?.length)
133
+ lines.push(...description.split("\n").map((s) => `${s}`));
134
+
135
+ const filtered: IJsDocTagInfo[] =
136
+ !!atomics.length && !!jsDocTags?.length
137
+ ? jsDocTags.filter(
138
+ (tag) =>
139
+ !atomics.some((a) =>
140
+ a.tags.some((r) => r.some((t) => t.kind === tag.name)),
141
+ ),
142
+ )
143
+ : jsDocTags ?? [];
144
+
145
+ if (description?.length && filtered.length) lines.push("");
146
+ if (filtered.length)
147
+ lines.push(
148
+ ...filtered.map((t) =>
149
+ t.text?.length
150
+ ? `@${t.name} ${t.text.map((e) => e.text).join("")}`
151
+ : `@${t.name}`,
152
+ ),
153
+ );
154
+ return lines.join("\n");
155
+ };