@flink-app/flink 0.14.3 → 2.0.0-alpha.100
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 +1051 -0
- package/SCHEMA_EXTRACTION_ANALYSIS.md +494 -0
- package/SIMPLE_AST_FEASIBILITY.md +570 -0
- package/bin/flink.ts +13 -2
- package/cli/build.ts +24 -44
- package/cli/clean.ts +13 -25
- package/cli/cli-utils.ts +190 -17
- package/cli/dev.ts +252 -0
- package/cli/loadEnvFiles.ts +116 -0
- package/cli/run.ts +45 -62
- package/dist/bin/flink.js +61 -2
- package/dist/cli/build.js +20 -25
- package/dist/cli/clean.js +12 -10
- package/dist/cli/cli-utils.d.ts +34 -3
- package/dist/cli/cli-utils.js +193 -12
- package/dist/cli/dev.d.ts +2 -0
- package/dist/cli/dev.js +279 -0
- package/dist/cli/loadEnvFiles.d.ts +30 -0
- package/dist/cli/loadEnvFiles.js +113 -0
- package/dist/cli/run.js +47 -46
- package/dist/src/DependencyTracker.d.ts +44 -0
- package/dist/src/DependencyTracker.js +239 -0
- package/dist/src/FlinkApp.d.ts +163 -10
- package/dist/src/FlinkApp.js +847 -184
- package/dist/src/FlinkContext.d.ts +41 -0
- package/dist/src/FlinkErrors.d.ts +19 -6
- package/dist/src/FlinkErrors.js +36 -42
- package/dist/src/FlinkHttpHandler.d.ts +219 -26
- package/dist/src/FlinkHttpHandler.js +37 -1
- package/dist/src/FlinkJob.d.ts +10 -0
- package/dist/src/FlinkLog.d.ts +82 -18
- package/dist/src/FlinkLog.js +165 -13
- package/dist/src/FlinkLogFactory.d.ts +288 -0
- package/dist/src/FlinkLogFactory.js +619 -0
- package/dist/src/FlinkRepo.d.ts +10 -2
- package/dist/src/FlinkRepo.js +11 -1
- package/dist/src/FlinkRequestContext.d.ts +63 -0
- package/dist/src/FlinkRequestContext.js +74 -0
- package/dist/src/FlinkResponse.d.ts +6 -0
- package/dist/src/FlinkService.d.ts +38 -0
- package/dist/src/FlinkService.js +46 -0
- package/dist/src/LeaderElection.d.ts +45 -0
- package/dist/src/LeaderElection.js +269 -0
- package/dist/src/SchemaCache.d.ts +84 -0
- package/dist/src/SchemaCache.js +289 -0
- package/dist/src/TypeScriptCompiler.d.ts +161 -51
- package/dist/src/TypeScriptCompiler.js +1253 -617
- package/dist/src/TypeScriptUtils.js +4 -0
- package/dist/src/ai/AgentRunner.d.ts +39 -0
- package/dist/src/ai/AgentRunner.js +760 -0
- package/dist/src/ai/ConversationAgent.d.ts +279 -0
- package/dist/src/ai/ConversationAgent.js +404 -0
- package/dist/src/ai/ConversationFlinkAgent.d.ts +278 -0
- package/dist/src/ai/ConversationFlinkAgent.js +404 -0
- package/dist/src/ai/FlinkAgent.d.ts +690 -0
- package/dist/src/ai/FlinkAgent.js +729 -0
- package/dist/src/ai/FlinkTool.d.ts +135 -0
- package/dist/src/ai/FlinkTool.js +2 -0
- package/dist/src/ai/InMemoryConversationAgent.d.ts +121 -0
- package/dist/src/ai/InMemoryConversationAgent.js +209 -0
- package/dist/src/ai/LLMAdapter.d.ts +148 -0
- package/dist/src/ai/LLMAdapter.js +2 -0
- package/dist/src/ai/PersistentFlinkAgent.d.ts +278 -0
- package/dist/src/ai/PersistentFlinkAgent.js +403 -0
- package/dist/src/ai/SubAgentExecutor.d.ts +38 -0
- package/dist/src/ai/SubAgentExecutor.js +223 -0
- package/dist/src/ai/ToolExecutor.d.ts +64 -0
- package/dist/src/ai/ToolExecutor.js +497 -0
- package/dist/src/ai/agentInstructions.d.ts +68 -0
- package/dist/src/ai/agentInstructions.js +286 -0
- package/dist/src/ai/index.d.ts +8 -0
- package/dist/src/ai/index.js +26 -0
- package/dist/src/ai/instructionFileLoader.d.ts +44 -0
- package/dist/src/ai/instructionFileLoader.js +179 -0
- package/dist/src/auth/FlinkAuthPlugin.d.ts +1 -1
- package/dist/src/handlers/StreamWriterFactory.d.ts +20 -0
- package/dist/src/handlers/StreamWriterFactory.js +83 -0
- package/dist/src/index.d.ts +14 -0
- package/dist/src/index.js +17 -0
- package/dist/src/loadPluginSchemas.d.ts +45 -0
- package/dist/src/loadPluginSchemas.js +143 -0
- package/dist/src/schema-extraction/ComplexTypeDetection.d.ts +40 -0
- package/dist/src/schema-extraction/ComplexTypeDetection.js +75 -0
- package/dist/src/schema-extraction/TypeScriptSourceParser.d.ts +321 -0
- package/dist/src/schema-extraction/TypeScriptSourceParser.js +925 -0
- package/dist/src/schema-extraction/TypeScriptSourceParser.spec.d.ts +1 -0
- package/dist/src/schema-extraction/TypeScriptSourceParser.spec.js +233 -0
- package/dist/src/schema-extraction/TypeScriptTokenizer.d.ts +57 -0
- package/dist/src/schema-extraction/TypeScriptTokenizer.js +177 -0
- package/dist/src/schema-extraction/index.d.ts +2 -0
- package/dist/src/schema-extraction/index.js +20 -0
- package/dist/src/schema-extraction/types.d.ts +31 -0
- package/dist/src/schema-extraction/types.js +2 -0
- package/dist/src/utils/loadFlinkConfig.d.ts +53 -0
- package/dist/src/utils/loadFlinkConfig.js +77 -0
- package/dist/src/utils.d.ts +30 -0
- package/dist/src/utils.js +52 -0
- package/dist/src/workers/SchemaGeneratorWorker.d.ts +1 -0
- package/dist/src/workers/SchemaGeneratorWorker.js +49 -0
- package/dist/src/workers/WorkerPool.d.ts +60 -0
- package/dist/src/workers/WorkerPool.js +306 -0
- package/examples/logging-hierarchical-example.ts +125 -0
- package/package.json +29 -4
- package/readme.md +499 -0
- package/spec/AgentDescendantDetection.spec.ts +335 -0
- package/spec/AgentDuplicateDetection.spec.ts +112 -0
- package/spec/AgentObserver.spec.ts +266 -0
- package/spec/AgentRunner.spec.ts +1062 -0
- package/spec/AsyncLocalStorageContext.spec.ts +223 -0
- package/spec/ConversationHooks.spec.ts +257 -0
- package/spec/FlinkAgent.spec.ts +681 -0
- package/spec/FlinkApp.htmlResponse.spec.ts +260 -0
- package/spec/FlinkApp.onError.invocation.spec.ts +151 -0
- package/spec/FlinkApp.onError.spec.ts +1 -2
- package/spec/FlinkApp.query.spec.ts +107 -0
- package/spec/FlinkApp.routeOrdering.spec.ts +61 -0
- package/spec/FlinkApp.undefinedResponse.spec.ts +123 -0
- package/spec/FlinkApp.validationMode.spec.ts +155 -0
- package/spec/FlinkJob.spec.ts +171 -0
- package/spec/FlinkLogFactory.spec.ts +337 -0
- package/spec/FlinkRepo.spec.ts +1 -1
- package/spec/LeaderElection.spec.ts +174 -0
- package/spec/StreamingIntegration.spec.ts +139 -0
- package/spec/ToolExecutor.spec.ts +465 -0
- package/spec/TypeScriptCompiler.spec.ts +1 -1
- package/spec/TypeScriptSourceParser.spec.ts +1215 -0
- package/spec/TypeScriptTokenizer.spec.ts +366 -0
- package/spec/ai/ContextCompaction.spec.ts +405 -0
- package/spec/ai/ConversationAgent.spec.ts +520 -0
- package/spec/ai/InMemoryConversationAgent.spec.ts +144 -0
- package/spec/ai/agentInstructions.spec.ts +358 -0
- package/spec/fixtures/agent-instructions/TestAgent.ts +24 -0
- package/spec/fixtures/agent-instructions/simple.md +3 -0
- package/spec/fixtures/agent-instructions/template.md +18 -0
- package/spec/fixtures/agent-instructions/yaml-format.yaml +9 -0
- package/spec/mock-project/dist/.tsbuildinfo +1 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCar.js +56 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCar2.js +58 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema.js +52 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema2.js +52 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithArraySchema3.js +52 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithLiteralSchema.js +54 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithLiteralSchema2.js +54 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithSchemaInFile.js +57 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/GetCarWithSchemaInFile2.js +57 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/ManuallyAddedHandler.js +53 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/ManuallyAddedHandler2.js +55 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchCar.js +57 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchOnboardingSession.js +75 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchOrderWithComplexTypes.js +57 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchProductWithIntersection.js +58 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PatchUserWithUnion.js +58 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PostCar.js +54 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PostLogin.js +55 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PostLogout.js +54 -0
- package/spec/mock-project/dist/spec/mock-project/src/handlers/PutCar.js +54 -0
- package/spec/mock-project/dist/spec/mock-project/src/index.js +83 -0
- package/spec/mock-project/dist/spec/mock-project/src/repos/CarRepo.js +26 -0
- package/spec/mock-project/dist/spec/mock-project/src/schemas/Car.js +2 -0
- package/spec/mock-project/dist/spec/mock-project/src/schemas/DefaultExportSchema.js +2 -0
- package/spec/mock-project/dist/spec/mock-project/src/schemas/FileWithTwoSchemas.js +2 -0
- package/spec/mock-project/dist/src/FlinkApp.js +1000 -0
- package/spec/mock-project/dist/src/FlinkContext.js +2 -0
- package/spec/mock-project/dist/src/FlinkErrors.js +143 -0
- package/spec/mock-project/dist/src/FlinkHttpHandler.js +47 -0
- package/spec/mock-project/dist/src/FlinkJob.js +2 -0
- package/spec/mock-project/dist/src/FlinkLog.js +119 -0
- package/spec/mock-project/dist/src/FlinkLogFactory.js +617 -0
- package/spec/mock-project/dist/src/FlinkPlugin.js +2 -0
- package/spec/mock-project/dist/src/FlinkRepo.js +224 -0
- package/spec/mock-project/dist/src/FlinkRequestContext.js +74 -0
- package/spec/mock-project/dist/src/FlinkResponse.js +2 -0
- package/spec/mock-project/dist/src/ai/AgentExecutor.js +279 -0
- package/spec/mock-project/dist/src/ai/AgentRunner.js +632 -0
- package/spec/mock-project/dist/src/ai/ConversationAgent.js +402 -0
- package/spec/mock-project/dist/src/ai/ConversationFlinkAgent.js +422 -0
- package/spec/mock-project/dist/src/ai/FlinkAgent.js +699 -0
- package/spec/mock-project/dist/src/ai/FlinkTool.js +2 -0
- package/spec/mock-project/dist/src/ai/InMemoryConversationAgent.js +209 -0
- package/spec/mock-project/dist/src/ai/LLMAdapter.js +2 -0
- package/spec/mock-project/dist/src/ai/SubAgentExecutor.js +223 -0
- package/spec/mock-project/dist/src/ai/ToolExecutor.js +412 -0
- package/spec/mock-project/dist/src/ai/agentInstructions.js +246 -0
- package/spec/mock-project/dist/src/auth/FlinkAuthPlugin.js +2 -0
- package/spec/mock-project/dist/src/auth/FlinkAuthUser.js +2 -0
- package/spec/mock-project/dist/src/handlers/GetCar.js +26 -52
- package/spec/mock-project/dist/src/handlers/GetCar.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCar2.js +32 -54
- package/spec/mock-project/dist/src/handlers/GetCar2.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema.js +26 -48
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema2.js +28 -48
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema2.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema3.js +29 -48
- package/spec/mock-project/dist/src/handlers/GetCarWithArraySchema3.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema.js +26 -50
- package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema2.js +28 -50
- package/spec/mock-project/dist/src/handlers/GetCarWithLiteralSchema2.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile.js +27 -53
- package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile2.js +29 -53
- package/spec/mock-project/dist/src/handlers/GetCarWithSchemaInFile2.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler.js +16 -49
- package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler2.js +25 -50
- package/spec/mock-project/dist/src/handlers/ManuallyAddedHandler2.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PatchCar.js +27 -53
- package/spec/mock-project/dist/src/handlers/PatchCar.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PatchOnboardingSession.js +44 -70
- package/spec/mock-project/dist/src/handlers/PatchOnboardingSession.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PatchOrderWithComplexTypes.js +27 -53
- package/spec/mock-project/dist/src/handlers/PatchOrderWithComplexTypes.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PatchProductWithIntersection.js +28 -54
- package/spec/mock-project/dist/src/handlers/PatchProductWithIntersection.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PatchUserWithUnion.js +28 -54
- package/spec/mock-project/dist/src/handlers/PatchUserWithUnion.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PostCar.js +24 -50
- package/spec/mock-project/dist/src/handlers/PostCar.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PostLogin.js +25 -51
- package/spec/mock-project/dist/src/handlers/PostLogin.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PostLogout.js +24 -50
- package/spec/mock-project/dist/src/handlers/PostLogout.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/PutCar.js +24 -50
- package/spec/mock-project/dist/src/handlers/PutCar.js.map +1 -0
- package/spec/mock-project/dist/src/handlers/StreamWriterFactory.js +83 -0
- package/spec/mock-project/dist/src/index.js +52 -76
- package/spec/mock-project/dist/src/index.js.map +1 -0
- package/spec/mock-project/dist/src/mock-data-generator.js +9 -0
- package/spec/mock-project/dist/src/repos/CarRepo.js +12 -24
- package/spec/mock-project/dist/src/repos/CarRepo.js.map +1 -0
- package/spec/mock-project/dist/src/schemas/Car.js +3 -1
- package/spec/mock-project/dist/src/schemas/Car.js.map +1 -0
- package/spec/mock-project/dist/src/schemas/DefaultExportSchema.js +3 -1
- package/spec/mock-project/dist/src/schemas/DefaultExportSchema.js.map +1 -0
- package/spec/mock-project/dist/src/schemas/FileWithTwoSchemas.js +3 -1
- package/spec/mock-project/dist/src/schemas/FileWithTwoSchemas.js.map +1 -0
- package/spec/mock-project/dist/src/utils.js +290 -0
- package/spec/mock-project/tsconfig.json +6 -1
- package/spec/schema-generation-nested-objects.spec.ts +97 -0
- package/spec/testHelpers.ts +49 -0
- package/spec/utils.caseConversion.spec.ts +78 -0
- package/spec/utils.spec.ts +13 -13
- package/src/DependencyTracker.ts +166 -0
- package/src/FlinkApp.ts +919 -155
- package/src/FlinkContext.ts +43 -0
- package/src/FlinkErrors.ts +32 -12
- package/src/FlinkHttpHandler.ts +246 -28
- package/src/FlinkJob.ts +11 -0
- package/src/FlinkLog.ts +119 -12
- package/src/FlinkLogFactory.ts +699 -0
- package/src/FlinkRepo.ts +10 -3
- package/src/FlinkRequestContext.ts +95 -0
- package/src/FlinkResponse.ts +6 -0
- package/src/FlinkService.ts +49 -0
- package/src/LeaderElection.ts +203 -0
- package/src/SchemaCache.ts +232 -0
- package/src/TypeScriptCompiler.ts +1347 -610
- package/src/TypeScriptUtils.ts +5 -0
- package/src/ai/AgentRunner.ts +646 -0
- package/src/ai/ConversationAgent.ts +413 -0
- package/src/ai/FlinkAgent.ts +1069 -0
- package/src/ai/FlinkTool.ts +165 -0
- package/src/ai/InMemoryConversationAgent.ts +149 -0
- package/src/ai/LLMAdapter.ts +126 -0
- package/src/ai/ToolExecutor.ts +485 -0
- package/src/ai/agentInstructions.ts +245 -0
- package/src/ai/index.ts +8 -0
- package/src/ai/instructionFileLoader.ts +156 -0
- package/src/auth/FlinkAuthPlugin.ts +2 -1
- package/src/handlers/StreamWriterFactory.ts +84 -0
- package/src/index.ts +14 -0
- package/src/loadPluginSchemas.ts +141 -0
- package/src/schema-extraction/TypeScriptSourceParser.ts +1058 -0
- package/src/schema-extraction/TypeScriptTokenizer.ts +205 -0
- package/src/schema-extraction/index.ts +2 -0
- package/src/schema-extraction/types.ts +34 -0
- package/src/utils/loadFlinkConfig.ts +89 -0
- package/src/utils.ts +52 -0
- package/tsconfig.json +6 -1
|
@@ -85,32 +85,80 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
85
85
|
var fs_1 = __importStar(require("fs"));
|
|
86
86
|
var path_1 = require("path");
|
|
87
87
|
var tiny_glob_1 = __importDefault(require("tiny-glob"));
|
|
88
|
-
var ts_json_schema_generator_1 = require("ts-json-schema-generator");
|
|
89
88
|
var ts_morph_1 = require("ts-morph");
|
|
89
|
+
var FlinkLogFactory_1 = require("./FlinkLogFactory");
|
|
90
90
|
var FsUtils_1 = require("./FsUtils");
|
|
91
|
-
var
|
|
91
|
+
var schema_extraction_1 = require("./schema-extraction");
|
|
92
92
|
var utils_1 = require("./utils");
|
|
93
|
+
var loadFlinkConfig_1 = require("./utils/loadFlinkConfig");
|
|
94
|
+
var perfLog = FlinkLogFactory_1.FlinkLogFactory.createLogger("flink.perf");
|
|
95
|
+
var initLog = FlinkLogFactory_1.FlinkLogFactory.createLogger("flink.init");
|
|
93
96
|
var TypeScriptCompiler = /** @class */ (function () {
|
|
94
97
|
function TypeScriptCompiler(cwd) {
|
|
95
|
-
|
|
98
|
+
var _a, _b, _c, _d;
|
|
96
99
|
/**
|
|
97
|
-
*
|
|
98
|
-
* schemas.ts file.
|
|
99
|
-
*
|
|
100
|
-
* This will be written to file in a batch for performance reasons.
|
|
100
|
+
* Handler schemas collected during parseHandlers, to be generated later
|
|
101
101
|
*/
|
|
102
|
-
this.
|
|
102
|
+
this.handlerSchemasToGenerate = [];
|
|
103
103
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* This will be added to file in a batch for performance reasons.
|
|
104
|
+
* Tool schemas collected during parseTools, to be generated later
|
|
107
105
|
*/
|
|
108
|
-
this.
|
|
106
|
+
this.toolSchemasToGenerate = [];
|
|
107
|
+
/**
|
|
108
|
+
* Pre-segmented source files by type (cached for performance)
|
|
109
|
+
*/
|
|
110
|
+
this.handlerFiles = [];
|
|
111
|
+
this.repoFiles = [];
|
|
112
|
+
this.toolFiles = [];
|
|
113
|
+
this.agentFiles = [];
|
|
114
|
+
this.jobFiles = [];
|
|
115
|
+
this.serviceFiles = [];
|
|
116
|
+
/**
|
|
117
|
+
* Tool ID registry for agent validation (built during segmentation)
|
|
118
|
+
*/
|
|
119
|
+
this.toolIdRegistry = new Set();
|
|
120
|
+
/**
|
|
121
|
+
* Compiler plugins loaded from flink.config.js
|
|
122
|
+
*/
|
|
123
|
+
this.compilerPlugins = [];
|
|
124
|
+
this.disableServices = false;
|
|
125
|
+
/**
|
|
126
|
+
* Extension files collected during segmentation, keyed by generatedFile name
|
|
127
|
+
*/
|
|
128
|
+
this.extensionFiles = new Map();
|
|
129
|
+
var path = require("path");
|
|
130
|
+
// Convert to absolute path to ensure consistent path comparisons
|
|
131
|
+
this.cwd = path.resolve(cwd);
|
|
109
132
|
// Detect if project is using ESM based solely on package.json "type": "module"
|
|
110
|
-
this.isEsm = this.isEsmProject(cwd);
|
|
133
|
+
this.isEsm = this.isEsmProject(this.cwd);
|
|
134
|
+
var tsConfigPath = (0, path_1.join)(this.cwd, "tsconfig.json");
|
|
135
|
+
// Read and inherit important settings from tsconfig.json
|
|
136
|
+
var userTsConfig = {};
|
|
137
|
+
try {
|
|
138
|
+
if (fs_1.default.existsSync(tsConfigPath)) {
|
|
139
|
+
var tsConfigContent = fs_1.default.readFileSync(tsConfigPath, "utf8");
|
|
140
|
+
userTsConfig = JSON.parse(tsConfigContent);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.warn("Warning: Could not read tsconfig.json:", error);
|
|
145
|
+
}
|
|
111
146
|
var compilerOptions = {
|
|
112
147
|
noEmit: false, // We need to emit files
|
|
113
148
|
outDir: (0, path_1.join)(cwd, "dist"),
|
|
149
|
+
// Inherit important performance options from user's tsconfig
|
|
150
|
+
skipLibCheck: (_b = (_a = userTsConfig.compilerOptions) === null || _a === void 0 ? void 0 : _a.skipLibCheck) !== null && _b !== void 0 ? _b : true, // Default to true for performance
|
|
151
|
+
// Performance optimizations for emit phase
|
|
152
|
+
// Since we already run getPreEmitDiagnostics() for type checking,
|
|
153
|
+
// we can use faster transpilation-only options
|
|
154
|
+
isolatedModules: true, // Transpile each file independently (much faster, no cross-file analysis)
|
|
155
|
+
// removeComments: true, // Smaller output, faster emit
|
|
156
|
+
importHelpers: false, // Don't import tslib helpers
|
|
157
|
+
// EXPERIMENTAL: Enable incremental compilation
|
|
158
|
+
// This creates a .tsbuildinfo file to cache type information
|
|
159
|
+
// Should speed up subsequent builds by avoiding full type checking
|
|
160
|
+
// incremental: true,
|
|
161
|
+
// tsBuildInfoFile: join(cwd, "dist", ".tsbuildinfo"),
|
|
114
162
|
};
|
|
115
163
|
// Set appropriate module settings based on detected module system
|
|
116
164
|
if (this.isEsm) {
|
|
@@ -124,17 +172,351 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
124
172
|
compilerOptions.module = ts_morph_1.ts.ModuleKind.CommonJS;
|
|
125
173
|
compilerOptions.moduleResolution = ts_morph_1.ts.ModuleResolutionKind.NodeJs;
|
|
126
174
|
}
|
|
127
|
-
|
|
128
|
-
console.log("
|
|
129
|
-
|
|
175
|
+
initLog.info("TypeScript version:", ts_morph_1.ts.version, "config path", require("path").resolve(tsConfigPath));
|
|
176
|
+
// console.log("Compiler options:", JSON.stringify(compilerOptions, null, 2));
|
|
177
|
+
var projectStartTime = Date.now();
|
|
130
178
|
this.project = new ts_morph_1.Project({
|
|
131
179
|
tsConfigFilePath: tsConfigPath,
|
|
132
180
|
compilerOptions: compilerOptions,
|
|
181
|
+
skipAddingFilesFromTsConfig: true, // Don't auto-load all files - we'll add specific directories we need
|
|
182
|
+
skipFileDependencyResolution: true, // Don't resolve /// <reference> and type dependencies from node_modules
|
|
133
183
|
});
|
|
184
|
+
var projectTime = Date.now() - projectStartTime;
|
|
185
|
+
perfLog.debug("\u2713 Project initialization completed in ".concat(projectTime, "ms"));
|
|
186
|
+
// Load Flink-specific source paths from tsconfig.json if available
|
|
187
|
+
var additionalSourcePaths = this.getFlinkSourcePaths(tsConfigPath);
|
|
188
|
+
// Load all TypeScript files from src/ directory
|
|
189
|
+
// This is simpler and faster than recursive import resolution
|
|
190
|
+
// We exclude test files and declarations to keep it lean
|
|
191
|
+
var defaultSourcePaths = [
|
|
192
|
+
(0, path_1.join)(cwd, "src/**/*.ts"),
|
|
193
|
+
"!" + (0, path_1.join)(cwd, "src/**/*.spec.ts"),
|
|
194
|
+
"!" + (0, path_1.join)(cwd, "src/**/*.test.ts"),
|
|
195
|
+
"!" + (0, path_1.join)(cwd, "src/**/*.d.ts"),
|
|
196
|
+
];
|
|
197
|
+
var allSourcePaths = __spreadArray(__spreadArray([], defaultSourcePaths, true), additionalSourcePaths, true);
|
|
198
|
+
var loadStartTime = Date.now();
|
|
199
|
+
this.project.addSourceFilesAtPaths(allSourcePaths);
|
|
200
|
+
var loadTime = Date.now() - loadStartTime;
|
|
201
|
+
var fileCount = this.project.getSourceFiles().length;
|
|
202
|
+
perfLog.debug("\u2713 All source files loaded in ".concat(loadTime, "ms (").concat(fileCount, " files)"));
|
|
203
|
+
// Load config from flink.config.js
|
|
204
|
+
var flinkCfg = (0, loadFlinkConfig_1.loadFlinkConfig)(this.cwd);
|
|
205
|
+
this.compilerPlugins = (_c = flinkCfg === null || flinkCfg === void 0 ? void 0 : flinkCfg.compilerPlugins) !== null && _c !== void 0 ? _c : [];
|
|
206
|
+
this.disableServices = (_d = flinkCfg === null || flinkCfg === void 0 ? void 0 : flinkCfg.disableServices) !== null && _d !== void 0 ? _d : false;
|
|
207
|
+
if (this.compilerPlugins.length > 0) {
|
|
208
|
+
initLog.info("Compiler plugins loaded (".concat(this.compilerPlugins.length, "):"), this.compilerPlugins.map(function (p) { return "".concat(p.package, " \u2192 ").concat(p.scanDir); }).join(", "));
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
initLog.info("No compiler plugins configured");
|
|
212
|
+
}
|
|
213
|
+
// Segment files by type for efficient processing
|
|
214
|
+
this.segmentSourceFiles();
|
|
134
215
|
console.log("Loaded", this.project.getSourceFiles().length, "source file(s) from", cwd);
|
|
135
216
|
console.log("Module system:", this.isEsm ? "ESM" : "CommonJS");
|
|
136
217
|
console.log("Using module:", compilerOptions.module === ts_morph_1.ts.ModuleKind.ESNext ? "ESNext" : "CommonJS");
|
|
137
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Generates a schema $id from a file path and type name using the same algorithm
|
|
221
|
+
* as the schema generator's defineId callback.
|
|
222
|
+
*
|
|
223
|
+
* Examples:
|
|
224
|
+
* - src/schemas/Car.ts, "Car" → "Car"
|
|
225
|
+
* - src/schemas/wrappers/PartialLoginReq.ts, "PartialLoginReq" → "wrappers.PartialLoginReq"
|
|
226
|
+
* - src/schemas/PatchCarSchemas.ts, "PatchCarReq" → "PatchCarSchemas.PatchCarReq"
|
|
227
|
+
*/
|
|
228
|
+
TypeScriptCompiler.prototype.filePathToSchemaId = function (absolutePath, typeName) {
|
|
229
|
+
var path = require("path");
|
|
230
|
+
var schemaDir = path.join(this.cwd, "src/schemas");
|
|
231
|
+
// Get path relative to src/schemas/
|
|
232
|
+
var relativePath = path.relative(schemaDir, absolutePath);
|
|
233
|
+
// Remove .ts extension
|
|
234
|
+
var pathWithoutExt = relativePath.replace(/\.ts$/, "");
|
|
235
|
+
// Split by path separator
|
|
236
|
+
var parts = pathWithoutExt.split(path.sep);
|
|
237
|
+
var fileName = parts[parts.length - 1];
|
|
238
|
+
// Root file with matching name: just type name
|
|
239
|
+
if (parts.length === 1 && fileName === typeName) {
|
|
240
|
+
return typeName;
|
|
241
|
+
}
|
|
242
|
+
// Nested file or multiple exports: include path
|
|
243
|
+
var pathPrefix = parts.join(".");
|
|
244
|
+
if (fileName === typeName) {
|
|
245
|
+
return pathPrefix; // Avoid duplication
|
|
246
|
+
}
|
|
247
|
+
return "".concat(pathPrefix, ".").concat(typeName);
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Resolves a type name to its schema $id by looking up its import path.
|
|
251
|
+
* Returns undefined if the type is not imported from src/schemas/.
|
|
252
|
+
*/
|
|
253
|
+
TypeScriptCompiler.prototype.resolveTypeNameToSchemaId = function (fileText, typeName, handlerFilePath) {
|
|
254
|
+
var path = require("path");
|
|
255
|
+
// Extract import statement for this type
|
|
256
|
+
var importStmt = schema_extraction_1.TypeScriptSourceParser.extractImportForType(fileText, typeName);
|
|
257
|
+
if (!importStmt) {
|
|
258
|
+
perfLog.trace("Type ".concat(typeName, " not found in imports"));
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
261
|
+
// Extract module specifier from import
|
|
262
|
+
// e.g., import { Foo } from "../schemas/Bar" → "../schemas/Bar"
|
|
263
|
+
var moduleMatch = importStmt.match(/from\s+["']([^"']+)["']/);
|
|
264
|
+
if (!moduleMatch) {
|
|
265
|
+
perfLog.trace("Could not extract module specifier from: ".concat(importStmt));
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
var moduleSpecifier = moduleMatch[1];
|
|
269
|
+
// Resolve relative import to absolute path
|
|
270
|
+
var handlerDir = path.dirname(handlerFilePath);
|
|
271
|
+
var importPath = path.resolve(handlerDir, moduleSpecifier);
|
|
272
|
+
// Add .ts extension if not present
|
|
273
|
+
var importPathWithExt = importPath.endsWith(".ts") ? importPath : importPath + ".ts";
|
|
274
|
+
// Check if this is from src/schemas/
|
|
275
|
+
var schemaDir = path.join(this.cwd, "src/schemas");
|
|
276
|
+
if (!importPathWithExt.startsWith(schemaDir)) {
|
|
277
|
+
perfLog.trace("Type ".concat(typeName, " is not from src/schemas/ (from ").concat(importPathWithExt, ")"));
|
|
278
|
+
return undefined;
|
|
279
|
+
}
|
|
280
|
+
// Generate schema $id using the same algorithm
|
|
281
|
+
return this.filePathToSchemaId(importPathWithExt, typeName);
|
|
282
|
+
};
|
|
283
|
+
/**
|
|
284
|
+
* Loads additional source paths from tsconfig.json's flink configuration.
|
|
285
|
+
* Allows projects to specify extra directories to include in compilation.
|
|
286
|
+
*
|
|
287
|
+
* Example tsconfig.json:
|
|
288
|
+
* {
|
|
289
|
+
* "flink": {
|
|
290
|
+
* "sourcePaths": ["src/custom-types/**\/*.ts", "src/utils/**\/*.ts"]
|
|
291
|
+
* }
|
|
292
|
+
* }
|
|
293
|
+
*/
|
|
294
|
+
TypeScriptCompiler.prototype.getFlinkSourcePaths = function (tsConfigPath) {
|
|
295
|
+
var _this = this;
|
|
296
|
+
try {
|
|
297
|
+
if (fs_1.default.existsSync(tsConfigPath)) {
|
|
298
|
+
var tsConfigContent = fs_1.default.readFileSync(tsConfigPath, "utf8");
|
|
299
|
+
var tsConfig = JSON.parse(tsConfigContent);
|
|
300
|
+
if (tsConfig.flink && Array.isArray(tsConfig.flink.sourcePaths)) {
|
|
301
|
+
console.log("Found Flink-specific source paths:", tsConfig.flink.sourcePaths);
|
|
302
|
+
return tsConfig.flink.sourcePaths.map(function (path) { return (0, path_1.join)(_this.cwd, path); });
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
console.warn("Error reading Flink source paths from tsconfig.json:", error);
|
|
308
|
+
}
|
|
309
|
+
return [];
|
|
310
|
+
};
|
|
311
|
+
/**
|
|
312
|
+
* Initializes the schema generator.
|
|
313
|
+
*
|
|
314
|
+
* Note: ts-source-to-json-schema is ESM-only while @flink-app/flink is CommonJS.
|
|
315
|
+
* We use new Function() to preserve the actual import() in compiled output.
|
|
316
|
+
* Without this, TypeScript converts import() to require() which can't load ESM.
|
|
317
|
+
*/
|
|
318
|
+
TypeScriptCompiler.prototype.initSchemaGenerator = function () {
|
|
319
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
320
|
+
var dynamicImport, module_1, error_1;
|
|
321
|
+
return __generator(this, function (_a) {
|
|
322
|
+
switch (_a.label) {
|
|
323
|
+
case 0:
|
|
324
|
+
if (this.schemaGenerator !== undefined) {
|
|
325
|
+
return [2 /*return*/]; // Already initialized
|
|
326
|
+
}
|
|
327
|
+
_a.label = 1;
|
|
328
|
+
case 1:
|
|
329
|
+
_a.trys.push([1, 3, , 4]);
|
|
330
|
+
dynamicImport = new Function("specifier", "return import(specifier)");
|
|
331
|
+
return [4 /*yield*/, dynamicImport("@flink-app/ts-source-to-json-schema")];
|
|
332
|
+
case 2:
|
|
333
|
+
module_1 = _a.sent();
|
|
334
|
+
if (typeof module_1.toJsonSchemasFromFile !== "function") {
|
|
335
|
+
throw new Error("toJsonSchemasFromFile function not found. Please update @flink-app/ts-source-to-json-schema to >= 0.2.0");
|
|
336
|
+
}
|
|
337
|
+
this.schemaGenerator = module_1.toJsonSchemasFromFile;
|
|
338
|
+
return [3 /*break*/, 4];
|
|
339
|
+
case 3:
|
|
340
|
+
error_1 = _a.sent();
|
|
341
|
+
console.error("\n❌ Schema generator could not be loaded:\n" +
|
|
342
|
+
" Error: ".concat(error_1.message, "\n") +
|
|
343
|
+
"\n💡 Make sure @flink-app/ts-source-to-json-schema is installed:\n" +
|
|
344
|
+
" npm install @flink-app/ts-source-to-json-schema\n");
|
|
345
|
+
process.exit(1);
|
|
346
|
+
return [3 /*break*/, 4];
|
|
347
|
+
case 4: return [2 /*return*/];
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* Recursively resolves and adds imported files to the project.
|
|
354
|
+
* This ensures that files imported by handlers, schemas, etc. are available for type resolution.
|
|
355
|
+
*
|
|
356
|
+
* Handles three types of imports:
|
|
357
|
+
* 1. Relative imports (./foo, ../bar) - always resolved
|
|
358
|
+
* 2. Workspace package imports (@mycompany/shared) - resolved if symlinked outside node_modules
|
|
359
|
+
* 3. External packages (lodash, express) - skipped to avoid loading entire dependency trees
|
|
360
|
+
*/
|
|
361
|
+
TypeScriptCompiler.prototype.resolveImportedFiles = function () {
|
|
362
|
+
// TODO: Check if this really is needed!
|
|
363
|
+
var processedFiles = new Set();
|
|
364
|
+
var filesToProcess = __spreadArray([], this.project.getSourceFiles(), true);
|
|
365
|
+
var totalImports = 0;
|
|
366
|
+
var skippedImports = 0;
|
|
367
|
+
var resolvedImports = 0;
|
|
368
|
+
while (filesToProcess.length > 0) {
|
|
369
|
+
var sourceFile = filesToProcess.pop();
|
|
370
|
+
var filePath = sourceFile.getFilePath();
|
|
371
|
+
if (processedFiles.has(filePath)) {
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
processedFiles.add(filePath);
|
|
375
|
+
// Get all import declarations
|
|
376
|
+
var importDeclarations = sourceFile.getImportDeclarations();
|
|
377
|
+
for (var _i = 0, importDeclarations_1 = importDeclarations; _i < importDeclarations_1.length; _i++) {
|
|
378
|
+
var importDecl = importDeclarations_1[_i];
|
|
379
|
+
var moduleSpecifier = importDecl.getModuleSpecifierValue();
|
|
380
|
+
totalImports++;
|
|
381
|
+
// For relative imports (./foo, ../bar), always resolve
|
|
382
|
+
var isRelativeImport = moduleSpecifier.startsWith(".") || moduleSpecifier.startsWith("/");
|
|
383
|
+
// For package imports, check if it might be a workspace package
|
|
384
|
+
// Workspace packages are typically scoped (@company/pkg) or match the workspace pattern
|
|
385
|
+
var isLikelyWorkspacePackage = !isRelativeImport && (moduleSpecifier.startsWith("@" + this.getWorkspaceScope() + "/") || this.isLikelyWorkspaceImport(moduleSpecifier));
|
|
386
|
+
// Skip resolution for external packages (performance optimization)
|
|
387
|
+
// Only resolve relative imports and likely workspace packages
|
|
388
|
+
if (!isRelativeImport && !isLikelyWorkspacePackage) {
|
|
389
|
+
skippedImports++;
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
// Try to resolve the imported file (expensive operation)
|
|
393
|
+
resolvedImports++;
|
|
394
|
+
var moduleSourceFile = importDecl.getModuleSpecifierSourceFile();
|
|
395
|
+
if (moduleSourceFile) {
|
|
396
|
+
var importedPath = moduleSourceFile.getFilePath();
|
|
397
|
+
// Double-check it's not in node_modules (for workspace packages)
|
|
398
|
+
var isWorkspacePackage = !isRelativeImport && !importedPath.includes("node_modules");
|
|
399
|
+
// Add to processing queue if it's a relative import or workspace package
|
|
400
|
+
if ((isRelativeImport || isWorkspacePackage) && !processedFiles.has(importedPath)) {
|
|
401
|
+
filesToProcess.push(moduleSourceFile);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
console.log("Resolved imports, total files loaded:", processedFiles.size);
|
|
407
|
+
console.log(" Import stats: ".concat(totalImports, " total, ").concat(skippedImports, " skipped, ").concat(resolvedImports, " resolved"));
|
|
408
|
+
};
|
|
409
|
+
/**
|
|
410
|
+
* Gets the workspace scope from package.json (e.g., "@mycompany" from "@mycompany/my-app")
|
|
411
|
+
* Returns empty string if not a scoped package.
|
|
412
|
+
*/
|
|
413
|
+
TypeScriptCompiler.prototype.getWorkspaceScope = function () {
|
|
414
|
+
try {
|
|
415
|
+
var packageJson = JSON.parse(fs_1.default.readFileSync((0, path_1.join)(this.cwd, "package.json"), "utf8"));
|
|
416
|
+
var name = packageJson.name || "";
|
|
417
|
+
if (name.startsWith("@")) {
|
|
418
|
+
return name.split("/")[0].substring(1); // Remove @ and get scope
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
// Ignore errors
|
|
423
|
+
}
|
|
424
|
+
return "";
|
|
425
|
+
};
|
|
426
|
+
/**
|
|
427
|
+
* Checks if an import is likely to be a workspace package.
|
|
428
|
+
* This is a heuristic - we check for common workspace patterns but can't be 100% sure
|
|
429
|
+
* without actually resolving. This is a performance optimization to avoid resolving
|
|
430
|
+
* obvious external packages like "express", "lodash", etc.
|
|
431
|
+
*/
|
|
432
|
+
TypeScriptCompiler.prototype.isLikelyWorkspaceImport = function (moduleSpecifier) {
|
|
433
|
+
// If it contains a workspace marker in the name, it might be workspace
|
|
434
|
+
// Common patterns: starts with project name, contains "internal", etc.
|
|
435
|
+
// For now, be conservative and return false - only workspace packages with
|
|
436
|
+
// matching scope will be resolved
|
|
437
|
+
return false;
|
|
438
|
+
};
|
|
439
|
+
/**
|
|
440
|
+
* Segments source files by type for efficient processing.
|
|
441
|
+
* Performs all path checks and AST inspections in a single pass.
|
|
442
|
+
*
|
|
443
|
+
* This runs once during construction and caches results to avoid
|
|
444
|
+
* multiple full-file iterations during parse methods.
|
|
445
|
+
*/
|
|
446
|
+
TypeScriptCompiler.prototype.segmentSourceFiles = function () {
|
|
447
|
+
var _a;
|
|
448
|
+
var startTime = Date.now();
|
|
449
|
+
var allFiles = this.project.getSourceFiles();
|
|
450
|
+
var handlerTime = 0, repoTime = 0, toolTime = 0, agentTime = 0, jobTime = 0, serviceTime = 0;
|
|
451
|
+
for (var _i = 0, allFiles_1 = allFiles; _i < allFiles_1.length; _i++) {
|
|
452
|
+
var sf = allFiles_1[_i];
|
|
453
|
+
var filePath = sf.getFilePath();
|
|
454
|
+
var fileStartTime = Date.now();
|
|
455
|
+
// Handlers: simple path check
|
|
456
|
+
if (filePath.includes("src/handlers/")) {
|
|
457
|
+
this.handlerFiles.push(sf);
|
|
458
|
+
handlerTime += Date.now() - fileStartTime;
|
|
459
|
+
continue; // Skip further checks (mutually exclusive)
|
|
460
|
+
}
|
|
461
|
+
// Repos: simple path check
|
|
462
|
+
if (filePath.includes("src/repos/")) {
|
|
463
|
+
this.repoFiles.push(sf);
|
|
464
|
+
repoTime += Date.now() - fileStartTime;
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
// Tools: path check + fast text-based detection
|
|
468
|
+
// Check if file contains "FlinkToolProps" without parsing AST (much faster)
|
|
469
|
+
if (filePath.includes("src/tools/")) {
|
|
470
|
+
var fileText = sf.getFullText();
|
|
471
|
+
// Fast text check: must have both "export" and ": FlinkToolProps"
|
|
472
|
+
if (fileText.includes("FlinkToolProps") && fileText.includes("export")) {
|
|
473
|
+
this.toolFiles.push(sf);
|
|
474
|
+
// Extract tool ID using regex (faster than AST inspection)
|
|
475
|
+
// Matches: id: "tool-name" or name: "tool-name"
|
|
476
|
+
var idMatch = fileText.match(/(?:id|name):\s*["']([^"']+)["']/);
|
|
477
|
+
if (idMatch) {
|
|
478
|
+
this.toolIdRegistry.add(idMatch[1]);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
toolTime += Date.now() - fileStartTime;
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
// Agents: convention-based detection (all .ts files in src/agents/)
|
|
485
|
+
// Trust that files in src/agents/ are valid agents - validate at runtime
|
|
486
|
+
if (filePath.includes("src/agents/")) {
|
|
487
|
+
this.agentFiles.push(sf);
|
|
488
|
+
agentTime += Date.now() - fileStartTime;
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
// Jobs: simple path check
|
|
492
|
+
if (filePath.includes("src/jobs/")) {
|
|
493
|
+
this.jobFiles.push(sf);
|
|
494
|
+
jobTime += Date.now() - fileStartTime;
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
// Services: simple path check (opt-out via flink.config.js disableServices)
|
|
498
|
+
if (!this.disableServices && filePath.includes("src/services/")) {
|
|
499
|
+
this.serviceFiles.push(sf);
|
|
500
|
+
serviceTime += Date.now() - fileStartTime;
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
// Extension dirs from compiler plugins
|
|
504
|
+
for (var _b = 0, _c = this.compilerPlugins; _b < _c.length; _b++) {
|
|
505
|
+
var ext = _c[_b];
|
|
506
|
+
if (filePath.includes(ext.scanDir)) {
|
|
507
|
+
if (!ext.detectBy || ext.detectBy(sf.getFullText(), filePath)) {
|
|
508
|
+
var list = (_a = this.extensionFiles.get(ext.generatedFile)) !== null && _a !== void 0 ? _a : [];
|
|
509
|
+
list.push(sf);
|
|
510
|
+
this.extensionFiles.set(ext.generatedFile, list);
|
|
511
|
+
}
|
|
512
|
+
break;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
var segmentTime = Date.now() - startTime;
|
|
517
|
+
perfLog.debug("\u2713 File segmentation completed in ".concat(segmentTime, "ms ") +
|
|
518
|
+
"(".concat(this.handlerFiles.length, " handlers, ").concat(this.repoFiles.length, " repos, ").concat(this.toolFiles.length, " tools, ").concat(this.agentFiles.length, " agents, ").concat(this.jobFiles.length, " jobs, ").concat(this.serviceFiles.length, " services)"));
|
|
519
|
+
};
|
|
138
520
|
/**
|
|
139
521
|
* Detects if the project is using ESM (ECMAScript Modules)
|
|
140
522
|
* by checking type in package.json.
|
|
@@ -156,14 +538,29 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
156
538
|
};
|
|
157
539
|
/**
|
|
158
540
|
* Gets the module specifier for imports, adding .js extension for ESM
|
|
541
|
+
* Uses fast path calculation instead of ts-morph's getRelativePathAsModuleSpecifierTo
|
|
542
|
+
* which triggers expensive language service initialization
|
|
159
543
|
*/
|
|
160
544
|
TypeScriptCompiler.prototype.getModuleSpecifier = function (fromFile, toFile) {
|
|
161
|
-
var
|
|
162
|
-
//
|
|
163
|
-
|
|
164
|
-
|
|
545
|
+
var path = require("path");
|
|
546
|
+
// Get directory paths
|
|
547
|
+
var fromDir = path.dirname(fromFile.getFilePath());
|
|
548
|
+
var toPath = toFile.getFilePath();
|
|
549
|
+
// Calculate relative path
|
|
550
|
+
var relativePath = path.relative(fromDir, toPath);
|
|
551
|
+
// Convert to forward slashes (module specifiers use forward slashes)
|
|
552
|
+
relativePath = relativePath.replace(/\\/g, "/");
|
|
553
|
+
// Remove .ts extension
|
|
554
|
+
relativePath = relativePath.replace(/\.ts$/, "");
|
|
555
|
+
// Ensure it starts with ./ or ../
|
|
556
|
+
if (!relativePath.startsWith(".")) {
|
|
557
|
+
relativePath = "./" + relativePath;
|
|
558
|
+
}
|
|
559
|
+
// Add .js extension for ESM imports
|
|
560
|
+
if (this.isEsm) {
|
|
561
|
+
relativePath += ".js";
|
|
165
562
|
}
|
|
166
|
-
return
|
|
563
|
+
return relativePath;
|
|
167
564
|
};
|
|
168
565
|
/**
|
|
169
566
|
* Deletes all generated files.
|
|
@@ -210,10 +607,136 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
210
607
|
});
|
|
211
608
|
};
|
|
212
609
|
/**
|
|
213
|
-
*
|
|
610
|
+
* Saves all modified source files in a single batch operation.
|
|
611
|
+
* Call this before emit() to persist all changes to disk.
|
|
612
|
+
*/
|
|
613
|
+
TypeScriptCompiler.prototype.saveAllModifiedFiles = function () {
|
|
614
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
615
|
+
var startTime, flinkFiles, unsavedFlinkFiles, saveTime;
|
|
616
|
+
return __generator(this, function (_a) {
|
|
617
|
+
switch (_a.label) {
|
|
618
|
+
case 0:
|
|
619
|
+
startTime = Date.now();
|
|
620
|
+
flinkFiles = this.project.getSourceFiles("**/.flink/**/*.ts");
|
|
621
|
+
unsavedFlinkFiles = flinkFiles.filter(function (sf) { return !sf.isSaved(); });
|
|
622
|
+
return [4 /*yield*/, Promise.all(unsavedFlinkFiles.map(function (sf) { return sf.save(); }))];
|
|
623
|
+
case 1:
|
|
624
|
+
_a.sent();
|
|
625
|
+
saveTime = Date.now() - startTime;
|
|
626
|
+
perfLog.debug("\u2713 Batch save completed in ".concat(saveTime, "ms (").concat(unsavedFlinkFiles.length, " files)"));
|
|
627
|
+
return [2 /*return*/];
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
});
|
|
631
|
+
};
|
|
632
|
+
/**
|
|
633
|
+
* Emits compiled javascript source to dist folder using swc (20-50x faster than tsc)
|
|
634
|
+
*/
|
|
635
|
+
TypeScriptCompiler.prototype.emitWithSwc = function () {
|
|
636
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
637
|
+
var emitStartTime, swc, fs, path, allSourceFiles, emitTime;
|
|
638
|
+
var _this = this;
|
|
639
|
+
return __generator(this, function (_a) {
|
|
640
|
+
switch (_a.label) {
|
|
641
|
+
case 0:
|
|
642
|
+
emitStartTime = Date.now();
|
|
643
|
+
swc = require("@swc/core");
|
|
644
|
+
fs = require("fs-extra");
|
|
645
|
+
path = require("path");
|
|
646
|
+
allSourceFiles = this.project.getSourceFiles().filter(function (sf) {
|
|
647
|
+
var filePath = sf.getFilePath();
|
|
648
|
+
return !filePath.endsWith(".d.ts") && !filePath.includes("/node_modules/");
|
|
649
|
+
});
|
|
650
|
+
initLog.debug("Starting swc compilation for ".concat(allSourceFiles.length, " source files..."));
|
|
651
|
+
// Transpile all files in parallel using swc
|
|
652
|
+
return [4 /*yield*/, Promise.all(allSourceFiles.map(function (sf) { return __awaiter(_this, void 0, void 0, function () {
|
|
653
|
+
var filePath, code, result, relativePath, outPath;
|
|
654
|
+
return __generator(this, function (_a) {
|
|
655
|
+
switch (_a.label) {
|
|
656
|
+
case 0:
|
|
657
|
+
filePath = sf.getFilePath();
|
|
658
|
+
code = sf.getFullText();
|
|
659
|
+
return [4 /*yield*/, swc.transform(code, {
|
|
660
|
+
filename: filePath,
|
|
661
|
+
jsc: {
|
|
662
|
+
parser: {
|
|
663
|
+
syntax: "typescript",
|
|
664
|
+
decorators: true,
|
|
665
|
+
tsx: false, // Flink doesn't use JSX
|
|
666
|
+
},
|
|
667
|
+
target: "es2017", // Async/await support, modern enough for Node 14+
|
|
668
|
+
transform: {
|
|
669
|
+
legacyDecorator: true,
|
|
670
|
+
decoratorMetadata: true, // Required for reflect-metadata
|
|
671
|
+
},
|
|
672
|
+
keepClassNames: true, // Preserve class names for debugging
|
|
673
|
+
},
|
|
674
|
+
module: {
|
|
675
|
+
type: this.isEsm ? "es6" : "commonjs",
|
|
676
|
+
},
|
|
677
|
+
sourceMaps: true,
|
|
678
|
+
})];
|
|
679
|
+
case 1:
|
|
680
|
+
result = _a.sent();
|
|
681
|
+
relativePath = path.relative(this.cwd, filePath);
|
|
682
|
+
outPath = path.join(this.cwd, "dist", relativePath).replace(/\.ts$/, ".js");
|
|
683
|
+
return [4 /*yield*/, fs.ensureDir(path.dirname(outPath))];
|
|
684
|
+
case 2:
|
|
685
|
+
_a.sent();
|
|
686
|
+
return [4 /*yield*/, fs.writeFile(outPath, result.code)];
|
|
687
|
+
case 3:
|
|
688
|
+
_a.sent();
|
|
689
|
+
if (!result.map) return [3 /*break*/, 5];
|
|
690
|
+
return [4 /*yield*/, fs.writeFile(outPath + ".map", result.map)];
|
|
691
|
+
case 4:
|
|
692
|
+
_a.sent();
|
|
693
|
+
_a.label = 5;
|
|
694
|
+
case 5: return [2 /*return*/];
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
}); }))];
|
|
698
|
+
case 1:
|
|
699
|
+
// Transpile all files in parallel using swc
|
|
700
|
+
_a.sent();
|
|
701
|
+
emitTime = Date.now() - emitStartTime;
|
|
702
|
+
initLog.debug("\u2713 Emitted ".concat(allSourceFiles.length, " files with swc in ").concat(emitTime, "ms (").concat((emitTime / allSourceFiles.length).toFixed(1), "ms per file)"));
|
|
703
|
+
return [2 /*return*/];
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
});
|
|
707
|
+
};
|
|
708
|
+
/**
|
|
709
|
+
* Emits compiled javascript source to dist folder (defaults to swc for speed, falls back to tsc)
|
|
214
710
|
*/
|
|
215
711
|
TypeScriptCompiler.prototype.emit = function () {
|
|
712
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
713
|
+
var _a;
|
|
714
|
+
return __generator(this, function (_b) {
|
|
715
|
+
switch (_b.label) {
|
|
716
|
+
case 0:
|
|
717
|
+
_b.trys.push([0, 2, , 3]);
|
|
718
|
+
require.resolve("@swc/core");
|
|
719
|
+
return [4 /*yield*/, this.emitWithSwc()];
|
|
720
|
+
case 1: return [2 /*return*/, _b.sent()];
|
|
721
|
+
case 2:
|
|
722
|
+
_a = _b.sent();
|
|
723
|
+
initLog.debug("@swc/core not found, falling back to TypeScript compiler (slower)");
|
|
724
|
+
return [2 /*return*/, this.emitWithTsc()];
|
|
725
|
+
case 3: return [2 /*return*/];
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
};
|
|
730
|
+
/**
|
|
731
|
+
* Emits compiled javascript source to dist folder using TypeScript compiler (slower, kept for fallback)
|
|
732
|
+
*/
|
|
733
|
+
TypeScriptCompiler.prototype.emitWithTsc = function () {
|
|
734
|
+
var emitStartTime = Date.now();
|
|
735
|
+
var sourceFileCount = this.project.getSourceFiles().length;
|
|
736
|
+
perfLog.debug("Starting TypeScript compilation for ".concat(sourceFileCount, " source files..."));
|
|
216
737
|
this.project.emitSync();
|
|
738
|
+
var emitTime = Date.now() - emitStartTime;
|
|
739
|
+
perfLog.debug("\u2713 Emitted ".concat(sourceFileCount, " files with tsc in ").concat(emitTime, "ms (").concat((emitTime / sourceFileCount).toFixed(1), "ms per file)"));
|
|
217
740
|
};
|
|
218
741
|
/**
|
|
219
742
|
* Catch any compilation errors. Will return false if any Errors
|
|
@@ -253,28 +776,27 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
253
776
|
* type arguments.
|
|
254
777
|
*/
|
|
255
778
|
TypeScriptCompiler.prototype.parseHandlers = function () {
|
|
256
|
-
return __awaiter(this,
|
|
257
|
-
var generatedFile, handlersArr, handlers,
|
|
258
|
-
if (excludeDirs === void 0) { excludeDirs = []; }
|
|
779
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
780
|
+
var startTime, generatedFile, handlersArr, handlers, handlerParseTime;
|
|
259
781
|
return __generator(this, function (_a) {
|
|
260
782
|
switch (_a.label) {
|
|
261
783
|
case 0:
|
|
784
|
+
startTime = Date.now();
|
|
262
785
|
generatedFile = this.createSourceFile(["generatedHandlers.ts"], "// Generated ".concat(new Date(), "\nimport { autoRegisteredHandlers, HttpMethod } from \"@flink-app/flink\";\nexport const handlers = [];\nautoRegisteredHandlers.push(...handlers);\n "));
|
|
263
786
|
handlersArr = generatedFile.getVariableDeclarationOrThrow("handlers").getFirstDescendantByKindOrThrow(ts_morph_1.SyntaxKind.ArrayLiteralExpression);
|
|
264
787
|
return [4 /*yield*/, this.parseHandlerDir(generatedFile, handlersArr)];
|
|
265
788
|
case 1:
|
|
266
789
|
handlers = _a.sent();
|
|
267
790
|
generatedFile.addImportDeclarations(handlers.imports);
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
this.appendSchemasToHandlerSourceFiles(handlers.schemasToGenerate, jsonSchemas);
|
|
791
|
+
// Defer save until batch save at end (performance optimization)
|
|
792
|
+
// Store handler schemas for later batch processing
|
|
793
|
+
this.handlerSchemasToGenerate = handlers.schemasToGenerate;
|
|
794
|
+
// Cleanup: forget handler file nodes to reduce memory overhead (ts-morph performance optimization)
|
|
795
|
+
this.handlerFiles.forEach(function (sf) {
|
|
796
|
+
sf.getClasses().forEach(function (cls) { return cls.forget(); });
|
|
797
|
+
});
|
|
798
|
+
handlerParseTime = Date.now() - startTime;
|
|
799
|
+
perfLog.info("\u2713 Handler parsing completed in ".concat(handlerParseTime, "ms"));
|
|
278
800
|
return [2 /*return*/, generatedFile];
|
|
279
801
|
}
|
|
280
802
|
});
|
|
@@ -285,129 +807,342 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
285
807
|
*/
|
|
286
808
|
TypeScriptCompiler.prototype.parseHandlerDir = function (generatedFile, handlersArr) {
|
|
287
809
|
return __awaiter(this, void 0, void 0, function () {
|
|
288
|
-
var imports,
|
|
289
|
-
|
|
290
|
-
|
|
810
|
+
var imports, schemasToGenerate, handlerFiles, handlerResults, handlerElements, _i, handlerResults_1, result, sf, isAutoRegister, namespaceImport, assumedHttpMethod, schemaTypes;
|
|
811
|
+
var _this = this;
|
|
812
|
+
return __generator(this, function (_a) {
|
|
813
|
+
switch (_a.label) {
|
|
291
814
|
case 0:
|
|
292
815
|
imports = [];
|
|
293
|
-
i = 0;
|
|
294
816
|
schemasToGenerate = [];
|
|
295
|
-
|
|
296
|
-
|
|
817
|
+
handlerFiles = this.handlerFiles;
|
|
818
|
+
return [4 /*yield*/, Promise.all(handlerFiles.map(function (sf, index) { return __awaiter(_this, void 0, void 0, function () {
|
|
819
|
+
var startTime, isAutoRegister, namespaceImport, assumedHttpMethod, schemaTypes, _a;
|
|
820
|
+
return __generator(this, function (_b) {
|
|
821
|
+
switch (_b.label) {
|
|
822
|
+
case 0:
|
|
823
|
+
startTime = Date.now();
|
|
824
|
+
isAutoRegister = this.isAutoRegisterableHandler(sf);
|
|
825
|
+
namespaceImport = sf.getBaseNameWithoutExtension().replace(/\./g, "_") + "_" + index;
|
|
826
|
+
assumedHttpMethod = (0, utils_1.getHttpMethodFromHandlerName)(sf.getBaseName());
|
|
827
|
+
if (!isAutoRegister) return [3 /*break*/, 2];
|
|
828
|
+
return [4 /*yield*/, this.extractSchemasFromHandlerFast(sf.getFilePath())];
|
|
829
|
+
case 1:
|
|
830
|
+
_a = _b.sent();
|
|
831
|
+
return [3 /*break*/, 3];
|
|
832
|
+
case 2:
|
|
833
|
+
_a = undefined;
|
|
834
|
+
_b.label = 3;
|
|
835
|
+
case 3:
|
|
836
|
+
schemaTypes = _a;
|
|
837
|
+
perfLog.trace("".concat(sf.getBaseName(), " took ").concat(Date.now() - startTime, "ms"));
|
|
838
|
+
return [2 /*return*/, {
|
|
839
|
+
sf: sf,
|
|
840
|
+
isAutoRegister: isAutoRegister,
|
|
841
|
+
namespaceImport: namespaceImport,
|
|
842
|
+
assumedHttpMethod: assumedHttpMethod,
|
|
843
|
+
schemaTypes: schemaTypes,
|
|
844
|
+
index: index,
|
|
845
|
+
}];
|
|
846
|
+
}
|
|
847
|
+
});
|
|
848
|
+
}); }))];
|
|
297
849
|
case 1:
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
case 2:
|
|
314
|
-
_b = _c.sent();
|
|
315
|
-
return [3 /*break*/, 4];
|
|
316
|
-
case 3:
|
|
317
|
-
_b = undefined;
|
|
318
|
-
_c.label = 4;
|
|
319
|
-
case 4:
|
|
320
|
-
schemaTypes = _b;
|
|
321
|
-
existingVars = sf.getVariableStatements().filter(function (vs) {
|
|
322
|
-
var varNames = vs.getDeclarations().map(function (d) { return d.getName(); });
|
|
323
|
-
return varNames.some(function (name) { return ["__assumedHttpMethod", "__file", "__query", "__params"].includes(name); });
|
|
324
|
-
});
|
|
325
|
-
existingVars.forEach(function (v) { return v.remove(); });
|
|
326
|
-
// Append schemas and metadata to source file that will be part of emitted dist bundle (javascript)
|
|
327
|
-
sf.addVariableStatement({
|
|
328
|
-
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
|
|
329
|
-
isExported: true,
|
|
330
|
-
declarations: [
|
|
331
|
-
{
|
|
332
|
-
name: "__assumedHttpMethod",
|
|
333
|
-
initializer: "\"".concat(assumedHttpMethod || "", "\""),
|
|
334
|
-
},
|
|
335
|
-
{
|
|
336
|
-
name: "__file",
|
|
337
|
-
initializer: "\"".concat(sf.getBaseName(), "\""),
|
|
338
|
-
},
|
|
339
|
-
{
|
|
340
|
-
name: "__query",
|
|
341
|
-
initializer: "[".concat(((schemaTypes === null || schemaTypes === void 0 ? void 0 : schemaTypes.queryMetadata) || [])
|
|
342
|
-
.map(function (_a) {
|
|
343
|
-
var description = _a.description, name = _a.name;
|
|
344
|
-
return "{description: \"".concat(description, "\", name: \"").concat(name, "\"}");
|
|
345
|
-
})
|
|
346
|
-
.join(","), "]"),
|
|
347
|
-
},
|
|
348
|
-
{
|
|
349
|
-
name: "__params",
|
|
350
|
-
initializer: "[".concat(((schemaTypes === null || schemaTypes === void 0 ? void 0 : schemaTypes.paramsMetadata) || [])
|
|
351
|
-
.map(function (_a) {
|
|
352
|
-
var description = _a.description, name = _a.name;
|
|
353
|
-
return "{description: \"".concat(description, "\", name: \"").concat(name, "\"}");
|
|
354
|
-
})
|
|
355
|
-
.join(","), "]"),
|
|
356
|
-
},
|
|
357
|
-
],
|
|
358
|
-
});
|
|
359
|
-
if (isAutoRegister) {
|
|
360
|
-
handlersArr.insertElement(i, "{handler: ".concat(namespaceImport, ", assumedHttpMethod: ").concat(assumedHttpMethod ? "HttpMethod." + assumedHttpMethod : undefined, "}"));
|
|
361
|
-
i++;
|
|
362
|
-
// Add schemas to generate list
|
|
363
|
-
if (schemaTypes) {
|
|
364
|
-
schemasToGenerate.push(__assign(__assign({}, schemaTypes), { sourceFile: sf }));
|
|
850
|
+
handlerResults = _a.sent();
|
|
851
|
+
handlerElements = [];
|
|
852
|
+
for (_i = 0, handlerResults_1 = handlerResults; _i < handlerResults_1.length; _i++) {
|
|
853
|
+
result = handlerResults_1[_i];
|
|
854
|
+
sf = result.sf, isAutoRegister = result.isAutoRegister, namespaceImport = result.namespaceImport, assumedHttpMethod = result.assumedHttpMethod, schemaTypes = result.schemaTypes;
|
|
855
|
+
imports.push({
|
|
856
|
+
defaultImport: "* as " + namespaceImport,
|
|
857
|
+
moduleSpecifier: this.getModuleSpecifier(generatedFile, sf),
|
|
858
|
+
});
|
|
859
|
+
if (isAutoRegister) {
|
|
860
|
+
handlerElements.push("{handler: ".concat(namespaceImport, ", assumedHttpMethod: ").concat(assumedHttpMethod ? "HttpMethod." + assumedHttpMethod : undefined, ", __file: \"").concat(this.getRelativePath(sf), "\"}"));
|
|
861
|
+
// Add schemas to generate list
|
|
862
|
+
if (schemaTypes) {
|
|
863
|
+
schemasToGenerate.push(__assign(__assign({}, schemaTypes), { sourceFile: sf }));
|
|
864
|
+
}
|
|
365
865
|
}
|
|
366
866
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
schemasToGenerate: schemasToGenerate,
|
|
374
|
-
}];
|
|
867
|
+
// Add all handler elements in one batch operation
|
|
868
|
+
handlersArr.addElements(handlerElements);
|
|
869
|
+
return [2 /*return*/, {
|
|
870
|
+
imports: imports,
|
|
871
|
+
schemasToGenerate: schemasToGenerate,
|
|
872
|
+
}];
|
|
375
873
|
}
|
|
376
874
|
});
|
|
377
875
|
});
|
|
378
876
|
};
|
|
379
877
|
TypeScriptCompiler.prototype.parseRepos = function () {
|
|
380
878
|
return __awaiter(this, void 0, void 0, function () {
|
|
381
|
-
var generatedFile, reposArr, imports,
|
|
879
|
+
var startTime, generatedFile, reposArr, imports, repoFiles, repoElements, _i, repoFiles_1, sf, repoParseTime;
|
|
880
|
+
return __generator(this, function (_a) {
|
|
881
|
+
startTime = Date.now();
|
|
882
|
+
generatedFile = this.createSourceFile(["generatedRepos.ts"], "// Generated ".concat(new Date(), "\n import { autoRegisteredRepos } from \"@flink-app/flink\";\n export const repos = [];\n autoRegisteredRepos.push(...repos);\n "));
|
|
883
|
+
reposArr = generatedFile.getVariableDeclarationOrThrow("repos").getFirstDescendantByKindOrThrow(ts_morph_1.SyntaxKind.ArrayLiteralExpression);
|
|
884
|
+
imports = [];
|
|
885
|
+
repoFiles = this.repoFiles;
|
|
886
|
+
repoElements = [];
|
|
887
|
+
for (_i = 0, repoFiles_1 = repoFiles; _i < repoFiles_1.length; _i++) {
|
|
888
|
+
sf = repoFiles_1[_i];
|
|
889
|
+
console.log("Detected repo ".concat(sf.getBaseName()));
|
|
890
|
+
imports.push({
|
|
891
|
+
defaultImport: sf.getBaseNameWithoutExtension(),
|
|
892
|
+
moduleSpecifier: this.getModuleSpecifier(generatedFile, sf),
|
|
893
|
+
});
|
|
894
|
+
repoElements.push("{collectionName: \"".concat((0, utils_1.getCollectionNameForRepo)(sf.getBaseName()), "\", repoInstanceName: \"").concat((0, utils_1.getRepoInstanceName)(sf.getBaseName()), "\", Repo: ").concat(sf.getBaseNameWithoutExtension(), "}"));
|
|
895
|
+
}
|
|
896
|
+
// Add all repo elements in one batch operation
|
|
897
|
+
reposArr.addElements(repoElements);
|
|
898
|
+
generatedFile.addImportDeclarations(imports);
|
|
899
|
+
// Defer save until batch save at end (performance optimization)
|
|
900
|
+
// Cleanup: forget repo file nodes to reduce memory overhead (ts-morph performance optimization)
|
|
901
|
+
this.repoFiles.forEach(function (sf) {
|
|
902
|
+
sf.getClasses().forEach(function (cls) { return cls.forget(); });
|
|
903
|
+
});
|
|
904
|
+
repoParseTime = Date.now() - startTime;
|
|
905
|
+
initLog.info("\u2713 Repo parsing completed in ".concat(repoParseTime, "ms (").concat(repoElements.length, " repos)"));
|
|
906
|
+
return [2 /*return*/, generatedFile];
|
|
907
|
+
});
|
|
908
|
+
});
|
|
909
|
+
};
|
|
910
|
+
/**
|
|
911
|
+
* Scans project for tools and adds those to Flink
|
|
912
|
+
* "singleton" property `autoRegisteredTools` so they can
|
|
913
|
+
* be registered during start.
|
|
914
|
+
*
|
|
915
|
+
* Also extracts input and output schemas from FlinkTool type arguments
|
|
916
|
+
* when manual schemas are not provided.
|
|
917
|
+
*/
|
|
918
|
+
TypeScriptCompiler.prototype.parseTools = function () {
|
|
919
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
920
|
+
var startTime, generatedFile, toolsArr, imports, schemasToGenerate, toolFiles, toolResults, _loop_1, index, _i, toolResults_1, result, schemaTypes, toolParseTime, toolElements, _a, toolResults_2, result, sf, namespaceImport, toolPropsExportName, schemaTypes;
|
|
382
921
|
return __generator(this, function (_b) {
|
|
383
922
|
switch (_b.label) {
|
|
384
923
|
case 0:
|
|
385
|
-
|
|
386
|
-
|
|
924
|
+
startTime = Date.now();
|
|
925
|
+
// Initialize schema generator BEFORE schema extraction
|
|
926
|
+
return [4 /*yield*/, this.initSchemaGenerator()];
|
|
927
|
+
case 1:
|
|
928
|
+
// Initialize schema generator BEFORE schema extraction
|
|
929
|
+
_b.sent();
|
|
930
|
+
generatedFile = this.createSourceFile(["generatedTools.ts"], "// Generated ".concat(new Date(), "\nimport { autoRegisteredTools } from \"@flink-app/flink\";\nexport const tools = [];\nautoRegisteredTools.push(...tools);\n "));
|
|
931
|
+
toolsArr = generatedFile.getVariableDeclarationOrThrow("tools").getFirstDescendantByKindOrThrow(ts_morph_1.SyntaxKind.ArrayLiteralExpression);
|
|
387
932
|
imports = [];
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
933
|
+
schemasToGenerate = [];
|
|
934
|
+
toolFiles = this.toolFiles;
|
|
935
|
+
toolResults = [];
|
|
936
|
+
_loop_1 = function (index) {
|
|
937
|
+
var sf = toolFiles[index];
|
|
938
|
+
(function () {
|
|
939
|
+
// Get file path ONCE and cache it to avoid triggering ts-morph lazy parsing
|
|
940
|
+
var filePath = sf.getFilePath();
|
|
941
|
+
var path = require("path");
|
|
942
|
+
var baseNameWithoutExt = path.basename(filePath, path.extname(filePath));
|
|
943
|
+
var namespaceImport = baseNameWithoutExt.replace(/\./g, "_") + "_" + index;
|
|
944
|
+
// Extract the export name using fast text matching instead of AST parsing
|
|
945
|
+
// Read file directly from disk to avoid ts-morph's lazy parsing
|
|
946
|
+
// Matches: export const Tool: FlinkToolProps or export const MyName: FlinkToolProps
|
|
947
|
+
var fileText = fs_1.default.readFileSync(filePath, "utf8");
|
|
948
|
+
var exportMatch = fileText.match(/export\s+const\s+(\w+)\s*:\s*FlinkToolProps/);
|
|
949
|
+
var toolPropsExportName = exportMatch ? exportMatch[1] : "Tool"; // Default to "Tool" if not found
|
|
950
|
+
toolResults.push({
|
|
951
|
+
sf: sf,
|
|
952
|
+
filePath: filePath, // Cache file path to avoid triggering sf.getFilePath() later
|
|
953
|
+
namespaceImport: namespaceImport,
|
|
954
|
+
toolPropsExportName: toolPropsExportName,
|
|
955
|
+
index: index,
|
|
956
|
+
});
|
|
957
|
+
})();
|
|
958
|
+
};
|
|
959
|
+
for (index = 0; index < toolFiles.length; index++) {
|
|
960
|
+
_loop_1(index);
|
|
961
|
+
}
|
|
962
|
+
_i = 0, toolResults_1 = toolResults;
|
|
963
|
+
_b.label = 2;
|
|
964
|
+
case 2:
|
|
965
|
+
if (!(_i < toolResults_1.length)) return [3 /*break*/, 5];
|
|
966
|
+
result = toolResults_1[_i];
|
|
967
|
+
return [4 /*yield*/, this.extractSchemasFromToolFast(result.filePath)];
|
|
968
|
+
case 3:
|
|
969
|
+
schemaTypes = _b.sent();
|
|
970
|
+
schemasToGenerate.push({
|
|
971
|
+
inputSchemaType: schemaTypes === null || schemaTypes === void 0 ? void 0 : schemaTypes.inputSchemaType,
|
|
972
|
+
outputSchemaType: schemaTypes === null || schemaTypes === void 0 ? void 0 : schemaTypes.outputSchemaType,
|
|
973
|
+
inputTypeHint: schemaTypes === null || schemaTypes === void 0 ? void 0 : schemaTypes.inputTypeHint,
|
|
974
|
+
outputTypeHint: schemaTypes === null || schemaTypes === void 0 ? void 0 : schemaTypes.outputTypeHint,
|
|
975
|
+
sourceFile: result.sf,
|
|
976
|
+
});
|
|
977
|
+
_b.label = 4;
|
|
978
|
+
case 4:
|
|
979
|
+
_i++;
|
|
980
|
+
return [3 /*break*/, 2];
|
|
981
|
+
case 5:
|
|
982
|
+
toolParseTime = Date.now() - startTime;
|
|
983
|
+
initLog.info("\u2713 Tool parsing completed in ".concat(toolParseTime, "ms (").concat(toolFiles.length, " tools)"));
|
|
984
|
+
toolElements = [];
|
|
985
|
+
for (_a = 0, toolResults_2 = toolResults; _a < toolResults_2.length; _a++) {
|
|
986
|
+
result = toolResults_2[_a];
|
|
987
|
+
sf = result.sf, namespaceImport = result.namespaceImport, toolPropsExportName = result.toolPropsExportName, schemaTypes = result.schemaTypes;
|
|
395
988
|
imports.push({
|
|
396
|
-
defaultImport:
|
|
989
|
+
defaultImport: "* as " + namespaceImport,
|
|
397
990
|
moduleSpecifier: this.getModuleSpecifier(generatedFile, sf),
|
|
398
991
|
});
|
|
399
|
-
|
|
400
|
-
|
|
992
|
+
// Create an object that wraps the namespace and provides normalized access to the tool props
|
|
993
|
+
// This creates a consistent "Tool" property regardless of the source export name
|
|
994
|
+
// Example: {Tool: SearchCarsTool_0.MyCustomToolConfig} works even if export was "MyCustomToolConfig"
|
|
995
|
+
// __file is set here on the registration object (not injected into source files)
|
|
996
|
+
toolElements.push("{...".concat(namespaceImport, ", Tool: ").concat(namespaceImport, ".").concat(toolPropsExportName, ", __file: \"").concat(this.getRelativePath(sf), "\"}"));
|
|
997
|
+
// Add schemas to generate list
|
|
998
|
+
if (schemaTypes) {
|
|
999
|
+
schemasToGenerate.push(__assign(__assign({}, schemaTypes), { sourceFile: sf }));
|
|
1000
|
+
}
|
|
401
1001
|
}
|
|
1002
|
+
// Add all tool elements in one batch operation
|
|
1003
|
+
toolsArr.addElements(toolElements);
|
|
402
1004
|
generatedFile.addImportDeclarations(imports);
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
1005
|
+
// Defer save until batch save at end (performance optimization)
|
|
1006
|
+
// Store tool schemas for later batch processing
|
|
1007
|
+
this.toolSchemasToGenerate = schemasToGenerate;
|
|
1008
|
+
// Cleanup: forget tool file nodes to reduce memory overhead (ts-morph performance optimization)
|
|
1009
|
+
// Note: We avoid calling methods on sf during iteration since we cached all needed data earlier
|
|
1010
|
+
this.toolFiles.forEach(function (sf) {
|
|
1011
|
+
// Only forget if we haven't already processed this file
|
|
1012
|
+
var classes = sf.getClasses();
|
|
1013
|
+
classes.forEach(function (cls) { return cls.forget(); });
|
|
1014
|
+
});
|
|
406
1015
|
return [2 /*return*/, generatedFile];
|
|
407
1016
|
}
|
|
408
1017
|
});
|
|
409
1018
|
});
|
|
410
1019
|
};
|
|
1020
|
+
/**
|
|
1021
|
+
* Scans project for agents and validates tool references.
|
|
1022
|
+
* Agents are classes extending FlinkAgent exported as default.
|
|
1023
|
+
*/
|
|
1024
|
+
TypeScriptCompiler.prototype.parseAgents = function () {
|
|
1025
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1026
|
+
var startTime, generatedFile, agentsArr, imports, registeredToolIds, agentElements, agentParseTime;
|
|
1027
|
+
var _this = this;
|
|
1028
|
+
return __generator(this, function (_a) {
|
|
1029
|
+
startTime = Date.now();
|
|
1030
|
+
generatedFile = this.createSourceFile(["generatedAgents.ts"], "// Generated ".concat(new Date(), "\nimport { autoRegisteredAgents } from \"@flink-app/flink\";\nexport const agents = [];\nautoRegisteredAgents.push(...agents);\n "));
|
|
1031
|
+
agentsArr = generatedFile.getVariableDeclarationOrThrow("agents").getFirstDescendantByKindOrThrow(ts_morph_1.SyntaxKind.ArrayLiteralExpression);
|
|
1032
|
+
imports = [];
|
|
1033
|
+
registeredToolIds = this.toolIdRegistry;
|
|
1034
|
+
agentElements = [];
|
|
1035
|
+
// Use pre-segmented agent files (convention-based: all files in src/agents/ are agents)
|
|
1036
|
+
this.agentFiles.forEach(function (sf, index) {
|
|
1037
|
+
var _a;
|
|
1038
|
+
// Convention-based approach: Trust that all files in src/agents/ are valid agents
|
|
1039
|
+
// Find the first exported class (assume it's the agent)
|
|
1040
|
+
var agentClass = sf.getClasses().find(function (cls) { return cls.isExported() || cls.isDefaultExport(); });
|
|
1041
|
+
// Skip if no exported class found (shouldn't happen, but defensive)
|
|
1042
|
+
if (!agentClass) {
|
|
1043
|
+
perfLog.debug("\u26A0 Skipping ".concat(sf.getBaseName(), " - no exported class found"));
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
// Create unique namespace import (same pattern as handlers and tools)
|
|
1047
|
+
var namespaceImport = sf.getBaseNameWithoutExtension().replace(/\./g, "_") + "_" + index;
|
|
1048
|
+
// Validate tool references exist (read from class properties)
|
|
1049
|
+
var toolsProperty = agentClass.getProperty("tools");
|
|
1050
|
+
if (toolsProperty) {
|
|
1051
|
+
var initializer = toolsProperty.getInitializer();
|
|
1052
|
+
if (initializer && initializer.getKind() === ts_morph_1.SyntaxKind.ArrayLiteralExpression) {
|
|
1053
|
+
var toolsArray = initializer;
|
|
1054
|
+
var toolElements = toolsArray.getElements();
|
|
1055
|
+
var _loop_2 = function (toolElement) {
|
|
1056
|
+
var toolName = void 0;
|
|
1057
|
+
// Handle string literals, method calls, and identifier references (tool imports)
|
|
1058
|
+
if (toolElement.getKind() === ts_morph_1.SyntaxKind.StringLiteral) {
|
|
1059
|
+
// Direct string: "tool-name"
|
|
1060
|
+
toolName = toolElement.getText().replace(/['"]/g, "");
|
|
1061
|
+
}
|
|
1062
|
+
else if (toolElement.getKind() === ts_morph_1.SyntaxKind.CallExpression) {
|
|
1063
|
+
// Method call: this.useTool("tool-name")
|
|
1064
|
+
var args = toolElement.getArguments();
|
|
1065
|
+
if (args.length > 0 && args[0].getKind() === ts_morph_1.SyntaxKind.StringLiteral) {
|
|
1066
|
+
toolName = args[0].getText().replace(/['"]/g, "");
|
|
1067
|
+
}
|
|
1068
|
+
else {
|
|
1069
|
+
console.warn("Agent ".concat(sf.getBaseName(), " has non-string tool reference, skipping validation"));
|
|
1070
|
+
return "continue";
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
else if (toolElement.getKind() === ts_morph_1.SyntaxKind.Identifier) {
|
|
1074
|
+
// Tool file reference (imported): SearchCarsByBrandTool
|
|
1075
|
+
// Look up the import to find the actual tool file
|
|
1076
|
+
var importName_1 = toolElement.getText();
|
|
1077
|
+
var importDecl = sf.getImportDeclarations().find(function (imp) {
|
|
1078
|
+
var namedImports = imp.getNamedImports();
|
|
1079
|
+
return namedImports.some(function (ni) { return ni.getName() === importName_1; });
|
|
1080
|
+
});
|
|
1081
|
+
if (!importDecl) {
|
|
1082
|
+
// Try namespace import (* as Foo)
|
|
1083
|
+
var namespaceImport_1 = sf.getImportDeclarations().find(function (imp) {
|
|
1084
|
+
var _a;
|
|
1085
|
+
return ((_a = imp.getNamespaceImport()) === null || _a === void 0 ? void 0 : _a.getText()) === importName_1;
|
|
1086
|
+
});
|
|
1087
|
+
if (namespaceImport_1) {
|
|
1088
|
+
var moduleSpecifier = namespaceImport_1.getModuleSpecifierValue();
|
|
1089
|
+
// Extract tool ID from the tool file path
|
|
1090
|
+
// e.g., "../tools/SearchCarsByBrandTool" -> find in registeredToolIds
|
|
1091
|
+
var toolFileName = (_a = moduleSpecifier.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(/\.ts$/, "");
|
|
1092
|
+
var matchingTool = Array.from(registeredToolIds).find(function (id) {
|
|
1093
|
+
// Try to match by searching for the tool ID
|
|
1094
|
+
// This is a heuristic - we'll validate it exists
|
|
1095
|
+
return true; // Skip validation for imported tools for now
|
|
1096
|
+
});
|
|
1097
|
+
return "continue";
|
|
1098
|
+
}
|
|
1099
|
+
console.warn("Agent ".concat(sf.getBaseName(), " references tool \"").concat(importName_1, "\" but it's not imported, skipping validation"));
|
|
1100
|
+
return "continue";
|
|
1101
|
+
}
|
|
1102
|
+
return "continue";
|
|
1103
|
+
}
|
|
1104
|
+
else {
|
|
1105
|
+
console.warn("Agent ".concat(sf.getBaseName(), " has unexpected tool reference format: ").concat(toolElement.getText()));
|
|
1106
|
+
return "continue";
|
|
1107
|
+
}
|
|
1108
|
+
if (!registeredToolIds.has(toolName)) {
|
|
1109
|
+
console.error("Agent ".concat(sf.getBaseName(), " references tool \"").concat(toolName, "\" which does not exist"));
|
|
1110
|
+
throw new Error("Invalid tool reference in agent ".concat(sf.getBaseName()));
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
for (var _i = 0, toolElements_1 = toolElements; _i < toolElements_1.length; _i++) {
|
|
1114
|
+
var toolElement = toolElements_1[_i];
|
|
1115
|
+
_loop_2(toolElement);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
var className = agentClass.getName();
|
|
1120
|
+
if (!className) {
|
|
1121
|
+
console.error("Agent class in ".concat(sf.getBaseName(), " has no name"));
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
imports.push({
|
|
1125
|
+
defaultImport: "* as " + namespaceImport,
|
|
1126
|
+
moduleSpecifier: _this.getModuleSpecifier(generatedFile, sf),
|
|
1127
|
+
});
|
|
1128
|
+
// Register the agent class (access default export via namespace)
|
|
1129
|
+
// __file is set here on the registration object (not injected into source files)
|
|
1130
|
+
agentElements.push("{ default: ".concat(namespaceImport, ".default, __file: \"").concat(_this.getRelativePath(sf), "\" }"));
|
|
1131
|
+
});
|
|
1132
|
+
// Add all agent elements in one batch operation
|
|
1133
|
+
agentsArr.addElements(agentElements);
|
|
1134
|
+
generatedFile.addImportDeclarations(imports);
|
|
1135
|
+
// Defer save until batch save at end (performance optimization)
|
|
1136
|
+
// Cleanup: forget agent file nodes to reduce memory overhead (ts-morph performance optimization)
|
|
1137
|
+
this.agentFiles.forEach(function (sf) {
|
|
1138
|
+
sf.getClasses().forEach(function (cls) { return cls.forget(); });
|
|
1139
|
+
});
|
|
1140
|
+
agentParseTime = Date.now() - startTime;
|
|
1141
|
+
initLog.info("\u2713 Agent parsing completed in ".concat(agentParseTime, "ms (").concat(agentElements.length, " agents)"));
|
|
1142
|
+
return [2 /*return*/, generatedFile];
|
|
1143
|
+
});
|
|
1144
|
+
});
|
|
1145
|
+
};
|
|
411
1146
|
/**
|
|
412
1147
|
* Generates a start script that will import references to handlers, repos and the
|
|
413
1148
|
* actual Flink app to start.
|
|
@@ -417,19 +1152,37 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
417
1152
|
*/
|
|
418
1153
|
TypeScriptCompiler.prototype.generateStartScript = function () {
|
|
419
1154
|
return __awaiter(this, arguments, void 0, function (appEntryScript) {
|
|
420
|
-
var sf;
|
|
1155
|
+
var path, entryScriptPath, specFiles, extensionImports, sf;
|
|
1156
|
+
var _this = this;
|
|
421
1157
|
if (appEntryScript === void 0) { appEntryScript = "/src/index.ts"; }
|
|
422
1158
|
return __generator(this, function (_a) {
|
|
423
1159
|
switch (_a.label) {
|
|
424
1160
|
case 0:
|
|
425
|
-
|
|
426
|
-
|
|
1161
|
+
path = require("path");
|
|
1162
|
+
entryScriptPath = path.resolve(this.cwd, appEntryScript.replace(/^\//, ""));
|
|
1163
|
+
if (!fs_1.default.existsSync(entryScriptPath)) {
|
|
1164
|
+
console.error("Cannot find entry script '".concat(appEntryScript, "' at ").concat(entryScriptPath));
|
|
427
1165
|
return [2 /*return*/, process.exit(1)];
|
|
428
1166
|
}
|
|
429
|
-
|
|
430
|
-
|
|
1167
|
+
if (!!this.project.getSourceFile(function (sf) { return sf.getFilePath().endsWith(appEntryScript); })) return [3 /*break*/, 3];
|
|
1168
|
+
this.project.addSourceFileAtPath(entryScriptPath);
|
|
1169
|
+
if (!appEntryScript.includes("/spec/")) return [3 /*break*/, 2];
|
|
1170
|
+
return [4 /*yield*/, (0, tiny_glob_1.default)((0, path_1.join)(this.cwd, "spec/**/*.ts"))];
|
|
431
1171
|
case 1:
|
|
432
|
-
_a.sent();
|
|
1172
|
+
specFiles = _a.sent();
|
|
1173
|
+
this.project.addSourceFilesAtPaths(specFiles);
|
|
1174
|
+
console.log("Added ".concat(specFiles.length, " spec files to compilation"));
|
|
1175
|
+
_a.label = 2;
|
|
1176
|
+
case 2:
|
|
1177
|
+
// Resolve any imports from the entry script
|
|
1178
|
+
this.resolveImportedFiles();
|
|
1179
|
+
_a.label = 3;
|
|
1180
|
+
case 3:
|
|
1181
|
+
extensionImports = this.compilerPlugins
|
|
1182
|
+
.map(function (ext) { return "import \"./".concat(ext.generatedFile).concat(_this.isEsm ? ".js" : "", "\";"); })
|
|
1183
|
+
.join("\n");
|
|
1184
|
+
sf = this.createSourceFile(["start.ts"], "// Generated ".concat(new Date(), "\nimport \"./generatedHandlers").concat(this.isEsm ? ".js" : "", "\";\nimport \"./generatedRepos").concat(this.isEsm ? ".js" : "", "\";\nimport \"./generatedTools").concat(this.isEsm ? ".js" : "", "\";\nimport \"./generatedAgents").concat(this.isEsm ? ".js" : "", "\";\nimport \"./generatedJobs").concat(this.isEsm ? ".js" : "", "\";\nimport \"./generatedServices").concat(this.isEsm ? ".js" : "", "\";\n").concat(extensionImports ? extensionImports + "\n" : "", "import \"..").concat(appEntryScript.replace(/\.ts/g, "")).concat(this.isEsm ? ".js" : "", "\";\nexport default {}; // Export an empty object to make it a module\n"));
|
|
1185
|
+
// Defer save until batch save at end (performance optimization)
|
|
433
1186
|
return [2 /*return*/, sf];
|
|
434
1187
|
}
|
|
435
1188
|
});
|
|
@@ -441,548 +1194,431 @@ var TypeScriptCompiler = /** @class */ (function () {
|
|
|
441
1194
|
});
|
|
442
1195
|
};
|
|
443
1196
|
/**
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
* There are multiple ways of defining schema types as valid ts and this
|
|
448
|
-
* implementation aims to support all of these.
|
|
449
|
-
*
|
|
450
|
-
* Some examples of different cases (check spec/mock-project/src/handlers for more):
|
|
451
|
-
*
|
|
452
|
-
* ```
|
|
453
|
-
* // Interface reference
|
|
454
|
-
* Handler<Ctx, Car>
|
|
455
|
-
* // Inline type definition with reference to interface
|
|
456
|
-
* Handler<Ctx, {car: Car}>
|
|
457
|
-
* // Inline type definition with literal values
|
|
458
|
-
* Handler<Ctx, {car: {model: string}}>
|
|
459
|
-
* // Array
|
|
460
|
-
* Handler<Ctx, Car[]>
|
|
461
|
-
* // Array with inline type definition
|
|
462
|
-
* Handler<Ctx, {car: Car}[]>
|
|
463
|
-
* ```
|
|
464
|
-
*
|
|
465
|
-
* Return names of req and/or res schema types.
|
|
1197
|
+
* Extracts schema information from a tool file using text-based parsing.
|
|
1198
|
+
* Resolves type names to schema $ids from the schema universe.
|
|
466
1199
|
*/
|
|
467
|
-
TypeScriptCompiler.prototype.
|
|
1200
|
+
TypeScriptCompiler.prototype.extractSchemasFromToolFast = function (filePath) {
|
|
468
1201
|
return __awaiter(this, void 0, void 0, function () {
|
|
469
|
-
var
|
|
1202
|
+
var fileText, schemaDetection, typeArgs, baseName, inputTypeName, outputTypeName, inputSchemaType, outputSchemaType, inputTypeHint, outputTypeHint, baseName, unwrappedTypeName, baseName;
|
|
470
1203
|
return __generator(this, function (_a) {
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
return [2 /*return*/,
|
|
1204
|
+
fileText = fs_1.default.readFileSync(filePath, "utf8");
|
|
1205
|
+
schemaDetection = schema_extraction_1.TypeScriptSourceParser.detectSchemaType(fileText);
|
|
1206
|
+
if (schemaDetection.shouldSkipTypeScriptExtraction) {
|
|
1207
|
+
return [2 /*return*/, {
|
|
1208
|
+
inputSchemaType: undefined,
|
|
1209
|
+
outputSchemaType: undefined,
|
|
1210
|
+
}];
|
|
1211
|
+
}
|
|
1212
|
+
typeArgs = schema_extraction_1.TypeScriptSourceParser.parseFlinkToolTypeArgs(fileText);
|
|
1213
|
+
if (!typeArgs) {
|
|
1214
|
+
baseName = require("path").basename(filePath, require("path").extname(filePath));
|
|
1215
|
+
perfLog.trace(" Tool ".concat(baseName, ": Could not parse FlinkTool type arguments"));
|
|
1216
|
+
return [2 /*return*/, {
|
|
1217
|
+
inputSchemaType: undefined,
|
|
1218
|
+
outputSchemaType: undefined,
|
|
1219
|
+
}];
|
|
1220
|
+
}
|
|
1221
|
+
inputTypeName = typeArgs.inputType;
|
|
1222
|
+
outputTypeName = typeArgs.outputType;
|
|
1223
|
+
inputSchemaType = undefined;
|
|
1224
|
+
outputSchemaType = undefined;
|
|
1225
|
+
inputTypeHint = undefined;
|
|
1226
|
+
outputTypeHint = undefined;
|
|
1227
|
+
// Determine input type hint
|
|
1228
|
+
if (inputTypeName.toLowerCase() === "void") {
|
|
1229
|
+
inputTypeHint = "void";
|
|
1230
|
+
}
|
|
1231
|
+
else if (inputTypeName.toLowerCase() === "any") {
|
|
1232
|
+
inputTypeHint = "any";
|
|
1233
|
+
}
|
|
1234
|
+
else if (schema_extraction_1.TypeScriptSourceParser.shouldGenerateSchema(inputTypeName)) {
|
|
1235
|
+
inputTypeHint = "named";
|
|
1236
|
+
inputSchemaType = this.resolveTypeNameToSchemaId(fileText, inputTypeName, filePath);
|
|
1237
|
+
if (!inputSchemaType) {
|
|
1238
|
+
baseName = require("path").basename(filePath);
|
|
1239
|
+
perfLog.warn("Tool ".concat(baseName, ": Could not resolve input type \"").concat(inputTypeName, "\" to schema $id. Make sure it's exported from src/schemas/"));
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
unwrappedTypeName = schema_extraction_1.TypeScriptSourceParser.unwrapToolResultType(outputTypeName);
|
|
1243
|
+
if (unwrappedTypeName.toLowerCase() === "void") {
|
|
1244
|
+
outputTypeHint = "void";
|
|
475
1245
|
}
|
|
476
|
-
else {
|
|
477
|
-
|
|
1246
|
+
else if (unwrappedTypeName.toLowerCase() === "any") {
|
|
1247
|
+
outputTypeHint = "any";
|
|
478
1248
|
}
|
|
479
|
-
|
|
1249
|
+
else if (schema_extraction_1.TypeScriptSourceParser.shouldGenerateSchema(unwrappedTypeName)) {
|
|
1250
|
+
outputTypeHint = "named";
|
|
1251
|
+
outputSchemaType = this.resolveTypeNameToSchemaId(fileText, unwrappedTypeName, filePath);
|
|
1252
|
+
if (!outputSchemaType) {
|
|
1253
|
+
baseName = require("path").basename(filePath);
|
|
1254
|
+
perfLog.warn("Tool ".concat(baseName, ": Could not resolve output type \"").concat(unwrappedTypeName, "\" to schema $id. Make sure it's exported from src/schemas/"));
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
return [2 /*return*/, {
|
|
1258
|
+
inputSchemaType: inputSchemaType,
|
|
1259
|
+
outputSchemaType: outputSchemaType,
|
|
1260
|
+
inputTypeHint: inputTypeHint,
|
|
1261
|
+
outputTypeHint: outputTypeHint,
|
|
1262
|
+
}];
|
|
480
1263
|
});
|
|
481
1264
|
});
|
|
482
1265
|
};
|
|
483
1266
|
/**
|
|
484
|
-
*
|
|
1267
|
+
* Extracts schema information from a handler file using text-based parsing.
|
|
1268
|
+
* Resolves type names to schema $ids from the schema universe.
|
|
485
1269
|
*/
|
|
486
|
-
TypeScriptCompiler.prototype.
|
|
487
|
-
var _a, _b, _c;
|
|
488
|
-
var interfaceName = ((_a = interfaceDecl.getName) === null || _a === void 0 ? void 0 : _a.call(interfaceDecl)) || ((_b = interfaceDecl.getFirstChildByKind(ts_morph_1.SyntaxKind.Identifier)) === null || _b === void 0 ? void 0 : _b.getText());
|
|
489
|
-
if (!interfaceName)
|
|
490
|
-
return;
|
|
491
|
-
// Check if already copied
|
|
492
|
-
var existingInterface = this.parsedTsSchemas.find(function (s) { return s.includes("interface ".concat(interfaceName, " ")) || s.includes("type ".concat(interfaceName, " =")); });
|
|
493
|
-
if (existingInterface)
|
|
494
|
-
return;
|
|
495
|
-
// Copy the interface
|
|
496
|
-
this.parsedTsSchemas.push(interfaceDecl.getText());
|
|
497
|
-
// Find and recursively copy dependencies from the same file
|
|
498
|
-
// First, find direct type references in this interface
|
|
499
|
-
var typeRefIdentifiers = interfaceDecl
|
|
500
|
-
.getDescendantsOfKind(ts_morph_1.SyntaxKind.TypeReference)
|
|
501
|
-
.filter(function (typeRefNode) { return !!typeRefNode.getFirstChildIfKind(ts_morph_1.SyntaxKind.Identifier); })
|
|
502
|
-
.map(function (typeRefNode) { return typeRefNode.getFirstChildIfKindOrThrow(ts_morph_1.SyntaxKind.Identifier); });
|
|
503
|
-
for (var _i = 0, typeRefIdentifiers_1 = typeRefIdentifiers; _i < typeRefIdentifiers_1.length; _i++) {
|
|
504
|
-
var typeRefIdentifier = typeRefIdentifiers_1[_i];
|
|
505
|
-
var typeSymbol = typeRefIdentifier.getSymbol();
|
|
506
|
-
if (typeSymbol) {
|
|
507
|
-
var declaredType = typeSymbol.getDeclaredType();
|
|
508
|
-
var declaration = (_c = declaredType.getSymbol()) === null || _c === void 0 ? void 0 : _c.getDeclarations()[0];
|
|
509
|
-
if (declaration && declaration.getSourceFile() === handlerFile) {
|
|
510
|
-
// Same file - recursively copy this dependency
|
|
511
|
-
this.copyInterfaceWithDependencies(declaration, handlerFile);
|
|
512
|
-
}
|
|
513
|
-
else if (declaration && declaration.getSourceFile() !== handlerFile) {
|
|
514
|
-
// Different file - add to imports
|
|
515
|
-
var declaredTypeSymbol = declaredType.getSymbol();
|
|
516
|
-
if (declaredTypeSymbol) {
|
|
517
|
-
this.tsSchemasSymbolsToImports.push(declaredTypeSymbol);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
};
|
|
523
|
-
TypeScriptCompiler.prototype.saveIntermediateTsSchema = function (schema, handlerFile, suffix) {
|
|
1270
|
+
TypeScriptCompiler.prototype.extractSchemasFromHandlerFast = function (filePath) {
|
|
524
1271
|
return __awaiter(this, void 0, void 0, function () {
|
|
525
|
-
var
|
|
526
|
-
return __generator(this, function (
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
return [2 /*return
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
schemaSymbol = schema.getSymbolOrThrow();
|
|
539
|
-
interfaceName = (0, TypeScriptUtils_1.getInterfaceName)(schemaSymbol);
|
|
540
|
-
declaration = schemaSymbol.getDeclarations()[0];
|
|
541
|
-
if (declaration.getSourceFile() === handlerFile) {
|
|
542
|
-
// Interface is declared within handler file
|
|
543
|
-
generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " {\n ").concat(schema
|
|
544
|
-
.getProperties()
|
|
545
|
-
.map(function (p) { return p.getValueDeclarationOrThrow().getText(); })
|
|
546
|
-
.join("\n"), "\n }");
|
|
547
|
-
for (_i = 0, _a = (0, TypeScriptUtils_1.getTypesToImport)(declaration); _i < _a.length; _i++) {
|
|
548
|
-
typeToImport = _a[_i];
|
|
549
|
-
typeSymbol = typeToImport.getSymbol();
|
|
550
|
-
if (typeSymbol) {
|
|
551
|
-
declaredTypeSymbol = typeSymbol.getDeclaredType().getSymbol();
|
|
552
|
-
if (declaredTypeSymbol) {
|
|
553
|
-
this.tsSchemasSymbolsToImports.push(declaredTypeSymbol);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
// Also check for utility types with indexed access patterns like Partial<Foo["bar"]>
|
|
558
|
-
for (_b = 0, _c = schema.getProperties(); _b < _c.length; _b++) {
|
|
559
|
-
prop = _c[_b];
|
|
560
|
-
propDecl = prop.getValueDeclaration();
|
|
561
|
-
if (propDecl) {
|
|
562
|
-
propText = propDecl.getText();
|
|
563
|
-
interfaceNameMatches = propText.match(/\b([A-Z][a-zA-Z0-9]*)\s*\[/g);
|
|
564
|
-
if (interfaceNameMatches) {
|
|
565
|
-
for (_d = 0, interfaceNameMatches_1 = interfaceNameMatches; _d < interfaceNameMatches_1.length; _d++) {
|
|
566
|
-
match = interfaceNameMatches_1[_d];
|
|
567
|
-
referencedInterfaceName = match.replace(/\s*\[$/, '').trim();
|
|
568
|
-
referencedInterfaceDecl = handlerFile.getInterface(referencedInterfaceName) || handlerFile.getTypeAlias(referencedInterfaceName);
|
|
569
|
-
if (referencedInterfaceDecl) {
|
|
570
|
-
// Interface is in same file - copy it and all its dependencies recursively
|
|
571
|
-
this.copyInterfaceWithDependencies(referencedInterfaceDecl, handlerFile);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
else {
|
|
579
|
-
// Interface is imported from other file
|
|
580
|
-
generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " extends ").concat(interfaceName, " {}");
|
|
581
|
-
this.tsSchemasSymbolsToImports.push(schemaSymbol);
|
|
582
|
-
}
|
|
1272
|
+
var fileText, typeArgs, baseName, reqTypeName, resTypeName, paramsTypeName, queryTypeName, reqSchemaType, resSchemaType, isSkipValidation, baseName, baseName, paramsMetadata, queryMetadata, metadata, metadata;
|
|
1273
|
+
return __generator(this, function (_a) {
|
|
1274
|
+
fileText = fs_1.default.readFileSync(filePath, "utf8");
|
|
1275
|
+
typeArgs = schema_extraction_1.TypeScriptSourceParser.parseHandlerTypeArgs(fileText);
|
|
1276
|
+
if (!typeArgs) {
|
|
1277
|
+
baseName = require("path").basename(filePath, require("path").extname(filePath));
|
|
1278
|
+
perfLog.trace(" Handler ".concat(baseName, ": Could not parse Handler type arguments"));
|
|
1279
|
+
return [2 /*return*/, {
|
|
1280
|
+
reqSchemaType: undefined,
|
|
1281
|
+
resSchemaType: undefined,
|
|
1282
|
+
queryMetadata: [],
|
|
1283
|
+
paramsMetadata: [],
|
|
1284
|
+
}];
|
|
583
1285
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
.getProperties()
|
|
597
|
-
.map(function (p) { return p.getValueDeclarationOrThrow().getText(); })
|
|
598
|
-
.join(" ");
|
|
599
|
-
generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " extends Array<{").concat(props, "}> {}");
|
|
600
|
-
}
|
|
601
|
-
else {
|
|
602
|
-
generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " extends Array<").concat(declaration.getText(), "> {}");
|
|
603
|
-
}
|
|
604
|
-
for (_e = 0, _f = (0, TypeScriptUtils_1.getTypesToImport)(declaration); _e < _f.length; _e++) {
|
|
605
|
-
typeToImport = _f[_e];
|
|
606
|
-
typeSymbol = typeToImport.getSymbol();
|
|
607
|
-
if (typeSymbol) {
|
|
608
|
-
declaredTypeSymbol = typeSymbol.getDeclaredType().getSymbol();
|
|
609
|
-
if (declaredTypeSymbol) {
|
|
610
|
-
this.tsSchemasSymbolsToImports.push(declaredTypeSymbol);
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
}
|
|
1286
|
+
reqTypeName = typeArgs.reqType;
|
|
1287
|
+
resTypeName = typeArgs.resType;
|
|
1288
|
+
paramsTypeName = typeArgs.paramsType;
|
|
1289
|
+
queryTypeName = typeArgs.queryType;
|
|
1290
|
+
reqSchemaType = undefined;
|
|
1291
|
+
resSchemaType = undefined;
|
|
1292
|
+
isSkipValidation = /ValidationMode\.SkipValidation/.test(fileText);
|
|
1293
|
+
if (reqTypeName && schema_extraction_1.TypeScriptSourceParser.shouldGenerateSchema(reqTypeName)) {
|
|
1294
|
+
reqSchemaType = this.resolveTypeNameToSchemaId(fileText, reqTypeName, filePath);
|
|
1295
|
+
if (!reqSchemaType && !isSkipValidation) {
|
|
1296
|
+
baseName = require("path").basename(filePath);
|
|
1297
|
+
perfLog.warn("Handler ".concat(baseName, ": Could not resolve request type \"").concat(reqTypeName, "\" to schema $id. Make sure it's exported from src/schemas/"));
|
|
614
1298
|
}
|
|
615
1299
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
var propName = prop.getName();
|
|
622
|
-
var propType = prop.getTypeAtLocation(handlerFile);
|
|
623
|
-
var propTypeText = propType.getText(undefined, ts_morph_1.ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
|
|
624
|
-
// Check if property is optional
|
|
625
|
-
// For utility types (Omit, Pick, etc.), properties may not have value declarations
|
|
626
|
-
var valueDeclaration = prop.getValueDeclaration();
|
|
627
|
-
var isOptional = false;
|
|
628
|
-
if (valueDeclaration) {
|
|
629
|
-
// Property has a source declaration (normal case)
|
|
630
|
-
isOptional = valueDeclaration.getType().isNullable() || valueDeclaration.compilerNode.questionToken !== undefined;
|
|
631
|
-
}
|
|
632
|
-
else {
|
|
633
|
-
// Property is synthetic (from utility types like Omit, Pick, etc.)
|
|
634
|
-
// Check if the property itself is optional by examining the symbol flags
|
|
635
|
-
isOptional = !!(prop.getFlags() & ts_morph_1.ts.SymbolFlags.Optional);
|
|
636
|
-
}
|
|
637
|
-
return "".concat(propName).concat(isOptional ? "?" : "", ": ").concat(propTypeText);
|
|
638
|
-
});
|
|
639
|
-
// Extract type references for imports from resolved types
|
|
640
|
-
for (_g = 0, _h = schema.getProperties(); _g < _h.length; _g++) {
|
|
641
|
-
prop = _h[_g];
|
|
642
|
-
propType = prop.getTypeAtLocation(handlerFile);
|
|
643
|
-
typeSymbol = propType.getSymbol();
|
|
644
|
-
if (typeSymbol) {
|
|
645
|
-
typeDeclaration = typeSymbol.getDeclarations()[0];
|
|
646
|
-
if (typeDeclaration && typeDeclaration.getSourceFile() !== handlerFile) {
|
|
647
|
-
this.tsSchemasSymbolsToImports.push(typeSymbol);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
// Also check for array element types
|
|
651
|
-
if (propType.isArray()) {
|
|
652
|
-
elementType = propType.getArrayElementType();
|
|
653
|
-
elementSymbol = elementType === null || elementType === void 0 ? void 0 : elementType.getSymbol();
|
|
654
|
-
if (elementSymbol) {
|
|
655
|
-
elementDeclaration = elementSymbol.getDeclarations()[0];
|
|
656
|
-
if (elementDeclaration && elementDeclaration.getSourceFile() !== handlerFile) {
|
|
657
|
-
this.tsSchemasSymbolsToImports.push(elementSymbol);
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
currentPropTypeText = propType.getText(undefined, ts_morph_1.ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
|
|
662
|
-
interfaceNameMatches = currentPropTypeText.match(/\b([A-Z][a-zA-Z0-9]*)\s*\[/g);
|
|
663
|
-
if (interfaceNameMatches) {
|
|
664
|
-
for (_j = 0, interfaceNameMatches_2 = interfaceNameMatches; _j < interfaceNameMatches_2.length; _j++) {
|
|
665
|
-
match = interfaceNameMatches_2[_j];
|
|
666
|
-
interfaceName = match.replace(/\s*\[$/, '').trim();
|
|
667
|
-
interfaceDecl = handlerFile.getInterface(interfaceName) || handlerFile.getTypeAlias(interfaceName);
|
|
668
|
-
if (interfaceDecl) {
|
|
669
|
-
// Interface is in same file - copy it and all its dependencies recursively
|
|
670
|
-
this.copyInterfaceWithDependencies(interfaceDecl, handlerFile);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
typeArgs = propType.getTypeArguments();
|
|
675
|
-
if (typeArgs && typeArgs.length > 0) {
|
|
676
|
-
for (_k = 0, typeArgs_1 = typeArgs; _k < typeArgs_1.length; _k++) {
|
|
677
|
-
typeArg = typeArgs_1[_k];
|
|
678
|
-
argSymbol = typeArg.getSymbol();
|
|
679
|
-
if (argSymbol) {
|
|
680
|
-
argDeclaration = argSymbol.getDeclarations()[0];
|
|
681
|
-
if (argDeclaration && argDeclaration.getSourceFile() !== handlerFile) {
|
|
682
|
-
this.tsSchemasSymbolsToImports.push(argSymbol);
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
// If we have a declaration, check if we need to import any types
|
|
689
|
-
if (declaration) {
|
|
690
|
-
for (_l = 0, _m = (0, TypeScriptUtils_1.getTypesToImport)(declaration); _l < _m.length; _l++) {
|
|
691
|
-
typeToImport = _m[_l];
|
|
692
|
-
typeSymbol = typeToImport.getSymbol();
|
|
693
|
-
if (typeSymbol) {
|
|
694
|
-
declaredTypeSymbol = typeSymbol.getDeclaredType().getSymbol();
|
|
695
|
-
if (declaredTypeSymbol) {
|
|
696
|
-
this.tsSchemasSymbolsToImports.push(declaredTypeSymbol);
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
}
|
|
1300
|
+
if (resTypeName && schema_extraction_1.TypeScriptSourceParser.shouldGenerateSchema(resTypeName)) {
|
|
1301
|
+
resSchemaType = this.resolveTypeNameToSchemaId(fileText, resTypeName, filePath);
|
|
1302
|
+
if (!resSchemaType && !isSkipValidation) {
|
|
1303
|
+
baseName = require("path").basename(filePath);
|
|
1304
|
+
perfLog.warn("Handler ".concat(baseName, ": Could not resolve response type \"").concat(resTypeName, "\" to schema $id. Make sure it's exported from src/schemas/"));
|
|
700
1305
|
}
|
|
701
|
-
generatedSchemaInterfaceStr = "export interface ".concat(schemaInterfaceName, " { ").concat(propertySignatures.join(";\n"), " }");
|
|
702
1306
|
}
|
|
703
|
-
|
|
704
|
-
|
|
1307
|
+
paramsMetadata = [];
|
|
1308
|
+
queryMetadata = [];
|
|
1309
|
+
if (paramsTypeName && paramsTypeName !== "any" && paramsTypeName !== "void") {
|
|
1310
|
+
metadata = schema_extraction_1.TypeScriptSourceParser.extractPropertyMetadata(fileText, paramsTypeName);
|
|
1311
|
+
if (metadata) {
|
|
1312
|
+
paramsMetadata = metadata;
|
|
1313
|
+
}
|
|
705
1314
|
}
|
|
706
|
-
if (
|
|
707
|
-
|
|
708
|
-
|
|
1315
|
+
if (queryTypeName && queryTypeName !== "any" && queryTypeName !== "void") {
|
|
1316
|
+
metadata = schema_extraction_1.TypeScriptSourceParser.extractPropertyMetadata(fileText, queryTypeName);
|
|
1317
|
+
if (metadata) {
|
|
1318
|
+
queryMetadata = metadata;
|
|
1319
|
+
}
|
|
709
1320
|
}
|
|
710
|
-
return [2 /*return
|
|
1321
|
+
return [2 /*return*/, {
|
|
1322
|
+
reqSchemaType: reqSchemaType,
|
|
1323
|
+
resSchemaType: resSchemaType,
|
|
1324
|
+
queryMetadata: queryMetadata,
|
|
1325
|
+
paramsMetadata: paramsMetadata,
|
|
1326
|
+
}];
|
|
711
1327
|
});
|
|
712
1328
|
});
|
|
713
1329
|
};
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
markdownDescription: false,
|
|
726
|
-
skipTypeCheck: false,
|
|
727
|
-
encodeRefs: false,
|
|
728
|
-
extraTags: [],
|
|
729
|
-
functions: "fail",
|
|
730
|
-
discriminatorType: "json-schema",
|
|
731
|
-
tsconfig: tsconfigPath,
|
|
732
|
-
};
|
|
733
|
-
console.log("Creating TypeScript program for schema generation:");
|
|
734
|
-
console.log(" Schema file:", schemaFilePath);
|
|
735
|
-
console.log(" tsconfig:", tsconfigPath);
|
|
736
|
-
// Create a fresh TypeScript Program that includes the schema file
|
|
737
|
-
// This ensures ts-json-schema-generator can find the types we just generated
|
|
738
|
-
var program;
|
|
739
|
-
try {
|
|
740
|
-
program = (0, ts_json_schema_generator_1.createProgram)(conf);
|
|
741
|
-
}
|
|
742
|
-
catch (error) {
|
|
743
|
-
// Format the error in a more developer-friendly way
|
|
744
|
-
console.error("\n❌ Schema generation failed due to TypeScript compilation errors:\n");
|
|
745
|
-
if (error.diagnostic && error.diagnostic.relatedInformation) {
|
|
746
|
-
// Extract and display only the relevant error messages
|
|
747
|
-
for (var _i = 0, _a = error.diagnostic.relatedInformation; _i < _a.length; _i++) {
|
|
748
|
-
var info = _a[_i];
|
|
749
|
-
if (info.file) {
|
|
750
|
-
var _b = info.file.getLineAndCharacterOfPosition(info.start), line = _b.line, character = _b.character;
|
|
751
|
-
var fileName = info.file.fileName.replace(this.cwd, ".");
|
|
752
|
-
var message = typeof info.messageText === "string" ? info.messageText : info.messageText.messageText;
|
|
753
|
-
console.error(" ".concat(fileName, ":").concat(line + 1, ":").concat(character + 1));
|
|
754
|
-
console.error(" ".concat(message, "\n"));
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
else if (error.message) {
|
|
759
|
-
console.error(" ".concat(error.message, "\n"));
|
|
760
|
-
}
|
|
761
|
-
console.error("💡 Tip: Fix the TypeScript errors above and try again.\n");
|
|
762
|
-
process.exit(1);
|
|
1330
|
+
/**
|
|
1331
|
+
* Check if handler source file is up for auto registration by inspecting
|
|
1332
|
+
* the Route.
|
|
1333
|
+
*
|
|
1334
|
+
* @param sf handler file
|
|
1335
|
+
* @returns
|
|
1336
|
+
*/
|
|
1337
|
+
TypeScriptCompiler.prototype.isAutoRegisterableHandler = function (sf) {
|
|
1338
|
+
var route = sf.getVariableDeclaration("Route");
|
|
1339
|
+
if (!route) {
|
|
1340
|
+
return false;
|
|
763
1341
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
1342
|
+
var routeProps = route.getFirstDescendantByKindOrThrow(ts_morph_1.SyntaxKind.ObjectLiteralExpression);
|
|
1343
|
+
var skipAutoRegProp = routeProps.getProperty("skipAutoRegister");
|
|
1344
|
+
return !skipAutoRegProp || skipAutoRegProp.getText().endsWith("false");
|
|
1345
|
+
};
|
|
1346
|
+
/**
|
|
1347
|
+
* Generates JSON schemas for all handlers and tools.
|
|
1348
|
+
* Should be called after parseHandlers() and parseTools() have completed.
|
|
1349
|
+
*
|
|
1350
|
+
* NEW SIMPLIFIED APPROACH:
|
|
1351
|
+
* 1. Generate schema universe from src/schemas/**\/*.ts (includes wrappers/)
|
|
1352
|
+
* 2. Handlers/tools reference schemas by $id
|
|
1353
|
+
* 3. Create manifest with schema universe and references
|
|
1354
|
+
*/
|
|
1355
|
+
TypeScriptCompiler.prototype.generateAllSchemas = function () {
|
|
772
1356
|
return __awaiter(this, void 0, void 0, function () {
|
|
773
|
-
var
|
|
774
|
-
var
|
|
775
|
-
return __generator(this, function (
|
|
776
|
-
switch (
|
|
1357
|
+
var schemaGenStartTime, path, schemaDir, schemaFiles, schemaUniverse, _i, schemaFiles_1, schemaFile, absolutePath, fileSchemas, schemaGenTime;
|
|
1358
|
+
var _this = this;
|
|
1359
|
+
return __generator(this, function (_a) {
|
|
1360
|
+
switch (_a.label) {
|
|
777
1361
|
case 0:
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
1362
|
+
schemaGenStartTime = Date.now();
|
|
1363
|
+
// Initialize schema generator
|
|
1364
|
+
return [4 /*yield*/, this.initSchemaGenerator()];
|
|
1365
|
+
case 1:
|
|
1366
|
+
// Initialize schema generator
|
|
1367
|
+
_a.sent();
|
|
1368
|
+
if (!this.schemaGenerator) {
|
|
1369
|
+
throw new Error("Schema generator not initialized");
|
|
1370
|
+
}
|
|
1371
|
+
path = require("path");
|
|
1372
|
+
schemaDir = path.join(this.cwd, "src/schemas");
|
|
1373
|
+
// Check if schemas directory exists
|
|
1374
|
+
if (!fs_1.default.existsSync(schemaDir)) {
|
|
1375
|
+
perfLog.warn("No src/schemas/ directory found. Skipping schema generation.");
|
|
1376
|
+
return [2 /*return*/];
|
|
1377
|
+
}
|
|
1378
|
+
return [4 /*yield*/, (0, tiny_glob_1.default)(path.join(schemaDir, "**/*.ts"))];
|
|
1379
|
+
case 2:
|
|
1380
|
+
schemaFiles = _a.sent();
|
|
1381
|
+
perfLog.debug("Found ".concat(schemaFiles.length, " schema files in src/schemas/"));
|
|
1382
|
+
schemaUniverse = {};
|
|
1383
|
+
for (_i = 0, schemaFiles_1 = schemaFiles; _i < schemaFiles_1.length; _i++) {
|
|
1384
|
+
schemaFile = schemaFiles_1[_i];
|
|
1385
|
+
absolutePath = path.join(this.cwd, schemaFile);
|
|
1386
|
+
try {
|
|
1387
|
+
fileSchemas = this.schemaGenerator(absolutePath, {
|
|
1388
|
+
followImports: "local",
|
|
1389
|
+
schemaVersion: "http://json-schema.org/draft-07/schema#",
|
|
1390
|
+
includeJSDoc: true,
|
|
1391
|
+
strictObjects: false,
|
|
1392
|
+
additionalProperties: undefined,
|
|
1393
|
+
defineId: function (typeName, declaration, context) {
|
|
1394
|
+
if (!context)
|
|
1395
|
+
return typeName;
|
|
1396
|
+
// Generate stable $id using same algorithm as resolveTypeNameToSchemaId
|
|
1397
|
+
return _this.filePathToSchemaId(context.absolutePath, typeName);
|
|
1398
|
+
},
|
|
1399
|
+
});
|
|
1400
|
+
// Merge schemas from this file into universe
|
|
1401
|
+
schemaUniverse = __assign(__assign({}, schemaUniverse), fileSchemas);
|
|
785
1402
|
}
|
|
786
|
-
|
|
787
|
-
|
|
1403
|
+
catch (error) {
|
|
1404
|
+
perfLog.warn("Failed to generate schemas from ".concat(schemaFile, ": ").concat(error.message));
|
|
788
1405
|
}
|
|
789
1406
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
return [4 /*yield*/, (0, FsUtils_1.writeJsonFile)(filePath, mergedSchemas)];
|
|
802
|
-
case 1:
|
|
803
|
-
_d.sent();
|
|
804
|
-
this.project.addSourceFileAtPath(filePath);
|
|
805
|
-
return [2 /*return*/, mergedSchemas];
|
|
1407
|
+
perfLog.debug("Generated ".concat(Object.keys(schemaUniverse).length, " schemas from ").concat(schemaFiles.length, " files"));
|
|
1408
|
+
perfLog.debug("Sample schema $ids: ".concat(Object.keys(schemaUniverse).slice(0, 10).join(", "), "..."));
|
|
1409
|
+
// Create manifest with schema universe and handler/tool references
|
|
1410
|
+
return [4 /*yield*/, this.generateSchemaManifest(schemaUniverse)];
|
|
1411
|
+
case 3:
|
|
1412
|
+
// Create manifest with schema universe and handler/tool references
|
|
1413
|
+
_a.sent();
|
|
1414
|
+
schemaGenTime = Date.now() - schemaGenStartTime;
|
|
1415
|
+
initLog.info("\u2713 Schema generation completed in ".concat(schemaGenTime, "ms ") +
|
|
1416
|
+
"(".concat(Object.keys(schemaUniverse).length, " schemas, ").concat(this.handlerSchemasToGenerate.length, " handlers, ").concat(this.toolSchemasToGenerate.length, " tools)"));
|
|
1417
|
+
return [2 /*return*/];
|
|
806
1418
|
}
|
|
807
1419
|
});
|
|
808
1420
|
});
|
|
809
1421
|
};
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
1422
|
+
/**
|
|
1423
|
+
* Computes relative path from project root for a source file.
|
|
1424
|
+
* This is used consistently for manifest keys and __file exports.
|
|
1425
|
+
*/
|
|
1426
|
+
TypeScriptCompiler.prototype.getRelativePath = function (sf) {
|
|
1427
|
+
var filePath = sf.getFilePath();
|
|
1428
|
+
return filePath.startsWith(this.cwd) ? filePath.substring(this.cwd.length + 1) : filePath;
|
|
815
1429
|
};
|
|
816
|
-
|
|
1430
|
+
/**
|
|
1431
|
+
* Generates schema manifest with schema universe and handler/tool references.
|
|
1432
|
+
*/
|
|
1433
|
+
TypeScriptCompiler.prototype.generateSchemaManifest = function (schemaUniverse) {
|
|
817
1434
|
return __awaiter(this, void 0, void 0, function () {
|
|
818
|
-
var
|
|
819
|
-
return __generator(this, function (
|
|
820
|
-
switch (
|
|
1435
|
+
var manifest, _i, _a, handler, relativePath, _b, _c, tool, relativePath, manifestPath;
|
|
1436
|
+
return __generator(this, function (_d) {
|
|
1437
|
+
switch (_d.label) {
|
|
821
1438
|
case 0:
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
//
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
1439
|
+
manifest = {
|
|
1440
|
+
version: "2.0",
|
|
1441
|
+
generated: new Date().toISOString(),
|
|
1442
|
+
schemas: schemaUniverse,
|
|
1443
|
+
handlers: {},
|
|
1444
|
+
tools: {},
|
|
1445
|
+
};
|
|
1446
|
+
// Map handlers with their schema references
|
|
1447
|
+
for (_i = 0, _a = this.handlerSchemasToGenerate; _i < _a.length; _i++) {
|
|
1448
|
+
handler = _a[_i];
|
|
1449
|
+
relativePath = this.getRelativePath(handler.sourceFile);
|
|
1450
|
+
// Validate schema references exist
|
|
1451
|
+
if (handler.reqSchemaType && !schemaUniverse[handler.reqSchemaType]) {
|
|
1452
|
+
perfLog.warn("Handler ".concat(handler.sourceFile.getBaseName(), " references request schema \"").concat(handler.reqSchemaType, "\" which was not found in schema universe"));
|
|
1453
|
+
}
|
|
1454
|
+
if (handler.resSchemaType && !schemaUniverse[handler.resSchemaType]) {
|
|
1455
|
+
perfLog.warn("Handler ".concat(handler.sourceFile.getBaseName(), " references response schema \"").concat(handler.resSchemaType, "\" which was not found in schema universe"));
|
|
1456
|
+
}
|
|
1457
|
+
manifest.handlers[relativePath] = {
|
|
1458
|
+
reqSchemaName: handler.reqSchemaType,
|
|
1459
|
+
resSchemaName: handler.resSchemaType,
|
|
1460
|
+
queryMetadata: handler.queryMetadata || [],
|
|
1461
|
+
paramsMetadata: handler.paramsMetadata || [],
|
|
1462
|
+
};
|
|
838
1463
|
}
|
|
839
|
-
|
|
840
|
-
|
|
1464
|
+
// Map tools with their schema references
|
|
1465
|
+
for (_b = 0, _c = this.toolSchemasToGenerate; _b < _c.length; _b++) {
|
|
1466
|
+
tool = _c[_b];
|
|
1467
|
+
relativePath = this.getRelativePath(tool.sourceFile);
|
|
1468
|
+
// Validate schema references exist
|
|
1469
|
+
if (tool.inputSchemaType && !schemaUniverse[tool.inputSchemaType]) {
|
|
1470
|
+
perfLog.warn("Tool ".concat(tool.sourceFile.getBaseName(), " references input schema \"").concat(tool.inputSchemaType, "\" which was not found in schema universe"));
|
|
1471
|
+
}
|
|
1472
|
+
if (tool.outputSchemaType && !schemaUniverse[tool.outputSchemaType]) {
|
|
1473
|
+
perfLog.warn("Tool ".concat(tool.sourceFile.getBaseName(), " references output schema \"").concat(tool.outputSchemaType, "\" which was not found in schema universe"));
|
|
1474
|
+
}
|
|
1475
|
+
manifest.tools[relativePath] = {
|
|
1476
|
+
inputSchemaName: tool.inputSchemaType,
|
|
1477
|
+
outputSchemaName: tool.outputSchemaType,
|
|
1478
|
+
inputTypeHint: tool.inputTypeHint,
|
|
1479
|
+
outputTypeHint: tool.outputTypeHint,
|
|
1480
|
+
};
|
|
841
1481
|
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
? this.saveIntermediateTsSchema(reqSchema, sf, "".concat(handlerTypeReference.getStartLineNumber(), "_ReqSchema"))
|
|
845
|
-
: Promise.resolve("");
|
|
846
|
-
createResSchemaPromise = resSchema
|
|
847
|
-
? this.saveIntermediateTsSchema(resSchema, sf, "".concat(handlerTypeReference.getStartLineNumber(), "_ResSchema"))
|
|
848
|
-
: Promise.resolve("");
|
|
849
|
-
return [4 /*yield*/, Promise.all([createReqSchemaPromise, createResSchemaPromise])];
|
|
1482
|
+
manifestPath = (0, path_1.join)(this.cwd, "dist/.flink/schema-manifest.json");
|
|
1483
|
+
return [4 /*yield*/, (0, FsUtils_1.writeJsonFile)(manifestPath, manifest, { ensureDir: true })];
|
|
850
1484
|
case 1:
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
resSchemaType: resSchemaType,
|
|
855
|
-
queryMetadata: (0, TypeScriptUtils_1.getTypeMetadata)(query),
|
|
856
|
-
paramsMetadata: (0, TypeScriptUtils_1.getTypeMetadata)(params),
|
|
857
|
-
}];
|
|
1485
|
+
_d.sent();
|
|
1486
|
+
perfLog.debug("Schema manifest written to: ".concat(manifestPath));
|
|
1487
|
+
return [2 /*return*/];
|
|
858
1488
|
}
|
|
859
1489
|
});
|
|
860
1490
|
});
|
|
861
1491
|
};
|
|
862
1492
|
/**
|
|
863
|
-
*
|
|
864
|
-
* TypeScript schemas that has been derived from handlers.
|
|
1493
|
+
* Scans project for jobs so they can be registered during start.
|
|
865
1494
|
*/
|
|
866
|
-
TypeScriptCompiler.prototype.
|
|
1495
|
+
TypeScriptCompiler.prototype.parseJobs = function () {
|
|
867
1496
|
return __awaiter(this, void 0, void 0, function () {
|
|
868
|
-
var
|
|
1497
|
+
var startTime, generatedFile, jobsArr, imports, jobElements, jobParseTime;
|
|
1498
|
+
var _this = this;
|
|
869
1499
|
return __generator(this, function (_a) {
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
1500
|
+
startTime = Date.now();
|
|
1501
|
+
generatedFile = this.createSourceFile(["generatedJobs.ts"], "// Generated ".concat(new Date(), "\nimport { autoRegisteredJobs } from \"@flink-app/flink\";\nexport const jobs = [];\nautoRegisteredJobs.push(...jobs);\n "));
|
|
1502
|
+
jobsArr = generatedFile.getVariableDeclarationOrThrow("jobs").getFirstDescendantByKindOrThrow(ts_morph_1.SyntaxKind.ArrayLiteralExpression);
|
|
1503
|
+
imports = [];
|
|
1504
|
+
jobElements = [];
|
|
1505
|
+
// Use pre-segmented job files (no filtering needed)
|
|
1506
|
+
this.jobFiles.forEach(function (sf, i) {
|
|
1507
|
+
console.log("Detected job ".concat(sf.getBaseName()));
|
|
1508
|
+
var namespaceImport = sf.getBaseNameWithoutExtension().replace(/\./g, "_") + "_" + i;
|
|
1509
|
+
imports.push({
|
|
1510
|
+
defaultImport: "* as " + namespaceImport,
|
|
1511
|
+
moduleSpecifier: _this.getModuleSpecifier(generatedFile, sf),
|
|
1512
|
+
});
|
|
1513
|
+
// __file is set on the registration object (not injected into source files)
|
|
1514
|
+
jobElements.push("{...".concat(namespaceImport, ", __file: \"").concat(_this.getRelativePath(sf), "\"}"));
|
|
1515
|
+
});
|
|
1516
|
+
// Add all job elements in one batch operation
|
|
1517
|
+
jobsArr.addElements(jobElements);
|
|
1518
|
+
generatedFile.addImportDeclarations(imports);
|
|
1519
|
+
// Defer save until batch save at end (performance optimization)
|
|
1520
|
+
// Cleanup: forget job file nodes to reduce memory overhead (ts-morph performance optimization)
|
|
1521
|
+
this.jobFiles.forEach(function (sf) {
|
|
1522
|
+
sf.getClasses().forEach(function (cls) { return cls.forget(); });
|
|
1523
|
+
});
|
|
1524
|
+
jobParseTime = Date.now() - startTime;
|
|
1525
|
+
perfLog.info("\u2713 Job parsing completed in ".concat(jobParseTime, "ms (").concat(jobElements.length, " jobs)"));
|
|
1526
|
+
return [2 /*return*/, generatedFile];
|
|
880
1527
|
});
|
|
881
1528
|
});
|
|
882
1529
|
};
|
|
883
1530
|
/**
|
|
884
|
-
*
|
|
885
|
-
* the Route.
|
|
886
|
-
*
|
|
887
|
-
* @param sf handler file
|
|
888
|
-
* @returns
|
|
1531
|
+
* Scans project for services so they can be registered during start.
|
|
889
1532
|
*/
|
|
890
|
-
TypeScriptCompiler.prototype.
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
return
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
1533
|
+
TypeScriptCompiler.prototype.parseServices = function () {
|
|
1534
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1535
|
+
var startTime, generatedFile, servicesArr, imports, serviceElements, _i, _a, sf, serviceParseTime;
|
|
1536
|
+
return __generator(this, function (_b) {
|
|
1537
|
+
if (this.disableServices) {
|
|
1538
|
+
initLog.info("Services disabled via flink.config.js (disableServices: true)");
|
|
1539
|
+
}
|
|
1540
|
+
startTime = Date.now();
|
|
1541
|
+
generatedFile = this.createSourceFile(["generatedServices.ts"], "// Generated ".concat(new Date(), "\nimport { autoRegisteredServices } from \"@flink-app/flink\";\nexport const services: any[] = [];\nautoRegisteredServices.push(...services);\n "));
|
|
1542
|
+
servicesArr = generatedFile.getVariableDeclarationOrThrow("services").getFirstDescendantByKindOrThrow(ts_morph_1.SyntaxKind.ArrayLiteralExpression);
|
|
1543
|
+
imports = [];
|
|
1544
|
+
serviceElements = [];
|
|
1545
|
+
for (_i = 0, _a = this.serviceFiles; _i < _a.length; _i++) {
|
|
1546
|
+
sf = _a[_i];
|
|
1547
|
+
console.log("Detected service ".concat(sf.getBaseName()));
|
|
1548
|
+
imports.push({
|
|
1549
|
+
defaultImport: sf.getBaseNameWithoutExtension(),
|
|
1550
|
+
moduleSpecifier: this.getModuleSpecifier(generatedFile, sf),
|
|
1551
|
+
});
|
|
1552
|
+
serviceElements.push("{serviceInstanceName: \"".concat((0, utils_1.getRepoInstanceName)(sf.getBaseName()), "\", Service: ").concat(sf.getBaseNameWithoutExtension(), "}"));
|
|
1553
|
+
}
|
|
1554
|
+
servicesArr.addElements(serviceElements);
|
|
1555
|
+
generatedFile.addImportDeclarations(imports);
|
|
1556
|
+
// Cleanup: forget service file nodes to reduce memory overhead
|
|
1557
|
+
this.serviceFiles.forEach(function (sf) {
|
|
1558
|
+
sf.getClasses().forEach(function (cls) { return cls.forget(); });
|
|
1559
|
+
});
|
|
1560
|
+
serviceParseTime = Date.now() - startTime;
|
|
1561
|
+
perfLog.info("\u2713 Service parsing completed in ".concat(serviceParseTime, "ms (").concat(serviceElements.length, " services)"));
|
|
1562
|
+
return [2 /*return*/, generatedFile];
|
|
1563
|
+
});
|
|
1564
|
+
});
|
|
898
1565
|
};
|
|
899
1566
|
/**
|
|
900
|
-
*
|
|
901
|
-
*
|
|
902
|
-
* @param handlers
|
|
903
|
-
* @param jsonSchemas
|
|
1567
|
+
* Generates a .flink/generatedXxx.ts file for a single compiler plugin extension.
|
|
1568
|
+
* Mirrors the same namespace-import + spread pattern used by parseJobs.
|
|
904
1569
|
*/
|
|
905
|
-
TypeScriptCompiler.prototype.
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
var
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
name: "__schemas",
|
|
931
|
-
type: "any",
|
|
932
|
-
initializer: "{ reqSchema: ".concat(reqJsonSchema, ", resSchema: ").concat(resJsonSchema, " }"),
|
|
933
|
-
},
|
|
934
|
-
],
|
|
1570
|
+
TypeScriptCompiler.prototype.parseExtensionDir = function (ext) {
|
|
1571
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1572
|
+
var startTime, files, generatedFile, itemsArr, imports, itemElements, elapsed;
|
|
1573
|
+
var _this = this;
|
|
1574
|
+
var _a;
|
|
1575
|
+
return __generator(this, function (_b) {
|
|
1576
|
+
startTime = Date.now();
|
|
1577
|
+
files = (_a = this.extensionFiles.get(ext.generatedFile)) !== null && _a !== void 0 ? _a : [];
|
|
1578
|
+
generatedFile = this.createSourceFile(["".concat(ext.generatedFile, ".ts")], "// Generated ".concat(new Date(), "\nimport { ").concat(ext.registrationVar, " } from \"").concat(ext.package, "\";\nexport const items: any[] = [];\n").concat(ext.registrationVar, ".push(...items);\n"));
|
|
1579
|
+
itemsArr = generatedFile.getVariableDeclarationOrThrow("items").getFirstDescendantByKindOrThrow(ts_morph_1.SyntaxKind.ArrayLiteralExpression);
|
|
1580
|
+
imports = [];
|
|
1581
|
+
itemElements = [];
|
|
1582
|
+
files.forEach(function (sf, i) {
|
|
1583
|
+
var namespaceImport = sf.getBaseNameWithoutExtension().replace(/\./g, "_") + "_" + i;
|
|
1584
|
+
imports.push({
|
|
1585
|
+
defaultImport: "* as " + namespaceImport,
|
|
1586
|
+
moduleSpecifier: _this.getModuleSpecifier(generatedFile, sf),
|
|
1587
|
+
});
|
|
1588
|
+
itemElements.push("{...".concat(namespaceImport, ", __file: \"").concat(_this.getRelativePath(sf), "\"}"));
|
|
1589
|
+
});
|
|
1590
|
+
itemsArr.addElements(itemElements);
|
|
1591
|
+
generatedFile.addImportDeclarations(imports);
|
|
1592
|
+
elapsed = Date.now() - startTime;
|
|
1593
|
+
initLog.info("\u2713 Extension dir \"".concat(ext.scanDir, "\" parsed in ").concat(elapsed, "ms (").concat(files.length, " files)"));
|
|
1594
|
+
return [2 /*return*/, generatedFile];
|
|
935
1595
|
});
|
|
936
|
-
}
|
|
1596
|
+
});
|
|
937
1597
|
};
|
|
938
1598
|
/**
|
|
939
|
-
*
|
|
1599
|
+
* Iterates all compilerPlugins from flink.config.js and generates
|
|
1600
|
+
* a .flink/generatedXxx.ts file for each one.
|
|
1601
|
+
* Call this after parseJobs() and before generateStartScript().
|
|
940
1602
|
*/
|
|
941
|
-
TypeScriptCompiler.prototype.
|
|
1603
|
+
TypeScriptCompiler.prototype.parseAllExtensionDirs = function () {
|
|
942
1604
|
return __awaiter(this, void 0, void 0, function () {
|
|
943
|
-
var
|
|
1605
|
+
var _i, _a, ext;
|
|
944
1606
|
return __generator(this, function (_b) {
|
|
945
1607
|
switch (_b.label) {
|
|
946
1608
|
case 0:
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
imports = [];
|
|
950
|
-
i = 0;
|
|
951
|
-
for (_i = 0, _a = this.project.getSourceFiles(); _i < _a.length; _i++) {
|
|
952
|
-
sf = _a[_i];
|
|
953
|
-
if (!sf.getFilePath().includes("src/jobs/")) {
|
|
954
|
-
continue;
|
|
955
|
-
}
|
|
956
|
-
console.log("Detected job ".concat(sf.getBaseName()));
|
|
957
|
-
namespaceImport = sf.getBaseNameWithoutExtension().replace(/\./g, "_") + "_" + i;
|
|
958
|
-
imports.push({
|
|
959
|
-
defaultImport: "* as " + namespaceImport,
|
|
960
|
-
moduleSpecifier: this.getModuleSpecifier(generatedFile, sf),
|
|
961
|
-
});
|
|
962
|
-
existingFile = sf.getVariableStatements().filter(function (vs) {
|
|
963
|
-
var varNames = vs.getDeclarations().map(function (d) { return d.getName(); });
|
|
964
|
-
return varNames.includes("__file");
|
|
965
|
-
});
|
|
966
|
-
existingFile.forEach(function (v) { return v.remove(); });
|
|
967
|
-
// Append metadata to source file that will be part of emitted dist bundle (javascript)
|
|
968
|
-
sf.addVariableStatement({
|
|
969
|
-
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
|
|
970
|
-
isExported: true,
|
|
971
|
-
declarations: [
|
|
972
|
-
{
|
|
973
|
-
name: "__file",
|
|
974
|
-
initializer: "\"".concat(sf.getBaseName(), "\""),
|
|
975
|
-
},
|
|
976
|
-
],
|
|
977
|
-
});
|
|
978
|
-
jobsArr.insertElement(i, namespaceImport);
|
|
979
|
-
i++;
|
|
980
|
-
}
|
|
981
|
-
generatedFile.addImportDeclarations(imports);
|
|
982
|
-
return [4 /*yield*/, generatedFile.save()];
|
|
1609
|
+
_i = 0, _a = this.compilerPlugins;
|
|
1610
|
+
_b.label = 1;
|
|
983
1611
|
case 1:
|
|
1612
|
+
if (!(_i < _a.length)) return [3 /*break*/, 4];
|
|
1613
|
+
ext = _a[_i];
|
|
1614
|
+
return [4 /*yield*/, this.parseExtensionDir(ext)];
|
|
1615
|
+
case 2:
|
|
984
1616
|
_b.sent();
|
|
985
|
-
|
|
1617
|
+
_b.label = 3;
|
|
1618
|
+
case 3:
|
|
1619
|
+
_i++;
|
|
1620
|
+
return [3 /*break*/, 1];
|
|
1621
|
+
case 4: return [2 /*return*/];
|
|
986
1622
|
}
|
|
987
1623
|
});
|
|
988
1624
|
});
|