@forgehive/forge-cli 0.3.6 → 0.3.7
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/dist/runner.js +3 -0
- package/dist/tasks/bundle/fingerprint.d.ts +12 -2
- package/dist/tasks/bundle/fingerprint.js +26 -12
- package/dist/tasks/conf/info.d.ts +12 -1
- package/dist/tasks/conf/info.js +36 -12
- package/dist/tasks/init.js +1 -0
- package/dist/tasks/task/fingerprint.d.ts +51 -8
- package/dist/tasks/task/fingerprint.js +12 -35
- package/dist/tasks/task/publish.d.ts +60 -4
- package/dist/tasks/task/publish.js +30 -8
- package/dist/tasks/types.d.ts +1 -0
- package/dist/utils/taskAnalysis.d.ts +27 -1
- package/dist/utils/taskAnalysis.js +760 -107
- package/forge.json +1 -0
- package/logs/bundle:fingerprint.log +1 -0
- package/package.json +10 -10
- package/specs/fingerprint.md +324 -60
- package/src/runner.ts +4 -0
- package/src/tasks/bundle/fingerprint.ts +32 -13
- package/src/tasks/conf/info.ts +36 -10
- package/src/tasks/init.ts +1 -0
- package/src/tasks/task/fingerprint.ts +13 -42
- package/src/tasks/task/publish.ts +35 -10
- package/src/tasks/types.ts +1 -0
- package/src/utils/taskAnalysis.ts +833 -118
package/forge.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"input":{"filePath":"/Users/danielzavaladlvega/forgehive/forge-mono-repo/apps/sample-project/src/tasks/test/errors.ts"},"boundaries":{"getCwd":[],"loadConf":[],"readFile":[],"writeFile":[],"ensureFingerprintsFolder":[]},"metadata":{"environment":"cli"},"metrics":[],"type":"error","error":"Invalid input on: descriptorName: Required"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgehive/forge-cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"description": "TypeScript CLI application",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@forgehive/hive-sdk": "^0.1.
|
|
14
|
-
"@forgehive/record-tape": "^0.2.
|
|
15
|
-
"@forgehive/runner": "^0.2.
|
|
13
|
+
"@forgehive/hive-sdk": "^0.1.2",
|
|
14
|
+
"@forgehive/record-tape": "^0.2.5",
|
|
15
|
+
"@forgehive/runner": "^0.2.5",
|
|
16
16
|
"@forgehive/schema": "^0.1.4",
|
|
17
|
-
"@forgehive/task": "^0.2.
|
|
17
|
+
"@forgehive/task": "^0.2.5",
|
|
18
18
|
"esbuild": "^0.25.0",
|
|
19
19
|
"handlebars": "^4.7.8",
|
|
20
20
|
"minimist": "^1.2.8"
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"esbuild": "^0.25.0",
|
|
28
28
|
"handlebars": "^4.7.8",
|
|
29
29
|
"minimist": "^1.2.8",
|
|
30
|
-
"@forgehive/
|
|
31
|
-
"@forgehive/
|
|
32
|
-
"@forgehive/task": "0.2.
|
|
33
|
-
"@forgehive/
|
|
34
|
-
"@forgehive/
|
|
30
|
+
"@forgehive/hive-sdk": "0.1.2",
|
|
31
|
+
"@forgehive/record-tape": "0.2.5",
|
|
32
|
+
"@forgehive/task": "0.2.5",
|
|
33
|
+
"@forgehive/runner": "0.2.5",
|
|
34
|
+
"@forgehive/schema": "0.1.4"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/archiver": "^6.0.3",
|
package/specs/fingerprint.md
CHANGED
|
@@ -64,25 +64,65 @@ interface TaskFingerprint {
|
|
|
64
64
|
type: string
|
|
65
65
|
properties: Record<string, any>
|
|
66
66
|
}
|
|
67
|
-
outputType:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
functionSource: string
|
|
67
|
+
outputType: {
|
|
68
|
+
type: string
|
|
69
|
+
properties?: Record<string, any>
|
|
70
|
+
elementType?: OutputType
|
|
71
|
+
}
|
|
72
|
+
boundaries: BoundaryFingerprint[]
|
|
74
73
|
hash: string
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface BoundaryFingerprint {
|
|
77
|
+
name: string
|
|
78
|
+
input: SchemaProperty[]
|
|
79
|
+
output: OutputType
|
|
80
|
+
errors: FingerprintError[]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface OutputType {
|
|
84
|
+
type: string
|
|
85
|
+
properties?: Record<string, SchemaProperty>
|
|
86
|
+
elementType?: OutputType
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface FingerprintError {
|
|
90
|
+
type: 'parsing' | 'analysis' | 'boundary' | 'schema'
|
|
91
|
+
message: string
|
|
92
|
+
location?: {
|
|
93
|
+
file: string
|
|
94
|
+
line?: number
|
|
95
|
+
column?: number
|
|
78
96
|
}
|
|
79
97
|
}
|
|
98
|
+
|
|
99
|
+
interface SchemaProperty {
|
|
100
|
+
name?: string
|
|
101
|
+
type: string
|
|
102
|
+
optional?: boolean
|
|
103
|
+
default?: string
|
|
104
|
+
properties?: Record<string, SchemaProperty>
|
|
105
|
+
}
|
|
80
106
|
```
|
|
81
107
|
|
|
82
|
-
####
|
|
108
|
+
#### TaskFingerprintOutput
|
|
83
109
|
```typescript
|
|
110
|
+
interface TaskFingerprintOutput {
|
|
111
|
+
description?: string
|
|
112
|
+
inputSchema: InputSchema
|
|
113
|
+
outputType: OutputType
|
|
114
|
+
boundaries: BoundaryFingerprint[]
|
|
115
|
+
errors: FingerprintError[]
|
|
116
|
+
analysisMetadata: {
|
|
117
|
+
timestamp: string
|
|
118
|
+
filePath: string
|
|
119
|
+
success: boolean
|
|
120
|
+
analysisVersion: string
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
84
124
|
interface FingerprintResult {
|
|
85
|
-
tasks:
|
|
125
|
+
tasks: TaskFingerprintOutput[]
|
|
86
126
|
buildInfo: {
|
|
87
127
|
entryPoint: string
|
|
88
128
|
outputFile: string
|
|
@@ -137,16 +177,57 @@ export const taskName = createTask(schema, boundaries, fn)
|
|
|
137
177
|
- Generate JSON Schema-compatible output
|
|
138
178
|
|
|
139
179
|
#### Boundary Analysis
|
|
140
|
-
- Extract function signatures from boundary object
|
|
141
|
-
- Parse parameter types
|
|
180
|
+
- Extract function signatures from boundary object as detailed objects
|
|
181
|
+
- Parse parameter types into structured SchemaProperty arrays
|
|
182
|
+
- Parse return types with support for complex object structures
|
|
142
183
|
- Handle async functions and Promise return types
|
|
143
|
-
-
|
|
184
|
+
- Collect runtime errors from throw statements in boundary functions
|
|
185
|
+
- Each boundary becomes a BoundaryFingerprint with name, input, output, and errors
|
|
144
186
|
|
|
145
187
|
#### Return Type Analysis
|
|
146
188
|
- Extract TypeScript return type annotations
|
|
147
189
|
- Parse Promise wrapper types
|
|
148
190
|
- Infer types from return statements when annotations missing
|
|
149
191
|
- Handle complex object return types
|
|
192
|
+
- Support for array element type detection with `elementType` property
|
|
193
|
+
|
|
194
|
+
#### Array Element Type Detection
|
|
195
|
+
The system now provides enhanced array type analysis:
|
|
196
|
+
|
|
197
|
+
**TypeScript Annotation Parsing**:
|
|
198
|
+
```typescript
|
|
199
|
+
// Boundary function with array return type
|
|
200
|
+
getPortfolio: async (userUUID: string): Promise<{ symbol: string, quantity: number, price: number }[]>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Generated Fingerprint**:
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"type": "array",
|
|
207
|
+
"elementType": {
|
|
208
|
+
"type": "object",
|
|
209
|
+
"properties": {
|
|
210
|
+
"symbol": { "type": "string" },
|
|
211
|
+
"quantity": { "type": "number" },
|
|
212
|
+
"price": { "type": "number" }
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**Supported Array Patterns**:
|
|
219
|
+
- `T[]` format: `{ symbol: string, quantity: number }[]`
|
|
220
|
+
- `Array<T>` format: `Array<{ symbol: string, quantity: number }>`
|
|
221
|
+
- Complex nested objects within arrays
|
|
222
|
+
- Propagation from boundary types to task output types
|
|
223
|
+
|
|
224
|
+
#### Error Collection
|
|
225
|
+
- **Boundary Errors**: Detect `throw` statements in boundary functions
|
|
226
|
+
- **Main Function Errors**: Detect `throw` statements in the main task function
|
|
227
|
+
- **Parsing Errors**: Capture TypeScript AST parsing failures
|
|
228
|
+
- **Schema Errors**: Capture schema analysis failures
|
|
229
|
+
- **Location Tracking**: Include precise line and column information for each error
|
|
230
|
+
- **Error Types**: Categorize errors as 'parsing', 'analysis', 'boundary', or 'schema'
|
|
150
231
|
|
|
151
232
|
### 4. Hash Generation Algorithm
|
|
152
233
|
|
|
@@ -193,43 +274,137 @@ const boundaries = {
|
|
|
193
274
|
|
|
194
275
|
```json
|
|
195
276
|
{
|
|
196
|
-
"
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
"
|
|
200
|
-
"
|
|
201
|
-
"
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
"
|
|
206
|
-
|
|
207
|
-
"
|
|
208
|
-
|
|
277
|
+
"taskFingerprint": {
|
|
278
|
+
"description": "Test task with intentional runtime errors for error collection testing",
|
|
279
|
+
"inputSchema": {
|
|
280
|
+
"type": "object",
|
|
281
|
+
"properties": {
|
|
282
|
+
"userId": { "type": "string" }
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
"outputType": {
|
|
286
|
+
"type": "object",
|
|
287
|
+
"properties": {
|
|
288
|
+
"user": { "type": "object" },
|
|
289
|
+
"profile": { "type": "string" },
|
|
290
|
+
"lastLogin": { "type": "string" },
|
|
291
|
+
"processed": { "type": "boolean" },
|
|
292
|
+
"portfolio": {
|
|
293
|
+
"type": "array",
|
|
294
|
+
"elementType": {
|
|
295
|
+
"type": "object",
|
|
296
|
+
"properties": {
|
|
297
|
+
"symbol": { "type": "string" },
|
|
298
|
+
"quantity": { "type": "number" },
|
|
299
|
+
"price": { "type": "number" }
|
|
300
|
+
}
|
|
301
|
+
}
|
|
209
302
|
}
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
"boundaries": [
|
|
306
|
+
{
|
|
307
|
+
"name": "getUserById",
|
|
308
|
+
"input": [
|
|
309
|
+
{
|
|
310
|
+
"type": "object",
|
|
311
|
+
"properties": {
|
|
312
|
+
"userId": { "type": "string" }
|
|
313
|
+
},
|
|
314
|
+
"name": "input"
|
|
315
|
+
}
|
|
316
|
+
],
|
|
317
|
+
"output": { "type": "User | null" },
|
|
318
|
+
"errors": []
|
|
210
319
|
},
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
"
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
320
|
+
{
|
|
321
|
+
"name": "getPortfolio",
|
|
322
|
+
"input": [
|
|
323
|
+
{
|
|
324
|
+
"type": "string",
|
|
325
|
+
"name": "userUUID"
|
|
326
|
+
}
|
|
327
|
+
],
|
|
328
|
+
"output": {
|
|
329
|
+
"type": "array",
|
|
330
|
+
"elementType": {
|
|
331
|
+
"type": "object",
|
|
332
|
+
"properties": {
|
|
333
|
+
"symbol": { "type": "string" },
|
|
334
|
+
"quantity": { "type": "number" },
|
|
335
|
+
"price": { "type": "number" }
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
"errors": [
|
|
340
|
+
{
|
|
341
|
+
"type": "boundary",
|
|
342
|
+
"message": "Boundary function throws: User not found",
|
|
343
|
+
"location": {
|
|
344
|
+
"file": "/path/to/tasks/stock/getPortfolio.ts",
|
|
345
|
+
"line": 19,
|
|
346
|
+
"column": 7
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
]
|
|
218
350
|
},
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
351
|
+
{
|
|
352
|
+
"name": "fetchUserProfile",
|
|
353
|
+
"input": [
|
|
354
|
+
{
|
|
355
|
+
"type": "object",
|
|
356
|
+
"properties": {
|
|
357
|
+
"userId": { "type": "string" }
|
|
358
|
+
},
|
|
359
|
+
"name": "input"
|
|
360
|
+
}
|
|
361
|
+
],
|
|
362
|
+
"output": {
|
|
363
|
+
"type": "object",
|
|
364
|
+
"properties": {
|
|
365
|
+
"profile": { "type": "string" },
|
|
366
|
+
"lastLogin": { "type": "string" }
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
"errors": [
|
|
370
|
+
{
|
|
371
|
+
"type": "boundary",
|
|
372
|
+
"message": "Boundary function throws: API temporarily unavailable",
|
|
373
|
+
"location": {
|
|
374
|
+
"file": "/path/to/tasks/test/errors.ts",
|
|
375
|
+
"line": 40,
|
|
376
|
+
"column": 7
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"type": "boundary",
|
|
381
|
+
"message": "Boundary function throws: External API authentication failed",
|
|
382
|
+
"location": {
|
|
383
|
+
"file": "/path/to/tasks/test/errors.ts",
|
|
384
|
+
"line": 44,
|
|
385
|
+
"column": 7
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
]
|
|
224
389
|
}
|
|
390
|
+
],
|
|
391
|
+
"errors": [
|
|
392
|
+
{
|
|
393
|
+
"type": "analysis",
|
|
394
|
+
"message": "Main task function throws: User with ID ${userId} not found",
|
|
395
|
+
"location": {
|
|
396
|
+
"file": "/path/to/tasks/test/errors.ts",
|
|
397
|
+
"line": 65,
|
|
398
|
+
"column": 7
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
],
|
|
402
|
+
"analysisMetadata": {
|
|
403
|
+
"timestamp": "2025-01-18T12:40:18.033Z",
|
|
404
|
+
"filePath": "/path/to/tasks/test/errors.ts",
|
|
405
|
+
"success": true,
|
|
406
|
+
"analysisVersion": "1.0.0"
|
|
225
407
|
}
|
|
226
|
-
],
|
|
227
|
-
"buildInfo": {
|
|
228
|
-
"entryPoint": "src/index.ts",
|
|
229
|
-
"outputFile": "dist/bundle.js",
|
|
230
|
-
"fingerprintsFile": "dist/bundle.fingerprints.json",
|
|
231
|
-
"totalTasks": 5,
|
|
232
|
-
"buildTimestamp": "2025-01-01T12:00:00.000Z"
|
|
233
408
|
}
|
|
234
409
|
}
|
|
235
410
|
```
|
|
@@ -291,6 +466,42 @@ console.log(`Generated ${result.taskFingerprints?.totalTasks} task fingerprints`
|
|
|
291
466
|
|
|
292
467
|
## Error Handling
|
|
293
468
|
|
|
469
|
+
### Runtime Error Collection
|
|
470
|
+
The fingerprinting system now collects runtime errors from task code:
|
|
471
|
+
|
|
472
|
+
#### Error Types Collected
|
|
473
|
+
1. **Boundary Errors** (`type: "boundary"`): Thrown errors in boundary functions
|
|
474
|
+
- Detects `throw new Error(...)` statements in boundary function bodies
|
|
475
|
+
- Captures error messages from string literals and template expressions
|
|
476
|
+
- Includes precise line and column location information
|
|
477
|
+
|
|
478
|
+
2. **Main Function Errors** (`type: "analysis"`): Thrown errors in main task functions
|
|
479
|
+
- Detects `throw new Error(...)` statements in the main task function
|
|
480
|
+
- Supports template literal error messages like `\`User with ID ${userId} not found\``
|
|
481
|
+
- Provides exact source code location
|
|
482
|
+
|
|
483
|
+
3. **Parsing Errors** (`type: "parsing"`): TypeScript AST parsing failures
|
|
484
|
+
- Occurs when TypeScript compiler cannot parse source code
|
|
485
|
+
- Includes error stack traces and detailed error information
|
|
486
|
+
|
|
487
|
+
4. **Schema Errors** (`type: "schema"`): Schema analysis failures
|
|
488
|
+
- Captures errors during Schema object analysis
|
|
489
|
+
- Reports issues with malformed schema definitions
|
|
490
|
+
|
|
491
|
+
#### Error Location Tracking
|
|
492
|
+
All errors include detailed location information:
|
|
493
|
+
```typescript
|
|
494
|
+
{
|
|
495
|
+
type: "analysis",
|
|
496
|
+
message: "Main task function throws: User with ID ${userId} not found",
|
|
497
|
+
location: {
|
|
498
|
+
file: "/path/to/task/file.ts",
|
|
499
|
+
line: 65, // 1-based line number
|
|
500
|
+
column: 7 // 1-based column number
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
294
505
|
### Plugin Error Scenarios
|
|
295
506
|
1. **TypeScript Parsing Errors**: Log warning, continue processing other files
|
|
296
507
|
2. **Invalid createTask Calls**: Skip malformed calls, log warnings
|
|
@@ -301,6 +512,7 @@ console.log(`Generated ${result.taskFingerprints?.totalTasks} task fingerprints`
|
|
|
301
512
|
- If TypeScript analysis fails, include raw source code snippets
|
|
302
513
|
- Provide partial fingerprints when complete type information unavailable
|
|
303
514
|
- Continue build process even if fingerprint generation fails
|
|
515
|
+
- Error collection continues even when main analysis partially fails
|
|
304
516
|
|
|
305
517
|
## Performance Considerations
|
|
306
518
|
|
|
@@ -363,18 +575,70 @@ export const testTask = createTask(
|
|
|
363
575
|
|
|
364
576
|
## Implementation Checklist
|
|
365
577
|
|
|
366
|
-
|
|
367
|
-
- [
|
|
368
|
-
- [
|
|
369
|
-
- [
|
|
370
|
-
- [
|
|
371
|
-
- [
|
|
372
|
-
- [
|
|
373
|
-
- [
|
|
374
|
-
- [
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
- [
|
|
378
|
-
- [
|
|
578
|
+
### Core Fingerprinting System
|
|
579
|
+
- [x] Implement `taskFingerprintPlugin` esbuild plugin
|
|
580
|
+
- [x] Create TypeScript AST analysis functions
|
|
581
|
+
- [x] Implement schema extraction logic
|
|
582
|
+
- [x] Implement boundary analysis logic
|
|
583
|
+
- [x] Implement return type extraction
|
|
584
|
+
- [x] Create hash generation function
|
|
585
|
+
- [x] Implement enhanced bundle task
|
|
586
|
+
- [x] Create CLI integration
|
|
587
|
+
|
|
588
|
+
### Enhanced Boundary Analysis
|
|
589
|
+
- [x] Convert boundaries from string arrays to detailed objects
|
|
590
|
+
- [x] Implement detailed boundary input/output type analysis
|
|
591
|
+
- [x] Add support for complex object structure detection
|
|
592
|
+
- [x] Enhance property access expression analysis (e.g., result1.result)
|
|
593
|
+
- [x] Add schema optional property detection with chained methods
|
|
594
|
+
- [x] Implement array element type detection with `elementType` support
|
|
595
|
+
- [x] Add support for complex array-of-objects type patterns
|
|
596
|
+
- [x] Enable type propagation from boundary arrays to task output arrays
|
|
597
|
+
|
|
598
|
+
### Runtime Error Collection System
|
|
599
|
+
- [x] Implement boundary error detection (throw statements in boundary functions)
|
|
600
|
+
- [x] Implement main task function error detection (throw statements in main function)
|
|
601
|
+
- [x] Add support for template literal error messages
|
|
602
|
+
- [x] Implement precise error location tracking (line and column numbers)
|
|
603
|
+
- [x] Create structured error categorization (parsing, analysis, boundary, schema)
|
|
604
|
+
- [x] Fix error duplication issues with deduplication logic
|
|
605
|
+
- [x] Clean up error format (remove details object, consistent location format)
|
|
606
|
+
|
|
607
|
+
### Error Handling and Metadata
|
|
608
|
+
- [x] Add comprehensive error handling and logging
|
|
609
|
+
- [x] Implement TaskFingerprintOutput interface with errors and metadata
|
|
610
|
+
- [x] Add analysisMetadata with timestamp, success status, and version
|
|
611
|
+
- [x] Implement graceful degradation for partial analysis failures
|
|
612
|
+
|
|
613
|
+
### Storage and Configuration
|
|
614
|
+
- [x] Update fingerprint storage to use project fingerprints folder
|
|
615
|
+
- [x] Add fingerprints path configuration support
|
|
616
|
+
- [x] Implement ensureFingerprintsFolder boundary
|
|
617
|
+
- [x] Update file naming conventions for consistency
|
|
618
|
+
|
|
619
|
+
### Documentation and Specification
|
|
620
|
+
- [x] Generate comprehensive specification documentation
|
|
621
|
+
- [x] Update core interfaces to reflect enhanced structure
|
|
622
|
+
- [x] Document error collection features and examples
|
|
623
|
+
- [x] Add implementation plan documentation
|
|
624
|
+
|
|
625
|
+
### Testing and Integration
|
|
626
|
+
- [ ] Write comprehensive unit tests for error collection
|
|
627
|
+
- [ ] Write integration tests for enhanced fingerprinting workflow
|
|
628
|
+
- [ ] Test error scenarios and edge cases
|
|
629
|
+
- [ ] Performance testing and optimization
|
|
630
|
+
- [ ] Add configuration validation tests
|
|
631
|
+
|
|
632
|
+
### Publish Integration
|
|
633
|
+
- [x] Integrate fingerprint generation into publish workflow
|
|
634
|
+
- [x] Add fingerprint data to publish payload
|
|
635
|
+
- [x] Implement error handling for fingerprint failures in publish
|
|
636
|
+
- [x] Add fingerprint status reporting in publish results
|
|
637
|
+
|
|
638
|
+
### Future Enhancements (Planned)
|
|
639
|
+
- [ ] Implement watch mode for incremental updates
|
|
640
|
+
- [ ] Create fingerprint comparison and diff tools
|
|
641
|
+
- [ ] Add IDE integration and language service plugin
|
|
642
|
+
- [ ] Add fingerprint validation and consistency checks
|
|
379
643
|
|
|
380
644
|
This specification provides a complete blueprint for implementing a sophisticated task fingerprinting system that operates at build time and provides comprehensive type introspection capabilities for TypeScript tasks.
|
package/src/runner.ts
CHANGED
|
@@ -160,6 +160,10 @@ runner.setHandler(async (data: ParsedArgs): Promise<unknown> => {
|
|
|
160
160
|
})
|
|
161
161
|
} else {
|
|
162
162
|
result = await task.run(args)
|
|
163
|
+
|
|
164
|
+
if (taskName === 'info') {
|
|
165
|
+
silent = true
|
|
166
|
+
}
|
|
163
167
|
}
|
|
164
168
|
|
|
165
169
|
if (taskName === 'task:describe' || taskName === 'task:list') {
|
|
@@ -7,7 +7,6 @@ import { Schema } from '@forgehive/schema'
|
|
|
7
7
|
import esbuild from 'esbuild'
|
|
8
8
|
import fs from 'fs/promises'
|
|
9
9
|
import path from 'path'
|
|
10
|
-
import os from 'os'
|
|
11
10
|
|
|
12
11
|
import { load as loadConf } from '../conf/load'
|
|
13
12
|
import { analyzeTaskFile, TaskFingerprintOutput } from '../../utils/taskAnalysis'
|
|
@@ -22,7 +21,9 @@ interface TaskFingerprint {
|
|
|
22
21
|
}
|
|
23
22
|
inputSchema: TaskFingerprintOutput['inputSchema']
|
|
24
23
|
outputType: TaskFingerprintOutput['outputType']
|
|
25
|
-
boundaries:
|
|
24
|
+
boundaries: TaskFingerprintOutput['boundaries']
|
|
25
|
+
errors: TaskFingerprintOutput['errors']
|
|
26
|
+
analysisMetadata: TaskFingerprintOutput['analysisMetadata']
|
|
26
27
|
hash: string
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -59,14 +60,14 @@ const boundaries = {
|
|
|
59
60
|
writeFile: async (filePath: string, content: string): Promise<void> => {
|
|
60
61
|
return fs.writeFile(filePath, content)
|
|
61
62
|
},
|
|
62
|
-
|
|
63
|
-
const
|
|
63
|
+
ensureFingerprintsFolder: async (cwd: string, conf: { paths?: { fingerprints?: string } }): Promise<string> => {
|
|
64
|
+
const fingerprintsPath = path.join(cwd, conf.paths?.fingerprints || 'fingerprints/')
|
|
64
65
|
try {
|
|
65
|
-
await fs.access(
|
|
66
|
+
await fs.access(fingerprintsPath)
|
|
66
67
|
} catch {
|
|
67
|
-
await fs.mkdir(
|
|
68
|
+
await fs.mkdir(fingerprintsPath, { recursive: true })
|
|
68
69
|
}
|
|
69
|
-
return
|
|
70
|
+
return fingerprintsPath
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
|
|
@@ -96,6 +97,8 @@ function taskFingerprintPlugin(): esbuild.Plugin {
|
|
|
96
97
|
inputSchema: taskFingerprint.inputSchema,
|
|
97
98
|
outputType: taskFingerprint.outputType,
|
|
98
99
|
boundaries: taskFingerprint.boundaries,
|
|
100
|
+
errors: taskFingerprint.errors,
|
|
101
|
+
analysisMetadata: taskFingerprint.analysisMetadata,
|
|
99
102
|
hash: 'generated-hash'
|
|
100
103
|
}
|
|
101
104
|
fingerprints.push(fullFingerprint)
|
|
@@ -121,7 +124,7 @@ export const fingerprint = createTask({
|
|
|
121
124
|
loadConf,
|
|
122
125
|
readFile,
|
|
123
126
|
writeFile,
|
|
124
|
-
|
|
127
|
+
ensureFingerprintsFolder
|
|
125
128
|
}) {
|
|
126
129
|
// If filePath is provided, analyze that file directly and return JSON
|
|
127
130
|
if (filePath) {
|
|
@@ -133,9 +136,23 @@ export const fingerprint = createTask({
|
|
|
133
136
|
throw new Error('Could not extract fingerprint from task file: ' + filePath)
|
|
134
137
|
}
|
|
135
138
|
|
|
136
|
-
|
|
139
|
+
// Write fingerprint to file for consistency
|
|
140
|
+
const cwd = await getCwd()
|
|
141
|
+
const forgeJson = await loadConf({})
|
|
142
|
+
const fingerprintsPath = await ensureFingerprintsFolder(cwd, forgeJson)
|
|
143
|
+
const fingerprintFile = path.join(fingerprintsPath, `${descriptorName}.fingerprint.json`)
|
|
144
|
+
|
|
145
|
+
const analysis = {
|
|
137
146
|
taskFingerprint: fingerprintOutput
|
|
138
147
|
}
|
|
148
|
+
|
|
149
|
+
await writeFile(fingerprintFile, JSON.stringify(analysis, null, 2))
|
|
150
|
+
console.log(`Fingerprint saved to: ${fingerprintFile}`)
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
taskFingerprint: fingerprintOutput,
|
|
154
|
+
fingerprintFile
|
|
155
|
+
}
|
|
139
156
|
}
|
|
140
157
|
|
|
141
158
|
// Original bundle logic when no filePath is provided
|
|
@@ -149,9 +166,9 @@ export const fingerprint = createTask({
|
|
|
149
166
|
}
|
|
150
167
|
|
|
151
168
|
const entryPoint = path.join(cwd, taskDescriptor.path)
|
|
152
|
-
const
|
|
153
|
-
const outputFile = path.join(
|
|
154
|
-
const fingerprintsFile = path.join(
|
|
169
|
+
const fingerprintsPath = await ensureFingerprintsFolder(cwd, forgeJson)
|
|
170
|
+
const outputFile = path.join(fingerprintsPath, `${descriptorName}.js`)
|
|
171
|
+
const fingerprintsFile = path.join(fingerprintsPath, `${descriptorName}.fingerprints.json`)
|
|
155
172
|
|
|
156
173
|
console.log(`Generating bundle with fingerprints for task: ${descriptorName}`)
|
|
157
174
|
console.log(`Entry point: ${entryPoint}`)
|
|
@@ -177,7 +194,9 @@ export const fingerprint = createTask({
|
|
|
177
194
|
description: fp.description,
|
|
178
195
|
inputSchema: fp.inputSchema,
|
|
179
196
|
outputType: fp.outputType,
|
|
180
|
-
boundaries: fp.boundaries
|
|
197
|
+
boundaries: fp.boundaries,
|
|
198
|
+
errors: fp.errors, // Preserve errors from analyzeTaskFile
|
|
199
|
+
analysisMetadata: fp.analysisMetadata // Preserve metadata from analyzeTaskFile
|
|
181
200
|
}))
|
|
182
201
|
|
|
183
202
|
// Create fingerprint result
|