@flink-app/flink 0.12.1-alpha.0 → 0.12.1-alpha.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/bin/flink.ts +6 -13
- package/dist/bin/flink.js +3 -10
- package/dist/cli/build.js +3 -3
- package/dist/cli/clean.js +2 -2
- package/dist/cli/cli-utils.js +1 -1
- package/dist/cli/run.js +2 -2
- package/dist/src/FlinkApp.d.ts +1 -1
- package/dist/src/FlinkApp.js +77 -77
- package/dist/src/FlinkErrors.d.ts +1 -1
- package/dist/src/FlinkErrors.js +5 -5
- package/dist/src/FlinkHttpHandler.d.ts +7 -7
- package/dist/src/FlinkHttpHandler.js +1 -1
- package/dist/src/FlinkJob.d.ts +2 -2
- package/dist/src/FlinkLog.d.ts +2 -2
- package/dist/src/FlinkRepo.d.ts +6 -2
- package/dist/src/FlinkRepo.js +19 -10
- package/dist/src/FlinkResponse.d.ts +2 -2
- package/dist/src/FsUtils.js +7 -7
- package/dist/src/TypeScriptCompiler.js +83 -68
- package/dist/src/TypeScriptUtils.js +11 -33
- package/dist/src/index.js +5 -1
- package/dist/src/mock-data-generator.js +1 -1
- package/dist/src/utils.js +6 -6
- package/package.json +6 -6
- package/spec/mock-project/dist/src/handlers/GetCar.js +10 -12
- package/spec/mock-project/dist/src/handlers/GetCar2.js +11 -13
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema.js +8 -10
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema2.js +8 -10
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema3.js +8 -10
- package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema.js +10 -12
- package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema2.js +10 -12
- package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile.js +10 -12
- package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile2.js +10 -12
- package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler.js +10 -12
- package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler2.js +10 -12
- package/spec/mock-project/dist/src/handlers/PostCar.js +10 -12
- package/spec/mock-project/dist/src/handlers/PostLogin.js +11 -13
- package/spec/mock-project/dist/src/handlers/PutCar.js +10 -12
- package/spec/mock-project/dist/src/index.js +6 -2
- package/src/FlinkApp.ts +5 -5
- package/src/FlinkRepo.ts +13 -4
- package/src/TypeScriptCompiler.ts +13 -2
- package/src/TypeScriptUtils.ts +110 -164
- package/cli/generate-schemas.ts +0 -153
- package/dist/cli/generate-schemas.d.ts +0 -2
- package/dist/cli/generate-schemas.js +0 -140
package/src/FlinkRepo.ts
CHANGED
|
@@ -26,12 +26,18 @@ export abstract class FlinkRepo<C extends FlinkContext, Model extends Document>
|
|
|
26
26
|
|
|
27
27
|
async getById(id: string | ObjectId) {
|
|
28
28
|
const res = await this.collection.findOne<Model>({ _id: this.buildId(id) });
|
|
29
|
-
|
|
29
|
+
if (res) {
|
|
30
|
+
return this.objectIdToString(res);
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
async getOne(query = {}) {
|
|
33
36
|
const res = await this.collection.findOne<Model>(query);
|
|
34
|
-
|
|
37
|
+
if (res) {
|
|
38
|
+
return this.objectIdToString(res);
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
async create<C = Omit<Model, "_id">>(model: C): Promise<C & { _id: string }> {
|
|
@@ -46,7 +52,10 @@ export abstract class FlinkRepo<C extends FlinkContext, Model extends Document>
|
|
|
46
52
|
|
|
47
53
|
const res = await this.collection.findOne<Model>({ _id: oid });
|
|
48
54
|
|
|
49
|
-
|
|
55
|
+
if (res) {
|
|
56
|
+
return this.objectIdToString(res);
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
50
59
|
}
|
|
51
60
|
|
|
52
61
|
async updateMany<U = Partial<Model>>(query: any, model: U): Promise<number> {
|
|
@@ -77,7 +86,7 @@ export abstract class FlinkRepo<C extends FlinkContext, Model extends Document>
|
|
|
77
86
|
return oid;
|
|
78
87
|
}
|
|
79
88
|
|
|
80
|
-
private objectIdToString(doc:
|
|
89
|
+
private objectIdToString<T>(doc: T & { _id?: any }) {
|
|
81
90
|
if (doc && doc._id) {
|
|
82
91
|
doc._id = doc._id.toString();
|
|
83
92
|
}
|
|
@@ -2,7 +2,7 @@ import { promises as fsPromises } from "fs";
|
|
|
2
2
|
import { JSONSchema7 } from "json-schema";
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
import glob from "tiny-glob";
|
|
5
|
-
import { Config, createFormatter, createParser, Schema, SchemaGenerator } from "ts-json-schema-generator";
|
|
5
|
+
import { CompletedConfig, Config, createFormatter, createParser, Schema, SchemaGenerator } from "ts-json-schema-generator";
|
|
6
6
|
import {
|
|
7
7
|
ArrayLiteralExpression,
|
|
8
8
|
DiagnosticCategory,
|
|
@@ -437,9 +437,20 @@ import "..${appEntryScript.replace(/\.ts/g, "")}";
|
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
private initJsonSchemaGenerator() {
|
|
440
|
-
const conf:
|
|
440
|
+
const conf: CompletedConfig = {
|
|
441
441
|
expose: "none", // Do not create shared $ref definitions.
|
|
442
442
|
topRef: false, // Removes the wrapper object around the schema.
|
|
443
|
+
additionalProperties: false,
|
|
444
|
+
jsDoc: "basic",
|
|
445
|
+
sortProps: false,
|
|
446
|
+
strictTuples: false,
|
|
447
|
+
minify: false,
|
|
448
|
+
markdownDescription: false,
|
|
449
|
+
skipTypeCheck: false,
|
|
450
|
+
encodeRefs: false,
|
|
451
|
+
extraTags: [],
|
|
452
|
+
functions: "fail",
|
|
453
|
+
discriminatorType: "json-schema",
|
|
443
454
|
};
|
|
444
455
|
const formatter = createFormatter(conf);
|
|
445
456
|
const parser = createParser(this.project.getProgram().compilerObject, conf);
|
package/src/TypeScriptUtils.ts
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ImportDeclarationStructure,
|
|
3
|
-
Node,
|
|
4
|
-
OptionalKind,
|
|
5
|
-
SourceFile,
|
|
6
|
-
Symbol,
|
|
7
|
-
SyntaxKind,
|
|
8
|
-
ts,
|
|
9
|
-
Type,
|
|
10
|
-
} from "ts-morph";
|
|
1
|
+
import { ImportDeclarationStructure, Node, OptionalKind, SourceFile, Symbol, SyntaxKind, ts, Type } from "ts-morph";
|
|
11
2
|
import { getJsDocComment } from "./utils";
|
|
12
3
|
|
|
13
4
|
/**
|
|
@@ -18,85 +9,66 @@ import { getJsDocComment } from "./utils";
|
|
|
18
9
|
* Declared types of those are returned.
|
|
19
10
|
*/
|
|
20
11
|
export function getTypesToImport(node: Node<ts.Node>) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
)
|
|
26
|
-
.map((typeRefNode) =>
|
|
27
|
-
typeRefNode.getFirstChildIfKindOrThrow(SyntaxKind.Identifier)
|
|
28
|
-
);
|
|
12
|
+
const typeRefIdentifiers = node
|
|
13
|
+
.getDescendantsOfKind(SyntaxKind.TypeReference)
|
|
14
|
+
.filter((typeRefNode) => !!typeRefNode.getFirstChildIfKind(SyntaxKind.Identifier))
|
|
15
|
+
.map((typeRefNode) => typeRefNode.getFirstChildIfKindOrThrow(SyntaxKind.Identifier));
|
|
29
16
|
|
|
30
|
-
|
|
17
|
+
const typesToImport: Type<ts.Type>[] = [];
|
|
31
18
|
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
for (const typeRefIdentifier of typeRefIdentifiers) {
|
|
20
|
+
const typeSymbol = typeRefIdentifier.getSymbolOrThrow();
|
|
34
21
|
|
|
35
|
-
|
|
36
|
-
|
|
22
|
+
const declaredType = typeSymbol.getDeclaredType();
|
|
23
|
+
const declaration = declaredType.getSymbol()?.getDeclarations()[0];
|
|
37
24
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
25
|
+
if (!declaration) {
|
|
26
|
+
continue; // should not happen, right?
|
|
27
|
+
}
|
|
41
28
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
29
|
+
if (declaration.getSourceFile() !== node.getSourceFile()) {
|
|
30
|
+
typesToImport.push(declaration.getSymbolOrThrow().getDeclaredType());
|
|
31
|
+
} else {
|
|
32
|
+
typesToImport.push(...getTypesToImport(declaration));
|
|
33
|
+
}
|
|
46
34
|
}
|
|
47
|
-
}
|
|
48
35
|
|
|
49
|
-
|
|
36
|
+
return typesToImport;
|
|
50
37
|
}
|
|
51
38
|
|
|
52
39
|
export function addImport(toSourceFile: SourceFile, symbol: Symbol) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (!symbolDeclaration) {
|
|
56
|
-
throw new Error(
|
|
57
|
-
"Missing declaration for symbol " + symbol.getFullyQualifiedName()
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const importName = symbol.getEscapedName();
|
|
62
|
-
const symbolSourceFile = symbolDeclaration.getSourceFile();
|
|
40
|
+
const symbolDeclaration = symbol.getDeclarations()[0];
|
|
63
41
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
.endsWith(".default");
|
|
42
|
+
if (!symbolDeclaration) {
|
|
43
|
+
throw new Error("Missing declaration for symbol " + symbol.getFullyQualifiedName());
|
|
44
|
+
}
|
|
68
45
|
|
|
69
|
-
|
|
70
|
-
.
|
|
71
|
-
.find(
|
|
72
|
-
(importDeclarataion) =>
|
|
73
|
-
importDeclarataion.getModuleSpecifierSourceFile() === symbolSourceFile
|
|
74
|
-
);
|
|
46
|
+
const importName = symbol.getEscapedName();
|
|
47
|
+
const symbolSourceFile = symbolDeclaration.getSourceFile();
|
|
75
48
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
49
|
+
const isDefaultExport = symbol.getDeclaredType().getText().endsWith(".default");
|
|
50
|
+
|
|
51
|
+
const importDec = toSourceFile.getImportDeclarations().find((importDeclarataion) => importDeclarataion.getModuleSpecifierSourceFile() === symbolSourceFile);
|
|
52
|
+
|
|
53
|
+
if (importDec) {
|
|
54
|
+
// File already has import to file
|
|
55
|
+
if (isDefaultExport) {
|
|
56
|
+
if (!importDec.getDefaultImport()) {
|
|
57
|
+
importDec.setDefaultImport(importName);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
if (!importDec.getNamedImports().find((specifier) => specifier.getText() === importName)) {
|
|
61
|
+
importDec.addNamedImport(importName);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
82
64
|
} else {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
65
|
+
// Add new import declaration
|
|
66
|
+
toSourceFile.addImportDeclaration({
|
|
67
|
+
moduleSpecifier: toSourceFile.getRelativePathAsModuleSpecifierTo(symbolSourceFile),
|
|
68
|
+
defaultImport: isDefaultExport ? symbol.getEscapedName() : undefined,
|
|
69
|
+
namedImports: isDefaultExport ? undefined : [symbol.getEscapedName()],
|
|
70
|
+
});
|
|
90
71
|
}
|
|
91
|
-
} else {
|
|
92
|
-
// Add new import declaration
|
|
93
|
-
toSourceFile.addImportDeclaration({
|
|
94
|
-
moduleSpecifier:
|
|
95
|
-
toSourceFile.getRelativePathAsModuleSpecifierTo(symbolSourceFile),
|
|
96
|
-
defaultImport: isDefaultExport ? symbol.getEscapedName() : undefined,
|
|
97
|
-
namedImports: isDefaultExport ? undefined : [symbol.getEscapedName()],
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
72
|
}
|
|
101
73
|
|
|
102
74
|
/**
|
|
@@ -106,63 +78,47 @@ export function addImport(toSourceFile: SourceFile, symbol: Symbol) {
|
|
|
106
78
|
* @param symbols
|
|
107
79
|
*/
|
|
108
80
|
export function addImports(toSourceFile: SourceFile, symbols: Symbol[]) {
|
|
109
|
-
|
|
110
|
-
string,
|
|
111
|
-
{ defaultImportName?: string; namedImports: string[] }
|
|
112
|
-
>();
|
|
81
|
+
const importsByModuleSpecifier = new Map<string, { defaultImportName?: string; namedImports: string[] }>();
|
|
113
82
|
|
|
114
|
-
|
|
115
|
-
|
|
83
|
+
for (const symbol of symbols) {
|
|
84
|
+
const symbolDeclaration = symbol.getDeclarations()[0];
|
|
116
85
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
);
|
|
121
|
-
}
|
|
86
|
+
if (!symbolDeclaration) {
|
|
87
|
+
throw new Error("Missing declaration for symbol " + symbol.getFullyQualifiedName());
|
|
88
|
+
}
|
|
122
89
|
|
|
123
|
-
|
|
124
|
-
? getInterfaceName(symbol)
|
|
125
|
-
: symbol.getEscapedName();
|
|
90
|
+
const importName = symbol.getDeclaredType().isInterface() ? getInterfaceName(symbol) : symbol.getEscapedName();
|
|
126
91
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
.getDeclaredType()
|
|
130
|
-
.getText()
|
|
131
|
-
.endsWith(".default");
|
|
92
|
+
const symbolSourceFile = symbolDeclaration.getSourceFile();
|
|
93
|
+
const isDefaultExport = symbol.getDeclaredType().getText().endsWith(".default");
|
|
132
94
|
|
|
133
|
-
|
|
134
|
-
toSourceFile.getRelativePathAsModuleSpecifierTo(symbolSourceFile);
|
|
95
|
+
const moduleSpecifier = toSourceFile.getRelativePathAsModuleSpecifierTo(symbolSourceFile);
|
|
135
96
|
|
|
136
|
-
|
|
97
|
+
let aImport = importsByModuleSpecifier.get(moduleSpecifier);
|
|
137
98
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
99
|
+
if (!aImport) {
|
|
100
|
+
importsByModuleSpecifier.set(moduleSpecifier, {
|
|
101
|
+
defaultImportName: isDefaultExport ? importName : undefined,
|
|
102
|
+
namedImports: isDefaultExport ? [] : [importName],
|
|
103
|
+
});
|
|
104
|
+
} else {
|
|
105
|
+
if (isDefaultExport) {
|
|
106
|
+
aImport.defaultImportName = importName;
|
|
107
|
+
} else if (!aImport.namedImports.includes(importName)) {
|
|
108
|
+
aImport.namedImports.push(importName);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
149
111
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
namedImports: aImport.namedImports.length
|
|
161
|
-
? aImport.namedImports
|
|
162
|
-
: undefined,
|
|
163
|
-
})
|
|
164
|
-
)
|
|
165
|
-
);
|
|
112
|
+
|
|
113
|
+
toSourceFile.addImportDeclarations(
|
|
114
|
+
Array.from(importsByModuleSpecifier.entries()).map(
|
|
115
|
+
([moduleSpecifier, aImport]): OptionalKind<ImportDeclarationStructure> => ({
|
|
116
|
+
moduleSpecifier,
|
|
117
|
+
defaultImport: aImport.defaultImportName,
|
|
118
|
+
namedImports: aImport.namedImports.length ? aImport.namedImports : undefined,
|
|
119
|
+
})
|
|
120
|
+
)
|
|
121
|
+
);
|
|
166
122
|
}
|
|
167
123
|
|
|
168
124
|
/**
|
|
@@ -171,21 +127,17 @@ export function addImports(toSourceFile: SourceFile, symbols: Symbol[]) {
|
|
|
171
127
|
* @returns
|
|
172
128
|
*/
|
|
173
129
|
export function getDefaultExport(sf: SourceFile) {
|
|
174
|
-
|
|
175
|
-
SyntaxKind.ExportAssignment
|
|
176
|
-
);
|
|
130
|
+
const exportAssignment = sf.getFirstDescendantByKind(SyntaxKind.ExportAssignment);
|
|
177
131
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
SyntaxKind.Identifier
|
|
181
|
-
);
|
|
132
|
+
if (exportAssignment) {
|
|
133
|
+
const identifier = exportAssignment.getFirstChildByKind(SyntaxKind.Identifier);
|
|
182
134
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
135
|
+
if (identifier) {
|
|
136
|
+
return identifier.getSymbolOrThrow().getDeclarations()[0];
|
|
137
|
+
} else {
|
|
138
|
+
return exportAssignment.getFirstChild();
|
|
139
|
+
}
|
|
187
140
|
}
|
|
188
|
-
}
|
|
189
141
|
}
|
|
190
142
|
|
|
191
143
|
/**
|
|
@@ -195,48 +147,42 @@ export function getDefaultExport(sf: SourceFile) {
|
|
|
195
147
|
* @returns
|
|
196
148
|
*/
|
|
197
149
|
export function getInterfaceName(symbol: Symbol) {
|
|
198
|
-
|
|
150
|
+
const declaration = symbol.getDeclarations()[0];
|
|
199
151
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
152
|
+
if (!declaration) {
|
|
153
|
+
throw new Error("Missing declaration of interface symbol");
|
|
154
|
+
}
|
|
203
155
|
|
|
204
|
-
|
|
205
|
-
.getFirstChildByKindOrThrow(SyntaxKind.Identifier)
|
|
206
|
-
.getText();
|
|
156
|
+
return declaration.getFirstChildByKindOrThrow(SyntaxKind.Identifier).getText();
|
|
207
157
|
}
|
|
208
158
|
|
|
209
159
|
export function getSymbolOrAlias(type: Type<ts.Type>) {
|
|
210
|
-
|
|
160
|
+
return type.getAliasSymbol() || type.getSymbol();
|
|
211
161
|
}
|
|
212
162
|
|
|
213
163
|
export function getTypeMetadata(type: Type<ts.Type>) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
164
|
+
if (!type || ["void", "any"].includes(type.getText())) {
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
217
167
|
|
|
218
|
-
|
|
168
|
+
const symbol = getSymbolOrAlias(type);
|
|
219
169
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
170
|
+
if (!symbol) {
|
|
171
|
+
throw new Error("Could not get type symbol for type: " + type.getText());
|
|
172
|
+
}
|
|
223
173
|
|
|
224
|
-
|
|
174
|
+
const [declaration] = symbol.getDeclarations();
|
|
225
175
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
176
|
+
if (!declaration) {
|
|
177
|
+
throw new Error("Could not get declaration for type: " + type.getText());
|
|
178
|
+
}
|
|
229
179
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
.map((prop) => {
|
|
233
|
-
const description = getJsDocComment(
|
|
234
|
-
prop.getLeadingCommentRanges()[0]?.getText() || ""
|
|
235
|
-
);
|
|
180
|
+
return declaration.getDescendantsOfKind(SyntaxKind.PropertySignature).map((prop) => {
|
|
181
|
+
const description = getJsDocComment(prop.getLeadingCommentRanges()[0]?.getText() || "");
|
|
236
182
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
183
|
+
return {
|
|
184
|
+
description,
|
|
185
|
+
name: prop.getName(),
|
|
186
|
+
};
|
|
241
187
|
});
|
|
242
188
|
}
|
package/cli/generate-schemas.ts
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { JSONSchema7, JSONSchema7Definition } from "json-schema";
|
|
3
|
-
import { join } from "path";
|
|
4
|
-
import {
|
|
5
|
-
createFormatter,
|
|
6
|
-
createParser,
|
|
7
|
-
SchemaGenerator,
|
|
8
|
-
} from "ts-json-schema-generator";
|
|
9
|
-
import { Project, SyntaxKind, ts } from "ts-morph";
|
|
10
|
-
import { writeJsonFile } from "../src/FsUtils";
|
|
11
|
-
import { getOption } from "./cli-utils";
|
|
12
|
-
|
|
13
|
-
module.exports = async function run(args: string[]) {
|
|
14
|
-
if (args.includes("--help")) {
|
|
15
|
-
console.log(`
|
|
16
|
-
Description
|
|
17
|
-
Generates JSON schemas for types located in schemas directory or if any other directory
|
|
18
|
-
is specified with option --types-dir.
|
|
19
|
-
|
|
20
|
-
Outputs generated file(s) to dir '.flink' or if any other --out-dir is specified.
|
|
21
|
-
|
|
22
|
-
Usage
|
|
23
|
-
$ flink generate-schemas <dir> --types-dir <types-dir> --out-file <out-file>
|
|
24
|
-
|
|
25
|
-
<dir> is project root as directory where tsconfig.son resides.
|
|
26
|
-
|
|
27
|
-
Options
|
|
28
|
-
--types-dir Directory where typescript types are located relative to <dir>, default "./src/schemas"
|
|
29
|
-
--out-file Path to file that will contain generated json schemas relative to <dir>, default "./.flink/generated-schemas.json"
|
|
30
|
-
--help Displays this message
|
|
31
|
-
`);
|
|
32
|
-
|
|
33
|
-
process.exit(0);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let dir = "./";
|
|
37
|
-
if (args[0] && !args[0].startsWith("--")) {
|
|
38
|
-
dir = args[0];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const verbose = getOption(args, "verbose", false, {
|
|
42
|
-
isBoolean: true,
|
|
43
|
-
}) as boolean;
|
|
44
|
-
|
|
45
|
-
const typesDir = getOption(args, "types-dir", "./src/schemas") as string;
|
|
46
|
-
|
|
47
|
-
const outFile = getOption(
|
|
48
|
-
args,
|
|
49
|
-
"out-file",
|
|
50
|
-
"./.flink/generated-schemas.json"
|
|
51
|
-
) as string;
|
|
52
|
-
|
|
53
|
-
const project = new Project({
|
|
54
|
-
tsConfigFilePath: join(dir, "tsconfig.json"),
|
|
55
|
-
skipAddingFilesFromTsConfig: true,
|
|
56
|
-
compilerOptions: {
|
|
57
|
-
noEmit: true,
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
project.addSourceFilesAtPaths(join(dir, typesDir, "**/*.ts"));
|
|
62
|
-
|
|
63
|
-
console.log("Found", project.getSourceFiles().length, "files");
|
|
64
|
-
|
|
65
|
-
const schemaDeclarations: ts.Node[] = [];
|
|
66
|
-
|
|
67
|
-
const generator = initJsonSchemaGenerator(project);
|
|
68
|
-
|
|
69
|
-
const jsonSchemas: JSONSchema7[] = [];
|
|
70
|
-
|
|
71
|
-
for (const sf of project.getSourceFiles()) {
|
|
72
|
-
if (sf.getDefaultExportSymbol()) {
|
|
73
|
-
console.warn(
|
|
74
|
-
`WARN: Schema file ${sf.getBaseName()} has default export, but only named exports are picked up by json schemas parser`
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const sourceFileInterfaceDeclarations = sf.getChildrenOfKind(
|
|
79
|
-
SyntaxKind.InterfaceDeclaration
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
const sourceFileEnumDeclarations = sf.getChildrenOfKind(
|
|
83
|
-
SyntaxKind.EnumDeclaration
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
const sourceFileDeclarations = [
|
|
87
|
-
...sourceFileEnumDeclarations,
|
|
88
|
-
...sourceFileInterfaceDeclarations,
|
|
89
|
-
];
|
|
90
|
-
|
|
91
|
-
schemaDeclarations.push(
|
|
92
|
-
...sourceFileDeclarations.map((d) => d.compilerNode)
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
verbose &&
|
|
96
|
-
console.log(
|
|
97
|
-
"Found",
|
|
98
|
-
sourceFileDeclarations.length,
|
|
99
|
-
"schema(s) in file",
|
|
100
|
-
sf.getBaseName()
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
const schema = generator.createSchemaFromNodes(
|
|
105
|
-
sourceFileInterfaceDeclarations.map((d) => d.compilerNode)
|
|
106
|
-
);
|
|
107
|
-
jsonSchemas.push(schema);
|
|
108
|
-
// console.log("Created schemas");
|
|
109
|
-
} catch (err) {
|
|
110
|
-
console.error(
|
|
111
|
-
"Failed to generate schema in file",
|
|
112
|
-
sf.getBaseName() + ":",
|
|
113
|
-
err
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const mergedSchemas = jsonSchemas.reduce(
|
|
119
|
-
(out, schema) => {
|
|
120
|
-
if (schema)
|
|
121
|
-
if (schema.definitions) {
|
|
122
|
-
out.definitions = { ...out.definitions, ...schema.definitions };
|
|
123
|
-
}
|
|
124
|
-
return out;
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
$schema: "http://json-schema.org/draft-07/schema#",
|
|
128
|
-
$ref: "#/definitions/Schemas",
|
|
129
|
-
definitions: {},
|
|
130
|
-
}
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
const file = join(dir, outFile);
|
|
134
|
-
|
|
135
|
-
await writeJsonFile(file, mergedSchemas, {
|
|
136
|
-
ensureDir: true,
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
console.log("Wrote file", file);
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
function initJsonSchemaGenerator(project: Project) {
|
|
143
|
-
const formatter = createFormatter({});
|
|
144
|
-
const parser = createParser(project.getProgram().compilerObject, {});
|
|
145
|
-
const generator = new SchemaGenerator(
|
|
146
|
-
project.getProgram().compilerObject,
|
|
147
|
-
parser,
|
|
148
|
-
formatter,
|
|
149
|
-
{ expose: "export" }
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
return generator;
|
|
153
|
-
}
|