@forgehive/forge-cli 0.2.13 → 0.3.0
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 +15 -7
- package/dist/tasks/auth/add.js +23 -19
- package/dist/tasks/auth/list.js +20 -16
- package/dist/tasks/auth/load.js +19 -15
- package/dist/tasks/auth/loadCurrent.js +13 -9
- package/dist/tasks/auth/remove.js +30 -26
- package/dist/tasks/auth/switch.js +19 -15
- package/dist/tasks/bundle/create.js +16 -12
- package/dist/tasks/bundle/fingerprint.d.ts +36 -0
- package/dist/tasks/bundle/fingerprint.js +164 -0
- package/dist/tasks/bundle/load.js +9 -5
- package/dist/tasks/bundle/zip.js +49 -45
- package/dist/tasks/conf/info.js +23 -19
- package/dist/tasks/conf/load.js +8 -4
- package/dist/tasks/fixture/download.js +40 -36
- package/dist/tasks/init.js +35 -31
- package/dist/tasks/runner/bundle.js +34 -30
- package/dist/tasks/runner/create.js +28 -24
- package/dist/tasks/runner/remove.js +22 -18
- package/dist/tasks/task/createTask.js +35 -28
- package/dist/tasks/task/describe.d.ts +35 -0
- package/dist/tasks/task/describe.js +130 -0
- package/dist/tasks/task/download.js +63 -59
- package/dist/tasks/task/fingerprint.d.ts +26 -0
- package/dist/tasks/task/fingerprint.js +87 -0
- package/dist/tasks/task/list.d.ts +12 -0
- package/dist/tasks/task/list.js +46 -0
- package/dist/tasks/task/publish.js +72 -68
- package/dist/tasks/task/remove.js +24 -20
- package/dist/tasks/task/replay.js +94 -90
- package/dist/tasks/task/run.js +84 -79
- package/dist/test/setup.d.ts +0 -0
- package/dist/test/setup.js +14 -0
- package/dist/test/tasks/create.test.js +6 -5
- package/dist/utils/taskAnalysis.d.ts +21 -0
- package/dist/utils/taskAnalysis.js +380 -0
- package/forge.json +20 -0
- package/jest.config.js +2 -1
- package/logs/task:fingerprint.log +10 -0
- package/package.json +8 -8
- package/specs/fingerprint.md +380 -0
- package/src/runner.ts +14 -5
- package/src/tasks/README.md +13 -13
- package/src/tasks/auth/add.ts +3 -3
- package/src/tasks/auth/list.ts +3 -3
- package/src/tasks/auth/load.ts +3 -3
- package/src/tasks/auth/loadCurrent.ts +3 -3
- package/src/tasks/auth/remove.ts +3 -3
- package/src/tasks/auth/switch.ts +3 -3
- package/src/tasks/bundle/README.md +7 -7
- package/src/tasks/bundle/create.ts +4 -4
- package/src/tasks/bundle/fingerprint.ts +218 -0
- package/src/tasks/bundle/load.ts +4 -4
- package/src/tasks/bundle/zip.ts +3 -3
- package/src/tasks/conf/info.ts +3 -3
- package/src/tasks/conf/load.ts +3 -3
- package/src/tasks/fixture/download.ts +3 -3
- package/src/tasks/init.ts +3 -3
- package/src/tasks/runner/bundle.ts +3 -3
- package/src/tasks/runner/create.ts +3 -3
- package/src/tasks/runner/remove.ts +3 -3
- package/src/tasks/task/createTask.ts +10 -7
- package/src/tasks/task/describe.ts +148 -0
- package/src/tasks/task/download.ts +3 -3
- package/src/tasks/task/fingerprint.ts +107 -0
- package/src/tasks/task/list.ts +58 -0
- package/src/tasks/task/publish.ts +3 -3
- package/src/tasks/task/remove.ts +3 -3
- package/src/tasks/task/replay.ts +3 -3
- package/src/tasks/task/run.ts +5 -4
- package/src/test/setup.ts +14 -0
- package/src/test/tasks/create.test.ts +9 -9
- package/src/utils/taskAnalysis.ts +419 -0
- package/dist/taskAdapter.d.ts +0 -34
- package/dist/taskAdapter.js +0 -85
- package/dist/templates/README.md +0 -23
- package/dist/templates/task.hbs +0 -27
- package/dist/test/utils.d.ts +0 -2
- package/dist/test/utils.js +0 -17
- package/logs/auth:list.log +0 -4
- package/logs/auth:load.log +0 -2
- package/logs/auth:loadCurrent.log +0 -1
- package/logs/conf:info.log +0 -2
- package/logs/runner:create.log +0 -4
package/src/runner.ts
CHANGED
|
@@ -12,13 +12,16 @@ import { info } from './tasks/conf/info'
|
|
|
12
12
|
import { createTaskCommand } from './tasks/task/createTask'
|
|
13
13
|
import { run as taskRunCommand } from './tasks/task/run'
|
|
14
14
|
import { remove as taskRemoveCommand } from './tasks/task/remove'
|
|
15
|
+
import { publish as publishTask } from './tasks/task/publish'
|
|
16
|
+
import { download as downloadTask } from './tasks/task/download'
|
|
17
|
+
import { replay as replayTask } from './tasks/task/replay'
|
|
18
|
+
import { list as listTasks } from './tasks/task/list'
|
|
19
|
+
import { describe as describeTask } from './tasks/task/describe'
|
|
20
|
+
import { fingerprint as fingerprintTask } from './tasks/task/fingerprint'
|
|
15
21
|
|
|
16
22
|
import { create as createRunner } from './tasks/runner/create'
|
|
17
23
|
import { remove as removeRunner } from './tasks/runner/remove'
|
|
18
24
|
import { bundle as bundleRunner } from './tasks/runner/bundle'
|
|
19
|
-
import { publish as publishTask } from './tasks/task/publish'
|
|
20
|
-
import { download as downloadTask } from './tasks/task/download'
|
|
21
|
-
import { replay as replayTask } from './tasks/task/replay'
|
|
22
25
|
|
|
23
26
|
import { download as downloadFixture } from './tasks/fixture/download'
|
|
24
27
|
|
|
@@ -52,6 +55,9 @@ runner.load('task:remove', taskRemoveCommand)
|
|
|
52
55
|
runner.load('task:publish', publishTask)
|
|
53
56
|
runner.load('task:download', downloadTask)
|
|
54
57
|
runner.load('task:replay', replayTask)
|
|
58
|
+
runner.load('task:list', listTasks)
|
|
59
|
+
runner.load('task:describe', describeTask)
|
|
60
|
+
runner.load('task:fingerprint', fingerprintTask)
|
|
55
61
|
|
|
56
62
|
// Runner commands
|
|
57
63
|
runner.load('runner:create', createRunner)
|
|
@@ -85,11 +91,10 @@ runner.setHandler(async (data: ParsedArgs): Promise<unknown> => {
|
|
|
85
91
|
try {
|
|
86
92
|
let result
|
|
87
93
|
|
|
88
|
-
const commandsWithDescriptor = ['task:create', 'task:remove', 'task:publish']
|
|
94
|
+
const commandsWithDescriptor = ['task:create', 'task:remove', 'task:publish', 'task:describe', 'task:fingerprint']
|
|
89
95
|
const commandsWithRunner = ['runner:create', 'runner:remove']
|
|
90
96
|
|
|
91
97
|
if (commandsWithDescriptor.includes(taskName)) {
|
|
92
|
-
console.log('Running:', taskName, action)
|
|
93
98
|
result = await task.run({ descriptorName: action })
|
|
94
99
|
} else if (commandsWithRunner.includes(taskName)) {
|
|
95
100
|
result = await task.run({
|
|
@@ -147,6 +152,10 @@ runner.setHandler(async (data: ParsedArgs): Promise<unknown> => {
|
|
|
147
152
|
result = await task.run(args)
|
|
148
153
|
}
|
|
149
154
|
|
|
155
|
+
if (taskName === 'task:describe' || taskName === 'task:list') {
|
|
156
|
+
silent = true
|
|
157
|
+
}
|
|
158
|
+
|
|
150
159
|
return {
|
|
151
160
|
silent,
|
|
152
161
|
outcome: 'Success',
|
package/src/tasks/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Forge CLI Task Guidelines
|
|
2
2
|
|
|
3
|
-
This document outlines the standard patterns and best practices for creating tasks in the
|
|
3
|
+
This document outlines the standard patterns and best practices for creating tasks in the Forge CLI.
|
|
4
4
|
|
|
5
5
|
## Task Structure
|
|
6
6
|
|
|
@@ -9,10 +9,10 @@ All tasks should follow this standard structure:
|
|
|
9
9
|
```typescript
|
|
10
10
|
// TASK: [task_name]
|
|
11
11
|
// Run this task with:
|
|
12
|
-
//
|
|
12
|
+
// forge task:run [namespace]:[task_name]
|
|
13
13
|
|
|
14
|
-
import { createTask } from '@
|
|
15
|
-
import { Schema } from '@
|
|
14
|
+
import { createTask } from '@forgehive/task'
|
|
15
|
+
import { Schema } from '@forgehive/schema'
|
|
16
16
|
// Import any additional dependencies
|
|
17
17
|
|
|
18
18
|
// Define the schema for task arguments
|
|
@@ -33,7 +33,7 @@ export const taskName = createTask(
|
|
|
33
33
|
boundaries,
|
|
34
34
|
async function ({ /* destructured parameters */ }) {
|
|
35
35
|
// Task implementation
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
// Return appropriate result
|
|
38
38
|
return result
|
|
39
39
|
}
|
|
@@ -45,8 +45,8 @@ export const taskName = createTask(
|
|
|
45
45
|
### Bundle Creation Task
|
|
46
46
|
|
|
47
47
|
```typescript
|
|
48
|
-
import { createTask } from '@
|
|
49
|
-
import { Schema } from '@
|
|
48
|
+
import { createTask } from '@forgehive/task'
|
|
49
|
+
import { Schema } from '@forgehive/schema'
|
|
50
50
|
import esbuild from 'esbuild'
|
|
51
51
|
|
|
52
52
|
const schema = new Schema({
|
|
@@ -80,8 +80,8 @@ export const create = createTask(
|
|
|
80
80
|
### Bundle Loading Task
|
|
81
81
|
|
|
82
82
|
```typescript
|
|
83
|
-
import { createTask } from '@
|
|
84
|
-
import { Schema } from '@
|
|
83
|
+
import { createTask } from '@forgehive/task'
|
|
84
|
+
import { Schema } from '@forgehive/schema'
|
|
85
85
|
|
|
86
86
|
const schema = new Schema({
|
|
87
87
|
bundlePath: Schema.string()
|
|
@@ -129,11 +129,11 @@ Common schema types include:
|
|
|
129
129
|
Tasks can be run using the CLI:
|
|
130
130
|
|
|
131
131
|
```bash
|
|
132
|
-
|
|
132
|
+
forge task:run [namespace]:[task_name] --paramName=value
|
|
133
133
|
```
|
|
134
134
|
|
|
135
135
|
For example:
|
|
136
136
|
|
|
137
137
|
```bash
|
|
138
|
-
|
|
139
|
-
```
|
|
138
|
+
forge task:run bundle:create --entryPoint=src/index.ts --outputFile=dist/bundle.js
|
|
139
|
+
```
|
package/src/tasks/auth/add.ts
CHANGED
|
@@ -27,10 +27,10 @@ const boundaries = {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export const add = createTask(
|
|
30
|
+
export const add = createTask({
|
|
31
31
|
schema,
|
|
32
32
|
boundaries,
|
|
33
|
-
async function ({ name, apiKey, apiSecret, url }, { loadProfiles, persistProfiles }) {
|
|
33
|
+
fn: async function ({ name, apiKey, apiSecret, url }, { loadProfiles, persistProfiles }) {
|
|
34
34
|
const profiles = await loadProfiles({})
|
|
35
35
|
|
|
36
36
|
// Check if profile with same name already exists
|
|
@@ -54,4 +54,4 @@ export const add = createTask(
|
|
|
54
54
|
message: `Profile '${name}' added and set as default`
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
)
|
|
57
|
+
})
|
package/src/tasks/auth/list.ts
CHANGED
|
@@ -14,10 +14,10 @@ const boundaries = {
|
|
|
14
14
|
loadProfiles: loadProfiles.asBoundary()
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export const list = createTask(
|
|
17
|
+
export const list = createTask({
|
|
18
18
|
schema,
|
|
19
19
|
boundaries,
|
|
20
|
-
async function (_argv, { loadProfiles }) {
|
|
20
|
+
fn: async function (_argv, { loadProfiles }) {
|
|
21
21
|
const profiles: Profiles = await loadProfiles({})
|
|
22
22
|
|
|
23
23
|
if (profiles.profiles.length === 0) {
|
|
@@ -40,4 +40,4 @@ export const list = createTask(
|
|
|
40
40
|
default: profiles.default
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
)
|
|
43
|
+
})
|
package/src/tasks/auth/load.ts
CHANGED
|
@@ -26,10 +26,10 @@ const boundaries = {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export const load = createTask(
|
|
29
|
+
export const load = createTask({
|
|
30
30
|
schema,
|
|
31
31
|
boundaries,
|
|
32
|
-
async function (argv, { ensureBuildsFolder }) {
|
|
32
|
+
fn: async function (argv, { ensureBuildsFolder }) {
|
|
33
33
|
const buildsPath = await ensureBuildsFolder()
|
|
34
34
|
|
|
35
35
|
let profiles: Profiles = {
|
|
@@ -48,4 +48,4 @@ export const load = createTask(
|
|
|
48
48
|
|
|
49
49
|
return profiles
|
|
50
50
|
}
|
|
51
|
-
)
|
|
51
|
+
})
|
|
@@ -14,10 +14,10 @@ const boundaries = {
|
|
|
14
14
|
loadProfiles: loadProfiles.asBoundary()
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export const loadCurrent = createTask(
|
|
17
|
+
export const loadCurrent = createTask({
|
|
18
18
|
schema,
|
|
19
19
|
boundaries,
|
|
20
|
-
async function (_argv, { loadProfiles }): Promise<Profile> {
|
|
20
|
+
fn: async function (_argv, { loadProfiles }): Promise<Profile> {
|
|
21
21
|
const profiles = await loadProfiles({})
|
|
22
22
|
|
|
23
23
|
if (!profiles.default || profiles.default === '') {
|
|
@@ -32,4 +32,4 @@ export const loadCurrent = createTask(
|
|
|
32
32
|
|
|
33
33
|
return { ...defaultProfile, name: profiles.default }
|
|
34
34
|
}
|
|
35
|
-
)
|
|
35
|
+
})
|
package/src/tasks/auth/remove.ts
CHANGED
|
@@ -24,10 +24,10 @@ const boundaries = {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export const remove = createTask(
|
|
27
|
+
export const remove = createTask({
|
|
28
28
|
schema,
|
|
29
29
|
boundaries,
|
|
30
|
-
async function ({ profileName }, { loadProfiles, persistProfiles }) {
|
|
30
|
+
fn: async function ({ profileName }, { loadProfiles, persistProfiles }) {
|
|
31
31
|
const profiles = await loadProfiles({})
|
|
32
32
|
|
|
33
33
|
// Check if profile exists
|
|
@@ -63,4 +63,4 @@ export const remove = createTask(
|
|
|
63
63
|
message: `Profile "${profileName}" has been removed.`
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
)
|
|
66
|
+
})
|
package/src/tasks/auth/switch.ts
CHANGED
|
@@ -24,10 +24,10 @@ const boundaries = {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export const switchProfile = createTask(
|
|
27
|
+
export const switchProfile = createTask({
|
|
28
28
|
schema,
|
|
29
29
|
boundaries,
|
|
30
|
-
async function ({ profileName }, { loadProfiles, persistProfiles }) {
|
|
30
|
+
fn: async function ({ profileName }, { loadProfiles, persistProfiles }) {
|
|
31
31
|
// Load profiles
|
|
32
32
|
const profiles = await loadProfiles({})
|
|
33
33
|
|
|
@@ -50,4 +50,4 @@ export const switchProfile = createTask(
|
|
|
50
50
|
default: profileName
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
)
|
|
53
|
+
})
|
|
@@ -17,7 +17,7 @@ Creates a bundled JavaScript file using esbuild.
|
|
|
17
17
|
|
|
18
18
|
**Example Usage:**
|
|
19
19
|
```bash
|
|
20
|
-
|
|
20
|
+
forge task:run bundle:create --entryPoint=src/index.ts --outputFile=dist/bundle.js
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
**Implementation Details:**
|
|
@@ -38,7 +38,7 @@ Dynamically loads a JavaScript bundle and returns its default export.
|
|
|
38
38
|
|
|
39
39
|
**Example Usage:**
|
|
40
40
|
```bash
|
|
41
|
-
|
|
41
|
+
forge task:run bundle:load --bundlePath=dist/bundle.js
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
**Implementation Details:**
|
|
@@ -51,10 +51,10 @@ shadow-cli bundle:load --bundlePath=dist/bundle.js
|
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
53
|
# First, create the bundle
|
|
54
|
-
|
|
54
|
+
forge task:run bundle:create --entryPoint=src/index.ts --outputFile=dist/bundle.js
|
|
55
55
|
|
|
56
56
|
# Then, load the bundle
|
|
57
|
-
|
|
57
|
+
forge task:run bundle:load --bundlePath=dist/bundle.js
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
### Using in Scripts
|
|
@@ -71,13 +71,13 @@ async function buildAndLoad() {
|
|
|
71
71
|
entryPoint: 'src/index.ts',
|
|
72
72
|
outputFile: 'dist/bundle.js'
|
|
73
73
|
})
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
// Load bundle
|
|
76
76
|
const bundleExport = await loadBundle({
|
|
77
77
|
bundlePath: 'dist/bundle.js'
|
|
78
78
|
})
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
// Use the loaded bundle
|
|
81
81
|
return bundleExport
|
|
82
82
|
}
|
|
83
|
-
```
|
|
83
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// TASK: create
|
|
2
2
|
// Run this task with:
|
|
3
|
-
//
|
|
3
|
+
// forge task:run bundle:create
|
|
4
4
|
|
|
5
5
|
import { createTask } from '@forgehive/task'
|
|
6
6
|
import { Schema } from '@forgehive/schema'
|
|
@@ -13,10 +13,10 @@ const schema = new Schema({
|
|
|
13
13
|
|
|
14
14
|
const boundaries = {}
|
|
15
15
|
|
|
16
|
-
export const create = createTask(
|
|
16
|
+
export const create = createTask({
|
|
17
17
|
schema,
|
|
18
18
|
boundaries,
|
|
19
|
-
async function ({ entryPoint, outputFile }) {
|
|
19
|
+
fn: async function ({ entryPoint, outputFile }) {
|
|
20
20
|
// Build using esbuild
|
|
21
21
|
await esbuild.build({
|
|
22
22
|
entryPoints: [entryPoint],
|
|
@@ -29,4 +29,4 @@ export const create = createTask(
|
|
|
29
29
|
|
|
30
30
|
return { outputFile }
|
|
31
31
|
}
|
|
32
|
-
)
|
|
32
|
+
})
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// TASK: fingerprint
|
|
2
|
+
// Run this task with:
|
|
3
|
+
// forge task:run bundle:fingerprint --descriptorName task-name
|
|
4
|
+
|
|
5
|
+
import { createTask } from '@forgehive/task'
|
|
6
|
+
import { Schema } from '@forgehive/schema'
|
|
7
|
+
import esbuild from 'esbuild'
|
|
8
|
+
import fs from 'fs/promises'
|
|
9
|
+
import path from 'path'
|
|
10
|
+
import os from 'os'
|
|
11
|
+
|
|
12
|
+
import { load as loadConf } from '../conf/load'
|
|
13
|
+
import { analyzeTaskFile, TaskFingerprintOutput } from '../../utils/taskAnalysis'
|
|
14
|
+
|
|
15
|
+
interface TaskFingerprint {
|
|
16
|
+
name: string
|
|
17
|
+
description?: string
|
|
18
|
+
location: {
|
|
19
|
+
file: string
|
|
20
|
+
line: number
|
|
21
|
+
column: number
|
|
22
|
+
}
|
|
23
|
+
inputSchema: TaskFingerprintOutput['inputSchema']
|
|
24
|
+
outputType: TaskFingerprintOutput['outputType']
|
|
25
|
+
boundaries: string[]
|
|
26
|
+
hash: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface EsbuildResultWithFingerprints extends esbuild.BuildResult {
|
|
30
|
+
fingerprints?: TaskFingerprint[]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface FingerprintResult {
|
|
34
|
+
tasks: TaskFingerprintOutput[]
|
|
35
|
+
buildInfo: {
|
|
36
|
+
entryPoint: string
|
|
37
|
+
outputFile: string
|
|
38
|
+
fingerprintsFile?: string
|
|
39
|
+
totalTasks: number
|
|
40
|
+
buildTimestamp: string
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const description = 'Generate task bundle with comprehensive fingerprinting and type extraction'
|
|
45
|
+
|
|
46
|
+
const schema = new Schema({
|
|
47
|
+
descriptorName: Schema.string(),
|
|
48
|
+
filePath: Schema.string().optional()
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const boundaries = {
|
|
52
|
+
getCwd: async (): Promise<string> => {
|
|
53
|
+
return process.cwd()
|
|
54
|
+
},
|
|
55
|
+
loadConf: loadConf.asBoundary(),
|
|
56
|
+
readFile: async (filePath: string): Promise<string> => {
|
|
57
|
+
return fs.readFile(filePath, 'utf-8')
|
|
58
|
+
},
|
|
59
|
+
writeFile: async (filePath: string, content: string): Promise<void> => {
|
|
60
|
+
return fs.writeFile(filePath, content)
|
|
61
|
+
},
|
|
62
|
+
ensureForgeFolder: async (): Promise<string> => {
|
|
63
|
+
const forgePath = path.join(os.homedir(), '.forge')
|
|
64
|
+
try {
|
|
65
|
+
await fs.access(forgePath)
|
|
66
|
+
} catch {
|
|
67
|
+
await fs.mkdir(forgePath, { recursive: true })
|
|
68
|
+
}
|
|
69
|
+
return forgePath
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// esbuild plugin for fingerprinting
|
|
74
|
+
function taskFingerprintPlugin(): esbuild.Plugin {
|
|
75
|
+
return {
|
|
76
|
+
name: 'task-fingerprint',
|
|
77
|
+
setup(build): void {
|
|
78
|
+
const fingerprints: TaskFingerprint[] = []
|
|
79
|
+
|
|
80
|
+
build.onLoad({ filter: /\.ts$/ }, async (args) => {
|
|
81
|
+
const sourceCode = await fs.readFile(args.path, 'utf-8')
|
|
82
|
+
|
|
83
|
+
// Only analyze files that contain createTask
|
|
84
|
+
if (sourceCode.includes('createTask')) {
|
|
85
|
+
const taskFingerprint = analyzeTaskFile(sourceCode, args.path)
|
|
86
|
+
if (taskFingerprint) {
|
|
87
|
+
// Convert to full TaskFingerprint for plugin compatibility
|
|
88
|
+
const fullFingerprint: TaskFingerprint = {
|
|
89
|
+
name: path.basename(args.path, '.ts'),
|
|
90
|
+
description: taskFingerprint.description,
|
|
91
|
+
location: {
|
|
92
|
+
file: args.path,
|
|
93
|
+
line: 1,
|
|
94
|
+
column: 1
|
|
95
|
+
},
|
|
96
|
+
inputSchema: taskFingerprint.inputSchema,
|
|
97
|
+
outputType: taskFingerprint.outputType,
|
|
98
|
+
boundaries: taskFingerprint.boundaries,
|
|
99
|
+
hash: 'generated-hash'
|
|
100
|
+
}
|
|
101
|
+
fingerprints.push(fullFingerprint)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return null // Let esbuild handle the file normally
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
build.onEnd((result): void => {
|
|
109
|
+
// Store fingerprints for later use
|
|
110
|
+
(result as EsbuildResultWithFingerprints).fingerprints = fingerprints
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export const fingerprint = createTask({
|
|
117
|
+
schema,
|
|
118
|
+
boundaries,
|
|
119
|
+
fn: async function ({ descriptorName, filePath }, {
|
|
120
|
+
getCwd,
|
|
121
|
+
loadConf,
|
|
122
|
+
readFile,
|
|
123
|
+
writeFile,
|
|
124
|
+
ensureForgeFolder
|
|
125
|
+
}) {
|
|
126
|
+
// If filePath is provided, analyze that file directly and return JSON
|
|
127
|
+
if (filePath) {
|
|
128
|
+
console.log(`Analyzing task file: ${filePath}`)
|
|
129
|
+
const sourceCode = await readFile(filePath)
|
|
130
|
+
const fingerprintOutput = analyzeTaskFile(sourceCode, filePath)
|
|
131
|
+
|
|
132
|
+
if (!fingerprintOutput) {
|
|
133
|
+
throw new Error('Could not extract fingerprint from task file: ' + filePath)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
taskFingerprint: fingerprintOutput
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Original bundle logic when no filePath is provided
|
|
142
|
+
const cwd = await getCwd()
|
|
143
|
+
const forgeJson = await loadConf({})
|
|
144
|
+
|
|
145
|
+
const taskDescriptor = forgeJson.tasks[descriptorName as keyof typeof forgeJson.tasks]
|
|
146
|
+
|
|
147
|
+
if (taskDescriptor === undefined) {
|
|
148
|
+
throw new Error(`Task "${descriptorName}" is not defined in forge.json`)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const entryPoint = path.join(cwd, taskDescriptor.path)
|
|
152
|
+
const forgePath = await ensureForgeFolder()
|
|
153
|
+
const outputFile = path.join(forgePath, `${descriptorName}.js`)
|
|
154
|
+
const fingerprintsFile = path.join(forgePath, `${descriptorName}.fingerprints.json`)
|
|
155
|
+
|
|
156
|
+
console.log(`Generating bundle with fingerprints for task: ${descriptorName}`)
|
|
157
|
+
console.log(`Entry point: ${entryPoint}`)
|
|
158
|
+
console.log(`Output: ${outputFile}`)
|
|
159
|
+
|
|
160
|
+
// Build with fingerprinting plugin
|
|
161
|
+
const result = await esbuild.build({
|
|
162
|
+
entryPoints: [entryPoint],
|
|
163
|
+
outfile: outputFile,
|
|
164
|
+
bundle: true,
|
|
165
|
+
minify: true,
|
|
166
|
+
platform: 'node',
|
|
167
|
+
sourcemap: true,
|
|
168
|
+
plugins: [taskFingerprintPlugin()],
|
|
169
|
+
metafile: true
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
// Extract fingerprints from build result
|
|
173
|
+
const taskFingerprints = (result as EsbuildResultWithFingerprints).fingerprints || []
|
|
174
|
+
|
|
175
|
+
// Convert to simplified output format (remove name, location, hash)
|
|
176
|
+
const simplifiedFingerprints: TaskFingerprintOutput[] = taskFingerprints.map((fp: TaskFingerprint) => ({
|
|
177
|
+
description: fp.description,
|
|
178
|
+
inputSchema: fp.inputSchema,
|
|
179
|
+
outputType: fp.outputType,
|
|
180
|
+
boundaries: fp.boundaries
|
|
181
|
+
}))
|
|
182
|
+
|
|
183
|
+
// Create fingerprint result
|
|
184
|
+
const fingerprintResult: FingerprintResult = {
|
|
185
|
+
tasks: simplifiedFingerprints,
|
|
186
|
+
buildInfo: {
|
|
187
|
+
entryPoint,
|
|
188
|
+
outputFile,
|
|
189
|
+
fingerprintsFile,
|
|
190
|
+
totalTasks: simplifiedFingerprints.length,
|
|
191
|
+
buildTimestamp: new Date().toISOString()
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Write fingerprints to file
|
|
196
|
+
await writeFile(fingerprintsFile, JSON.stringify(fingerprintResult, null, 2))
|
|
197
|
+
|
|
198
|
+
console.log(`Generated ${taskFingerprints.length} task fingerprints`)
|
|
199
|
+
console.log(`Fingerprints saved to: ${fingerprintsFile}`)
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
outputFile,
|
|
203
|
+
fingerprintsFile,
|
|
204
|
+
taskFingerprints: {
|
|
205
|
+
totalTasks: taskFingerprints.length,
|
|
206
|
+
tasks: taskFingerprints.map((fp: TaskFingerprint) => ({
|
|
207
|
+
name: fp.name,
|
|
208
|
+
inputType: fp.inputSchema.type,
|
|
209
|
+
outputType: fp.outputType.type,
|
|
210
|
+
boundaryCount: fp.boundaries.length,
|
|
211
|
+
hash: fp.hash
|
|
212
|
+
}))
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
fingerprint.setDescription(description)
|
package/src/tasks/bundle/load.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// TASK: load
|
|
2
2
|
// Run this task with:
|
|
3
|
-
//
|
|
3
|
+
// forge task:run bundle:load
|
|
4
4
|
|
|
5
5
|
import { createTask } from '@forgehive/task'
|
|
6
6
|
import { Schema } from '@forgehive/schema'
|
|
@@ -11,13 +11,13 @@ const schema = new Schema({
|
|
|
11
11
|
|
|
12
12
|
const boundaries = {}
|
|
13
13
|
|
|
14
|
-
export const load = createTask(
|
|
14
|
+
export const load = createTask({
|
|
15
15
|
schema,
|
|
16
16
|
boundaries,
|
|
17
|
-
async function ({ bundlePath }) {
|
|
17
|
+
fn: async function ({ bundlePath }) {
|
|
18
18
|
// Dynamically import the bundle from the specified path
|
|
19
19
|
const bundle = await import(bundlePath)
|
|
20
20
|
|
|
21
21
|
return bundle
|
|
22
22
|
}
|
|
23
|
-
)
|
|
23
|
+
})
|
package/src/tasks/bundle/zip.ts
CHANGED
|
@@ -41,10 +41,10 @@ export const bytesToMB = (bytes: number): string => {
|
|
|
41
41
|
return `${MB.toFixed(2)} MB`
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export const zip = createTask(
|
|
44
|
+
export const zip = createTask({
|
|
45
45
|
schema,
|
|
46
46
|
boundaries,
|
|
47
|
-
async function ({ dir, input, output }, { createWriteStream, createArchiver, resolvePathDir, fileExists }) {
|
|
47
|
+
fn: async function ({ dir, input, output }, { createWriteStream, createArchiver, resolvePathDir, fileExists }) {
|
|
48
48
|
const outputPath = await resolvePathDir(dir, output)
|
|
49
49
|
const inputPath = await resolvePathDir(dir, input)
|
|
50
50
|
const inputMapPath = inputPath + '.map'
|
|
@@ -104,6 +104,6 @@ export const zip = createTask(
|
|
|
104
104
|
archive.finalize()
|
|
105
105
|
})
|
|
106
106
|
}
|
|
107
|
-
)
|
|
107
|
+
})
|
|
108
108
|
|
|
109
109
|
zip.setDescription(description)
|
package/src/tasks/conf/info.ts
CHANGED
|
@@ -16,10 +16,10 @@ const boundaries = {
|
|
|
16
16
|
loadCurrentProfile: loadCurrentProfile.asBoundary()
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export const info = createTask(
|
|
19
|
+
export const info = createTask({
|
|
20
20
|
schema,
|
|
21
21
|
boundaries,
|
|
22
|
-
async function (_argv, { loadCurrentProfile, readFile }) {
|
|
22
|
+
fn: async function (_argv, { loadCurrentProfile, readFile }) {
|
|
23
23
|
const packageJsonPath = path.join(__dirname, '../../../package.json')
|
|
24
24
|
|
|
25
25
|
const packageJsonContent = await readFile(packageJsonPath)
|
|
@@ -45,4 +45,4 @@ export const info = createTask(
|
|
|
45
45
|
|
|
46
46
|
return info
|
|
47
47
|
}
|
|
48
|
-
)
|
|
48
|
+
})
|
package/src/tasks/conf/load.ts
CHANGED
|
@@ -14,13 +14,13 @@ const boundaries = {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export const load = createTask(
|
|
17
|
+
export const load = createTask({
|
|
18
18
|
schema,
|
|
19
19
|
boundaries,
|
|
20
|
-
async function (_, { readFile }) {
|
|
20
|
+
fn: async function (_, { readFile }) {
|
|
21
21
|
const forgePath = path.join(process.cwd(), 'forge.json')
|
|
22
22
|
|
|
23
23
|
const content = await readFile(forgePath)
|
|
24
24
|
return JSON.parse(content) as ForgeConf
|
|
25
25
|
}
|
|
26
|
-
)
|
|
26
|
+
})
|
|
@@ -62,10 +62,10 @@ const boundaries = {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
export const download = createTask(
|
|
65
|
+
export const download = createTask({
|
|
66
66
|
schema,
|
|
67
67
|
boundaries,
|
|
68
|
-
async function ({ uuid }, {
|
|
68
|
+
fn: async function ({ uuid }, {
|
|
69
69
|
downloadFixture,
|
|
70
70
|
getCwd,
|
|
71
71
|
persistFixture,
|
|
@@ -131,6 +131,6 @@ forge task:replay ${taskName} --path ${shortPath}
|
|
|
131
131
|
shortPath: shortPath
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
-
)
|
|
134
|
+
})
|
|
135
135
|
|
|
136
136
|
download.setDescription(description)
|
package/src/tasks/init.ts
CHANGED
|
@@ -20,10 +20,10 @@ const boundaries = {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
// Create a task with type inference from schema and boundaries
|
|
23
|
-
export const init = createTask(
|
|
23
|
+
export const init = createTask({
|
|
24
24
|
schema,
|
|
25
25
|
boundaries,
|
|
26
|
-
async function (argv, { saveFile, getCwd }) {
|
|
26
|
+
fn: async function (argv, { saveFile, getCwd }) {
|
|
27
27
|
// Handle the dryRun flag
|
|
28
28
|
const isDryRun = Boolean(argv.dryRun)
|
|
29
29
|
|
|
@@ -60,4 +60,4 @@ export const init = createTask(
|
|
|
60
60
|
|
|
61
61
|
return config
|
|
62
62
|
}
|
|
63
|
-
)
|
|
63
|
+
})
|
|
@@ -29,10 +29,10 @@ const boundaries = {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
export const bundle = createTask(
|
|
32
|
+
export const bundle = createTask({
|
|
33
33
|
schema,
|
|
34
34
|
boundaries,
|
|
35
|
-
async function ({ runnerName, targetPath }, { loadConf, getCwd, ensureDir }) {
|
|
35
|
+
fn: async function ({ runnerName, targetPath }, { loadConf, getCwd, ensureDir }) {
|
|
36
36
|
// Load forge configuration
|
|
37
37
|
const forge: ForgeConf = await loadConf({})
|
|
38
38
|
const cwd = await getCwd()
|
|
@@ -76,4 +76,4 @@ export const bundle = createTask(
|
|
|
76
76
|
outputFile: path.join(targetPath, `${runnerName}.js`)
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
-
)
|
|
79
|
+
})
|