@tsofist/schema-forge 2.8.0 → 2.10.0-next.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.
Files changed (114) hide show
  1. package/lib/artefacts-policy.d.ts +3 -0
  2. package/lib/artefacts-policy.d.ts.map +1 -0
  3. package/lib/artefacts-policy.js +7 -0
  4. package/lib/dbml-generator/converter.d.ts +5 -0
  5. package/lib/dbml-generator/converter.d.ts.map +1 -0
  6. package/lib/dbml-generator/converter.js +15 -0
  7. package/lib/dbml-generator/generator.d.ts +4 -0
  8. package/lib/dbml-generator/generator.d.ts.map +1 -0
  9. package/lib/dbml-generator/generator.js +423 -0
  10. package/lib/dbml-generator/generator.spec.d.ts +2 -0
  11. package/lib/dbml-generator/generator.spec.d.ts.map +1 -0
  12. package/lib/dbml-generator/generator.spec.js +94 -0
  13. package/lib/dbml-generator/types.d.ts +144 -0
  14. package/lib/dbml-generator/types.d.ts.map +1 -0
  15. package/lib/dbml-generator/types.js +53 -0
  16. package/lib/definition-info/api-signature.d.ts +18 -0
  17. package/lib/definition-info/api-signature.d.ts.map +1 -0
  18. package/lib/definition-info/api-signature.js +31 -0
  19. package/lib/definition-info/parser.d.ts +3 -0
  20. package/lib/definition-info/parser.d.ts.map +1 -0
  21. package/lib/definition-info/parser.js +44 -0
  22. package/lib/definition-info/ref.d.ts +3 -0
  23. package/lib/definition-info/ref.d.ts.map +1 -0
  24. package/lib/definition-info/ref.js +6 -0
  25. package/lib/definition-info/types.d.ts +48 -0
  26. package/lib/definition-info/types.d.ts.map +1 -0
  27. package/lib/definition-info/types.js +20 -0
  28. package/lib/efc.d.ts +27 -0
  29. package/lib/efc.d.ts.map +1 -0
  30. package/lib/efc.js +9 -0
  31. package/lib/fake-generator/generator-host.d.ts +4 -0
  32. package/lib/fake-generator/generator-host.d.ts.map +1 -0
  33. package/lib/fake-generator/generator-host.js +57 -0
  34. package/lib/fake-generator/generator.d.ts +6 -0
  35. package/lib/fake-generator/generator.d.ts.map +1 -0
  36. package/lib/fake-generator/generator.js +64 -0
  37. package/lib/fake-generator/generator.spec.d.ts +2 -0
  38. package/lib/fake-generator/generator.spec.d.ts.map +1 -0
  39. package/lib/{fake-generator.spec.js → fake-generator/generator.spec.js} +21 -19
  40. package/lib/fake-generator/modules.d.ts +3 -0
  41. package/lib/fake-generator/modules.d.ts.map +1 -0
  42. package/lib/fake-generator/modules.js +44 -0
  43. package/lib/fake-generator/types.d.ts +18 -0
  44. package/lib/fake-generator/types.d.ts.map +1 -0
  45. package/lib/fake-generator/types.js +2 -0
  46. package/lib/schema-generator/extended-annotations-reader.d.ts +2 -0
  47. package/lib/schema-generator/extended-annotations-reader.d.ts.map +1 -0
  48. package/lib/{util/patch.extended-annotations-reader.js → schema-generator/extended-annotations-reader.js} +2 -2
  49. package/lib/schema-generator/forge.d.ts +3 -0
  50. package/lib/schema-generator/forge.d.ts.map +1 -0
  51. package/lib/{generator.js → schema-generator/forge.js} +13 -33
  52. package/lib/schema-generator/forge.spec.d.ts +2 -0
  53. package/lib/schema-generator/forge.spec.d.ts.map +1 -0
  54. package/lib/{generator.spec.js → schema-generator/forge.spec.js} +157 -103
  55. package/lib/schema-generator/format-error.d.ts +2 -0
  56. package/lib/schema-generator/format-error.d.ts.map +1 -0
  57. package/lib/{util/format.error.js → schema-generator/format-error.js} +3 -2
  58. package/lib/schema-generator/generate-drafts.d.ts +17 -0
  59. package/lib/schema-generator/generate-drafts.d.ts.map +1 -0
  60. package/lib/{generator/types-generator.js → schema-generator/generate-drafts.js} +140 -120
  61. package/lib/schema-generator/generate-schema.d.ts +15 -0
  62. package/lib/schema-generator/generate-schema.d.ts.map +1 -0
  63. package/lib/{generator/schema-generator.js → schema-generator/generate-schema.js} +46 -19
  64. package/lib/{util/tsc.d.ts → schema-generator/helpers-tsc.d.ts} +2 -1
  65. package/lib/schema-generator/helpers-tsc.d.ts.map +1 -0
  66. package/lib/schema-generator/shrink-definition-name.d.ts +7 -0
  67. package/lib/schema-generator/shrink-definition-name.d.ts.map +1 -0
  68. package/lib/schema-generator/shrink-definition-name.js +21 -0
  69. package/lib/schema-generator/sort-properties.d.ts +3 -0
  70. package/lib/schema-generator/sort-properties.d.ts.map +1 -0
  71. package/lib/{util → schema-generator}/sort-properties.js +2 -2
  72. package/lib/schema-generator/types.d.ts +18 -0
  73. package/lib/schema-generator/types.d.ts.map +1 -0
  74. package/lib/{generator → schema-generator}/types.js +20 -8
  75. package/lib/schema-registry/kw-api.d.ts +3 -0
  76. package/lib/schema-registry/kw-api.d.ts.map +1 -0
  77. package/lib/schema-registry/kw-api.js +25 -0
  78. package/lib/schema-registry/kw-common.d.ts +3 -0
  79. package/lib/schema-registry/kw-common.d.ts.map +1 -0
  80. package/lib/schema-registry/kw-common.js +47 -0
  81. package/lib/schema-registry/kw-dbml.d.ts +3 -0
  82. package/lib/schema-registry/kw-dbml.d.ts.map +1 -0
  83. package/lib/schema-registry/kw-dbml.js +79 -0
  84. package/lib/schema-registry/loader.d.ts +10 -0
  85. package/lib/schema-registry/loader.d.ts.map +1 -0
  86. package/lib/schema-registry/loader.js +24 -0
  87. package/lib/schema-registry/registry.d.ts +25 -0
  88. package/lib/schema-registry/registry.d.ts.map +1 -0
  89. package/lib/schema-registry/registry.js +230 -0
  90. package/lib/schema-registry/types.d.ts +78 -0
  91. package/lib/schema-registry/types.d.ts.map +1 -0
  92. package/lib/schema-registry/types.js +2 -0
  93. package/lib/types.d.ts +53 -79
  94. package/lib/types.d.ts.map +1 -0
  95. package/lib/types.js +0 -15
  96. package/package.json +9 -6
  97. package/lib/fake-generator.d.ts +0 -21
  98. package/lib/fake-generator.js +0 -158
  99. package/lib/fake-generator.spec.d.ts +0 -1
  100. package/lib/generator/schema-generator.d.ts +0 -20
  101. package/lib/generator/types-generator.d.ts +0 -13
  102. package/lib/generator/types.d.ts +0 -40
  103. package/lib/generator.d.ts +0 -5
  104. package/lib/generator.spec.d.ts +0 -1
  105. package/lib/index.d.ts +0 -7
  106. package/lib/index.js +0 -64
  107. package/lib/types/db.types.d.ts +0 -64
  108. package/lib/types/db.types.js +0 -17
  109. package/lib/util/format.error.d.ts +0 -1
  110. package/lib/util/patch.extended-annotations-reader.d.ts +0 -1
  111. package/lib/util/sort-properties.d.ts +0 -2
  112. package/lib/validator.d.ts +0 -47
  113. package/lib/validator.js +0 -385
  114. /package/lib/{util/tsc.js → schema-generator/helpers-tsc.js} +0 -0
@@ -1,120 +1,103 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateDraftTypeFiles = generateDraftTypeFiles;
4
- const promises_1 = require("fs/promises");
5
- const path_1 = require("path");
6
- const as_bool_1 = require("@tsofist/stem/lib/as-bool");
4
+ const promises_1 = require("node:fs/promises");
5
+ const node_path_1 = require("node:path");
7
6
  const error_1 = require("@tsofist/stem/lib/error");
8
7
  const text_builder_1 = require("@tsofist/stem/lib/string/text-builder");
9
8
  const ts_json_schema_generator_1 = require("ts-json-schema-generator");
10
9
  const Config_1 = require("ts-json-schema-generator/dist/src/Config");
11
10
  const typescript_1 = require("typescript");
12
- const index_1 = require("../index");
13
- const types_1 = require("../types");
14
- const tsc_1 = require("../util/tsc");
15
- const types_2 = require("./types");
11
+ const api_signature_1 = require("../definition-info/api-signature");
12
+ const helpers_tsc_1 = require("./helpers-tsc");
13
+ const types_1 = require("./types");
14
+ /**
15
+ * @internal
16
+ */
16
17
  async function generateDraftTypeFiles(options) {
17
- const explicitPublic = (0, as_bool_1.asBool)(options.explicitPublic, true);
18
18
  const sourcesTypesGeneratorConfig = {
19
19
  ...Config_1.DEFAULT_CONFIG,
20
- ...types_2.SG_CONFIG_DEFAULTS,
21
- expose: options.expose ?? types_2.SG_CONFIG_DEFAULTS.expose,
20
+ ...types_1.SFG_CONFIG_DEFAULTS,
21
+ expose: options.expose ?? types_1.SFG_CONFIG_DEFAULTS.expose,
22
22
  path: options.sourcesPattern.length > 1 ? undefined : options.sourcesPattern[0],
23
23
  tsconfig: options.tsconfig,
24
24
  discriminatorType: Config_1.DEFAULT_CONFIG.discriminatorType,
25
- ...types_2.SG_CONFIG_MANDATORY,
25
+ ...types_1.SFG_CONFIG_MANDATORY,
26
26
  };
27
- const files = [];
28
- let definitions = [];
29
- const program = (0, ts_json_schema_generator_1.createProgram)(sourcesTypesGeneratorConfig);
30
- const checker = program.getTypeChecker();
31
- const compilerOptions = program.getCompilerOptions();
32
- const compilerHost = (0, typescript_1.createCompilerHost)(compilerOptions);
33
- const fileNames = program.getRootFileNames();
34
- const namesBySourceFile = new Map();
35
- for (const sourceFileName of fileNames) {
36
- const context = {
37
- program,
38
- compilerOptions,
39
- compilerHost,
40
- typeChecker: checker,
41
- options,
42
- fileContent: [],
43
- registerDefinition(...names) {
44
- let set = namesBySourceFile.get(sourceFileName);
45
- if (!set)
46
- namesBySourceFile.set(sourceFileName, (set = new Set()));
47
- for (const name of names) {
48
- definitions.push(name);
49
- set.add(name);
50
- }
51
- },
52
- };
53
- const source = program.getSourceFile(sourceFileName);
54
- if (!source)
55
- continue;
56
- const statements = [...source.statements];
57
- while (statements.length) {
58
- const statement = statements.pop();
59
- if (!statement)
60
- break;
61
- if ((0, typescript_1.isExportDeclaration)(statement)) {
62
- processExportDeclaration(statement, sourceFileName, statements, context);
63
- continue;
64
- }
65
- if (explicitPublic) {
66
- const isPublic = (0, typescript_1.getJSDocPublicTag)(statement) != null;
67
- if (!isPublic)
68
- continue;
69
- }
70
- else {
71
- const isPrivate = (0, typescript_1.getJSDocPrivateTag)(statement) != null || (0, tsc_1.hasJSDocTag)(statement, 'internal');
72
- if (isPrivate)
73
- continue;
74
- }
75
- switch (statement.kind) {
76
- case typescript_1.SyntaxKind.ImportDeclaration:
77
- case typescript_1.SyntaxKind.VariableStatement:
78
- continue;
79
- case typescript_1.SyntaxKind.EnumDeclaration:
80
- passDeclaration(statement, context);
81
- break;
82
- case typescript_1.SyntaxKind.TypeAliasDeclaration:
83
- passDeclaration(statement, context);
84
- break;
85
- case typescript_1.SyntaxKind.InterfaceDeclaration:
86
- if ((0, tsc_1.hasJSDocTag)(statement, 'api')) {
87
- processAPIInterfaceDeclaration(statement, context);
88
- }
89
- else {
90
- passDeclaration(statement, context);
91
- }
92
- break;
93
- default:
94
- console.error(`[current statement]`, statement.getText(), '\n');
95
- (0, error_1.raise)(`Unsupported statement kind: ${statement.kind} (${typescript_1.SyntaxKind[statement.kind]}) in ${sourceFileName}`);
96
- }
97
- }
98
- const outputFileName = `${(0, path_1.dirname)(sourceFileName)}/${(0, path_1.basename)(sourceFileName, (0, path_1.extname)(sourceFileName))}${types_2.TMP_FILES_SUFFIX}.ts`;
99
- await (0, promises_1.writeFile)(outputFileName, [source.getFullText(), context.fileContent.join('\n')].join('\n'), { encoding: 'utf8' });
100
- files.push(outputFileName);
27
+ // const files: string[] = [];
28
+ const ctx = createContext(options, sourcesTypesGeneratorConfig);
29
+ let definitions = ctx.definitions;
30
+ for (const sourceFileName of ctx.fileNames) {
31
+ ctx.currentSourceFileName = sourceFileName;
32
+ ctx.currentFileContent = [];
33
+ await processSourceFile(sourceFileName, ctx);
101
34
  }
102
35
  if (options.definitionsFilter) {
103
36
  definitions = definitions.filter(options.definitionsFilter);
104
37
  }
105
38
  definitions.sort();
106
39
  return {
107
- sourcesTypesGeneratorConfig,
108
- files,
40
+ files: ctx.files,
109
41
  definitions,
110
- namesBySourceFile,
42
+ sourcesTypesGeneratorConfig,
43
+ namesBySourceFile: ctx.namesBySourceFile,
111
44
  };
112
45
  }
113
- const S = ' '.repeat(4);
46
+ async function processSourceFile(sourceFileName, context) {
47
+ const source = context.program.getSourceFile(sourceFileName);
48
+ if (!source)
49
+ return;
50
+ const explicitPublic = context.options.explicitPublic ?? true;
51
+ const statements = [...source.statements];
52
+ const outputFileName = `${(0, node_path_1.dirname)(sourceFileName)}/${(0, node_path_1.basename)(sourceFileName, (0, node_path_1.extname)(sourceFileName))}${types_1.TMP_FILES_SUFFIX}.ts`;
53
+ while (statements.length) {
54
+ const statement = statements.pop();
55
+ if (!statement)
56
+ break;
57
+ if ((0, typescript_1.isExportDeclaration)(statement)) {
58
+ processExportDeclaration(statement, statements, context);
59
+ continue;
60
+ }
61
+ if (explicitPublic) {
62
+ const isPublic = (0, typescript_1.getJSDocPublicTag)(statement) != null;
63
+ if (!isPublic)
64
+ continue;
65
+ }
66
+ else {
67
+ const isPrivate = (0, typescript_1.getJSDocPrivateTag)(statement) != null || (0, helpers_tsc_1.hasJSDocTag)(statement, 'internal');
68
+ if (isPrivate)
69
+ continue;
70
+ }
71
+ switch (statement.kind) {
72
+ case typescript_1.SyntaxKind.ImportDeclaration:
73
+ case typescript_1.SyntaxKind.VariableStatement:
74
+ continue;
75
+ case typescript_1.SyntaxKind.EnumDeclaration:
76
+ passDeclaration(statement, context);
77
+ break;
78
+ case typescript_1.SyntaxKind.TypeAliasDeclaration:
79
+ passDeclaration(statement, context);
80
+ break;
81
+ case typescript_1.SyntaxKind.InterfaceDeclaration:
82
+ if ((0, helpers_tsc_1.hasJSDocTag)(statement, 'api')) {
83
+ processAPIInterfaceDeclaration(statement, context);
84
+ }
85
+ else {
86
+ passDeclaration(statement, context);
87
+ }
88
+ break;
89
+ default:
90
+ console.error(`[current statement]`, statement.getText(), '\n');
91
+ (0, error_1.raise)(`Unsupported statement kind: ${statement.kind} (${typescript_1.SyntaxKind[statement.kind]}) in ${sourceFileName}`);
92
+ }
93
+ }
94
+ await (0, promises_1.writeFile)(outputFileName, [source.getFullText(), context.currentFileContent.join('\n')].join('\n'), { encoding: 'utf8' });
95
+ context.files.push(outputFileName);
96
+ }
114
97
  function passDeclaration(statement, context) {
115
- context.registerDefinition(statement.name.getText());
98
+ context.registerDefinition(context.currentSourceFileName, statement.name.getText());
116
99
  }
117
- function processExportDeclaration(statement, sourceFileName, list, context) {
100
+ function processExportDeclaration(statement, list, context) {
118
101
  if (!statement.exportClause ||
119
102
  !(0, typescript_1.isNamedExports)(statement.exportClause) ||
120
103
  !statement.moduleSpecifier ||
@@ -127,12 +110,12 @@ function processExportDeclaration(statement, sourceFileName, list, context) {
127
110
  }
128
111
  let module;
129
112
  const moduleSpecifier = statement.moduleSpecifier.text;
130
- if (!(0, path_1.isAbsolute)(moduleSpecifier)) {
131
- const fn = (0, path_1.resolve)((0, path_1.dirname)(sourceFileName), moduleSpecifier) + '.ts';
113
+ if (!(0, node_path_1.isAbsolute)(moduleSpecifier)) {
114
+ const fn = (0, node_path_1.resolve)((0, node_path_1.dirname)(context.currentSourceFileName), moduleSpecifier) + '.ts';
132
115
  module = context.program.getSourceFile(fn);
133
116
  }
134
117
  if (!module) {
135
- const filename = (0, tsc_1.resolveModuleFileName)(sourceFileName, moduleSpecifier, context.compilerOptions, context.compilerHost);
118
+ const filename = (0, helpers_tsc_1.resolveModuleFileName)(context.currentSourceFileName, moduleSpecifier, context.compilerOptions, context.compilerHost);
136
119
  if (filename)
137
120
  module = context.program.getSourceFile(filename);
138
121
  }
@@ -157,9 +140,9 @@ function processExportDeclaration(statement, sourceFileName, list, context) {
157
140
  function processAPIInterfaceDeclaration(statement, context) {
158
141
  const allowUseFallbackDescription = context.options.allowUseFallbackDescription;
159
142
  const definitionsMetaList = [];
160
- const interfaceName = (0, tsc_1.readNodeName)(statement);
161
- const interfaceGenericText = (0, tsc_1.readInterfaceGenericText)(statement);
162
- const interfaceDesc = (0, tsc_1.readJSDocDescription)(statement, allowUseFallbackDescription);
143
+ const interfaceName = (0, helpers_tsc_1.readNodeName)(statement);
144
+ const interfaceGenericText = (0, helpers_tsc_1.readInterfaceGenericText)(statement);
145
+ const interfaceDesc = (0, helpers_tsc_1.readJSDocDescription)(statement, allowUseFallbackDescription);
163
146
  const interfaceDeprecated = (0, typescript_1.getTextOfJSDocComment)((0, typescript_1.getJSDocDeprecatedTag)(statement)?.comment);
164
147
  function onSignature(method, memberName, memberDescription, deprecated) {
165
148
  const minArgsNum = countRequiredParams(method.parameters);
@@ -170,7 +153,7 @@ function processAPIInterfaceDeclaration(statement, context) {
170
153
  const name = parameter.name.getText();
171
154
  argsNames.push(name);
172
155
  const text = parameter.type?.getText() || (0, error_1.raise)(`No type specified for ${name}`);
173
- let desc = (0, tsc_1.readJSDocDescription)(parameter, allowUseFallbackDescription, false);
156
+ let desc = (0, helpers_tsc_1.readJSDocDescription)(parameter, allowUseFallbackDescription, false);
174
157
  desc = desc ? `/** @description ${desc} */ ` : '';
175
158
  return `${S}${desc}${name}: ${text}`;
176
159
  })
@@ -180,9 +163,9 @@ function processAPIInterfaceDeclaration(statement, context) {
180
163
  return `${item}${index + 1 <= minArgsNum ? '*' : ''}`;
181
164
  })
182
165
  .join(', ');
183
- const resultTypeName = (0, tsc_1.readMemberTypeName)(method);
184
- const definitionNameArgs = (0, index_1.buildAPIInterfaceSchemaSignature)(interfaceName, memberName, types_1.SchemaForgeSignatureSuffix.MethodArguments);
185
- const definitionNameResult = (0, index_1.buildAPIInterfaceSchemaSignature)(interfaceName, memberName, types_1.SchemaForgeSignatureSuffix.MethodResult);
166
+ const resultTypeName = (0, helpers_tsc_1.readMemberTypeName)(method);
167
+ const definitionNameArgs = (0, api_signature_1.buildAPIMethodArgsSDS)(interfaceName, memberName);
168
+ const definitionNameResult = (0, api_signature_1.buildAPIMethodResultSDS)(interfaceName, memberName);
186
169
  const comment = `Method:${interfaceName}#${memberName}`;
187
170
  definitionsMetaList.push({
188
171
  name: memberName,
@@ -190,12 +173,12 @@ function processAPIInterfaceDeclaration(statement, context) {
190
173
  deprecated,
191
174
  desc: [definitionNameArgs, definitionNameResult],
192
175
  });
193
- context.registerDefinition(definitionNameArgs, definitionNameResult);
194
- context.fileContent.push(...[
195
- // ARGUMENTS
176
+ context.registerDefinition(context.currentSourceFileName, definitionNameArgs, definitionNameResult);
177
+ context.currentFileContent.push(...[
178
+ // Arguments ->
196
179
  `/**`,
197
- ` * @interface ${interfaceName}`,
198
- ` * @member ${interfaceName}#${memberName}`,
180
+ ` * @apiInterface ${interfaceName}`,
181
+ ` * @apiMember ${interfaceName}#${memberName}`,
199
182
  ` * @description Arguments for ${comment} ${argsNames.length ? `(${argsNamesText})` : ''}`,
200
183
  ` * @comment ${comment}`,
201
184
  ` *`,
@@ -204,10 +187,11 @@ function processAPIInterfaceDeclaration(statement, context) {
204
187
  ` */`,
205
188
  `export type ${definitionNameArgs} = readonly [\n${argsTypesText}\n];`,
206
189
  ``,
207
- // RESULT
190
+ // Result ->
208
191
  `/**`,
209
- ` * @interface ${interfaceName}`,
210
- ` * @member ${interfaceName}#${memberName}`,
192
+ ` * @apiInterface ${interfaceName}`,
193
+ ` * @apiMember ${interfaceName}#${memberName}`,
194
+ ` *`,
211
195
  ` * @description Result type for ${comment}`,
212
196
  ` * @comment ${comment}`,
213
197
  ` */`,
@@ -216,11 +200,11 @@ function processAPIInterfaceDeclaration(statement, context) {
216
200
  ]);
217
201
  }
218
202
  function onMember(member) {
219
- const isPrivate = (0, typescript_1.getJSDocPrivateTag)(member) != null || (0, tsc_1.hasJSDocTag)(member, 'internal');
203
+ const isPrivate = (0, typescript_1.getJSDocPrivateTag)(member) != null || (0, helpers_tsc_1.hasJSDocTag)(member, 'internal');
220
204
  if (isPrivate)
221
205
  return;
222
- const memberName = (0, tsc_1.readNodeName)(member);
223
- const memberDescription = (0, tsc_1.readJSDocDescription)(member, allowUseFallbackDescription);
206
+ const memberName = (0, helpers_tsc_1.readNodeName)(member);
207
+ const memberDescription = (0, helpers_tsc_1.readJSDocDescription)(member, allowUseFallbackDescription);
224
208
  const deprecated = (0, typescript_1.getTextOfJSDocComment)((0, typescript_1.getJSDocDeprecatedTag)(member)?.comment);
225
209
  if ((0, typescript_1.isMethodSignature)(member)) {
226
210
  onSignature(member, memberName, memberDescription, deprecated);
@@ -234,12 +218,12 @@ function processAPIInterfaceDeclaration(statement, context) {
234
218
  name: memberName,
235
219
  description: memberDescription,
236
220
  deprecated,
237
- desc: (0, tsc_1.readMemberTypeName)(member) || 'unknown',
221
+ desc: (0, helpers_tsc_1.readMemberTypeName)(member) || 'unknown',
238
222
  });
239
223
  }
240
224
  }
241
225
  }
242
- // inheritance first
226
+ // Inheritance first
243
227
  if (statement.heritageClauses) {
244
228
  for (const clause of statement.heritageClauses) {
245
229
  for (const type of clause.types) {
@@ -263,8 +247,9 @@ function processAPIInterfaceDeclaration(statement, context) {
263
247
  const isMethod = Array.isArray(member.desc);
264
248
  membersText.push([
265
249
  `/**`,
266
- ` * @interface ${interfaceName}`,
267
- ` * @${isMethod ? 'method' : 'property'} ${member.name}`,
250
+ ` * @apiInterface ${interfaceName}`,
251
+ ` *`,
252
+ ` * @${isMethod ? 'apiMethod' : 'apiProperty'} ${member.name}`,
268
253
  member.description && ` * @description ${member.description}`,
269
254
  member.deprecated && ` * @deprecated ${member.deprecated}`,
270
255
  ` * @comment ${isMethod ? 'Method' : 'Property'}:${interfaceName}#${member.name}`,
@@ -276,18 +261,19 @@ function processAPIInterfaceDeclaration(statement, context) {
276
261
  }
277
262
  const interfaceText = new text_builder_1.TextBuilder([
278
263
  `/**`,
279
- ` * @interface ${interfaceName}`,
264
+ ` * @apiInterface ${interfaceName}`,
265
+ ` *`,
280
266
  interfaceDesc && ` * @description ${interfaceDesc}`,
281
267
  interfaceDeprecated && ` * @deprecated ${interfaceDeprecated}`,
282
268
  ` * @comment Interface:${interfaceName}`,
283
269
  ` */`,
284
- `export interface ${(0, index_1.buildAPIInterfaceSchemaSignature)(interfaceName)}${interfaceGenericText} {`,
270
+ `export interface ${(0, api_signature_1.buildAPIInterfaceSDS)(interfaceName)}${interfaceGenericText} {`,
285
271
  membersText.stringify('\n'),
286
272
  `}`,
287
273
  ``,
288
274
  ]);
289
- context.registerDefinition((0, index_1.buildAPIInterfaceSchemaSignature)(interfaceName));
290
- context.fileContent.push(interfaceText.stringify('\n'));
275
+ context.registerDefinition(context.currentSourceFileName, (0, api_signature_1.buildAPIInterfaceSDS)(interfaceName));
276
+ context.currentFileContent.push(interfaceText.stringify('\n'));
291
277
  }
292
278
  }
293
279
  function countRequiredParams(params) {
@@ -301,3 +287,37 @@ function countRequiredParams(params) {
301
287
  }
302
288
  return result;
303
289
  }
290
+ function createContext(options, sourcesTypesGeneratorConfig) {
291
+ const program = (0, ts_json_schema_generator_1.createProgram)(sourcesTypesGeneratorConfig);
292
+ const checker = program.getTypeChecker();
293
+ const compilerOptions = program.getCompilerOptions();
294
+ const compilerHost = (0, typescript_1.createCompilerHost)(compilerOptions);
295
+ const fileNames = program.getRootFileNames();
296
+ const namesBySourceFile = new Map();
297
+ const definitions = [];
298
+ const files = [];
299
+ const currentFileContent = [];
300
+ return {
301
+ currentFileContent,
302
+ currentSourceFileName: '',
303
+ namesBySourceFile,
304
+ fileNames,
305
+ definitions,
306
+ program,
307
+ compilerOptions,
308
+ compilerHost,
309
+ typeChecker: checker,
310
+ options,
311
+ files,
312
+ registerDefinition(sourceFilename, ...names) {
313
+ let set = namesBySourceFile.get(sourceFilename);
314
+ if (!set)
315
+ namesBySourceFile.set(sourceFilename, (set = new Set()));
316
+ for (const name of names) {
317
+ definitions.push(name);
318
+ set.add(name);
319
+ }
320
+ },
321
+ };
322
+ }
323
+ const S = ' '.repeat(4);
@@ -0,0 +1,15 @@
1
+ import './extended-annotations-reader';
2
+ import { SchemaObject } from 'ajv';
3
+ import { CompletedConfig } from 'ts-json-schema-generator';
4
+ import { ForgeSchemaOptions } from '../types';
5
+ /**
6
+ * @internal
7
+ */
8
+ export declare function generateSchemaByDraftTypes(options: InternalOptions): Promise<SchemaObject>;
9
+ interface InternalOptions extends ForgeSchemaOptions {
10
+ tsconfig: string;
11
+ definitions: readonly string[];
12
+ sourcesTypesGeneratorConfig: CompletedConfig;
13
+ }
14
+ export {};
15
+ //# sourceMappingURL=generate-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-schema.d.ts","sourceRoot":"","sources":["../../src/schema-generator/generate-schema.ts"],"names":[],"mappings":"AAAA,OAAO,+BAA+B,CAAC;AAGvC,OAAY,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AAExC,OAAO,EAGH,eAAe,EAgBlB,MAAM,0BAA0B,CAAC;AAelC,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAM9C;;GAEG;AACH,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CAqGhG;AAsGD,UAAU,eAAgB,SAAQ,kBAAkB;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,2BAA2B,EAAE,eAAe,CAAC;CAChD"}
@@ -1,15 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateSchemaByDraftTypes = generateSchemaByDraftTypes;
4
- require("../util/patch.extended-annotations-reader");
4
+ require("./extended-annotations-reader");
5
5
  const error_1 = require("@tsofist/stem/lib/error");
6
6
  const ajv_1 = require("ajv");
7
7
  const jsonpath_plus_1 = require("jsonpath-plus");
8
8
  const ts_json_schema_generator_1 = require("ts-json-schema-generator");
9
9
  const typescript_1 = require("typescript");
10
- const sort_properties_1 = require("../util/sort-properties");
11
- const tsc_1 = require("../util/tsc");
10
+ const helpers_tsc_1 = require("./helpers-tsc");
11
+ const shrink_definition_name_1 = require("./shrink-definition-name");
12
+ const sort_properties_1 = require("./sort-properties");
12
13
  const types_1 = require("./types");
14
+ /**
15
+ * @internal
16
+ */
13
17
  async function generateSchemaByDraftTypes(options) {
14
18
  {
15
19
  const seen = new Set();
@@ -22,14 +26,12 @@ async function generateSchemaByDraftTypes(options) {
22
26
  const allowUseFallbackDescription = options.allowUseFallbackDescription;
23
27
  const generatorConfig = {
24
28
  ...ts_json_schema_generator_1.DEFAULT_CONFIG,
25
- ...types_1.SG_CONFIG_DEFAULTS,
26
- expose: options.expose ?? types_1.SG_CONFIG_DEFAULTS.expose,
29
+ ...types_1.SFG_CONFIG_DEFAULTS,
30
+ expose: options.expose ?? types_1.SFG_CONFIG_DEFAULTS.expose,
27
31
  path: `${options.sourcesDirectoryPattern}/*${types_1.TMP_FILES_SUFFIX}.ts`,
28
32
  tsconfig: options.tsconfig,
29
- discriminatorType: options.openapiCompatible
30
- ? 'open-api'
31
- : ts_json_schema_generator_1.DEFAULT_CONFIG.discriminatorType,
32
- ...types_1.SG_CONFIG_MANDATORY,
33
+ discriminatorType: options.discriminatorType ?? ts_json_schema_generator_1.DEFAULT_CONFIG.discriminatorType,
34
+ ...types_1.SFG_CONFIG_MANDATORY,
33
35
  };
34
36
  const generatorProgram = (0, ts_json_schema_generator_1.createProgram)(generatorConfig);
35
37
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
@@ -37,6 +39,7 @@ async function generateSchemaByDraftTypes(options) {
37
39
  const parser = (0, ts_json_schema_generator_1.createParser)(generatorProgram, options.sourcesTypesGeneratorConfig, (parser) => {
38
40
  parser.addNodeParser(new TupleTypeParser(parser, allowUseFallbackDescription));
39
41
  parser.addNodeParser(new ArrayLiteralExpressionIdentifierParser(typeChecker));
42
+ parser.addNodeParser(new TypeofNodeParserEx(typeChecker, parser));
40
43
  });
41
44
  const formatter = (0, ts_json_schema_generator_1.createFormatter)(options.sourcesTypesGeneratorConfig);
42
45
  const generator = new ts_json_schema_generator_1.SchemaGenerator(generatorProgram, parser, formatter, generatorConfig);
@@ -54,18 +57,23 @@ async function generateSchemaByDraftTypes(options) {
54
57
  const schema = generator.createSchema(definitionName);
55
58
  Object.assign(result.definitions, schema.definitions);
56
59
  }
57
- if (options.shrinkDefinitionNames) {
60
+ const shrinkDefinitionNames = !options.shrinkDefinitionNames
61
+ ? undefined
62
+ : options.shrinkDefinitionNames === true
63
+ ? shrink_definition_name_1.shrinkDefinitionName
64
+ : options.shrinkDefinitionNames;
65
+ if (shrinkDefinitionNames) {
58
66
  const replacement = new Set();
59
67
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
60
68
  for (const name of Object.keys(result.definitions)) {
61
- const r = options.shrinkDefinitionNames(name);
62
- if (r) {
63
- if (replacement.has(r) || r in result.definitions) {
64
- (0, error_1.raise)(`Duplicate replacement definition name: ${r}`);
69
+ const shortName = shrinkDefinitionNames(name);
70
+ if (shortName) {
71
+ if (replacement.has(shortName) || shortName in result.definitions) {
72
+ (0, error_1.raise)(`Duplicate replacement definition name: ${shortName}`);
65
73
  }
66
74
  // rename property
67
75
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
68
- result.definitions[r] = result.definitions[name];
76
+ result.definitions[shortName] = result.definitions[name];
69
77
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
70
78
  delete result.definitions[name];
71
79
  // rename references
@@ -75,20 +83,20 @@ async function generateSchemaByDraftTypes(options) {
75
83
  eval: 'safe',
76
84
  });
77
85
  targets?.forEach((item) => {
78
- item.$ref = item.$ref.replace(`#/definitions/${name}`, `#/definitions/${r}`);
86
+ item.$ref = item.$ref.replace(`#/definitions/${name}`, `#/definitions/${shortName}`);
79
87
  });
80
88
  }
81
89
  }
82
90
  }
83
91
  result.definitions = Object.fromEntries(Object.entries((result.definitions || {})).sort());
84
92
  if (options.sortObjectProperties)
85
- (0, sort_properties_1.sortProperties)(result.definitions);
93
+ (0, sort_properties_1.sortSchemaProperties)(result.definitions);
86
94
  await new ajv_1.default({
87
95
  strict: true,
88
96
  allErrors: true,
89
97
  strictSchema: true,
90
98
  strictTypes: false,
91
- strictTuples: false,
99
+ strictTuples: true,
92
100
  allowUnionTypes: true,
93
101
  }).validateSchema(result, true);
94
102
  return result;
@@ -96,6 +104,25 @@ async function generateSchemaByDraftTypes(options) {
96
104
  function escapeDefinitionNameForJSONPath(value) {
97
105
  return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
98
106
  }
107
+ class TypeofNodeParserEx extends ts_json_schema_generator_1.TypeofNodeParser {
108
+ createType(node, context, reference) {
109
+ const tc = this.typeChecker;
110
+ let symbol = tc.getSymbolAtLocation(node.exprName);
111
+ if (symbol && symbol.flags & typescript_1.SymbolFlags.Alias) {
112
+ symbol = tc.getAliasedSymbol(symbol);
113
+ const declaration = symbol.valueDeclaration;
114
+ if (declaration &&
115
+ (0, typescript_1.isSourceFile)(declaration) &&
116
+ declaration.fileName.endsWith('.json')) {
117
+ const statement = declaration.statements.at(0);
118
+ if (statement && (0, typescript_1.isExpressionStatement)(statement)) {
119
+ return this.childNodeParser.createType(statement.expression, context, reference);
120
+ }
121
+ }
122
+ }
123
+ return super.createType(node, context, reference);
124
+ }
125
+ }
99
126
  class TupleTypeParser {
100
127
  constructor(childNodeParser, allowUseFallbackDescription) {
101
128
  Object.defineProperty(this, "childNodeParser", {
@@ -118,7 +145,7 @@ class TupleTypeParser {
118
145
  const items = node.elements.map((element) => {
119
146
  const type = this.childNodeParser.createType(element, context);
120
147
  if ((0, typescript_1.isNamedTupleMember)(element)) {
121
- const description = (0, tsc_1.readJSDocDescription)(element, this.allowUseFallbackDescription);
148
+ const description = (0, helpers_tsc_1.readJSDocDescription)(element, this.allowUseFallbackDescription);
122
149
  const nullable = type instanceof ts_json_schema_generator_1.AnnotatedType ? type.isNullable() : false;
123
150
  return description ? new ts_json_schema_generator_1.AnnotatedType(type, { description }, nullable) : type;
124
151
  }
@@ -1,7 +1,8 @@
1
- import { CompilerHost, CompilerOptions, MethodSignature, NamedDeclaration, Node, PropertySignature, SignatureDeclarationBase } from 'typescript';
1
+ import { type CompilerHost, type CompilerOptions, type MethodSignature, type NamedDeclaration, type Node, type PropertySignature, type SignatureDeclarationBase } from 'typescript';
2
2
  export declare function readMemberTypeName(member: MethodSignature | PropertySignature | SignatureDeclarationBase): string | undefined;
3
3
  export declare function readJSDocDescription(node: Node, allowUseFallbackDescription: boolean | undefined, allowUseFallbackDescriptionFromParent?: boolean): string | undefined;
4
4
  export declare function readNodeName(node: NamedDeclaration): string;
5
5
  export declare function readInterfaceGenericText(node: NamedDeclaration): string;
6
6
  export declare function hasJSDocTag(statement: Node, tagName: string): boolean;
7
7
  export declare function resolveModuleFileName(containingFile: string, moduleName: string, compilerOptions: CompilerOptions, compilerHost: CompilerHost): string | undefined;
8
+ //# sourceMappingURL=helpers-tsc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers-tsc.d.ts","sourceRoot":"","sources":["../../src/schema-generator/helpers-tsc.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,YAAY,EACjB,KAAK,eAAe,EAGpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,IAAI,EACT,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAUhC,MAAM,YAAY,CAAC;AAEpB,wBAAgB,kBAAkB,CAC9B,MAAM,EAAE,eAAe,GAAG,iBAAiB,GAAG,wBAAwB,GACvE,MAAM,GAAG,SAAS,CAapB;AAED,wBAAgB,oBAAoB,CAChC,IAAI,EAAE,IAAI,EACV,2BAA2B,EAAE,OAAO,GAAG,SAAS,EAChD,qCAAqC,UAAO,GAC7C,MAAM,GAAG,SAAS,CAsCpB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAE3D;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAKvE;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAM3D;AAED,wBAAgB,qBAAqB,CACjC,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,eAAe,EAChC,YAAY,EAAE,YAAY,GAC3B,MAAM,GAAG,SAAS,CAQpB"}
@@ -0,0 +1,7 @@
1
+ import type { NonEmptyString } from '@tsofist/stem';
2
+ /**
3
+ * Shrink definition name by removing generic type parameters
4
+ * and appending a digest of the removed part.
5
+ */
6
+ export declare function shrinkDefinitionName(definitionName: string, suffixLength?: number): NonEmptyString | undefined;
7
+ //# sourceMappingURL=shrink-definition-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shrink-definition-name.d.ts","sourceRoot":"","sources":["../../src/schema-generator/shrink-definition-name.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;;GAGG;AACH,wBAAgB,oBAAoB,CAChC,cAAc,EAAE,MAAM,EACtB,YAAY,SAAI,GACjB,cAAc,GAAG,SAAS,CAc5B"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shrinkDefinitionName = shrinkDefinitionName;
4
+ const node_crypto_1 = require("node:crypto");
5
+ /**
6
+ * Shrink definition name by removing generic type parameters
7
+ * and appending a digest of the removed part.
8
+ */
9
+ function shrinkDefinitionName(definitionName, suffixLength = 8) {
10
+ const startPos = definitionName.indexOf('<');
11
+ if (startPos >= 0) {
12
+ const hashSource = definitionName.substring(startPos);
13
+ const prefix = definitionName.substring(0, startPos);
14
+ const digest = (0, node_crypto_1.createHash)('sha256')
15
+ .update(hashSource)
16
+ .digest('hex')
17
+ .substring(0, suffixLength);
18
+ return `${prefix}_H${digest}`;
19
+ }
20
+ return undefined;
21
+ }
@@ -0,0 +1,3 @@
1
+ import type { JSONSchema7Object } from 'json-schema';
2
+ export declare function sortSchemaProperties<T extends JSONSchema7Object>(schema: T): T;
3
+ //# sourceMappingURL=sort-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sort-properties.d.ts","sourceRoot":"","sources":["../../src/schema-generator/sort-properties.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,iBAAiB,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAyC9E"}
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sortProperties = sortProperties;
3
+ exports.sortSchemaProperties = sortSchemaProperties;
4
4
  const is_empty_1 = require("@tsofist/stem/lib/object/is-empty");
5
5
  const compare_1 = require("@tsofist/stem/lib/string/compare");
6
- function sortProperties(schema) {
6
+ function sortSchemaProperties(schema) {
7
7
  const stack = [];
8
8
  const isTarget = (target) => {
9
9
  return (target != null &&
@@ -0,0 +1,18 @@
1
+ export declare const TMP_FILES_SUFFIX = ".schema-forge.temporary-generated.tmp";
2
+ export declare const SFG_CONFIG_DEFAULTS: {
3
+ readonly sortProps: true;
4
+ readonly additionalProperties: false;
5
+ readonly expose: "export";
6
+ readonly strictTuples: true;
7
+ readonly extraTags: ["apiMember", "apiMethod", "apiInterface", "apiProperty", "dbColumn", "dbIndex", "dbEntity", "faker"];
8
+ readonly encodeRefs: false;
9
+ readonly markdownDescription: false;
10
+ readonly discriminatorType: undefined;
11
+ readonly functions: "hide";
12
+ };
13
+ export declare const SFG_CONFIG_MANDATORY: {
14
+ readonly jsDoc: "extended";
15
+ readonly topRef: true;
16
+ readonly skipTypeCheck: false;
17
+ };
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/schema-generator/types.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB,0CAA0C,CAAC;AAExE,eAAO,MAAM,mBAAmB;;;;;;;;;;CAsBL,CAAC;AAE5B,eAAO,MAAM,oBAAoB;;;;CAIN,CAAC"}