@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 +14 -0
- package/dist/src/TypeScriptCompiler.js +46 -19
- package/dist/src/TypeScriptUtils.js +40 -0
- package/package.json +1 -1
- package/src/TypeScriptCompiler.ts +51 -17
- package/src/TypeScriptUtils.ts +49 -0
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,
|
|
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,49 @@ 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() || 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(
|
|
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
|
-
|
|
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
|
@@ -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
|
-
//
|
|
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() || (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} { ${
|
|
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
|
-
|
|
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`);
|
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) {
|