@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
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
# Simple AST / Enhanced Text Parsing: Feasibility Analysis
|
|
2
|
+
|
|
3
|
+
## Question
|
|
4
|
+
Can we handle high-risk TypeScript features (template literals, conditional types, mapped types, string literals with brackets) by building more sophisticated text parsing instead of falling back to ts-morph?
|
|
5
|
+
|
|
6
|
+
## TL;DR Recommendation
|
|
7
|
+
|
|
8
|
+
**✅ YES for String Literals** - Build simple tokenizer (High ROI, Low complexity)
|
|
9
|
+
**🤔 MAYBE for Template Literals** - Possible but complex (Medium ROI, Medium complexity)
|
|
10
|
+
**❌ NO for Conditional/Mapped Types** - Use ts-morph fallback (Low ROI, High complexity)
|
|
11
|
+
|
|
12
|
+
**Recommended Approach:** Hybrid strategy
|
|
13
|
+
1. Enhanced tokenizer for strings/comments (handles 99% of cases)
|
|
14
|
+
2. ts-morph fallback for truly complex types (handles remaining 1%)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Feasibility Analysis by Feature
|
|
19
|
+
|
|
20
|
+
### 1. String Literals with Brackets ✅ FEASIBLE
|
|
21
|
+
|
|
22
|
+
**Problem:**
|
|
23
|
+
```typescript
|
|
24
|
+
interface Config {
|
|
25
|
+
pattern: "{user:id}"; // Parser sees { as object start
|
|
26
|
+
regex: "/test>/"; // Parser sees > as generic close
|
|
27
|
+
quote: "He said \"hi\""; // Escape handling
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Solution: Simple String State Machine**
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
/**
|
|
35
|
+
* Enhanced bracket counting with string literal awareness
|
|
36
|
+
*/
|
|
37
|
+
function findMatchingBracket(text: string, startPos: number): number {
|
|
38
|
+
let depth = 1;
|
|
39
|
+
let i = startPos + 1;
|
|
40
|
+
let inString = false;
|
|
41
|
+
let stringChar = '';
|
|
42
|
+
|
|
43
|
+
while (i < text.length && depth > 0) {
|
|
44
|
+
const char = text[i];
|
|
45
|
+
const prevChar = text[i - 1];
|
|
46
|
+
|
|
47
|
+
// Handle string state transitions
|
|
48
|
+
if (!inString) {
|
|
49
|
+
if (char === '"' || char === "'" || char === '`') {
|
|
50
|
+
inString = true;
|
|
51
|
+
stringChar = char;
|
|
52
|
+
} else {
|
|
53
|
+
// Only count brackets outside strings
|
|
54
|
+
if (char === '{') depth++;
|
|
55
|
+
else if (char === '}') depth--;
|
|
56
|
+
else if (char === '<') depth++;
|
|
57
|
+
else if (char === '>') depth--;
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
// Inside string - check for closing quote
|
|
61
|
+
if (char === stringChar && prevChar !== '\\') {
|
|
62
|
+
inString = false;
|
|
63
|
+
stringChar = '';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
i++;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return depth === 0 ? i - 1 : -1;
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Complexity:** Low
|
|
75
|
+
**Benefit:** High (fixes most common edge case)
|
|
76
|
+
**Verdict:** ✅ **IMPLEMENT THIS**
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### 2. Template Literal Types 🤔 MAYBE FEASIBLE
|
|
81
|
+
|
|
82
|
+
**Problem:**
|
|
83
|
+
```typescript
|
|
84
|
+
type Route = `/${string}`;
|
|
85
|
+
type EventName = `on${Capitalize<string>}`;
|
|
86
|
+
type Path = `users/${number}/posts/${number}`;
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Challenge:** Template expressions `${...}` contain TypeScript code
|
|
90
|
+
|
|
91
|
+
**Solution: Template Literal State Machine**
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
/**
|
|
95
|
+
* Parse template literal type
|
|
96
|
+
*/
|
|
97
|
+
function parseTemplateLiteral(text: string, startPos: number): {
|
|
98
|
+
literalParts: string[];
|
|
99
|
+
expressions: string[];
|
|
100
|
+
} {
|
|
101
|
+
const literalParts: string[] = [];
|
|
102
|
+
const expressions: string[] = [];
|
|
103
|
+
|
|
104
|
+
let i = startPos + 1; // Skip opening `
|
|
105
|
+
let currentLiteral = '';
|
|
106
|
+
let inExpression = false;
|
|
107
|
+
let exprDepth = 0;
|
|
108
|
+
|
|
109
|
+
while (i < text.length) {
|
|
110
|
+
const char = text[i];
|
|
111
|
+
const nextChar = text[i + 1];
|
|
112
|
+
|
|
113
|
+
if (!inExpression) {
|
|
114
|
+
if (char === '$' && nextChar === '{') {
|
|
115
|
+
// Start of expression
|
|
116
|
+
literalParts.push(currentLiteral);
|
|
117
|
+
currentLiteral = '';
|
|
118
|
+
inExpression = true;
|
|
119
|
+
exprDepth = 1;
|
|
120
|
+
i += 2; // Skip ${
|
|
121
|
+
continue;
|
|
122
|
+
} else if (char === '`') {
|
|
123
|
+
// End of template
|
|
124
|
+
literalParts.push(currentLiteral);
|
|
125
|
+
break;
|
|
126
|
+
} else {
|
|
127
|
+
currentLiteral += char;
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
// Inside ${...} expression
|
|
131
|
+
if (char === '{') exprDepth++;
|
|
132
|
+
else if (char === '}') {
|
|
133
|
+
exprDepth--;
|
|
134
|
+
if (exprDepth === 0) {
|
|
135
|
+
inExpression = false;
|
|
136
|
+
i++;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
expressions.push(char);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
i++;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return { literalParts, expressions };
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**But wait... the expressions contain TypeScript code!**
|
|
151
|
+
|
|
152
|
+
Inside `${}` we can have:
|
|
153
|
+
- Type references: `${string}`, `${User}`
|
|
154
|
+
- Utility types: `${Capitalize<string>}`
|
|
155
|
+
- Conditional types: `${T extends string ? T : never}`
|
|
156
|
+
- Mapped types: `${keyof T}`
|
|
157
|
+
|
|
158
|
+
This means we need to **recursively parse TypeScript types** inside template expressions!
|
|
159
|
+
|
|
160
|
+
**Complexity:** Medium-High (needs recursive type parser)
|
|
161
|
+
**Benefit:** Medium (template literal types are growing in popularity but still relatively rare)
|
|
162
|
+
**Verdict:** 🤔 **POSSIBLE BUT COMPLEX - Consider ts-morph fallback**
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### 3. Conditional Types ❌ NOT FEASIBLE
|
|
167
|
+
|
|
168
|
+
**Problem:**
|
|
169
|
+
```typescript
|
|
170
|
+
type ExtractParams<T> = T extends `${infer Start}/${infer Rest}`
|
|
171
|
+
? Start | ExtractParams<Rest>
|
|
172
|
+
: T;
|
|
173
|
+
|
|
174
|
+
type IsString<T> = T extends string ? true : false;
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Challenge:** Understanding `extends`, `infer`, ternary operator in type context
|
|
178
|
+
|
|
179
|
+
**What we'd need to parse:**
|
|
180
|
+
1. Generic type parameters with constraints: `<T extends Constraint>`
|
|
181
|
+
2. Type inference: `infer Start`, `infer Rest`
|
|
182
|
+
3. Ternary operator: `? TrueType : FalseType`
|
|
183
|
+
4. Recursive type references: `ExtractParams<Rest>`
|
|
184
|
+
5. Template literal patterns: `` `${infer Start}` ``
|
|
185
|
+
|
|
186
|
+
**Attempted Solution:**
|
|
187
|
+
```typescript
|
|
188
|
+
function parseConditionalType(text: string) {
|
|
189
|
+
// Need to:
|
|
190
|
+
// 1. Find the "extends" keyword (but not in other contexts!)
|
|
191
|
+
// 2. Parse the constraint expression
|
|
192
|
+
// 3. Find the "?" operator (but not in other contexts!)
|
|
193
|
+
// 4. Parse the true branch (might contain nested conditionals!)
|
|
194
|
+
// 5. Find the ":" operator (but not in other contexts!)
|
|
195
|
+
// 6. Parse the false branch (might contain nested conditionals!)
|
|
196
|
+
// 7. Handle "infer" keyword and capture groups
|
|
197
|
+
// 8. Track nested template literals with expressions
|
|
198
|
+
|
|
199
|
+
// This is essentially re-implementing TypeScript's type parser! 😱
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Reality Check:**
|
|
204
|
+
- TypeScript's parser is ~50,000 lines of code
|
|
205
|
+
- Conditional types interact with ALL other type features
|
|
206
|
+
- Edge cases are numerous and subtle
|
|
207
|
+
- We'd be maintaining a subset parser that needs to evolve with TypeScript
|
|
208
|
+
|
|
209
|
+
**Complexity:** Very High
|
|
210
|
+
**Benefit:** Low (conditional types are rare in tool schemas)
|
|
211
|
+
**Verdict:** ❌ **NOT WORTH IT - Use ts-morph fallback**
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
### 4. Mapped Types ❌ NOT FEASIBLE
|
|
216
|
+
|
|
217
|
+
**Problem:**
|
|
218
|
+
```typescript
|
|
219
|
+
type Readonly<T> = {
|
|
220
|
+
readonly [P in keyof T]: T[P];
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
type Getters<T> = {
|
|
224
|
+
[K in keyof T as `get${Capitalize<K>}`]: () => T[K];
|
|
225
|
+
};
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Challenge:** Understanding `in`, `keyof`, `as`, type remapping
|
|
229
|
+
|
|
230
|
+
**What we'd need to parse:**
|
|
231
|
+
1. Index signature with type parameter: `[P in keyof T]`
|
|
232
|
+
2. Type operators: `keyof T`, `typeof x`, `T[K]`
|
|
233
|
+
3. Type remapping: `as NewType`
|
|
234
|
+
4. Template literal remapping: `` as `get${Capitalize<K>}` ``
|
|
235
|
+
5. Modifiers: `readonly`, `?`, `+`, `-`
|
|
236
|
+
|
|
237
|
+
**Complexity:** Very High
|
|
238
|
+
**Benefit:** Very Low (mapped types almost never appear in tool schemas)
|
|
239
|
+
**Verdict:** ❌ **NOT WORTH IT - Use ts-morph fallback**
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Comparative Analysis
|
|
244
|
+
|
|
245
|
+
| Feature | Text Parsing Complexity | Frequency in Schemas | Benefit/Effort Ratio |
|
|
246
|
+
|---------|------------------------|---------------------|---------------------|
|
|
247
|
+
| String literals with brackets | ⭐ Low | ⭐⭐⭐ High | ✅ **Excellent** |
|
|
248
|
+
| Template literal types | ⭐⭐⭐ Medium-High | ⭐⭐ Medium | 🤔 **Fair** |
|
|
249
|
+
| Conditional types | ⭐⭐⭐⭐⭐ Very High | ⭐ Low | ❌ **Poor** |
|
|
250
|
+
| Mapped types | ⭐⭐⭐⭐⭐ Very High | ⭐ Very Low | ❌ **Poor** |
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Recommended Implementation: Hybrid Strategy
|
|
255
|
+
|
|
256
|
+
### Phase 1: Enhanced Tokenizer (High Value, Low Effort) ✅
|
|
257
|
+
|
|
258
|
+
Build a simple tokenizer that properly handles:
|
|
259
|
+
- String literals (all three quote types)
|
|
260
|
+
- Escape sequences
|
|
261
|
+
- Comments (line and block)
|
|
262
|
+
- Bracket/paren/angle depth tracking
|
|
263
|
+
|
|
264
|
+
**Implementation:**
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
/**
|
|
268
|
+
* Simple TypeScript tokenizer for schema extraction
|
|
269
|
+
*/
|
|
270
|
+
class TypeScriptTokenizer {
|
|
271
|
+
private text: string;
|
|
272
|
+
private pos: number = 0;
|
|
273
|
+
|
|
274
|
+
constructor(text: string) {
|
|
275
|
+
this.text = text;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Find matching closing bracket, properly handling strings and comments
|
|
280
|
+
*/
|
|
281
|
+
findMatchingBracket(openChar: '{' | '<' | '(' | '['): number {
|
|
282
|
+
const closeChar = this.getClosingBracket(openChar);
|
|
283
|
+
let depth = 1;
|
|
284
|
+
let i = this.pos + 1;
|
|
285
|
+
|
|
286
|
+
while (i < this.text.length && depth > 0) {
|
|
287
|
+
const token = this.getNextToken(i);
|
|
288
|
+
|
|
289
|
+
if (token.type === 'bracket') {
|
|
290
|
+
if (token.value === openChar) depth++;
|
|
291
|
+
else if (token.value === closeChar) depth--;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
i = token.endPos;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return depth === 0 ? i - 1 : -1;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Get next meaningful token, skipping strings and comments
|
|
302
|
+
*/
|
|
303
|
+
private getNextToken(startPos: number): Token {
|
|
304
|
+
const char = this.text[startPos];
|
|
305
|
+
|
|
306
|
+
// String literal
|
|
307
|
+
if (char === '"' || char === "'" || char === '`') {
|
|
308
|
+
return this.parseStringLiteral(startPos, char);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Line comment
|
|
312
|
+
if (char === '/' && this.text[startPos + 1] === '/') {
|
|
313
|
+
return this.parseLineComment(startPos);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Block comment
|
|
317
|
+
if (char === '/' && this.text[startPos + 1] === '*') {
|
|
318
|
+
return this.parseBlockComment(startPos);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Bracket
|
|
322
|
+
if ('{}<>()[]'.includes(char)) {
|
|
323
|
+
return {
|
|
324
|
+
type: 'bracket',
|
|
325
|
+
value: char,
|
|
326
|
+
startPos,
|
|
327
|
+
endPos: startPos + 1,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Other character
|
|
332
|
+
return {
|
|
333
|
+
type: 'char',
|
|
334
|
+
value: char,
|
|
335
|
+
startPos,
|
|
336
|
+
endPos: startPos + 1,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
private parseStringLiteral(startPos: number, quoteChar: string): Token {
|
|
341
|
+
let i = startPos + 1;
|
|
342
|
+
let escaped = false;
|
|
343
|
+
|
|
344
|
+
while (i < this.text.length) {
|
|
345
|
+
if (escaped) {
|
|
346
|
+
escaped = false;
|
|
347
|
+
i++;
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (this.text[i] === '\\') {
|
|
352
|
+
escaped = true;
|
|
353
|
+
i++;
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (this.text[i] === quoteChar) {
|
|
358
|
+
return {
|
|
359
|
+
type: 'string',
|
|
360
|
+
value: this.text.slice(startPos, i + 1),
|
|
361
|
+
startPos,
|
|
362
|
+
endPos: i + 1,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
i++;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
throw new Error(`Unclosed string literal at position ${startPos}`);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
private parseLineComment(startPos: number): Token {
|
|
373
|
+
const newlinePos = this.text.indexOf('\n', startPos);
|
|
374
|
+
const endPos = newlinePos === -1 ? this.text.length : newlinePos + 1;
|
|
375
|
+
|
|
376
|
+
return {
|
|
377
|
+
type: 'comment',
|
|
378
|
+
value: this.text.slice(startPos, endPos),
|
|
379
|
+
startPos,
|
|
380
|
+
endPos,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
private parseBlockComment(startPos: number): Token {
|
|
385
|
+
const endPos = this.text.indexOf('*/', startPos + 2);
|
|
386
|
+
|
|
387
|
+
if (endPos === -1) {
|
|
388
|
+
throw new Error(`Unclosed block comment at position ${startPos}`);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return {
|
|
392
|
+
type: 'comment',
|
|
393
|
+
value: this.text.slice(startPos, endPos + 2),
|
|
394
|
+
startPos,
|
|
395
|
+
endPos: endPos + 2,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
private getClosingBracket(open: string): string {
|
|
400
|
+
const pairs: Record<string, string> = {
|
|
401
|
+
'{': '}',
|
|
402
|
+
'<': '>',
|
|
403
|
+
'(': ')',
|
|
404
|
+
'[': ']',
|
|
405
|
+
};
|
|
406
|
+
return pairs[open];
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
interface Token {
|
|
411
|
+
type: 'string' | 'comment' | 'bracket' | 'char';
|
|
412
|
+
value: string;
|
|
413
|
+
startPos: number;
|
|
414
|
+
endPos: number;
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**Usage in findTypeDefinition():**
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
static findTypeDefinition(sourceText: string, typeName: string): TypeDefinition | null {
|
|
422
|
+
// ... existing regex to find interface/type ...
|
|
423
|
+
|
|
424
|
+
// Use tokenizer instead of manual bracket counting
|
|
425
|
+
const tokenizer = new TypeScriptTokenizer(sourceText);
|
|
426
|
+
tokenizer.pos = braceStart;
|
|
427
|
+
const endPos = tokenizer.findMatchingBracket('{');
|
|
428
|
+
|
|
429
|
+
if (endPos === -1) {
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const definition = sourceText.slice(startIndex, endPos + 1).trim();
|
|
434
|
+
return { name: typeName, definition, kind: 'interface' };
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
**Benefits:**
|
|
439
|
+
- ✅ Fixes string literal edge cases
|
|
440
|
+
- ✅ Robust comment handling
|
|
441
|
+
- ✅ Proper escape sequence handling
|
|
442
|
+
- ✅ ~100 lines of code (manageable)
|
|
443
|
+
- ✅ Reusable for all bracket matching
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
### Phase 2: Template Literal Detection (Optional) 🤔
|
|
448
|
+
|
|
449
|
+
**Simple Approach:** Detect but don't parse
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
function hasTemplateLiteralType(text: string): boolean {
|
|
453
|
+
// Match: type Name = `...`
|
|
454
|
+
return /type\s+\w+\s*=\s*`/.test(text);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function extractSchemasFast(filePath: string) {
|
|
458
|
+
const fileText = fs.readFileSync(filePath, 'utf8');
|
|
459
|
+
|
|
460
|
+
// Detect template literal types
|
|
461
|
+
if (hasTemplateLiteralType(fileText)) {
|
|
462
|
+
perfLog.info(`${path.basename(filePath)}: Template literal types detected, using ts-morph`);
|
|
463
|
+
return extractSchemasWithTsMorph(filePath);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Continue with fast extraction...
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**Benefits:**
|
|
471
|
+
- ✅ Simple detection (1 line regex)
|
|
472
|
+
- ✅ Maintains safety for complex case
|
|
473
|
+
- ✅ No need to parse template expressions
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
### Phase 3: ts-morph Fallback for Complex Types ✅
|
|
478
|
+
|
|
479
|
+
For conditional and mapped types, just use ts-morph:
|
|
480
|
+
|
|
481
|
+
```typescript
|
|
482
|
+
function hasComplexTypeFeatures(text: string): boolean {
|
|
483
|
+
return (
|
|
484
|
+
hasConditionalType(text) ||
|
|
485
|
+
hasMappedType(text) ||
|
|
486
|
+
hasTemplateLiteralType(text) // If Phase 2 not implemented
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function hasConditionalType(text: string): boolean {
|
|
491
|
+
// Match: T extends U ? A : B
|
|
492
|
+
return /\bextends\b.*?\?.*?:/.test(text);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function hasMappedType(text: string): boolean {
|
|
496
|
+
// Match: [K in keyof T]
|
|
497
|
+
return /\[\s*\w+\s+in\s+keyof\s+/.test(text);
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
**Benefits:**
|
|
502
|
+
- ✅ 100% correctness for complex cases
|
|
503
|
+
- ✅ Minimal performance impact (rare cases)
|
|
504
|
+
- ✅ No need to maintain complex parser
|
|
505
|
+
|
|
506
|
+
---
|
|
507
|
+
|
|
508
|
+
## Implementation Effort vs Benefit
|
|
509
|
+
|
|
510
|
+
| Approach | Lines of Code | Dev Time | Maintenance | Performance | Safety |
|
|
511
|
+
|----------|--------------|----------|-------------|-------------|--------|
|
|
512
|
+
| **Enhanced Tokenizer** | ~100 | 4 hours | Low | 1200x | 99% |
|
|
513
|
+
| **+ Template Parsing** | ~300 | 16 hours | Medium | 1150x | 99.5% |
|
|
514
|
+
| **+ Full Type Parser** | ~5000+ | 200+ hours | High | 1100x | 99.9% |
|
|
515
|
+
| **Hybrid (Tokenizer + Fallback)** | ~150 | 6 hours | Low | 1100x | **100%** |
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## Recommended Path Forward
|
|
520
|
+
|
|
521
|
+
### ✅ Implement Now
|
|
522
|
+
1. **Enhanced tokenizer** for string/comment handling (~4 hours, high value)
|
|
523
|
+
2. **Detection functions** for complex types (~1 hour)
|
|
524
|
+
3. **ts-morph fallback** for complex cases (~1 hour)
|
|
525
|
+
|
|
526
|
+
**Total effort:** ~6 hours
|
|
527
|
+
**Result:** 99.9%+ safety, ~1100x speedup, minimal maintenance
|
|
528
|
+
|
|
529
|
+
### 🤔 Consider Later
|
|
530
|
+
4. **Template literal parsing** if usage grows (~16 hours, medium value)
|
|
531
|
+
|
|
532
|
+
### ❌ Don't Implement
|
|
533
|
+
5. **Full conditional type parsing** - not worth the effort
|
|
534
|
+
6. **Full mapped type parsing** - not worth the effort
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
## Conclusion
|
|
539
|
+
|
|
540
|
+
**YES** to enhanced tokenizer (string/comment handling) ✅
|
|
541
|
+
**NO** to full AST for complex types ❌
|
|
542
|
+
**RECOMMENDED:** Hybrid approach with simple tokenizer + ts-morph fallback
|
|
543
|
+
|
|
544
|
+
### Why Hybrid is Optimal
|
|
545
|
+
|
|
546
|
+
1. **Performance:** Maintains ~1100x speedup (vs 1250x pure text)
|
|
547
|
+
2. **Safety:** 100% correctness via ts-morph fallback
|
|
548
|
+
3. **Complexity:** ~150 lines of tokenizer code (manageable)
|
|
549
|
+
4. **Maintenance:** Minimal - only maintain tokenizer, not full parser
|
|
550
|
+
5. **Future-proof:** TypeScript can add new features, we just fallback
|
|
551
|
+
|
|
552
|
+
### The Reality
|
|
553
|
+
|
|
554
|
+
Building a full TypeScript type parser means:
|
|
555
|
+
- Re-implementing 10-20% of TypeScript's parser
|
|
556
|
+
- Keeping up with TypeScript versions (3-4 releases/year)
|
|
557
|
+
- Handling edge cases that take TypeScript team months to fix
|
|
558
|
+
- Testing against thousands of type combinations
|
|
559
|
+
|
|
560
|
+
**It's not worth it when ts-morph is available as a safety net.**
|
|
561
|
+
|
|
562
|
+
### Final Recommendation
|
|
563
|
+
|
|
564
|
+
Implement **enhanced tokenizer** (Phase 1) to handle string literals robustly, then use **ts-morph fallback** for truly complex types. This gives us:
|
|
565
|
+
- ✅ Best performance (1100x+ speedup)
|
|
566
|
+
- ✅ Best safety (100% correctness)
|
|
567
|
+
- ✅ Best maintainability (small codebase)
|
|
568
|
+
- ✅ Best of both worlds
|
|
569
|
+
|
|
570
|
+
**Start with Phase 1, measure real-world fallback frequency, then decide if Phase 2 is needed.**
|
package/bin/flink.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const commands = ["build", "generate" /* 'generate' is alias for 'build'
|
|
3
|
+
const commands = ["build", "generate" /* 'generate' is alias for 'build' */, "run", "dev", "clean", "help"];
|
|
4
4
|
|
|
5
5
|
const argv = process.argv.slice(2);
|
|
6
6
|
let argCommand = argv[0];
|
|
@@ -21,6 +21,17 @@ if (argCommand === "generate") {
|
|
|
21
21
|
|
|
22
22
|
const cmd = require("../cli/" + argCommand);
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
(async () => {
|
|
25
|
+
try {
|
|
26
|
+
await cmd(argv.slice(1));
|
|
27
|
+
} catch (error: any) {
|
|
28
|
+
if (process.env.DEBUG === "true") {
|
|
29
|
+
console.error(error);
|
|
30
|
+
} else {
|
|
31
|
+
console.error(`Error: ${error.message}`);
|
|
32
|
+
}
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
})();
|
|
25
36
|
|
|
26
37
|
export default () => {};
|
package/cli/build.ts
CHANGED
|
@@ -1,48 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Options
|
|
22
|
-
--help Displays this message
|
|
23
|
-
`);
|
|
24
|
-
|
|
25
|
-
process.exit(0);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
let dir = "./";
|
|
29
|
-
if (args[0] && !args[0].startsWith("--")) {
|
|
30
|
-
dir = args[0];
|
|
2
|
+
import { parseArgs, hasFlag, printHelp, compile } from "./cli-utils";
|
|
3
|
+
import { FlinkLogFactory } from "../src/FlinkLogFactory";
|
|
4
|
+
import { loadFlinkConfig } from "../src/utils/loadFlinkConfig";
|
|
5
|
+
|
|
6
|
+
// Load config BEFORE creating logger
|
|
7
|
+
const flinkConfig = loadFlinkConfig();
|
|
8
|
+
FlinkLogFactory.configure(flinkConfig?.logging);
|
|
9
|
+
|
|
10
|
+
module.exports = async function build(args: string[]) {
|
|
11
|
+
const parsed = parseArgs(args);
|
|
12
|
+
|
|
13
|
+
if (hasFlag(parsed, "help")) {
|
|
14
|
+
printHelp({
|
|
15
|
+
description:
|
|
16
|
+
"Builds the application.\n Will generate intermediates files in .flink and compile/transpile\n javascript bundle in /dist folder",
|
|
17
|
+
usage: "$ flink build <dir>",
|
|
18
|
+
options: [{ name: "help", description: "Displays this message" }],
|
|
19
|
+
});
|
|
20
|
+
return;
|
|
31
21
|
}
|
|
32
22
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (!compiler.getPreEmitDiagnostics()) {
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
await Promise.all([compiler.parseRepos(), compiler.parseHandlers(exclude.split(",")), compiler.parseJobs(), compiler.generateStartScript()]);
|
|
44
|
-
|
|
45
|
-
console.log(`Compilation done, took ${Date.now() - startTime}ms`);
|
|
46
|
-
|
|
47
|
-
compiler.emit();
|
|
23
|
+
await compile({
|
|
24
|
+
dir: parsed.dir,
|
|
25
|
+
typeCheck: true,
|
|
26
|
+
timingLogs: true,
|
|
27
|
+
});
|
|
48
28
|
};
|