ts-runtime-validation 1.6.16 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +9 -0
- package/CONTRIBUTING.md +430 -0
- package/README.md +444 -64
- package/dist/ICommandOptions.js +3 -0
- package/dist/ICommandOptions.js.map +1 -0
- package/dist/SchemaGenerator.integration.test.js +323 -0
- package/dist/SchemaGenerator.integration.test.js.map +1 -0
- package/dist/SchemaGenerator.js +120 -0
- package/dist/SchemaGenerator.js.map +1 -0
- package/dist/SchemaGenerator.test.js +132 -0
- package/dist/SchemaGenerator.test.js.map +1 -0
- package/dist/errors/index.js +95 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/index.test.js +232 -0
- package/dist/errors/index.test.js.map +1 -0
- package/dist/getPosixPath.js +13 -0
- package/dist/getPosixPath.js.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.js.map +1 -0
- package/dist/services/CodeGenerator.js +305 -0
- package/dist/services/CodeGenerator.js.map +1 -0
- package/dist/services/FileDiscovery.js +121 -0
- package/dist/services/FileDiscovery.js.map +1 -0
- package/dist/services/FileDiscovery.test.js +184 -0
- package/dist/services/FileDiscovery.test.js.map +1 -0
- package/dist/services/SchemaProcessor.js +182 -0
- package/dist/services/SchemaProcessor.js.map +1 -0
- package/dist/services/SchemaProcessor.test.js +395 -0
- package/dist/services/SchemaProcessor.test.js.map +1 -0
- package/dist/services/SchemaWriter.js +76 -0
- package/dist/services/SchemaWriter.js.map +1 -0
- package/dist/services/SchemaWriter.test.js +255 -0
- package/dist/services/SchemaWriter.test.js.map +1 -0
- package/dist/test/basic-scenario/types.jsonschema.js +3 -0
- package/dist/test/basic-scenario/types.jsonschema.js.map +1 -0
- package/dist/test/duplicate-symbols-different-implementation/IBaseType.js +3 -0
- package/dist/test/duplicate-symbols-different-implementation/IBaseType.js.map +1 -0
- package/dist/test/duplicate-symbols-different-implementation/IBaseTypeDefinitionReplicated.js +3 -0
- package/dist/test/duplicate-symbols-different-implementation/IBaseTypeDefinitionReplicated.js.map +1 -0
- package/dist/test/duplicate-symbols-different-implementation/IBasicTypesA.jsonschema.js +3 -0
- package/dist/test/duplicate-symbols-different-implementation/IBasicTypesA.jsonschema.js.map +1 -0
- package/dist/test/duplicate-symbols-different-implementation/IBasicTypesB.jsonschema.js +3 -0
- package/dist/test/duplicate-symbols-different-implementation/IBasicTypesB.jsonschema.js.map +1 -0
- package/dist/test/duplicate-symbols-identitcal-implementation/IBaseType.js +3 -0
- package/dist/test/duplicate-symbols-identitcal-implementation/IBaseType.js.map +1 -0
- package/dist/test/duplicate-symbols-identitcal-implementation/IBaseTypeDefinitionReplicated.js +3 -0
- package/dist/test/duplicate-symbols-identitcal-implementation/IBaseTypeDefinitionReplicated.js.map +1 -0
- package/dist/test/duplicate-symbols-identitcal-implementation/IBasicTypesA.jsonschema.js +3 -0
- package/dist/test/duplicate-symbols-identitcal-implementation/IBasicTypesA.jsonschema.js.map +1 -0
- package/dist/test/duplicate-symbols-identitcal-implementation/IBasicTypesB.jsonschema.js +3 -0
- package/dist/test/duplicate-symbols-identitcal-implementation/IBasicTypesB.jsonschema.js.map +1 -0
- package/dist/test/output/duplicate-symbols-identitcal-implementation/ValidationType.js +3 -0
- package/dist/test/output/duplicate-symbols-identitcal-implementation/ValidationType.js.map +1 -0
- package/dist/test/output/duplicate-symbols-identitcal-implementation/isValidSchema.js +49 -0
- package/dist/test/output/duplicate-symbols-identitcal-implementation/isValidSchema.js.map +1 -0
- package/dist/utils/ProgressReporter.js +67 -0
- package/dist/utils/ProgressReporter.js.map +1 -0
- package/dist/utils/ProgressReporter.test.js +267 -0
- package/dist/utils/ProgressReporter.test.js.map +1 -0
- package/dist/writeLine.js +12 -0
- package/dist/writeLine.js.map +1 -0
- package/package.json +2 -2
- package/src/ICommandOptions.ts +7 -0
- package/src/SchemaGenerator.integration.test.ts +411 -0
- package/src/SchemaGenerator.test.ts +7 -0
- package/src/SchemaGenerator.ts +112 -298
- package/src/errors/index.test.ts +319 -0
- package/src/errors/index.ts +92 -0
- package/src/index.ts +7 -0
- package/src/services/CodeGenerator.ts +352 -0
- package/src/services/FileDiscovery.test.ts +216 -0
- package/src/services/FileDiscovery.ts +137 -0
- package/src/services/SchemaProcessor.test.ts +464 -0
- package/src/services/SchemaProcessor.ts +173 -0
- package/src/services/SchemaWriter.test.ts +304 -0
- package/src/services/SchemaWriter.ts +75 -0
- package/src/utils/ProgressReporter.test.ts +357 -0
- package/src/utils/ProgressReporter.ts +76 -0
package/src/SchemaGenerator.ts
CHANGED
|
@@ -1,316 +1,130 @@
|
|
|
1
|
-
import { fdir } from "fdir";
|
|
2
1
|
import { ICommandOptions } from "./ICommandOptions";
|
|
3
|
-
import fs from "fs";
|
|
4
|
-
import picomatch from "picomatch";
|
|
5
2
|
import path from "path";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
VariableDeclarationKind,
|
|
13
|
-
CodeBlockWriter,
|
|
14
|
-
ProjectOptions,
|
|
15
|
-
SourceFileCreateOptions,
|
|
16
|
-
} from "ts-morph";
|
|
17
|
-
import * as tsj from "ts-json-schema-generator";
|
|
18
|
-
import { Config, Schema } from "ts-json-schema-generator";
|
|
19
|
-
import assert from "assert";
|
|
20
|
-
import { writeLine } from "./writeLine";
|
|
21
|
-
import { getPosixPath } from "./getPosixPath";
|
|
22
|
-
|
|
23
|
-
const defaultTsMorphProjectSettings: ProjectOptions = {
|
|
24
|
-
manipulationSettings: {
|
|
25
|
-
indentationText: IndentationText.FourSpaces,
|
|
26
|
-
newLineKind: NewLineKind.LineFeed,
|
|
27
|
-
quoteKind: QuoteKind.Double,
|
|
28
|
-
usePrefixAndSuffixTextForRename: false,
|
|
29
|
-
useTrailingCommas: true,
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const defaultCreateFileOptions: SourceFileCreateOptions = {
|
|
34
|
-
overwrite: true,
|
|
35
|
-
};
|
|
3
|
+
import { FileDiscovery } from "./services/FileDiscovery";
|
|
4
|
+
import { SchemaProcessor } from "./services/SchemaProcessor";
|
|
5
|
+
import { CodeGenerator } from "./services/CodeGenerator";
|
|
6
|
+
import { SchemaWriter } from "./services/SchemaWriter";
|
|
7
|
+
import { ProgressReporter } from "./utils/ProgressReporter";
|
|
8
|
+
import { formatError, isKnownError } from "./errors";
|
|
36
9
|
|
|
37
10
|
const validationSchemaFileName = "validation.schema.json";
|
|
38
11
|
const schemaDefinitionFileName = "SchemaDefinition.ts";
|
|
39
12
|
const validationInterfacesFile = "ValidationType.ts";
|
|
13
|
+
const isValidSchemaFileName = "isValidSchema.ts";
|
|
40
14
|
|
|
41
15
|
export class SchemaGenerator {
|
|
42
16
|
private outputPath = path.join(this.options.rootPath, this.options.output);
|
|
43
|
-
private jsonSchemaOutputFile = path.join(this.
|
|
44
|
-
private tsSchemaDefinitionOutputFile = path.join(this.
|
|
45
|
-
private validationTypesOutputFile = path.join(this.
|
|
46
|
-
private isValidSchemaOutputFile = path.join(this.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (fileSchemas.size === 0) {
|
|
62
|
-
writeLine(`Aborting - no types found: ${glob}`);
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
this.writeSchemaMapToValidationSchema(fileSchemas);
|
|
66
|
-
if (helpers === false) {
|
|
67
|
-
writeLine("Skipping helper file generation");
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
await this.writeSchemaMapToValidationTypes(fileSchemas);
|
|
71
|
-
this.writeValidatorFunction();
|
|
72
|
-
writeLine("Writing validation types file");
|
|
73
|
-
this.writeValidationTypes(fileSchemas);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
private getMatchingFiles = async () => {
|
|
77
|
-
const { glob, rootPath } = this.options;
|
|
78
|
-
const api = new fdir({
|
|
79
|
-
includeBasePath: true,
|
|
80
|
-
includeDirs: false,
|
|
81
|
-
filters: [
|
|
82
|
-
(path) => {
|
|
83
|
-
return picomatch.isMatch(path, glob, { contains: true });
|
|
84
|
-
},
|
|
85
|
-
],
|
|
86
|
-
}).crawl(rootPath);
|
|
87
|
-
return api.withPromise();
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
private getJsonSchemasForFiles = async (filesList: Array<string>) => {
|
|
91
|
-
const { additionalProperties, tsconfigPath } = this.options;
|
|
92
|
-
const schemaMap = new Map<string, Schema>();
|
|
93
|
-
const tsconfig = tsconfigPath.length > 0 ? tsconfigPath : undefined;
|
|
94
|
-
filesList.forEach((file, index) => {
|
|
95
|
-
writeLine(`\rProcessing file ${index + 1} of ${filesList.length}: ${file}`);
|
|
96
|
-
const config: Config = {
|
|
97
|
-
path: file,
|
|
98
|
-
type: "*",
|
|
99
|
-
additionalProperties,
|
|
100
|
-
encodeRefs: false,
|
|
101
|
-
sortProps: true,
|
|
102
|
-
...(tsconfig !== null ? { tsconfig } : {}),
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
const schemaGenerator = tsj.createGenerator(config);
|
|
106
|
-
const fileSchemas = schemaGenerator.createSchema(config.type);
|
|
107
|
-
schemaMap.set(file, fileSchemas);
|
|
108
|
-
});
|
|
109
|
-
return schemaMap;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
private getSchemaVersion = (schemaMap: Map<string, Schema>) => {
|
|
113
|
-
const firstEntry = schemaMap.values().next().value;
|
|
114
|
-
return firstEntry?.["$schema"] ?? "";
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
private ensureOutputPathExists = () => {
|
|
118
|
-
if (!fs.existsSync(this.outputPath)) {
|
|
119
|
-
fs.mkdirSync(this.outputPath, { recursive: true });
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
private writeSchemaMapToValidationSchema = (schemaMap: Map<string, Schema>) => {
|
|
124
|
-
const definitions: { [id: string]: Schema } = {};
|
|
125
|
-
schemaMap.forEach((fileSchema) => {
|
|
126
|
-
const defs = fileSchema.definitions ?? {};
|
|
127
|
-
|
|
128
|
-
Object.keys(defs).forEach((key) => {
|
|
129
|
-
if (definitions[key] !== undefined) {
|
|
130
|
-
try {
|
|
131
|
-
assert.deepEqual(definitions[key], defs[key]);
|
|
132
|
-
} catch (e) {
|
|
133
|
-
console.error(
|
|
134
|
-
`Duplicate symbol: ${key} found with varying definitions.\nDefinition 1:\n${JSON.stringify(
|
|
135
|
-
definitions[key],
|
|
136
|
-
null,
|
|
137
|
-
4
|
|
138
|
-
)}\nDefinition 2:\n${JSON.stringify(defs[key], null, 4)}`
|
|
139
|
-
);
|
|
140
|
-
throw e;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
const schema = defs[key] as Schema;
|
|
144
|
-
definitions[key] = schema;
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
const outputBuffer: Schema = {
|
|
148
|
-
$schema: this.getSchemaVersion(schemaMap),
|
|
149
|
-
definitions,
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
this.ensureOutputPathExists();
|
|
153
|
-
fs.writeFileSync(this.jsonSchemaOutputFile, JSON.stringify(outputBuffer, null, 4));
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
private writeSchemaMapToValidationTypes = async (schemaMap: Map<string, Schema>) => {
|
|
157
|
-
const project = new Project(defaultTsMorphProjectSettings);
|
|
158
|
-
const readerProject = new Project(defaultTsMorphProjectSettings);
|
|
159
|
-
|
|
160
|
-
const symbols: Array<string> = [];
|
|
161
|
-
|
|
162
|
-
const importMap = new Map<string, Array<string>>();
|
|
163
|
-
schemaMap.forEach((schema, filePath) => {
|
|
164
|
-
const dir = path.dirname(filePath);
|
|
165
|
-
const fileWithoutExtension = path.parse(filePath).name;
|
|
166
|
-
const relativeFilePath = path.relative(this.outputPath, dir);
|
|
167
|
-
const relativeImportPath = `${relativeFilePath}/${fileWithoutExtension}`;
|
|
168
|
-
const defs = schema.definitions ?? {};
|
|
169
|
-
|
|
170
|
-
const readerSourceFile = readerProject.addSourceFileAtPath(filePath);
|
|
171
|
-
|
|
172
|
-
Object.keys(defs).forEach((symbol) => {
|
|
173
|
-
const typeAlias = readerSourceFile.getTypeAlias(symbol);
|
|
174
|
-
const typeInterface = readerSourceFile.getInterface(symbol);
|
|
175
|
-
const hasTypeOrInterface = (typeAlias ?? typeInterface) !== undefined;
|
|
176
|
-
if (hasTypeOrInterface) {
|
|
177
|
-
const namedImports = importMap.get(relativeImportPath) ?? [];
|
|
178
|
-
namedImports.push(symbol);
|
|
179
|
-
importMap.set(relativeImportPath, namedImports);
|
|
180
|
-
symbols.push(symbol);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
const sourceFile = project.createSourceFile(this.tsSchemaDefinitionOutputFile, {}, defaultCreateFileOptions);
|
|
186
|
-
|
|
187
|
-
importMap.forEach((namedImports, importPath) => {
|
|
188
|
-
sourceFile.addImportDeclaration({ namedImports, moduleSpecifier: getPosixPath(importPath) });
|
|
17
|
+
private jsonSchemaOutputFile = path.join(this.outputPath, validationSchemaFileName);
|
|
18
|
+
private tsSchemaDefinitionOutputFile = path.join(this.outputPath, schemaDefinitionFileName);
|
|
19
|
+
private validationTypesOutputFile = path.join(this.outputPath, validationInterfacesFile);
|
|
20
|
+
private isValidSchemaOutputFile = path.join(this.outputPath, isValidSchemaFileName);
|
|
21
|
+
|
|
22
|
+
private fileDiscovery: FileDiscovery;
|
|
23
|
+
private schemaProcessor: SchemaProcessor;
|
|
24
|
+
private codeGenerator: CodeGenerator;
|
|
25
|
+
private schemaWriter: SchemaWriter;
|
|
26
|
+
private progressReporter: ProgressReporter;
|
|
27
|
+
|
|
28
|
+
public constructor(private options: ICommandOptions) {
|
|
29
|
+
this.fileDiscovery = new FileDiscovery({
|
|
30
|
+
glob: options.glob,
|
|
31
|
+
rootPath: options.rootPath,
|
|
32
|
+
cacheEnabled: options.cache || false,
|
|
33
|
+
cachePath: path.join(options.rootPath, ".ts-runtime-validation-cache")
|
|
189
34
|
});
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
name: "schemas",
|
|
197
|
-
type: "Record<keyof ISchema, string>",
|
|
198
|
-
initializer: (writer: CodeBlockWriter) => {
|
|
199
|
-
writer.writeLine(`{`);
|
|
200
|
-
symbols.forEach((symbol) => {
|
|
201
|
-
writer.writeLine(`["#/definitions/${symbol}"] : "${symbol}",`);
|
|
202
|
-
}),
|
|
203
|
-
writer.writeLine(`}`);
|
|
204
|
-
},
|
|
205
|
-
},
|
|
206
|
-
],
|
|
35
|
+
|
|
36
|
+
this.schemaProcessor = new SchemaProcessor({
|
|
37
|
+
additionalProperties: options.additionalProperties,
|
|
38
|
+
tsconfigPath: options.tsconfigPath || undefined,
|
|
39
|
+
parallel: options.parallel !== false,
|
|
40
|
+
verbose: options.verbose || false
|
|
207
41
|
});
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
return { name: `readonly ["#/definitions/${symbol}"]`, type: symbol };
|
|
215
|
-
}),
|
|
42
|
+
|
|
43
|
+
this.codeGenerator = new CodeGenerator({
|
|
44
|
+
outputPath: this.outputPath,
|
|
45
|
+
minify: options.minify || false,
|
|
46
|
+
treeShaking: options.treeShaking || false,
|
|
47
|
+
lazyLoad: options.lazyLoad || false
|
|
216
48
|
});
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
private writeValidatorFunction = async () => {
|
|
222
|
-
const project = new Project(defaultTsMorphProjectSettings);
|
|
223
|
-
const sourceFile = project.createSourceFile(this.isValidSchemaOutputFile, {}, defaultCreateFileOptions);
|
|
224
|
-
sourceFile.addImportDeclaration({ namespaceImport: "schema", moduleSpecifier: `./${validationSchemaFileName}` });
|
|
225
|
-
sourceFile.addImportDeclaration({ defaultImport: "Ajv", moduleSpecifier: "ajv" });
|
|
226
|
-
sourceFile.addImportDeclaration({
|
|
227
|
-
namedImports: ["ISchema", "schemas"],
|
|
228
|
-
moduleSpecifier: `./${path.parse(schemaDefinitionFileName).name}`,
|
|
49
|
+
|
|
50
|
+
this.schemaWriter = new SchemaWriter({
|
|
51
|
+
outputPath: this.outputPath,
|
|
52
|
+
minify: options.minify || false
|
|
229
53
|
});
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
{
|
|
235
|
-
name: "validator",
|
|
236
|
-
initializer: (writer: CodeBlockWriter) => {
|
|
237
|
-
writer.writeLine(`new Ajv({ allErrors: true });`);
|
|
238
|
-
writer.writeLine(`validator.compile(schema)`);
|
|
239
|
-
},
|
|
240
|
-
},
|
|
241
|
-
],
|
|
54
|
+
|
|
55
|
+
this.progressReporter = new ProgressReporter({
|
|
56
|
+
enabled: options.progress || false,
|
|
57
|
+
showBar: true
|
|
242
58
|
});
|
|
59
|
+
}
|
|
243
60
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
61
|
+
public Generate = async () => {
|
|
62
|
+
try {
|
|
63
|
+
this.progressReporter.start("Starting schema generation...");
|
|
64
|
+
|
|
65
|
+
const { helpers } = this.options;
|
|
66
|
+
|
|
67
|
+
// Discover files
|
|
68
|
+
this.progressReporter.update(0, "Discovering files...");
|
|
69
|
+
const files = await this.fileDiscovery.discoverFiles();
|
|
70
|
+
|
|
71
|
+
if (this.options.verbose) {
|
|
72
|
+
console.log(`Found ${files.length} schema file(s)`);
|
|
73
|
+
files.forEach(file => console.log(` - ${file.path}`));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Process schemas
|
|
77
|
+
this.progressReporter.update(1, "Processing TypeScript files...");
|
|
78
|
+
this.progressReporter.options.total = files.length + 4; // files + 4 generation steps
|
|
79
|
+
|
|
80
|
+
const schemaMap = await this.schemaProcessor.processFiles(files);
|
|
81
|
+
|
|
82
|
+
if (schemaMap.size === 0) {
|
|
83
|
+
console.log("No types found to generate schemas for");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Validate schema compatibility
|
|
88
|
+
this.progressReporter.update(files.length + 1, "Validating schema compatibility...");
|
|
89
|
+
this.schemaProcessor.validateSchemaCompatibility(schemaMap);
|
|
90
|
+
|
|
91
|
+
// Merge and write JSON schema
|
|
92
|
+
this.progressReporter.update(files.length + 2, "Writing JSON schema...");
|
|
93
|
+
const mergedSchema = this.schemaProcessor.mergeSchemas(schemaMap);
|
|
94
|
+
await this.schemaWriter.writeJsonSchema(mergedSchema, this.jsonSchemaOutputFile);
|
|
95
|
+
|
|
96
|
+
if (helpers === false) {
|
|
97
|
+
this.progressReporter.complete("Schema generation completed (helpers skipped)");
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Generate TypeScript helpers
|
|
102
|
+
this.progressReporter.update(files.length + 3, "Generating TypeScript helpers...");
|
|
103
|
+
await Promise.all([
|
|
104
|
+
this.codeGenerator.generateSchemaDefinition(schemaMap, this.tsSchemaDefinitionOutputFile),
|
|
105
|
+
this.codeGenerator.generateValidatorFunction(this.isValidSchemaOutputFile),
|
|
106
|
+
this.codeGenerator.generateValidationTypes(schemaMap, this.validationTypesOutputFile)
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
this.progressReporter.complete("Schema generation completed successfully");
|
|
110
|
+
|
|
111
|
+
} catch (error) {
|
|
112
|
+
const formattedError = formatError(error, this.options.verbose || false);
|
|
113
|
+
console.error(`Schema generation failed: ${formattedError}`);
|
|
114
|
+
|
|
115
|
+
if (!isKnownError(error) && this.options.verbose) {
|
|
116
|
+
console.error(error);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
260
121
|
};
|
|
261
122
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
schemaMap.forEach((schema, filePath) => {
|
|
270
|
-
const dir = path.dirname(filePath);
|
|
271
|
-
const fileWithoutExtension = path.parse(filePath).name;
|
|
272
|
-
const relativeFilePath = path.relative(this.outputPath, dir);
|
|
273
|
-
const relativeImportPath = `${relativeFilePath}/${fileWithoutExtension}`;
|
|
274
|
-
const defs = schema.definitions ?? {};
|
|
275
|
-
|
|
276
|
-
const readerSourceFile = readerProject.addSourceFileAtPath(filePath);
|
|
277
|
-
|
|
278
|
-
Object.keys(defs).forEach((symbol) => {
|
|
279
|
-
const typeAlias = readerSourceFile.getTypeAlias(symbol);
|
|
280
|
-
const typeInterface = readerSourceFile.getInterface(symbol);
|
|
281
|
-
const hasTypeOrInterface = (typeAlias ?? typeInterface) !== undefined;
|
|
282
|
-
if (hasTypeOrInterface) {
|
|
283
|
-
const namedImports = importMap.get(relativeImportPath) ?? [];
|
|
284
|
-
namedImports.push(symbol);
|
|
285
|
-
importMap.set(relativeImportPath, namedImports);
|
|
286
|
-
symbols.push(symbol);
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
const sourceFile = project.createSourceFile(this.validationTypesOutputFile, {}, defaultCreateFileOptions);
|
|
292
|
-
|
|
293
|
-
importMap.forEach((namedImports, importPath) => {
|
|
294
|
-
const declaration = sourceFile.addImportDeclaration({ moduleSpecifier: getPosixPath(importPath) });
|
|
295
|
-
namedImports.forEach((namedImport) => {
|
|
296
|
-
const name = namedImport.valueOf();
|
|
297
|
-
const alias = `_${name}`;
|
|
298
|
-
declaration.addNamedImport({ name, alias });
|
|
299
|
-
});
|
|
300
|
-
});
|
|
301
|
-
const namespace = sourceFile.addModule({
|
|
302
|
-
name: "ValidationType",
|
|
303
|
-
isExported: true,
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
importMap.forEach((namedImports) => {
|
|
307
|
-
namedImports.forEach((namedImport) => {
|
|
308
|
-
const name = namedImport.valueOf();
|
|
309
|
-
const alias = `_${name}`;
|
|
310
|
-
namespace.addTypeAlias({ name, type: alias, isExported: true });
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
await project.save();
|
|
315
|
-
};
|
|
123
|
+
public clearCache(): void {
|
|
124
|
+
this.fileDiscovery.clearCache();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public async cleanOutput(): Promise<void> {
|
|
128
|
+
await this.schemaWriter.cleanOutputDirectory();
|
|
129
|
+
}
|
|
316
130
|
}
|