ts-runtime-validation 1.0.2 → 1.0.5
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 +5 -1
- package/dist/SchemaGenerator.js +253 -0
- package/dist/SchemaGenerator.js.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/package.json +1 -1
- package/src/SchemaGenerator.ts +12 -5
- package/src/index.ts +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
|
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.SchemaGenerator = void 0;
|
|
39
|
+
const fdir_1 = require("fdir");
|
|
40
|
+
const path_1 = require("path");
|
|
41
|
+
const TJS = __importStar(require("typescript-json-schema"));
|
|
42
|
+
const fs_1 = __importDefault(require("fs"));
|
|
43
|
+
const picomatch_1 = __importDefault(require("picomatch"));
|
|
44
|
+
const path_2 = __importDefault(require("path"));
|
|
45
|
+
const ts_morph_1 = require("ts-morph");
|
|
46
|
+
const defaultProjectSettings = {
|
|
47
|
+
manipulationSettings: {
|
|
48
|
+
indentationText: ts_morph_1.IndentationText.FourSpaces,
|
|
49
|
+
newLineKind: ts_morph_1.NewLineKind.LineFeed,
|
|
50
|
+
quoteKind: ts_morph_1.QuoteKind.Double,
|
|
51
|
+
usePrefixAndSuffixTextForRename: false,
|
|
52
|
+
useTrailingCommas: true,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
const defaultCreateFileOptions = {
|
|
56
|
+
overwrite: true,
|
|
57
|
+
};
|
|
58
|
+
const validationSchemaFileName = "validation.schema.json";
|
|
59
|
+
const schemaDefinitionFileName = "SchemaDefinition.ts";
|
|
60
|
+
class SchemaGenerator {
|
|
61
|
+
constructor(options) {
|
|
62
|
+
this.options = options;
|
|
63
|
+
this.outputPath = path_2.default.join(this.options.rootPath, this.options.output);
|
|
64
|
+
this.jsonSchemaOutputFile = path_2.default.join(this.options.rootPath, this.options.output, validationSchemaFileName);
|
|
65
|
+
this.tsSchemaDefinitionOutputFile = path_2.default.join(this.options.rootPath, this.options.output, schemaDefinitionFileName);
|
|
66
|
+
this.isValidSchemaOutputFile = path_2.default.join(this.options.rootPath, this.options.output, "isSchemaValid.ts");
|
|
67
|
+
this.Generate = () => __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
const { helpers, glob } = this.options;
|
|
69
|
+
const fileList = yield this.getMatchingFiles();
|
|
70
|
+
console.log(`Found ${fileList.length} schema file(s)`);
|
|
71
|
+
if (fileList.length === 0) {
|
|
72
|
+
console.log(`Aborting - no files found with glob: ${glob}`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const map = yield this.getJsonSchemaMap(fileList);
|
|
76
|
+
console.log(`Generating ${map.size} validation schema(s)`);
|
|
77
|
+
if (map.size === 0) {
|
|
78
|
+
console.log(`Aborting - no interfaces found: ${glob}`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
this.writeSchemaMapToValidationSchema(map);
|
|
82
|
+
if (helpers === false) {
|
|
83
|
+
console.log("Skipping helper file generation");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
yield this.writeSchemaMapToValidationTypes(map, fileList);
|
|
87
|
+
this.writeValidatorFunction();
|
|
88
|
+
});
|
|
89
|
+
this.getMatchingFiles = () => __awaiter(this, void 0, void 0, function* () {
|
|
90
|
+
const { glob, rootPath } = this.options;
|
|
91
|
+
const api = new fdir_1.fdir().crawlWithOptions(rootPath, {
|
|
92
|
+
includeBasePath: true,
|
|
93
|
+
includeDirs: false,
|
|
94
|
+
filters: [
|
|
95
|
+
(path) => {
|
|
96
|
+
return picomatch_1.default.isMatch(path, glob, { contains: true });
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
});
|
|
100
|
+
return api.withPromise();
|
|
101
|
+
});
|
|
102
|
+
this.getJsonSchemaMap = (filesList) => __awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
var _a;
|
|
104
|
+
const schemaMap = new Map();
|
|
105
|
+
const files = filesList.map((fileName) => {
|
|
106
|
+
return (0, path_1.resolve)(fileName);
|
|
107
|
+
});
|
|
108
|
+
const settings = {
|
|
109
|
+
required: true,
|
|
110
|
+
titles: true,
|
|
111
|
+
aliasRef: true,
|
|
112
|
+
ref: true,
|
|
113
|
+
noExtraProps: true,
|
|
114
|
+
propOrder: true,
|
|
115
|
+
};
|
|
116
|
+
const compilerOptions = {
|
|
117
|
+
strictNullChecks: true,
|
|
118
|
+
};
|
|
119
|
+
const program = TJS.getProgramFromFiles(files, compilerOptions);
|
|
120
|
+
const generator = TJS.buildGenerator(program, settings);
|
|
121
|
+
const userDefinedSymbols = (_a = generator === null || generator === void 0 ? void 0 : generator.getMainFileSymbols(program)) !== null && _a !== void 0 ? _a : [];
|
|
122
|
+
userDefinedSymbols.forEach((symbol) => {
|
|
123
|
+
if (schemaMap.has(symbol)) {
|
|
124
|
+
throw new Error(`Duplicate symbol "${symbol}" found.`);
|
|
125
|
+
}
|
|
126
|
+
const schema = generator === null || generator === void 0 ? void 0 : generator.getSchemaForSymbol(symbol);
|
|
127
|
+
if (schema) {
|
|
128
|
+
schemaMap.set(symbol, schema);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return schemaMap;
|
|
132
|
+
});
|
|
133
|
+
this.getSchemaVersion = (schemaMap) => {
|
|
134
|
+
var _a;
|
|
135
|
+
const firstEntry = schemaMap.values().next().value;
|
|
136
|
+
return (_a = firstEntry["$schema"]) !== null && _a !== void 0 ? _a : "";
|
|
137
|
+
};
|
|
138
|
+
this.ensureOutputPathExists = () => {
|
|
139
|
+
if (!fs_1.default.existsSync(this.outputPath)) {
|
|
140
|
+
fs_1.default.mkdirSync(this.outputPath, { recursive: true });
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
this.writeSchemaMapToValidationSchema = (schemaMap) => {
|
|
144
|
+
const definitions = {};
|
|
145
|
+
schemaMap.forEach((schema, key) => {
|
|
146
|
+
definitions[key] = schema;
|
|
147
|
+
});
|
|
148
|
+
const outputBuffer = {
|
|
149
|
+
$schema: this.getSchemaVersion(schemaMap),
|
|
150
|
+
definitions,
|
|
151
|
+
};
|
|
152
|
+
this.ensureOutputPathExists();
|
|
153
|
+
fs_1.default.writeFileSync(this.jsonSchemaOutputFile, JSON.stringify(outputBuffer, null, 4));
|
|
154
|
+
};
|
|
155
|
+
this.writeSchemaMapToValidationTypes = (schemaMap, fileList) => __awaiter(this, void 0, void 0, function* () {
|
|
156
|
+
const project = new ts_morph_1.Project(defaultProjectSettings);
|
|
157
|
+
const symbols = Array.from(schemaMap.keys()).filter((symbol) => {
|
|
158
|
+
return symbol !== "ISchema" && symbol !== "Schemas";
|
|
159
|
+
});
|
|
160
|
+
const readerProject = new ts_morph_1.Project();
|
|
161
|
+
readerProject.addSourceFilesAtPaths(fileList);
|
|
162
|
+
const importMap = new Map();
|
|
163
|
+
fileList.forEach((file) => {
|
|
164
|
+
const dir = path_2.default.dirname(file);
|
|
165
|
+
const fileWithoutExtension = path_2.default.parse(file).name;
|
|
166
|
+
const relativeFilePath = path_2.default.relative(this.outputPath, dir);
|
|
167
|
+
const importPath = `${relativeFilePath}/${fileWithoutExtension}`;
|
|
168
|
+
const source = readerProject.getSourceFile(file);
|
|
169
|
+
source === null || source === void 0 ? void 0 : source.getInterfaces().forEach((interfaceDeclaration) => {
|
|
170
|
+
var _a;
|
|
171
|
+
const structure = interfaceDeclaration.getStructure();
|
|
172
|
+
const namedImports = (_a = importMap.get(importPath)) !== null && _a !== void 0 ? _a : [];
|
|
173
|
+
namedImports.push(structure.name);
|
|
174
|
+
importMap.set(importPath, namedImports);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
const sourceFile = project.createSourceFile(this.tsSchemaDefinitionOutputFile, {}, defaultCreateFileOptions);
|
|
178
|
+
importMap.forEach((namedImports, importPath) => {
|
|
179
|
+
sourceFile.addImportDeclaration({ namedImports, moduleSpecifier: importPath });
|
|
180
|
+
});
|
|
181
|
+
sourceFile.addVariableStatement({
|
|
182
|
+
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
|
|
183
|
+
declarations: [
|
|
184
|
+
{
|
|
185
|
+
name: "schemas",
|
|
186
|
+
type: "Record<keyof ISchema, string>",
|
|
187
|
+
initializer: (writer) => {
|
|
188
|
+
writer.writeLine(`{`);
|
|
189
|
+
symbols.forEach((symbol) => {
|
|
190
|
+
writer.writeLine(`["#/definitions/${symbol}"] : "${symbol}",`);
|
|
191
|
+
}),
|
|
192
|
+
writer.writeLine(`}`);
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
});
|
|
197
|
+
sourceFile.addInterface({
|
|
198
|
+
kind: ts_morph_1.StructureKind.Interface,
|
|
199
|
+
name: "ISchema",
|
|
200
|
+
isExported: false,
|
|
201
|
+
properties: symbols.map((symbol) => {
|
|
202
|
+
return { name: `readonly ["#/definitions/${symbol}"]`, type: symbol };
|
|
203
|
+
}),
|
|
204
|
+
});
|
|
205
|
+
sourceFile.addExportDeclaration({
|
|
206
|
+
namedExports: ["schemas", "ISchema"],
|
|
207
|
+
});
|
|
208
|
+
yield project.save();
|
|
209
|
+
});
|
|
210
|
+
this.writeValidatorFunction = () => __awaiter(this, void 0, void 0, function* () {
|
|
211
|
+
const project = new ts_morph_1.Project(defaultProjectSettings);
|
|
212
|
+
const sourceFile = project.createSourceFile(this.isValidSchemaOutputFile, {}, defaultCreateFileOptions);
|
|
213
|
+
sourceFile.addImportDeclaration({ namespaceImport: "schema", moduleSpecifier: `./${validationSchemaFileName}` });
|
|
214
|
+
sourceFile.addImportDeclaration({ defaultImport: "Ajv", moduleSpecifier: "ajv" });
|
|
215
|
+
sourceFile.addImportDeclaration({
|
|
216
|
+
namedImports: ["ISchema", "schemas"],
|
|
217
|
+
moduleSpecifier: `./${path_2.default.parse(schemaDefinitionFileName).name}`,
|
|
218
|
+
});
|
|
219
|
+
sourceFile.addVariableStatement({
|
|
220
|
+
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
|
|
221
|
+
declarations: [
|
|
222
|
+
{
|
|
223
|
+
name: "validator",
|
|
224
|
+
initializer: (writer) => {
|
|
225
|
+
writer.writeLine(`new Ajv({ allErrors: true });`);
|
|
226
|
+
writer.writeLine(`validator.compile(schema)`);
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
});
|
|
231
|
+
sourceFile.addVariableStatement({
|
|
232
|
+
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
|
|
233
|
+
declarations: [
|
|
234
|
+
{
|
|
235
|
+
name: "isValidSchema",
|
|
236
|
+
initializer: (writer) => {
|
|
237
|
+
writer.writeLine(`<T extends keyof typeof schemas>(data: unknown, schemaKeyRef: T): data is ISchema[T] => {`);
|
|
238
|
+
writer.writeLine(`validator.validate(schemaKeyRef as string, data);`);
|
|
239
|
+
writer.writeLine(`return Boolean(validator.errors) === false;`);
|
|
240
|
+
writer.writeLine(`}`);
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
});
|
|
245
|
+
sourceFile.addExportDeclaration({
|
|
246
|
+
namedExports: ["validator", "isValidSchema"],
|
|
247
|
+
});
|
|
248
|
+
yield project.save();
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
exports.SchemaGenerator = SchemaGenerator;
|
|
253
|
+
//# sourceMappingURL=SchemaGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaGenerator.js","sourceRoot":"","sources":["../src/SchemaGenerator.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const SchemaGenerator_1 = require("./SchemaGenerator");
|
|
5
|
+
const commander_1 = require("commander");
|
|
6
|
+
const defaultGlobPattern = "*.jsonschema.{ts,tsx}";
|
|
7
|
+
const defaultRootPath = "./src";
|
|
8
|
+
const defaultOutputFolder = "./.ts-runtime-validation";
|
|
9
|
+
commander_1.program.option("--glob", `Glob file path of typescript files to generate ts-interface -> json-schema validations - default: ${defaultGlobPattern}`, defaultGlobPattern);
|
|
10
|
+
commander_1.program.option("--rootPath", `RootPath of source - default: ${defaultRootPath}`, defaultRootPath);
|
|
11
|
+
commander_1.program.option("--output", `Validation schema + typescript interface output directory (relative to root path) - default: ${defaultOutputFolder}`, defaultOutputFolder);
|
|
12
|
+
commander_1.program.option("--no-helpers", "Only generate JSON schema without typescript helper files", true);
|
|
13
|
+
commander_1.program.parse();
|
|
14
|
+
const options = commander_1.program.opts();
|
|
15
|
+
const generator = new SchemaGenerator_1.SchemaGenerator(options);
|
|
16
|
+
generator.Generate();
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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;AASvD,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;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
package/src/SchemaGenerator.ts
CHANGED
|
@@ -40,16 +40,23 @@ 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)`);
|
|
50
|
+
if (fileList.length === 0) {
|
|
51
|
+
console.log(`Aborting - no files found with glob: ${glob}`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
51
54
|
const map = await this.getJsonSchemaMap(fileList);
|
|
52
55
|
console.log(`Generating ${map.size} validation schema(s)`);
|
|
56
|
+
if (map.size === 0) {
|
|
57
|
+
console.log(`Aborting - no interfaces found: ${glob}`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
53
60
|
this.writeSchemaMapToValidationSchema(map);
|
|
54
61
|
if (helpers === false) {
|
|
55
62
|
console.log("Skipping helper file generation");
|
package/src/index.ts
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
|
-
});
|