@flink-app/flink 0.13.0 → 0.13.2
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 +14 -0
- package/dist/src/TypeScriptCompiler.js +73 -16
- package/dist/src/TypeScriptUtils.js +40 -0
- package/package.json +1 -1
- package/src/TypeScriptCompiler.ts +78 -14
- package/src/TypeScriptUtils.ts +49 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @flink-app/flink
|
|
2
2
|
|
|
3
|
+
## 0.13.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- - Fix schema generator to support built-in types, generic parameters, utility types, and recursive schemas.
|
|
8
|
+
- Prevented schema generator from attempting to import built-in TypeScript types (Array, Date, etc.) from lib files.
|
|
9
|
+
- Fixed generic type parameter resolution (e.g., PaginatedResponse<T> now correctly expands to concrete types)
|
|
10
|
+
|
|
11
|
+
## 0.13.1
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Fixed invalid types and improve typescript error message during schema compilation
|
|
16
|
+
|
|
3
17
|
## 0.13.0
|
|
4
18
|
|
|
5
19
|
### Minor 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,
|
|
486
|
-
|
|
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,50 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
541
540
|
else if (schema.isObject()) {
|
|
542
541
|
declarations = schema.getSymbolOrThrow().getDeclarations();
|
|
543
542
|
declaration = declarations[0];
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
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() ||
|
|
554
|
+
valueDeclaration.compilerNode.questionToken !== undefined;
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
// Property is synthetic (from utility types like Omit, Pick, etc.)
|
|
558
|
+
// Check if the property itself is optional by examining the symbol flags
|
|
559
|
+
isOptional = !!(prop.getFlags() & ts_morph_1.ts.SymbolFlags.Optional);
|
|
560
|
+
}
|
|
561
|
+
return "".concat(propName).concat(isOptional ? '?' : '', ": ").concat(propTypeText);
|
|
562
|
+
});
|
|
563
|
+
// Extract type references for imports from resolved types
|
|
564
|
+
for (_d = 0, _e = schema.getProperties(); _d < _e.length; _d++) {
|
|
565
|
+
prop = _e[_d];
|
|
566
|
+
propType = prop.getTypeAtLocation(handlerFile);
|
|
567
|
+
typeSymbol = propType.getSymbol();
|
|
568
|
+
if (typeSymbol) {
|
|
569
|
+
typeDeclaration = typeSymbol.getDeclarations()[0];
|
|
570
|
+
if (typeDeclaration && typeDeclaration.getSourceFile() !== handlerFile) {
|
|
571
|
+
this.tsSchemasSymbolsToImports.push(typeSymbol);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
// Also check for array element types
|
|
575
|
+
if (propType.isArray()) {
|
|
576
|
+
elementType = propType.getArrayElementType();
|
|
577
|
+
elementSymbol = elementType === null || elementType === void 0 ? void 0 : elementType.getSymbol();
|
|
578
|
+
if (elementSymbol) {
|
|
579
|
+
elementDeclaration = elementSymbol.getDeclarations()[0];
|
|
580
|
+
if (elementDeclaration && elementDeclaration.getSourceFile() !== handlerFile) {
|
|
581
|
+
this.tsSchemasSymbolsToImports.push(elementSymbol);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
552
585
|
}
|
|
553
|
-
generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " { ").concat(
|
|
554
|
-
.getProperties()
|
|
555
|
-
.map(function (p) { return p.getValueDeclarationOrThrow().getText(); })
|
|
556
|
-
.join("\n"), " }");
|
|
586
|
+
generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " { ").concat(propertySignatures.join(";\n"), " }");
|
|
557
587
|
}
|
|
558
588
|
else {
|
|
559
589
|
console.log("[WARN] Unknown schema type", schema.getText());
|
|
@@ -590,7 +620,34 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
590
620
|
console.log(" tsconfig:", tsconfigPath);
|
|
591
621
|
// Create a fresh TypeScript Program that includes the schema file
|
|
592
622
|
// This ensures ts-json-schema-generator can find the types we just generated
|
|
593
|
-
var program
|
|
623
|
+
var program;
|
|
624
|
+
try {
|
|
625
|
+
program = (0, ts_json_schema_generator_1.createProgram)(conf);
|
|
626
|
+
}
|
|
627
|
+
catch (error) {
|
|
628
|
+
// Format the error in a more developer-friendly way
|
|
629
|
+
console.error("\n❌ Schema generation failed due to TypeScript compilation errors:\n");
|
|
630
|
+
if (error.diagnostic && error.diagnostic.relatedInformation) {
|
|
631
|
+
// Extract and display only the relevant error messages
|
|
632
|
+
for (var _i = 0, _a = error.diagnostic.relatedInformation; _i < _a.length; _i++) {
|
|
633
|
+
var info = _a[_i];
|
|
634
|
+
if (info.file) {
|
|
635
|
+
var _b = info.file.getLineAndCharacterOfPosition(info.start), line = _b.line, character = _b.character;
|
|
636
|
+
var fileName = info.file.fileName.replace(this.cwd, ".");
|
|
637
|
+
var message = typeof info.messageText === "string"
|
|
638
|
+
? info.messageText
|
|
639
|
+
: info.messageText.messageText;
|
|
640
|
+
console.error(" ".concat(fileName, ":").concat(line + 1, ":").concat(character + 1));
|
|
641
|
+
console.error(" ".concat(message, "\n"));
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
else if (error.message) {
|
|
646
|
+
console.error(" ".concat(error.message, "\n"));
|
|
647
|
+
}
|
|
648
|
+
console.error("💡 Tip: Fix the TypeScript errors above and try again.\n");
|
|
649
|
+
process.exit(1);
|
|
650
|
+
}
|
|
594
651
|
console.log(" TypeScript version:", ts_morph_1.ts.version);
|
|
595
652
|
console.log(" Program root files:", program.getRootFileNames().length);
|
|
596
653
|
var formatter = (0, ts_json_schema_generator_1.createFormatter)(conf);
|
|
@@ -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
|
@@ -480,21 +480,58 @@ 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
|
-
//
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
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() ||
|
|
498
|
+
(valueDeclaration.compilerNode as any).questionToken !== undefined;
|
|
499
|
+
} else {
|
|
500
|
+
// Property is synthetic (from utility types like Omit, Pick, etc.)
|
|
501
|
+
// Check if the property itself is optional by examining the symbol flags
|
|
502
|
+
isOptional = !!(prop.getFlags() & ts.SymbolFlags.Optional);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
return `${propName}${isOptional ? '?' : ''}: ${propTypeText}`;
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
// Extract type references for imports from resolved types
|
|
509
|
+
for (const prop of schema.getProperties()) {
|
|
510
|
+
const propType = prop.getTypeAtLocation(handlerFile);
|
|
511
|
+
|
|
512
|
+
// Get symbol for the property type
|
|
513
|
+
const typeSymbol = propType.getSymbol();
|
|
514
|
+
if (typeSymbol) {
|
|
515
|
+
const typeDeclaration = typeSymbol.getDeclarations()[0];
|
|
516
|
+
if (typeDeclaration && typeDeclaration.getSourceFile() !== handlerFile) {
|
|
517
|
+
this.tsSchemasSymbolsToImports.push(typeSymbol);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// Also check for array element types
|
|
522
|
+
if (propType.isArray()) {
|
|
523
|
+
const elementType = propType.getArrayElementType();
|
|
524
|
+
const elementSymbol = elementType?.getSymbol();
|
|
525
|
+
if (elementSymbol) {
|
|
526
|
+
const elementDeclaration = elementSymbol.getDeclarations()[0];
|
|
527
|
+
if (elementDeclaration && elementDeclaration.getSourceFile() !== handlerFile) {
|
|
528
|
+
this.tsSchemasSymbolsToImports.push(elementSymbol);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
492
532
|
}
|
|
493
533
|
|
|
494
|
-
generatedSchemaInterfaceStr = `export interface ${schemaInterfaceName} { ${
|
|
495
|
-
.getProperties()
|
|
496
|
-
.map((p) => p.getValueDeclarationOrThrow().getText())
|
|
497
|
-
.join("\n")} }`;
|
|
534
|
+
generatedSchemaInterfaceStr = `export interface ${schemaInterfaceName} { ${propertySignatures.join(";\n")} }`;
|
|
498
535
|
} else {
|
|
499
536
|
console.log("[WARN] Unknown schema type", schema.getText());
|
|
500
537
|
}
|
|
@@ -533,7 +570,34 @@ export default {}; // Export an empty object to make it a module
|
|
|
533
570
|
|
|
534
571
|
// Create a fresh TypeScript Program that includes the schema file
|
|
535
572
|
// This ensures ts-json-schema-generator can find the types we just generated
|
|
536
|
-
|
|
573
|
+
let program;
|
|
574
|
+
try {
|
|
575
|
+
program = createProgram(conf);
|
|
576
|
+
} catch (error: any) {
|
|
577
|
+
// Format the error in a more developer-friendly way
|
|
578
|
+
console.error("\n❌ Schema generation failed due to TypeScript compilation errors:\n");
|
|
579
|
+
|
|
580
|
+
if (error.diagnostic && error.diagnostic.relatedInformation) {
|
|
581
|
+
// Extract and display only the relevant error messages
|
|
582
|
+
for (const info of error.diagnostic.relatedInformation) {
|
|
583
|
+
if (info.file) {
|
|
584
|
+
const { line, character } = info.file.getLineAndCharacterOfPosition(info.start);
|
|
585
|
+
const fileName = info.file.fileName.replace(this.cwd, ".");
|
|
586
|
+
const message = typeof info.messageText === "string"
|
|
587
|
+
? info.messageText
|
|
588
|
+
: info.messageText.messageText;
|
|
589
|
+
|
|
590
|
+
console.error(` ${fileName}:${line + 1}:${character + 1}`);
|
|
591
|
+
console.error(` ${message}\n`);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
} else if (error.message) {
|
|
595
|
+
console.error(` ${error.message}\n`);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
console.error("💡 Tip: Fix the TypeScript errors above and try again.\n");
|
|
599
|
+
process.exit(1);
|
|
600
|
+
}
|
|
537
601
|
|
|
538
602
|
console.log(" TypeScript version:", ts.version);
|
|
539
603
|
console.log(" Program root files:", program.getRootFileNames().length);
|
package/src/TypeScriptUtils.ts
CHANGED
|
@@ -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) {
|