ts-runtime-validation 1.0.4 → 1.1.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.
- package/README.md +11 -6
- package/dist/SchemaGenerator.js +55 -60
- package/dist/SchemaGenerator.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/SchemaGenerator.ts +58 -66
- package/src/index.ts +4 -1
- package/tsconfig.json +2 -1
- package/.scripts/generate-validation-enum.js +0 -39
package/README.md
CHANGED
|
@@ -6,7 +6,11 @@ Get bulletproof type validation based off typescript interfaces without any extr
|
|
|
6
6
|
|
|
7
7
|
## How?
|
|
8
8
|
|
|
9
|
-
This is a code generator that is designed to run as a yarn / npm script. By default scans your source directory for files ending in the provided glob pattern. By default: `*.jsonschema.{ts,tsx}`.
|
|
9
|
+
This is a code generator that is designed to run as a yarn / npm script. By default scans your source directory for files ending in the provided glob pattern. By default: `*.jsonschema.{ts,tsx}`. The output will create three files:
|
|
10
|
+
|
|
11
|
+
1. `./src/ts-runtime-validation/validation.schema.json` - containing the [jsonschema](http://json-schema.org/) types
|
|
12
|
+
1. `./src/SchemaDefinition.ts` - containing the typescript.
|
|
13
|
+
1. `./src/isSchemaValid.ts` - containing a type guard type inferring helper method (intended for consumption in your code base - examples below)
|
|
10
14
|
|
|
11
15
|
## Footnote
|
|
12
16
|
|
|
@@ -20,11 +24,12 @@ Ensure your project files containing the schemas you want to validate end with t
|
|
|
20
24
|
Usage: ts-runtime-validation [options]
|
|
21
25
|
|
|
22
26
|
Options:
|
|
23
|
-
--glob
|
|
24
|
-
--rootPath
|
|
25
|
-
--output
|
|
26
|
-
--no-helpers
|
|
27
|
-
|
|
27
|
+
--glob Glob file path of typescript files to generate ts-interface -> json-schema validations - default: *.jsonschema.{ts,tsx}
|
|
28
|
+
--rootPath RootPath of source - default: ./src
|
|
29
|
+
--output Validation schema + typescript interface output directory (relative to root path) - default: ./.ts-runtime-validation
|
|
30
|
+
--no-helpers Only generate JSON schema without typescript helper files
|
|
31
|
+
--additionalProperties Allow additional properties to pass validation (default: false)
|
|
32
|
+
-h, --help display help for command
|
|
28
33
|
```
|
|
29
34
|
|
|
30
35
|
## Example usage of generated ts type validation
|
package/dist/SchemaGenerator.js
CHANGED
|
@@ -37,13 +37,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
exports.SchemaGenerator = void 0;
|
|
39
39
|
const fdir_1 = require("fdir");
|
|
40
|
-
const path_1 = require("path");
|
|
41
|
-
const TJS = __importStar(require("typescript-json-schema"));
|
|
42
40
|
const fs_1 = __importDefault(require("fs"));
|
|
43
41
|
const picomatch_1 = __importDefault(require("picomatch"));
|
|
44
|
-
const
|
|
42
|
+
const path_1 = __importDefault(require("path"));
|
|
45
43
|
const ts_morph_1 = require("ts-morph");
|
|
46
|
-
const
|
|
44
|
+
const tsj = __importStar(require("ts-json-schema-generator"));
|
|
45
|
+
const defaultTsMorphProjectSettings = {
|
|
47
46
|
manipulationSettings: {
|
|
48
47
|
indentationText: ts_morph_1.IndentationText.FourSpaces,
|
|
49
48
|
newLineKind: ts_morph_1.NewLineKind.LineFeed,
|
|
@@ -60,22 +59,30 @@ const schemaDefinitionFileName = "SchemaDefinition.ts";
|
|
|
60
59
|
class SchemaGenerator {
|
|
61
60
|
constructor(options) {
|
|
62
61
|
this.options = options;
|
|
63
|
-
this.outputPath =
|
|
64
|
-
this.jsonSchemaOutputFile =
|
|
65
|
-
this.tsSchemaDefinitionOutputFile =
|
|
66
|
-
this.isValidSchemaOutputFile =
|
|
67
|
-
this.
|
|
68
|
-
const { helpers } = this.options;
|
|
62
|
+
this.outputPath = path_1.default.join(this.options.rootPath, this.options.output);
|
|
63
|
+
this.jsonSchemaOutputFile = path_1.default.join(this.options.rootPath, this.options.output, validationSchemaFileName);
|
|
64
|
+
this.tsSchemaDefinitionOutputFile = path_1.default.join(this.options.rootPath, this.options.output, schemaDefinitionFileName);
|
|
65
|
+
this.isValidSchemaOutputFile = path_1.default.join(this.options.rootPath, this.options.output, "isSchemaValid.ts");
|
|
66
|
+
this.Generate = () => __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
const { helpers, glob } = this.options;
|
|
69
68
|
const fileList = yield this.getMatchingFiles();
|
|
70
69
|
console.log(`Found ${fileList.length} schema file(s)`);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
if (fileList.length === 0) {
|
|
71
|
+
console.log(`Aborting - no files found with glob: ${glob}`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const fileSchemas = yield this.getJsonSchemaMap(fileList);
|
|
75
|
+
console.log(`Generating ${fileSchemas.size} validation schema(s)`);
|
|
76
|
+
if (fileSchemas.size === 0) {
|
|
77
|
+
console.log(`Aborting - no interfaces found: ${glob}`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
this.writeSchemaMapToValidationSchema(fileSchemas);
|
|
74
81
|
if (helpers === false) {
|
|
75
82
|
console.log("Skipping helper file generation");
|
|
76
83
|
return;
|
|
77
84
|
}
|
|
78
|
-
yield this.writeSchemaMapToValidationTypes(
|
|
85
|
+
yield this.writeSchemaMapToValidationTypes(fileSchemas);
|
|
79
86
|
this.writeValidatorFunction();
|
|
80
87
|
});
|
|
81
88
|
this.getMatchingFiles = () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -92,33 +99,17 @@ class SchemaGenerator {
|
|
|
92
99
|
return api.withPromise();
|
|
93
100
|
});
|
|
94
101
|
this.getJsonSchemaMap = (filesList) => __awaiter(this, void 0, void 0, function* () {
|
|
95
|
-
|
|
102
|
+
const { additionalProperties } = this.options;
|
|
96
103
|
const schemaMap = new Map();
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
propOrder: true,
|
|
107
|
-
};
|
|
108
|
-
const compilerOptions = {
|
|
109
|
-
strictNullChecks: true,
|
|
110
|
-
};
|
|
111
|
-
const program = TJS.getProgramFromFiles(files, compilerOptions);
|
|
112
|
-
const generator = TJS.buildGenerator(program, settings);
|
|
113
|
-
const userDefinedSymbols = (_a = generator === null || generator === void 0 ? void 0 : generator.getMainFileSymbols(program)) !== null && _a !== void 0 ? _a : [];
|
|
114
|
-
userDefinedSymbols.forEach((symbol) => {
|
|
115
|
-
if (schemaMap.has(symbol)) {
|
|
116
|
-
throw new Error(`Duplicate symbol "${symbol}" found.`);
|
|
117
|
-
}
|
|
118
|
-
const schema = generator === null || generator === void 0 ? void 0 : generator.getSchemaForSymbol(symbol);
|
|
119
|
-
if (schema) {
|
|
120
|
-
schemaMap.set(symbol, schema);
|
|
121
|
-
}
|
|
104
|
+
filesList.forEach((file) => {
|
|
105
|
+
const config = {
|
|
106
|
+
path: file,
|
|
107
|
+
type: "*",
|
|
108
|
+
additionalProperties,
|
|
109
|
+
};
|
|
110
|
+
const schemaGenerator = tsj.createGenerator(config);
|
|
111
|
+
const fileSchemas = schemaGenerator.createSchema(config.type);
|
|
112
|
+
schemaMap.set(file, fileSchemas);
|
|
122
113
|
});
|
|
123
114
|
return schemaMap;
|
|
124
115
|
});
|
|
@@ -134,8 +125,16 @@ class SchemaGenerator {
|
|
|
134
125
|
};
|
|
135
126
|
this.writeSchemaMapToValidationSchema = (schemaMap) => {
|
|
136
127
|
const definitions = {};
|
|
137
|
-
schemaMap.forEach((
|
|
138
|
-
|
|
128
|
+
schemaMap.forEach((fileSchema) => {
|
|
129
|
+
var _a;
|
|
130
|
+
const defs = (_a = fileSchema.definitions) !== null && _a !== void 0 ? _a : {};
|
|
131
|
+
Object.keys(defs).forEach((key) => {
|
|
132
|
+
if (definitions[key] !== undefined) {
|
|
133
|
+
throw new Error(`Duplicate symbol: ${key} found`);
|
|
134
|
+
}
|
|
135
|
+
const schema = defs[key];
|
|
136
|
+
definitions[key] = schema;
|
|
137
|
+
});
|
|
139
138
|
});
|
|
140
139
|
const outputBuffer = {
|
|
141
140
|
$schema: this.getSchemaVersion(schemaMap),
|
|
@@ -144,26 +143,23 @@ class SchemaGenerator {
|
|
|
144
143
|
this.ensureOutputPathExists();
|
|
145
144
|
fs_1.default.writeFileSync(this.jsonSchemaOutputFile, JSON.stringify(outputBuffer, null, 4));
|
|
146
145
|
};
|
|
147
|
-
this.writeSchemaMapToValidationTypes = (schemaMap
|
|
148
|
-
const project = new ts_morph_1.Project(
|
|
149
|
-
const symbols =
|
|
150
|
-
return symbol !== "ISchema" && symbol !== "Schemas";
|
|
151
|
-
});
|
|
152
|
-
const readerProject = new ts_morph_1.Project();
|
|
153
|
-
readerProject.addSourceFilesAtPaths(fileList);
|
|
146
|
+
this.writeSchemaMapToValidationTypes = (schemaMap) => __awaiter(this, void 0, void 0, function* () {
|
|
147
|
+
const project = new ts_morph_1.Project(defaultTsMorphProjectSettings);
|
|
148
|
+
const symbols = [];
|
|
154
149
|
const importMap = new Map();
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
const
|
|
150
|
+
schemaMap.forEach((schema, filePath) => {
|
|
151
|
+
var _a;
|
|
152
|
+
const dir = path_1.default.dirname(filePath);
|
|
153
|
+
const fileWithoutExtension = path_1.default.parse(filePath).name;
|
|
154
|
+
const relativeFilePath = path_1.default.relative(this.outputPath, dir);
|
|
159
155
|
const importPath = `${relativeFilePath}/${fileWithoutExtension}`;
|
|
160
|
-
const
|
|
161
|
-
|
|
156
|
+
const defs = (_a = schema.definitions) !== null && _a !== void 0 ? _a : {};
|
|
157
|
+
Object.keys(defs).forEach((symbol) => {
|
|
162
158
|
var _a;
|
|
163
|
-
const structure = interfaceDeclaration.getStructure();
|
|
164
159
|
const namedImports = (_a = importMap.get(importPath)) !== null && _a !== void 0 ? _a : [];
|
|
165
|
-
namedImports.push(
|
|
160
|
+
namedImports.push(symbol);
|
|
166
161
|
importMap.set(importPath, namedImports);
|
|
162
|
+
symbols.push(symbol);
|
|
167
163
|
});
|
|
168
164
|
});
|
|
169
165
|
const sourceFile = project.createSourceFile(this.tsSchemaDefinitionOutputFile, {}, defaultCreateFileOptions);
|
|
@@ -200,13 +196,13 @@ class SchemaGenerator {
|
|
|
200
196
|
yield project.save();
|
|
201
197
|
});
|
|
202
198
|
this.writeValidatorFunction = () => __awaiter(this, void 0, void 0, function* () {
|
|
203
|
-
const project = new ts_morph_1.Project(
|
|
199
|
+
const project = new ts_morph_1.Project(defaultTsMorphProjectSettings);
|
|
204
200
|
const sourceFile = project.createSourceFile(this.isValidSchemaOutputFile, {}, defaultCreateFileOptions);
|
|
205
201
|
sourceFile.addImportDeclaration({ namespaceImport: "schema", moduleSpecifier: `./${validationSchemaFileName}` });
|
|
206
202
|
sourceFile.addImportDeclaration({ defaultImport: "Ajv", moduleSpecifier: "ajv" });
|
|
207
203
|
sourceFile.addImportDeclaration({
|
|
208
204
|
namedImports: ["ISchema", "schemas"],
|
|
209
|
-
moduleSpecifier: `./${
|
|
205
|
+
moduleSpecifier: `./${path_1.default.parse(schemaDefinitionFileName).name}`,
|
|
210
206
|
});
|
|
211
207
|
sourceFile.addVariableStatement({
|
|
212
208
|
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
|
|
@@ -239,7 +235,6 @@ class SchemaGenerator {
|
|
|
239
235
|
});
|
|
240
236
|
yield project.save();
|
|
241
237
|
});
|
|
242
|
-
this.generateOutput();
|
|
243
238
|
}
|
|
244
239
|
}
|
|
245
240
|
exports.SchemaGenerator = SchemaGenerator;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchemaGenerator.js","sourceRoot":"","sources":["../src/SchemaGenerator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+BAA4B;AAE5B
|
|
1
|
+
{"version":3,"file":"SchemaGenerator.js","sourceRoot":"","sources":["../src/SchemaGenerator.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,9 @@ commander_1.program.option("--glob", `Glob file path of typescript files to gene
|
|
|
10
10
|
commander_1.program.option("--rootPath", `RootPath of source - default: ${defaultRootPath}`, defaultRootPath);
|
|
11
11
|
commander_1.program.option("--output", `Validation schema + typescript interface output directory (relative to root path) - default: ${defaultOutputFolder}`, defaultOutputFolder);
|
|
12
12
|
commander_1.program.option("--no-helpers", "Only generate JSON schema without typescript helper files", true);
|
|
13
|
+
commander_1.program.option("--additionalProperties", "Allow additional properties to pass validation", false);
|
|
13
14
|
commander_1.program.parse();
|
|
14
15
|
const options = commander_1.program.opts();
|
|
15
|
-
new SchemaGenerator_1.SchemaGenerator(options);
|
|
16
|
+
const generator = new SchemaGenerator_1.SchemaGenerator(options);
|
|
17
|
+
generator.Generate();
|
|
16
18
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,uDAAoD;AACpD,yCAAoC;AAEpC,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AAEnD,MAAM,eAAe,GAAG,OAAO,CAAC;AAChC,MAAM,mBAAmB,GAAG,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,uDAAoD;AACpD,yCAAoC;AAEpC,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AAEnD,MAAM,eAAe,GAAG,OAAO,CAAC;AAChC,MAAM,mBAAmB,GAAG,0BAA0B,CAAC;AAUvD,mBAAO,CAAC,MAAM,CACV,QAAQ,EACR,qGAAqG,kBAAkB,EAAE,EACzH,kBAAkB,CACrB,CAAC;AACF,mBAAO,CAAC,MAAM,CAAC,YAAY,EAAE,iCAAiC,eAAe,EAAE,EAAE,eAAe,CAAC,CAAC;AAClG,mBAAO,CAAC,MAAM,CACV,UAAU,EACV,gGAAgG,mBAAmB,EAAE,EACrH,mBAAmB,CACtB,CAAC;AACF,mBAAO,CAAC,MAAM,CAAC,cAAc,EAAE,2DAA2D,EAAE,IAAI,CAAC,CAAC;AAClG,mBAAO,CAAC,MAAM,CAAC,wBAAwB,EAAE,gDAAgD,EAAE,KAAK,CAAC,CAAC;AAElG,mBAAO,CAAC,KAAK,EAAE,CAAC;AAEhB,MAAM,OAAO,GAAG,mBAAO,CAAC,IAAI,EAAmB,CAAC;AAEhD,MAAM,SAAS,GAAG,IAAI,iCAAe,CAAC,OAAO,CAAC,CAAC;AAC/C,SAAS,CAAC,QAAQ,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-runtime-validation",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"author": "Matthew Duong <thegalah@gmail.com>",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"commander": "^9.1.0",
|
|
8
8
|
"fdir": "^5.2.0",
|
|
9
9
|
"picomatch": "^2.3.1",
|
|
10
|
-
"ts-
|
|
11
|
-
"
|
|
10
|
+
"ts-json-schema-generator": "^1.0.0",
|
|
11
|
+
"ts-morph": "^14.0.0"
|
|
12
12
|
},
|
|
13
13
|
"bin": {
|
|
14
14
|
"ts-runtime-validation": "dist/index.js"
|
package/src/SchemaGenerator.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { fdir } from "fdir";
|
|
2
2
|
import { ICommandOptions } from "./index";
|
|
3
|
-
import { resolve } from "path";
|
|
4
|
-
import * as TJS from "typescript-json-schema";
|
|
5
3
|
import fs from "fs";
|
|
6
4
|
import picomatch from "picomatch";
|
|
7
5
|
import path from "path";
|
|
@@ -16,8 +14,10 @@ import {
|
|
|
16
14
|
ProjectOptions,
|
|
17
15
|
SourceFileCreateOptions,
|
|
18
16
|
} from "ts-morph";
|
|
17
|
+
import * as tsj from "ts-json-schema-generator";
|
|
18
|
+
import { Config, Schema } from "ts-json-schema-generator";
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const defaultTsMorphProjectSettings: ProjectOptions = {
|
|
21
21
|
manipulationSettings: {
|
|
22
22
|
indentationText: IndentationText.FourSpaces,
|
|
23
23
|
newLineKind: NewLineKind.LineFeed,
|
|
@@ -40,22 +40,29 @@ export class SchemaGenerator {
|
|
|
40
40
|
private tsSchemaDefinitionOutputFile = path.join(this.options.rootPath, this.options.output, schemaDefinitionFileName);
|
|
41
41
|
private isValidSchemaOutputFile = path.join(this.options.rootPath, this.options.output, "isSchemaValid.ts");
|
|
42
42
|
|
|
43
|
-
public constructor(private options: ICommandOptions) {
|
|
44
|
-
this.generateOutput();
|
|
45
|
-
}
|
|
43
|
+
public constructor(private options: ICommandOptions) {}
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
const { helpers } = this.options;
|
|
45
|
+
public Generate = async () => {
|
|
46
|
+
const { helpers, glob } = this.options;
|
|
49
47
|
const fileList = await this.getMatchingFiles();
|
|
48
|
+
|
|
50
49
|
console.log(`Found ${fileList.length} schema file(s)`);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
if (fileList.length === 0) {
|
|
51
|
+
console.log(`Aborting - no files found with glob: ${glob}`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const fileSchemas = await this.getJsonSchemaMap(fileList);
|
|
55
|
+
console.log(`Generating ${fileSchemas.size} validation schema(s)`);
|
|
56
|
+
if (fileSchemas.size === 0) {
|
|
57
|
+
console.log(`Aborting - no interfaces found: ${glob}`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
this.writeSchemaMapToValidationSchema(fileSchemas);
|
|
54
61
|
if (helpers === false) {
|
|
55
62
|
console.log("Skipping helper file generation");
|
|
56
63
|
return;
|
|
57
64
|
}
|
|
58
|
-
await this.writeSchemaMapToValidationTypes(
|
|
65
|
+
await this.writeSchemaMapToValidationTypes(fileSchemas);
|
|
59
66
|
this.writeValidatorFunction();
|
|
60
67
|
};
|
|
61
68
|
|
|
@@ -74,41 +81,23 @@ export class SchemaGenerator {
|
|
|
74
81
|
};
|
|
75
82
|
|
|
76
83
|
private getJsonSchemaMap = async (filesList: Array<string>) => {
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const compilerOptions: TJS.CompilerOptions = {
|
|
91
|
-
strictNullChecks: true,
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const program = TJS.getProgramFromFiles(files, compilerOptions);
|
|
95
|
-
|
|
96
|
-
const generator = TJS.buildGenerator(program, settings);
|
|
97
|
-
const userDefinedSymbols = generator?.getMainFileSymbols(program) ?? [];
|
|
98
|
-
userDefinedSymbols.forEach((symbol) => {
|
|
99
|
-
if (schemaMap.has(symbol)) {
|
|
100
|
-
throw new Error(`Duplicate symbol "${symbol}" found.`);
|
|
101
|
-
}
|
|
102
|
-
const schema = generator?.getSchemaForSymbol(symbol);
|
|
103
|
-
if (schema) {
|
|
104
|
-
schemaMap.set(symbol, schema);
|
|
105
|
-
}
|
|
84
|
+
const { additionalProperties } = this.options;
|
|
85
|
+
const schemaMap = new Map<string, Schema>();
|
|
86
|
+
filesList.forEach((file) => {
|
|
87
|
+
const config: Config = {
|
|
88
|
+
path: file,
|
|
89
|
+
type: "*",
|
|
90
|
+
additionalProperties,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const schemaGenerator = tsj.createGenerator(config);
|
|
94
|
+
const fileSchemas = schemaGenerator.createSchema(config.type);
|
|
95
|
+
schemaMap.set(file, fileSchemas);
|
|
106
96
|
});
|
|
107
|
-
|
|
108
97
|
return schemaMap;
|
|
109
98
|
};
|
|
110
99
|
|
|
111
|
-
private getSchemaVersion = (schemaMap: Map<string,
|
|
100
|
+
private getSchemaVersion = (schemaMap: Map<string, Schema>) => {
|
|
112
101
|
const firstEntry = schemaMap.values().next().value;
|
|
113
102
|
return firstEntry["$schema"] ?? "";
|
|
114
103
|
};
|
|
@@ -119,12 +108,20 @@ export class SchemaGenerator {
|
|
|
119
108
|
}
|
|
120
109
|
};
|
|
121
110
|
|
|
122
|
-
private writeSchemaMapToValidationSchema = (schemaMap: Map<string,
|
|
123
|
-
const definitions: { [id: string]:
|
|
124
|
-
schemaMap.forEach((
|
|
125
|
-
|
|
111
|
+
private writeSchemaMapToValidationSchema = (schemaMap: Map<string, Schema>) => {
|
|
112
|
+
const definitions: { [id: string]: Schema } = {};
|
|
113
|
+
schemaMap.forEach((fileSchema) => {
|
|
114
|
+
const defs = fileSchema.definitions ?? {};
|
|
115
|
+
|
|
116
|
+
Object.keys(defs).forEach((key) => {
|
|
117
|
+
if (definitions[key] !== undefined) {
|
|
118
|
+
throw new Error(`Duplicate symbol: ${key} found`);
|
|
119
|
+
}
|
|
120
|
+
const schema = defs[key] as Schema;
|
|
121
|
+
definitions[key] = schema;
|
|
122
|
+
});
|
|
126
123
|
});
|
|
127
|
-
const outputBuffer:
|
|
124
|
+
const outputBuffer: Schema = {
|
|
128
125
|
$schema: this.getSchemaVersion(schemaMap),
|
|
129
126
|
definitions,
|
|
130
127
|
};
|
|
@@ -133,32 +130,29 @@ export class SchemaGenerator {
|
|
|
133
130
|
fs.writeFileSync(this.jsonSchemaOutputFile, JSON.stringify(outputBuffer, null, 4));
|
|
134
131
|
};
|
|
135
132
|
|
|
136
|
-
private writeSchemaMapToValidationTypes = async (schemaMap: Map<string,
|
|
137
|
-
const project = new Project(
|
|
138
|
-
|
|
139
|
-
const symbols = Array.from(schemaMap.keys()).filter((symbol) => {
|
|
140
|
-
return symbol !== "ISchema" && symbol !== "Schemas";
|
|
141
|
-
});
|
|
133
|
+
private writeSchemaMapToValidationTypes = async (schemaMap: Map<string, Schema>) => {
|
|
134
|
+
const project = new Project(defaultTsMorphProjectSettings);
|
|
142
135
|
|
|
143
|
-
const
|
|
144
|
-
readerProject.addSourceFilesAtPaths(fileList);
|
|
136
|
+
const symbols: Array<string> = [];
|
|
145
137
|
|
|
146
138
|
const importMap = new Map<string, Array<string>>();
|
|
147
|
-
|
|
148
|
-
const dir = path.dirname(
|
|
149
|
-
const fileWithoutExtension = path.parse(
|
|
139
|
+
schemaMap.forEach((schema, filePath) => {
|
|
140
|
+
const dir = path.dirname(filePath);
|
|
141
|
+
const fileWithoutExtension = path.parse(filePath).name;
|
|
150
142
|
const relativeFilePath = path.relative(this.outputPath, dir);
|
|
151
143
|
const importPath = `${relativeFilePath}/${fileWithoutExtension}`;
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
144
|
+
const defs = schema.definitions ?? {};
|
|
145
|
+
|
|
146
|
+
Object.keys(defs).forEach((symbol) => {
|
|
155
147
|
const namedImports = importMap.get(importPath) ?? [];
|
|
156
|
-
namedImports.push(
|
|
148
|
+
namedImports.push(symbol);
|
|
157
149
|
importMap.set(importPath, namedImports);
|
|
150
|
+
symbols.push(symbol);
|
|
158
151
|
});
|
|
159
152
|
});
|
|
160
153
|
|
|
161
154
|
const sourceFile = project.createSourceFile(this.tsSchemaDefinitionOutputFile, {}, defaultCreateFileOptions);
|
|
155
|
+
|
|
162
156
|
importMap.forEach((namedImports, importPath) => {
|
|
163
157
|
sourceFile.addImportDeclaration({ namedImports, moduleSpecifier: importPath });
|
|
164
158
|
});
|
|
@@ -192,12 +186,11 @@ export class SchemaGenerator {
|
|
|
192
186
|
sourceFile.addExportDeclaration({
|
|
193
187
|
namedExports: ["schemas", "ISchema"],
|
|
194
188
|
});
|
|
195
|
-
|
|
196
189
|
await project.save();
|
|
197
190
|
};
|
|
198
191
|
|
|
199
192
|
private writeValidatorFunction = async () => {
|
|
200
|
-
const project = new Project(
|
|
193
|
+
const project = new Project(defaultTsMorphProjectSettings);
|
|
201
194
|
const sourceFile = project.createSourceFile(this.isValidSchemaOutputFile, {}, defaultCreateFileOptions);
|
|
202
195
|
sourceFile.addImportDeclaration({ namespaceImport: "schema", moduleSpecifier: `./${validationSchemaFileName}` });
|
|
203
196
|
sourceFile.addImportDeclaration({ defaultImport: "Ajv", moduleSpecifier: "ajv" });
|
|
@@ -205,7 +198,6 @@ export class SchemaGenerator {
|
|
|
205
198
|
namedImports: ["ISchema", "schemas"],
|
|
206
199
|
moduleSpecifier: `./${path.parse(schemaDefinitionFileName).name}`,
|
|
207
200
|
});
|
|
208
|
-
|
|
209
201
|
sourceFile.addVariableStatement({
|
|
210
202
|
declarationKind: VariableDeclarationKind.Const,
|
|
211
203
|
declarations: [
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ export interface ICommandOptions {
|
|
|
13
13
|
readonly rootPath: string;
|
|
14
14
|
readonly output: string;
|
|
15
15
|
readonly helpers: boolean;
|
|
16
|
+
readonly additionalProperties: boolean;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
program.option(
|
|
@@ -27,9 +28,11 @@ program.option(
|
|
|
27
28
|
defaultOutputFolder
|
|
28
29
|
);
|
|
29
30
|
program.option("--no-helpers", "Only generate JSON schema without typescript helper files", true);
|
|
31
|
+
program.option("--additionalProperties", "Allow additional properties to pass validation", false);
|
|
30
32
|
|
|
31
33
|
program.parse();
|
|
32
34
|
|
|
33
35
|
const options = program.opts<ICommandOptions>();
|
|
34
36
|
|
|
35
|
-
new SchemaGenerator(options);
|
|
37
|
+
const generator = new SchemaGenerator(options);
|
|
38
|
+
generator.Generate();
|
package/tsconfig.json
CHANGED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const schema = require("../src/validation.schema.json");
|
|
3
|
-
const OUTPUT_FILE = "./src/SchemaDefinition.ts";
|
|
4
|
-
|
|
5
|
-
const reservedDefinitionNameFilterFn = (definition) => {
|
|
6
|
-
return definition !== "ISchema" && definition !== "Schemas";
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
const definitions = Object.keys(schema.definitions).filter(reservedDefinitionNameFilterFn);
|
|
10
|
-
|
|
11
|
-
const lines = [];
|
|
12
|
-
lines.push(`// THIS IS AN AUTOGENERATED FILE PLEASE DO NOT MODIFY MANUALLY`);
|
|
13
|
-
|
|
14
|
-
lines.push(`import {${definitions.join(", ")}} from "./Types";`);
|
|
15
|
-
lines.push("");
|
|
16
|
-
|
|
17
|
-
lines.push(`export const schemas: Record<keyof ISchema, string> = {`);
|
|
18
|
-
definitions.forEach((definition) => {
|
|
19
|
-
lines.push(` ["#/definitions/${definition}"]: "${definition}",`);
|
|
20
|
-
});
|
|
21
|
-
lines.push(`}`);
|
|
22
|
-
|
|
23
|
-
lines.push("");
|
|
24
|
-
|
|
25
|
-
lines.push("export interface ISchema {");
|
|
26
|
-
|
|
27
|
-
definitions.forEach((definition) => {
|
|
28
|
-
lines.push(` ["#/definitions/${definition}"]: ${definition},`);
|
|
29
|
-
});
|
|
30
|
-
lines.push("}");
|
|
31
|
-
lines.push("");
|
|
32
|
-
|
|
33
|
-
const output = lines.join("\n");
|
|
34
|
-
|
|
35
|
-
fs.writeFile(OUTPUT_FILE, output, { flag: "w" }, function (err) {
|
|
36
|
-
if (err) {
|
|
37
|
-
return console.log(err);
|
|
38
|
-
}
|
|
39
|
-
});
|