@flink-app/flink 0.13.1 → 0.13.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @flink-app/flink
2
2
 
3
+ ## 0.13.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Use projects tsconfig.json for schema generation
8
+
9
+ ## 0.13.2
10
+
11
+ ### Patch Changes
12
+
13
+ - - Fix schema generator to support built-in types, generic parameters, utility types, and recursive schemas.
14
+ - Prevented schema generator from attempting to import built-in TypeScript types (Array, Date, etc.) from lib files.
15
+ - Fixed generic type parameter resolution (e.g., PaginatedResponse<T> now correctly expands to concrete types)
16
+
3
17
  ## 0.13.1
4
18
 
5
19
  ### Patch Changes
@@ -482,9 +482,8 @@ var TypeScriptCompiler = /** @class */ (function () {
482
482
  };
483
483
  TypeScriptCompiler.prototype.saveIntermediateTsSchema = function (schema, handlerFile, suffix) {
484
484
  return __awaiter(this, void 0, void 0, function () {
485
- var handlerFileName, generatedSchemaInterfaceStr, schemaInterfaceName, schemaSymbol, interfaceName, declaration, _i, _a, typeToImport, arrayTypeArg, schemaSymbol, interfaceName, declaration, props, _b, _c, typeToImport, declarations, declaration, typeRefIdentifiers;
486
- var _this = this;
487
- return __generator(this, function (_d) {
485
+ var handlerFileName, generatedSchemaInterfaceStr, schemaInterfaceName, schemaSymbol, interfaceName, declaration, _i, _a, typeToImport, arrayTypeArg, schemaSymbol, interfaceName, declaration, props, _b, _c, typeToImport, declarations, declaration, propertySignatures, _d, _e, prop, propType, typeSymbol, typeDeclaration, elementType, elementSymbol, elementDeclaration;
486
+ return __generator(this, function (_f) {
488
487
  if (schema.isAny()) {
489
488
  return [2 /*return*/]; // 'any' indicates that no schema is used
490
489
  }
@@ -541,19 +540,49 @@ var TypeScriptCompiler = /** @class */ (function () {
541
540
  else if (schema.isObject()) {
542
541
  declarations = schema.getSymbolOrThrow().getDeclarations();
543
542
  declaration = declarations[0];
544
- // Only extract type references if declaration exists (won't exist for empty object literals like {})
545
- if (declaration) {
546
- typeRefIdentifiers = declaration
547
- .getDescendantsOfKind(ts_morph_1.SyntaxKind.TypeReference)
548
- .map(function (typeRef) { return typeRef.getFirstChildByKindOrThrow(ts_morph_1.SyntaxKind.Identifier); });
549
- typeRefIdentifiers.forEach(function (tr) {
550
- _this.tsSchemasSymbolsToImports.push(tr.getSymbolOrThrow().getDeclaredType().getSymbolOrThrow());
551
- });
543
+ propertySignatures = schema.getProperties().map(function (prop) {
544
+ var propName = prop.getName();
545
+ var propType = prop.getTypeAtLocation(handlerFile);
546
+ var propTypeText = propType.getText(undefined, ts_morph_1.ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
547
+ // Check if property is optional
548
+ // For utility types (Omit, Pick, etc.), properties may not have value declarations
549
+ var valueDeclaration = prop.getValueDeclaration();
550
+ var isOptional = false;
551
+ if (valueDeclaration) {
552
+ // Property has a source declaration (normal case)
553
+ isOptional = valueDeclaration.getType().isNullable() || valueDeclaration.compilerNode.questionToken !== undefined;
554
+ }
555
+ else {
556
+ // Property is synthetic (from utility types like Omit, Pick, etc.)
557
+ // Check if the property itself is optional by examining the symbol flags
558
+ isOptional = !!(prop.getFlags() & ts_morph_1.ts.SymbolFlags.Optional);
559
+ }
560
+ return "".concat(propName).concat(isOptional ? "?" : "", ": ").concat(propTypeText);
561
+ });
562
+ // Extract type references for imports from resolved types
563
+ for (_d = 0, _e = schema.getProperties(); _d < _e.length; _d++) {
564
+ prop = _e[_d];
565
+ propType = prop.getTypeAtLocation(handlerFile);
566
+ typeSymbol = propType.getSymbol();
567
+ if (typeSymbol) {
568
+ typeDeclaration = typeSymbol.getDeclarations()[0];
569
+ if (typeDeclaration && typeDeclaration.getSourceFile() !== handlerFile) {
570
+ this.tsSchemasSymbolsToImports.push(typeSymbol);
571
+ }
572
+ }
573
+ // Also check for array element types
574
+ if (propType.isArray()) {
575
+ elementType = propType.getArrayElementType();
576
+ elementSymbol = elementType === null || elementType === void 0 ? void 0 : elementType.getSymbol();
577
+ if (elementSymbol) {
578
+ elementDeclaration = elementSymbol.getDeclarations()[0];
579
+ if (elementDeclaration && elementDeclaration.getSourceFile() !== handlerFile) {
580
+ this.tsSchemasSymbolsToImports.push(elementSymbol);
581
+ }
582
+ }
583
+ }
552
584
  }
553
- generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " { ").concat(schema
554
- .getProperties()
555
- .map(function (p) { return p.getValueDeclarationOrThrow().getText(); })
556
- .join("\n"), " }");
585
+ generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " { ").concat(propertySignatures.join(";\n"), " }");
557
586
  }
558
587
  else {
559
588
  console.log("[WARN] Unknown schema type", schema.getText());
@@ -583,7 +612,7 @@ var TypeScriptCompiler = /** @class */ (function () {
583
612
  extraTags: [],
584
613
  functions: "fail",
585
614
  discriminatorType: "json-schema",
586
- // tsconfig: tsconfigPath,
615
+ tsconfig: tsconfigPath,
587
616
  };
588
617
  console.log("Creating TypeScript program for schema generation:");
589
618
  console.log(" Schema file:", schemaFilePath);
@@ -604,9 +633,7 @@ var TypeScriptCompiler = /** @class */ (function () {
604
633
  if (info.file) {
605
634
  var _b = info.file.getLineAndCharacterOfPosition(info.start), line = _b.line, character = _b.character;
606
635
  var fileName = info.file.fileName.replace(this.cwd, ".");
607
- var message = typeof info.messageText === "string"
608
- ? info.messageText
609
- : info.messageText.messageText;
636
+ var message = typeof info.messageText === "string" ? info.messageText : info.messageText.messageText;
610
637
  console.error(" ".concat(fileName, ":").concat(line + 1, ":").concat(character + 1));
611
638
  console.error(" ".concat(message, "\n"));
612
639
  }
@@ -71,6 +71,42 @@ function addImport(toSourceFile, symbol) {
71
71
  });
72
72
  }
73
73
  }
74
+ /**
75
+ * Checks if a symbol should be filtered out from imports.
76
+ * Returns true for built-in types, TypeScript lib types, and generic type parameters.
77
+ * @param symbol
78
+ * @returns
79
+ */
80
+ function shouldFilterSymbolFromImport(symbol) {
81
+ var symbolDeclaration = symbol.getDeclarations()[0];
82
+ if (!symbolDeclaration) {
83
+ return true; // Filter out symbols without declarations
84
+ }
85
+ var symbolSourceFile = symbolDeclaration.getSourceFile();
86
+ var sourceFilePath = symbolSourceFile.getFilePath();
87
+ // Filter out TypeScript lib files (lib.*.d.ts)
88
+ if (sourceFilePath.includes("/node_modules/typescript/lib/")) {
89
+ return true;
90
+ }
91
+ // Filter out common built-in global types by name
92
+ var symbolName = symbol.getEscapedName();
93
+ var builtInTypes = new Set([
94
+ "Array", "Date", "String", "Number", "Boolean", "Object", "Function",
95
+ "RegExp", "Error", "Promise", "Set", "Map", "WeakMap", "WeakSet",
96
+ "ArrayBuffer", "DataView", "Int8Array", "Uint8Array", "Uint8ClampedArray",
97
+ "Int16Array", "Uint16Array", "Int32Array", "Uint32Array", "Float32Array", "Float64Array",
98
+ "Readonly", "Partial", "Required", "Pick", "Record", "Exclude", "Extract", "Omit", "NonNullable",
99
+ "ReadonlyArray", "ReadonlyMap", "ReadonlySet"
100
+ ]);
101
+ if (builtInTypes.has(symbolName)) {
102
+ return true;
103
+ }
104
+ // Filter out single-letter type parameters (generic parameters like T, K, V, etc.)
105
+ if (symbolName.length === 1 && symbolName.match(/^[A-Z]$/)) {
106
+ return true;
107
+ }
108
+ return false;
109
+ }
74
110
  /**
75
111
  * Adds imports to modules where provided symbols resides.
76
112
  * Imports are added to provided source file.
@@ -81,6 +117,10 @@ function addImports(toSourceFile, symbols) {
81
117
  var importsByModuleSpecifier = new Map();
82
118
  for (var _i = 0, symbols_1 = symbols; _i < symbols_1.length; _i++) {
83
119
  var symbol = symbols_1[_i];
120
+ // Filter out built-in types and generic parameters
121
+ if (shouldFilterSymbolFromImport(symbol)) {
122
+ continue;
123
+ }
84
124
  var symbolDeclaration = symbol.getDeclarations()[0];
85
125
  if (!symbolDeclaration) {
86
126
  throw new Error("Missing declaration for symbol " + symbol.getFullyQualifiedName());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flink-app/flink",
3
- "version": "0.13.1",
3
+ "version": "0.13.3",
4
4
  "description": "Typescript only framework for creating REST-like APIs on top of Express and mongodb",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "main": "dist/src/index.js",
@@ -480,21 +480,57 @@ export default {}; // Export an empty object to make it a module
480
480
  const declarations = schema.getSymbolOrThrow().getDeclarations();
481
481
  const declaration = declarations[0];
482
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
- });
483
+ // Build property signatures using resolved types instead of source text
484
+ // This ensures generic type parameters are properly expanded
485
+ const propertySignatures = schema.getProperties().map((prop) => {
486
+ const propName = prop.getName();
487
+ const propType = prop.getTypeAtLocation(handlerFile);
488
+ const propTypeText = propType.getText(undefined, ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
489
+
490
+ // Check if property is optional
491
+ // For utility types (Omit, Pick, etc.), properties may not have value declarations
492
+ const valueDeclaration = prop.getValueDeclaration();
493
+ let isOptional = false;
494
+
495
+ if (valueDeclaration) {
496
+ // Property has a source declaration (normal case)
497
+ isOptional = valueDeclaration.getType().isNullable() || (valueDeclaration.compilerNode as any).questionToken !== undefined;
498
+ } else {
499
+ // Property is synthetic (from utility types like Omit, Pick, etc.)
500
+ // Check if the property itself is optional by examining the symbol flags
501
+ isOptional = !!(prop.getFlags() & ts.SymbolFlags.Optional);
502
+ }
503
+
504
+ return `${propName}${isOptional ? "?" : ""}: ${propTypeText}`;
505
+ });
506
+
507
+ // Extract type references for imports from resolved types
508
+ for (const prop of schema.getProperties()) {
509
+ const propType = prop.getTypeAtLocation(handlerFile);
510
+
511
+ // Get symbol for the property type
512
+ const typeSymbol = propType.getSymbol();
513
+ if (typeSymbol) {
514
+ const typeDeclaration = typeSymbol.getDeclarations()[0];
515
+ if (typeDeclaration && typeDeclaration.getSourceFile() !== handlerFile) {
516
+ this.tsSchemasSymbolsToImports.push(typeSymbol);
517
+ }
518
+ }
519
+
520
+ // Also check for array element types
521
+ if (propType.isArray()) {
522
+ const elementType = propType.getArrayElementType();
523
+ const elementSymbol = elementType?.getSymbol();
524
+ if (elementSymbol) {
525
+ const elementDeclaration = elementSymbol.getDeclarations()[0];
526
+ if (elementDeclaration && elementDeclaration.getSourceFile() !== handlerFile) {
527
+ this.tsSchemasSymbolsToImports.push(elementSymbol);
528
+ }
529
+ }
530
+ }
492
531
  }
493
532
 
494
- generatedSchemaInterfaceStr = `export interface ${schemaInterfaceName} { ${schema
495
- .getProperties()
496
- .map((p) => p.getValueDeclarationOrThrow().getText())
497
- .join("\n")} }`;
533
+ generatedSchemaInterfaceStr = `export interface ${schemaInterfaceName} { ${propertySignatures.join(";\n")} }`;
498
534
  } else {
499
535
  console.log("[WARN] Unknown schema type", schema.getText());
500
536
  }
@@ -524,7 +560,7 @@ export default {}; // Export an empty object to make it a module
524
560
  extraTags: [],
525
561
  functions: "fail",
526
562
  discriminatorType: "json-schema",
527
- // tsconfig: tsconfigPath,
563
+ tsconfig: tsconfigPath,
528
564
  };
529
565
 
530
566
  console.log("Creating TypeScript program for schema generation:");
@@ -546,9 +582,7 @@ export default {}; // Export an empty object to make it a module
546
582
  if (info.file) {
547
583
  const { line, character } = info.file.getLineAndCharacterOfPosition(info.start);
548
584
  const fileName = info.file.fileName.replace(this.cwd, ".");
549
- const message = typeof info.messageText === "string"
550
- ? info.messageText
551
- : info.messageText.messageText;
585
+ const message = typeof info.messageText === "string" ? info.messageText : info.messageText.messageText;
552
586
 
553
587
  console.error(` ${fileName}:${line + 1}:${character + 1}`);
554
588
  console.error(` ${message}\n`);
@@ -71,6 +71,50 @@ export function addImport(toSourceFile: SourceFile, symbol: Symbol) {
71
71
  }
72
72
  }
73
73
 
74
+ /**
75
+ * Checks if a symbol should be filtered out from imports.
76
+ * Returns true for built-in types, TypeScript lib types, and generic type parameters.
77
+ * @param symbol
78
+ * @returns
79
+ */
80
+ function shouldFilterSymbolFromImport(symbol: Symbol): boolean {
81
+ const symbolDeclaration = symbol.getDeclarations()[0];
82
+
83
+ if (!symbolDeclaration) {
84
+ return true; // Filter out symbols without declarations
85
+ }
86
+
87
+ const symbolSourceFile = symbolDeclaration.getSourceFile();
88
+ const sourceFilePath = symbolSourceFile.getFilePath();
89
+
90
+ // Filter out TypeScript lib files (lib.*.d.ts)
91
+ if (sourceFilePath.includes("/node_modules/typescript/lib/")) {
92
+ return true;
93
+ }
94
+
95
+ // Filter out common built-in global types by name
96
+ const symbolName = symbol.getEscapedName();
97
+ const builtInTypes = new Set([
98
+ "Array", "Date", "String", "Number", "Boolean", "Object", "Function",
99
+ "RegExp", "Error", "Promise", "Set", "Map", "WeakMap", "WeakSet",
100
+ "ArrayBuffer", "DataView", "Int8Array", "Uint8Array", "Uint8ClampedArray",
101
+ "Int16Array", "Uint16Array", "Int32Array", "Uint32Array", "Float32Array", "Float64Array",
102
+ "Readonly", "Partial", "Required", "Pick", "Record", "Exclude", "Extract", "Omit", "NonNullable",
103
+ "ReadonlyArray", "ReadonlyMap", "ReadonlySet"
104
+ ]);
105
+
106
+ if (builtInTypes.has(symbolName)) {
107
+ return true;
108
+ }
109
+
110
+ // Filter out single-letter type parameters (generic parameters like T, K, V, etc.)
111
+ if (symbolName.length === 1 && symbolName.match(/^[A-Z]$/)) {
112
+ return true;
113
+ }
114
+
115
+ return false;
116
+ }
117
+
74
118
  /**
75
119
  * Adds imports to modules where provided symbols resides.
76
120
  * Imports are added to provided source file.
@@ -81,6 +125,11 @@ export function addImports(toSourceFile: SourceFile, symbols: Symbol[]) {
81
125
  const importsByModuleSpecifier = new Map<string, { defaultImportName?: string; namedImports: string[] }>();
82
126
 
83
127
  for (const symbol of symbols) {
128
+ // Filter out built-in types and generic parameters
129
+ if (shouldFilterSymbolFromImport(symbol)) {
130
+ continue;
131
+ }
132
+
84
133
  const symbolDeclaration = symbol.getDeclarations()[0];
85
134
 
86
135
  if (!symbolDeclaration) {