@flink-app/flink 0.12.1-alpha.9 → 0.13.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/cli/build.js +2 -2
  3. package/dist/cli/clean.js +2 -2
  4. package/dist/cli/cli-utils.js +1 -2
  5. package/dist/cli/run.js +2 -2
  6. package/dist/src/FlinkApp.d.ts +6 -1
  7. package/dist/src/FlinkApp.js +28 -14
  8. package/dist/src/FlinkErrors.d.ts +69 -0
  9. package/dist/src/FlinkErrors.js +87 -8
  10. package/dist/src/FlinkHttpHandler.d.ts +14 -1
  11. package/dist/src/FlinkLog.d.ts +2 -2
  12. package/dist/src/FlinkRepo.d.ts +8 -1
  13. package/dist/src/FlinkRepo.js +9 -2
  14. package/dist/src/FlinkResponse.d.ts +0 -3
  15. package/dist/src/FsUtils.js +5 -6
  16. package/dist/src/TypeScriptCompiler.d.ts +10 -0
  17. package/dist/src/TypeScriptCompiler.js +169 -49
  18. package/dist/src/TypeScriptUtils.js +7 -8
  19. package/dist/src/index.d.ts +1 -0
  20. package/dist/src/utils.js +13 -14
  21. package/package.json +67 -69
  22. package/spec/TypeScriptCompiler.spec.ts +11 -1
  23. package/spec/mock-project/dist/src/handlers/GetCar.js +2 -2
  24. package/spec/mock-project/dist/src/handlers/GetCar2.js +2 -2
  25. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema.js +2 -2
  26. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema2.js +2 -2
  27. package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema3.js +2 -2
  28. package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema.js +2 -2
  29. package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema2.js +2 -2
  30. package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile.js +2 -2
  31. package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile2.js +2 -2
  32. package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler.js +3 -4
  33. package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler2.js +3 -4
  34. package/spec/mock-project/dist/src/handlers/PostCar.js +2 -2
  35. package/spec/mock-project/dist/src/handlers/PostLogin.js +2 -2
  36. package/spec/mock-project/dist/src/handlers/{GetCarWithOmitSchema.js → PostLogout.js} +16 -20
  37. package/spec/mock-project/dist/src/handlers/PutCar.js +2 -2
  38. package/spec/mock-project/dist/src/index.js +2 -2
  39. package/spec/mock-project/src/handlers/PostLogout.ts +19 -0
  40. package/spec/mock-project/tsconfig.json +1 -1
  41. package/src/FlinkApp.ts +24 -5
  42. package/src/FlinkErrors.ts +86 -6
  43. package/src/FlinkHttpHandler.ts +95 -96
  44. package/src/FlinkRepo.ts +8 -1
  45. package/src/FlinkResponse.ts +36 -39
  46. package/src/TypeScriptCompiler.ts +145 -39
  47. package/src/index.ts +12 -0
  48. package/tsconfig.json +1 -1
  49. package/dist/cli/generate-schemas.d.ts +0 -2
  50. package/dist/cli/generate-schemas.js +0 -140
  51. package/spec/mock-project/dist/src/handlers/GetCarWithTypeSchema.js +0 -60
  52. package/spec/mock-project/package-lock.json +0 -108
@@ -1,8 +1,8 @@
1
- import { promises as fsPromises } from "fs";
1
+ import fs, { 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 { CompletedConfig, Config, createFormatter, createParser, Schema, SchemaGenerator } from "ts-json-schema-generator";
5
+ import { CompletedConfig, createFormatter, createParser, createProgram, Schema, SchemaGenerator } from "ts-json-schema-generator";
6
6
  import {
7
7
  ArrayLiteralExpression,
8
8
  DiagnosticCategory,
@@ -24,6 +24,7 @@ import { getCollectionNameForRepo, getHttpMethodFromHandlerName, getRepoInstance
24
24
  class TypeScriptCompiler {
25
25
  private project: Project;
26
26
  private schemaGenerator?: SchemaGenerator;
27
+ private isEsm: boolean;
27
28
 
28
29
  /**
29
30
  * Parsed typescript schemas that will be added to intermediate
@@ -41,16 +42,72 @@ class TypeScriptCompiler {
41
42
  private tsSchemasSymbolsToImports: Symbol[] = [];
42
43
 
43
44
  constructor(private cwd: string) {
45
+ // Detect if project is using ESM based solely on package.json "type": "module"
46
+ this.isEsm = this.isEsmProject(cwd);
47
+
48
+ const compilerOptions: ts.CompilerOptions = {
49
+ noEmit: false, // We need to emit files
50
+ outDir: join(cwd, "dist"),
51
+ };
52
+
53
+ // Set appropriate module settings based on detected module system
54
+ if (this.isEsm) {
55
+ // For ESM projects, use ESNext module with Node resolution
56
+ compilerOptions.module = ts.ModuleKind.ESNext;
57
+ compilerOptions.moduleResolution = ts.ModuleResolutionKind.NodeJs;
58
+ compilerOptions.esModuleInterop = true;
59
+ } else {
60
+ // For CommonJS projects, use CommonJS module with Node resolution
61
+ compilerOptions.module = ts.ModuleKind.CommonJS;
62
+ compilerOptions.moduleResolution = ts.ModuleResolutionKind.NodeJs;
63
+ }
64
+
65
+ const tsConfigPath = join(cwd, "tsconfig.json");
66
+ console.log("TypeScript config path:", require("path").resolve(tsConfigPath));
67
+ console.log("TypeScript version:", ts.version);
68
+
44
69
  this.project = new Project({
45
- tsConfigFilePath: join(cwd, "tsconfig.json"),
46
- compilerOptions: {
47
- noEmit: false,
48
- outDir: join(cwd, "dist"),
49
- // incremental: true,
50
- },
70
+ tsConfigFilePath: tsConfigPath,
71
+ compilerOptions,
51
72
  });
52
73
 
53
74
  console.log("Loaded", this.project.getSourceFiles().length, "source file(s) from", cwd);
75
+ console.log("Module system:", this.isEsm ? "ESM" : "CommonJS");
76
+ console.log("Using module:", compilerOptions.module === ts.ModuleKind.ESNext ? "ESNext" : "CommonJS");
77
+ }
78
+
79
+ /**
80
+ * Detects if the project is using ESM (ECMAScript Modules)
81
+ * by checking type in package.json.
82
+ */
83
+ private isEsmProject(cwd: string): boolean {
84
+ try {
85
+ // Check package.json for "type": "module"
86
+ const packageJsonPath = join(cwd, "package.json");
87
+ if (fs.existsSync(packageJsonPath)) {
88
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
89
+ return packageJson.type === "module";
90
+ }
91
+ } catch (error) {
92
+ // If we can't determine, default to CommonJS
93
+ console.warn("Error detecting module system, defaulting to CommonJS:", error);
94
+ }
95
+
96
+ return false;
97
+ }
98
+
99
+ /**
100
+ * Gets the module specifier for imports, adding .js extension for ESM
101
+ */
102
+ private getModuleSpecifier(fromFile: SourceFile, toFile: SourceFile): string {
103
+ let moduleSpecifier = fromFile.getRelativePathAsModuleSpecifierTo(toFile);
104
+
105
+ // Add .js extension for ESM imports (only for relative paths)
106
+ if (this.isEsm && !moduleSpecifier.startsWith("@") && !moduleSpecifier.endsWith(".js")) {
107
+ moduleSpecifier += ".js";
108
+ }
109
+
110
+ return moduleSpecifier;
54
111
  }
55
112
 
56
113
  /**
@@ -139,9 +196,9 @@ autoRegisteredHandlers.push(...handlers);
139
196
 
140
197
  await generatedFile.save();
141
198
 
142
- await this.createIntermediateSchemaFile();
199
+ const schemaFilePath = await this.createIntermediateSchemaFile();
143
200
 
144
- const jsonSchemas = await this.generateAndSaveJsonSchemas(handlers.schemasToGenerate);
201
+ const jsonSchemas = await this.generateAndSaveJsonSchemas(handlers.schemasToGenerate, schemaFilePath);
145
202
 
146
203
  this.appendSchemasToHandlerSourceFiles(handlers.schemasToGenerate, jsonSchemas);
147
204
 
@@ -173,12 +230,20 @@ autoRegisteredHandlers.push(...handlers);
173
230
 
174
231
  imports.push({
175
232
  defaultImport: "* as " + namespaceImport,
176
- moduleSpecifier: generatedFile.getRelativePathAsModuleSpecifierTo(sf),
233
+ moduleSpecifier: this.getModuleSpecifier(generatedFile, sf),
177
234
  });
178
235
 
179
236
  const assumedHttpMethod = getHttpMethodFromHandlerName(sf.getBaseName());
180
237
 
181
- const schemaTypes = await this.extractSchemasFromHandlerSourceFile(sf);
238
+ // Only extract schemas for auto-registered handlers
239
+ const schemaTypes = isAutoRegister ? await this.extractSchemasFromHandlerSourceFile(sf) : undefined;
240
+
241
+ // Remove existing metadata variables if they exist (to avoid redeclaration errors)
242
+ const existingVars = sf.getVariableStatements().filter((vs) => {
243
+ const varNames = vs.getDeclarations().map((d) => d.getName());
244
+ return varNames.some((name) => ["__assumedHttpMethod", "__file", "__query", "__params"].includes(name));
245
+ });
246
+ existingVars.forEach((v) => v.remove());
182
247
 
183
248
  // Append schemas and metadata to source file that will be part of emitted dist bundle (javascript)
184
249
  sf.addVariableStatement({
@@ -214,10 +279,11 @@ autoRegisteredHandlers.push(...handlers);
214
279
  `{handler: ${namespaceImport}, assumedHttpMethod: ${assumedHttpMethod ? "HttpMethod." + assumedHttpMethod : undefined}}`
215
280
  );
216
281
  i++;
217
- }
218
282
 
219
- if (schemaTypes) {
220
- schemasToGenerate.push({ ...schemaTypes, sourceFile: sf });
283
+ // Add schemas to generate list
284
+ if (schemaTypes) {
285
+ schemasToGenerate.push({ ...schemaTypes, sourceFile: sf });
286
+ }
221
287
  }
222
288
  }
223
289
 
@@ -252,7 +318,7 @@ autoRegisteredHandlers.push(...handlers);
252
318
 
253
319
  imports.push({
254
320
  defaultImport: sf.getBaseNameWithoutExtension(),
255
- moduleSpecifier: generatedFile.getRelativePathAsModuleSpecifierTo(sf),
321
+ moduleSpecifier: this.getModuleSpecifier(generatedFile, sf),
256
322
  });
257
323
 
258
324
  reposArr.insertElement(
@@ -288,10 +354,11 @@ autoRegisteredHandlers.push(...handlers);
288
354
  const sf = this.createSourceFile(
289
355
  ["start.ts"],
290
356
  `// Generated ${new Date()}
291
- import "./generatedHandlers";
292
- import "./generatedRepos";
293
- import "./generatedJobs";
294
- import "..${appEntryScript.replace(/\.ts/g, "")}";
357
+ import "./generatedHandlers${this.isEsm ? ".js" : ""}";
358
+ import "./generatedRepos${this.isEsm ? ".js" : ""}";
359
+ import "./generatedJobs${this.isEsm ? ".js" : ""}";
360
+ import "..${appEntryScript.replace(/\.ts/g, "")}${this.isEsm ? ".js" : ""}";
361
+ export default {}; // Export an empty object to make it a module
295
362
  `
296
363
  );
297
364
 
@@ -410,15 +477,19 @@ import "..${appEntryScript.replace(/\.ts/g, "")}";
410
477
  * We need extract `{car: Car}` into its own interface and make sure
411
478
  * to import types if needed to
412
479
  */
413
- const declaration = schema.getSymbolOrThrow().getDeclarations()[0];
414
-
415
- const typeRefIdentifiers = declaration
416
- .getDescendantsOfKind(SyntaxKind.TypeReference)
417
- .map((typeRef) => typeRef.getFirstChildByKindOrThrow(SyntaxKind.Identifier));
418
-
419
- typeRefIdentifiers.forEach((tr) => {
420
- this.tsSchemasSymbolsToImports.push(tr.getSymbolOrThrow().getDeclaredType().getSymbolOrThrow());
421
- });
480
+ const declarations = schema.getSymbolOrThrow().getDeclarations();
481
+ const declaration = declarations[0];
482
+
483
+ // Only extract type references if declaration exists (won't exist for empty object literals like {})
484
+ if (declaration) {
485
+ const typeRefIdentifiers = declaration
486
+ .getDescendantsOfKind(SyntaxKind.TypeReference)
487
+ .map((typeRef) => typeRef.getFirstChildByKindOrThrow(SyntaxKind.Identifier));
488
+
489
+ typeRefIdentifiers.forEach((tr) => {
490
+ this.tsSchemasSymbolsToImports.push(tr.getSymbolOrThrow().getDeclaredType().getSymbolOrThrow());
491
+ });
492
+ }
422
493
 
423
494
  generatedSchemaInterfaceStr = `export interface ${schemaInterfaceName} { ${schema
424
495
  .getProperties()
@@ -436,8 +507,10 @@ import "..${appEntryScript.replace(/\.ts/g, "")}";
436
507
  return;
437
508
  }
438
509
 
439
- private initJsonSchemaGenerator() {
510
+ private initJsonSchemaGenerator(schemaFilePath: string) {
511
+ const tsconfigPath = join(this.cwd, "tsconfig.json");
440
512
  const conf: CompletedConfig = {
513
+ path: schemaFilePath, // Point to the intermediate schema file
441
514
  expose: "none", // Do not create shared $ref definitions.
442
515
  topRef: false, // Removes the wrapper object around the schema.
443
516
  additionalProperties: false,
@@ -451,23 +524,39 @@ import "..${appEntryScript.replace(/\.ts/g, "")}";
451
524
  extraTags: [],
452
525
  functions: "fail",
453
526
  discriminatorType: "json-schema",
527
+ // tsconfig: tsconfigPath,
454
528
  };
529
+
530
+ console.log("Creating TypeScript program for schema generation:");
531
+ console.log(" Schema file:", schemaFilePath);
532
+ console.log(" tsconfig:", tsconfigPath);
533
+
534
+ // Create a fresh TypeScript Program that includes the schema file
535
+ // This ensures ts-json-schema-generator can find the types we just generated
536
+ const program = createProgram(conf);
537
+
538
+ console.log(" TypeScript version:", ts.version);
539
+ console.log(" Program root files:", program.getRootFileNames().length);
540
+
455
541
  const formatter = createFormatter(conf);
456
- const parser = createParser(this.project.getProgram().compilerObject, conf);
457
- const generator = new SchemaGenerator(this.project.getProgram().compilerObject, parser, formatter, conf);
542
+ const parser = createParser(program, conf);
543
+ const generator = new SchemaGenerator(program, parser, formatter, conf);
458
544
 
459
545
  return generator;
460
546
  }
461
547
 
462
- private async generateAndSaveJsonSchemas(schemas: { reqSchemaType?: string; resSchemaType?: string }[]) {
548
+ private async generateAndSaveJsonSchemas(schemas: { reqSchemaType?: string; resSchemaType?: string }[], schemaFilePath: string) {
549
+ // Reset schema generator to use the newly created intermediate schema file
550
+ this.schemaGenerator = undefined;
551
+
463
552
  const jsonSchemas: Schema[] = [];
464
553
 
465
554
  for (const { reqSchemaType, resSchemaType } of schemas) {
466
555
  if (reqSchemaType) {
467
- jsonSchemas.push({ definitions: { [reqSchemaType]: this.generateJsonSchema(reqSchemaType) } });
556
+ jsonSchemas.push({ definitions: { [reqSchemaType]: this.generateJsonSchema(reqSchemaType, schemaFilePath) } });
468
557
  }
469
558
  if (resSchemaType) {
470
- jsonSchemas.push({ definitions: { [resSchemaType]: this.generateJsonSchema(resSchemaType) } });
559
+ jsonSchemas.push({ definitions: { [resSchemaType]: this.generateJsonSchema(resSchemaType, schemaFilePath) } });
471
560
  }
472
561
  }
473
562
 
@@ -494,9 +583,9 @@ import "..${appEntryScript.replace(/\.ts/g, "")}";
494
583
  return mergedSchemas;
495
584
  }
496
585
 
497
- private generateJsonSchema(typeName: string) {
586
+ private generateJsonSchema(typeName: string, schemaFilePath: string) {
498
587
  if (!this.schemaGenerator) {
499
- this.schemaGenerator = this.initJsonSchemaGenerator();
588
+ this.schemaGenerator = this.initJsonSchemaGenerator(schemaFilePath);
500
589
  }
501
590
  return this.schemaGenerator.createSchema(typeName);
502
591
  }
@@ -563,7 +652,10 @@ ${this.parsedTsSchemas.join("\n\n")}`
563
652
 
564
653
  addImports(schemaSourceFile, this.tsSchemasSymbolsToImports);
565
654
 
566
- return schemaSourceFile.save();
655
+ await schemaSourceFile.save();
656
+
657
+ // Return the file path so it can be used by ts-json-schema-generator
658
+ return schemaSourceFile.getFilePath();
567
659
  }
568
660
 
569
661
  /**
@@ -617,6 +709,13 @@ ${this.parsedTsSchemas.join("\n\n")}`
617
709
  const reqJsonSchema = JSON.stringify(reqSchemaType ? jsonSchemaDefs[reqSchemaType] : undefined);
618
710
  const resJsonSchema = JSON.stringify(resSchemaType ? jsonSchemaDefs[resSchemaType] : undefined);
619
711
 
712
+ // Remove existing __schemas variable if it exists (to avoid redeclaration errors)
713
+ const existingSchemas = sourceFile.getVariableStatements().filter((vs) => {
714
+ const varNames = vs.getDeclarations().map((d) => d.getName());
715
+ return varNames.includes("__schemas");
716
+ });
717
+ existingSchemas.forEach((v) => v.remove());
718
+
620
719
  sourceFile.addVariableStatement({
621
720
  declarationKind: VariableDeclarationKind.Const,
622
721
  isExported: true,
@@ -660,8 +759,15 @@ autoRegisteredJobs.push(...jobs);
660
759
 
661
760
  imports.push({
662
761
  defaultImport: "* as " + namespaceImport,
663
- moduleSpecifier: generatedFile.getRelativePathAsModuleSpecifierTo(sf),
762
+ moduleSpecifier: this.getModuleSpecifier(generatedFile, sf),
763
+ });
764
+
765
+ // Remove existing __file variable if it exists (to avoid redeclaration errors)
766
+ const existingFile = sf.getVariableStatements().filter((vs) => {
767
+ const varNames = vs.getDeclarations().map((d) => d.getName());
768
+ return varNames.includes("__file");
664
769
  });
770
+ existingFile.forEach((v) => v.remove());
665
771
 
666
772
  // Append metadata to source file that will be part of emitted dist bundle (javascript)
667
773
  sf.addVariableStatement({
package/src/index.ts CHANGED
@@ -9,3 +9,15 @@ export * from "./FlinkPlugin";
9
9
  export * from "./FlinkJob";
10
10
  export * from "./auth/FlinkAuthUser";
11
11
  export * from "./auth/FlinkAuthPlugin";
12
+
13
+ // Re-export Express types for plugins and consumer apps
14
+ // This ensures type consistency across the framework and plugins
15
+ export type {
16
+ Request as ExpressRequest,
17
+ Response as ExpressResponse,
18
+ NextFunction as ExpressNextFunction,
19
+ RequestHandler as ExpressRequestHandler,
20
+ ErrorRequestHandler as ExpressErrorRequestHandler,
21
+ Express,
22
+ static as expressStatic,
23
+ } from "express";
package/tsconfig.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "resolveJsonModule": true,
14
14
  "isolatedModules": true,
15
15
  "experimentalDecorators": true,
16
- "checkJs": true,
16
+ "checkJs": false,
17
17
  "typeRoots": ["./typings", "./node_modules/@types"],
18
18
  "declaration": true,
19
19
  "outDir": "dist"
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
@@ -1,140 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- var __assign = (this && this.__assign) || function () {
4
- __assign = Object.assign || function(t) {
5
- for (var s, i = 1, n = arguments.length; i < n; i++) {
6
- s = arguments[i];
7
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
8
- t[p] = s[p];
9
- }
10
- return t;
11
- };
12
- return __assign.apply(this, arguments);
13
- };
14
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
15
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
16
- return new (P || (P = Promise))(function (resolve, reject) {
17
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
20
- step((generator = generator.apply(thisArg, _arguments || [])).next());
21
- });
22
- };
23
- var __generator = (this && this.__generator) || function (thisArg, body) {
24
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
25
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
26
- function verb(n) { return function (v) { return step([n, v]); }; }
27
- function step(op) {
28
- if (f) throw new TypeError("Generator is already executing.");
29
- while (_) try {
30
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
31
- if (y = 0, t) op = [op[0] & 2, t.value];
32
- switch (op[0]) {
33
- case 0: case 1: t = op; break;
34
- case 4: _.label++; return { value: op[1], done: false };
35
- case 5: _.label++; y = op[1]; op = [0]; continue;
36
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
37
- default:
38
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
39
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
40
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
41
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
42
- if (t[2]) _.ops.pop();
43
- _.trys.pop(); continue;
44
- }
45
- op = body.call(thisArg, _);
46
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
47
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
48
- }
49
- };
50
- var __spreadArray = (this && this.__spreadArray) || function (to, from) {
51
- for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
52
- to[j] = from[i];
53
- return to;
54
- };
55
- Object.defineProperty(exports, "__esModule", { value: true });
56
- var path_1 = require("path");
57
- var ts_json_schema_generator_1 = require("ts-json-schema-generator");
58
- var ts_morph_1 = require("ts-morph");
59
- var FsUtils_1 = require("../src/FsUtils");
60
- var cli_utils_1 = require("./cli-utils");
61
- module.exports = function run(args) {
62
- return __awaiter(this, void 0, void 0, function () {
63
- var dir, verbose, typesDir, outFile, project, schemaDeclarations, generator, jsonSchemas, _i, _a, sf, sourceFileInterfaceDeclarations, sourceFileEnumDeclarations, sourceFileDeclarations, schema, mergedSchemas, file;
64
- return __generator(this, function (_b) {
65
- switch (_b.label) {
66
- case 0:
67
- if (args.includes("--help")) {
68
- console.log("\n Description\n Generates JSON schemas for types located in schemas directory or if any other directory\n is specified with option --types-dir. \n\n Outputs generated file(s) to dir '.flink' or if any other --out-dir is specified.\n\n Usage\n $ flink generate-schemas <dir> --types-dir <types-dir> --out-file <out-file>\n\n <dir> is project root as directory where tsconfig.son resides.\n \n Options \n --types-dir Directory where typescript types are located relative to <dir>, default \"./src/schemas\"\n --out-file Path to file that will contain generated json schemas relative to <dir>, default \"./.flink/generated-schemas.json\"\n --help Displays this message\n ");
69
- process.exit(0);
70
- }
71
- dir = "./";
72
- if (args[0] && !args[0].startsWith("--")) {
73
- dir = args[0];
74
- }
75
- verbose = cli_utils_1.getOption(args, "verbose", false, {
76
- isBoolean: true,
77
- });
78
- typesDir = cli_utils_1.getOption(args, "types-dir", "./src/schemas");
79
- outFile = cli_utils_1.getOption(args, "out-file", "./.flink/generated-schemas.json");
80
- project = new ts_morph_1.Project({
81
- tsConfigFilePath: path_1.join(dir, "tsconfig.json"),
82
- skipAddingFilesFromTsConfig: true,
83
- compilerOptions: {
84
- noEmit: true,
85
- },
86
- });
87
- project.addSourceFilesAtPaths(path_1.join(dir, typesDir, "**/*.ts"));
88
- console.log("Found", project.getSourceFiles().length, "files");
89
- schemaDeclarations = [];
90
- generator = initJsonSchemaGenerator(project);
91
- jsonSchemas = [];
92
- for (_i = 0, _a = project.getSourceFiles(); _i < _a.length; _i++) {
93
- sf = _a[_i];
94
- if (sf.getDefaultExportSymbol()) {
95
- console.warn("WARN: Schema file " + sf.getBaseName() + " has default export, but only named exports are picked up by json schemas parser");
96
- }
97
- sourceFileInterfaceDeclarations = sf.getChildrenOfKind(ts_morph_1.SyntaxKind.InterfaceDeclaration);
98
- sourceFileEnumDeclarations = sf.getChildrenOfKind(ts_morph_1.SyntaxKind.EnumDeclaration);
99
- sourceFileDeclarations = __spreadArray(__spreadArray([], sourceFileEnumDeclarations), sourceFileInterfaceDeclarations);
100
- schemaDeclarations.push.apply(schemaDeclarations, sourceFileDeclarations.map(function (d) { return d.compilerNode; }));
101
- verbose &&
102
- console.log("Found", sourceFileDeclarations.length, "schema(s) in file", sf.getBaseName());
103
- try {
104
- schema = generator.createSchemaFromNodes(sourceFileInterfaceDeclarations.map(function (d) { return d.compilerNode; }));
105
- jsonSchemas.push(schema);
106
- // console.log("Created schemas");
107
- }
108
- catch (err) {
109
- console.error("Failed to generate schema in file", sf.getBaseName() + ":", err);
110
- }
111
- }
112
- mergedSchemas = jsonSchemas.reduce(function (out, schema) {
113
- if (schema)
114
- if (schema.definitions) {
115
- out.definitions = __assign(__assign({}, out.definitions), schema.definitions);
116
- }
117
- return out;
118
- }, {
119
- $schema: "http://json-schema.org/draft-07/schema#",
120
- $ref: "#/definitions/Schemas",
121
- definitions: {},
122
- });
123
- file = path_1.join(dir, outFile);
124
- return [4 /*yield*/, FsUtils_1.writeJsonFile(file, mergedSchemas, {
125
- ensureDir: true,
126
- })];
127
- case 1:
128
- _b.sent();
129
- console.log("Wrote file", file);
130
- return [2 /*return*/];
131
- }
132
- });
133
- });
134
- };
135
- function initJsonSchemaGenerator(project) {
136
- var formatter = ts_json_schema_generator_1.createFormatter({});
137
- var parser = ts_json_schema_generator_1.createParser(project.getProgram().compilerObject, {});
138
- var generator = new ts_json_schema_generator_1.SchemaGenerator(project.getProgram().compilerObject, parser, formatter, { expose: "export" });
139
- return generator;
140
- }
@@ -1,60 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (_) try {
18
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.__schemas = exports.__params = exports.__query = exports.__file = exports.__assumedHttpMethod = exports.Route = void 0;
40
- var flink_1 = require("@flink-app/flink");
41
- exports.Route = {
42
- path: "/car-with-type-schema",
43
- method: flink_1.HttpMethod.get,
44
- permissions: "*",
45
- };
46
- var GetCarWithTypeSchema = function (_a) {
47
- var ctx = _a.ctx, req = _a.req;
48
- return __awaiter(void 0, void 0, void 0, function () {
49
- return __generator(this, function (_b) {
50
- return [2 /*return*/, {
51
- data: {
52
- model: "Volvo",
53
- },
54
- }];
55
- });
56
- });
57
- };
58
- exports.default = GetCarWithTypeSchema;
59
- exports.__assumedHttpMethod = "get", exports.__file = "GetCarWithTypeSchema.ts", exports.__query = [], exports.__params = [];
60
- exports.__schemas = { reqSchema: undefined, resSchema: { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "additionalProperties": false, "properties": { "model": { "type": "string" }, "metadata": { "type": "object", "properties": { "created": { "type": "string", "format": "date-time" } }, "additionalProperties": false } }, "required": ["model"], "definitions": {} } };
@@ -1,108 +0,0 @@
1
- {
2
- "name": "flink-test-app",
3
- "version": "0.1.0",
4
- "lockfileVersion": 2,
5
- "requires": true,
6
- "packages": {
7
- "": {
8
- "name": "flink-test-app",
9
- "version": "0.1.0",
10
- "dependencies": {
11
- "@flink-app/flink": "../../"
12
- },
13
- "devDependencies": {}
14
- },
15
- "../..": {
16
- "name": "@flink-app/flink",
17
- "version": "0.2.0-beta.3",
18
- "hasInstallScript": true,
19
- "license": "MIT",
20
- "dependencies": {
21
- "@types/cors": "^2.8.10",
22
- "@types/express": "^4.17.11",
23
- "@types/fs-extra": "^9.0.12",
24
- "@types/mongodb": "3.6.12",
25
- "@types/uuid": "^8.3.0",
26
- "ajv": "^8.2.0",
27
- "ajv-formats": "^2.1.0",
28
- "body-parser": "^1.19.0",
29
- "cors": "^2.8.5",
30
- "express": "^4.17.1",
31
- "folder-hash": "^4.0.1",
32
- "fs-extra": "^10.0.0",
33
- "mkdirp": "^1.0.4",
34
- "mock-json-schema": "^1.0.8",
35
- "mongodb": "^3.6.6",
36
- "node-color-log": "^5.2.0",
37
- "passport": "^0.4.1",
38
- "passport-jwt": "^4.0.0",
39
- "reflect-metadata": "^0.1.13",
40
- "tiny-glob": "^0.2.9",
41
- "ts-json-schema-generator": "^0.94.1",
42
- "ts-morph": "^11.0.0",
43
- "typescript": "4.2.3",
44
- "uuid": "^8.3.2"
45
- },
46
- "bin": {
47
- "flink": "dist/bin/flink.js"
48
- },
49
- "devDependencies": {
50
- "@types/folder-hash": "^4.0.0",
51
- "@types/jasmine": "^3.7.1",
52
- "@types/json-schema": "^7.0.7",
53
- "@types/mkdirp": "^1.0.1",
54
- "@types/node": "^15.0.1",
55
- "jasmine": "^3.7.0",
56
- "jasmine-spec-reporter": "^7.0.0",
57
- "jasmine-ts": "^0.3.3",
58
- "nodemon": "^2.0.7",
59
- "ts-node": "^9.1.1"
60
- }
61
- },
62
- "node_modules/@flink-app/flink": {
63
- "resolved": "../..",
64
- "link": true
65
- }
66
- },
67
- "dependencies": {
68
- "@flink-app/flink": {
69
- "version": "file:../..",
70
- "requires": {
71
- "@types/cors": "^2.8.10",
72
- "@types/express": "^4.17.11",
73
- "@types/folder-hash": "^4.0.0",
74
- "@types/fs-extra": "^9.0.12",
75
- "@types/jasmine": "^3.7.1",
76
- "@types/json-schema": "^7.0.7",
77
- "@types/mkdirp": "^1.0.1",
78
- "@types/mongodb": "3.6.12",
79
- "@types/node": "^15.0.1",
80
- "@types/uuid": "^8.3.0",
81
- "ajv": "^8.2.0",
82
- "ajv-formats": "^2.1.0",
83
- "body-parser": "^1.19.0",
84
- "cors": "^2.8.5",
85
- "express": "^4.17.1",
86
- "folder-hash": "^4.0.1",
87
- "fs-extra": "^10.0.0",
88
- "jasmine": "^3.7.0",
89
- "jasmine-spec-reporter": "^7.0.0",
90
- "jasmine-ts": "^0.3.3",
91
- "mkdirp": "^1.0.4",
92
- "mock-json-schema": "^1.0.8",
93
- "mongodb": "^3.6.6",
94
- "node-color-log": "^5.2.0",
95
- "nodemon": "^2.0.7",
96
- "passport": "^0.4.1",
97
- "passport-jwt": "^4.0.0",
98
- "reflect-metadata": "^0.1.13",
99
- "tiny-glob": "^0.2.9",
100
- "ts-json-schema-generator": "^0.94.1",
101
- "ts-morph": "^11.0.0",
102
- "ts-node": "^9.1.1",
103
- "typescript": "4.2.3",
104
- "uuid": "^8.3.2"
105
- }
106
- }
107
- }
108
- }