@forgehive/forge-cli 0.2.14 → 0.3.1
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 -1
- 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.js +85 -81
- 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.js +27 -23
- 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 +78 -79
- 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 +12 -0
- package/logs/task:fingerprint.log +10 -0
- package/package.json +7 -7
- package/specs/fingerprint.md +380 -0
- package/src/runner.ts +3 -1
- 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 +3 -3
- package/src/tasks/task/download.ts +3 -3
- package/src/tasks/task/fingerprint.ts +107 -0
- package/src/tasks/task/list.ts +3 -3
- 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 +12 -18
- package/src/test/tasks/create.test.ts +9 -9
- package/src/utils/taskAnalysis.ts +419 -0
package/dist/runner.js
CHANGED
|
@@ -18,6 +18,7 @@ const download_1 = require("./tasks/task/download");
|
|
|
18
18
|
const replay_1 = require("./tasks/task/replay");
|
|
19
19
|
const list_1 = require("./tasks/task/list");
|
|
20
20
|
const describe_1 = require("./tasks/task/describe");
|
|
21
|
+
const fingerprint_1 = require("./tasks/task/fingerprint");
|
|
21
22
|
const create_1 = require("./tasks/runner/create");
|
|
22
23
|
const remove_2 = require("./tasks/runner/remove");
|
|
23
24
|
const bundle_1 = require("./tasks/runner/bundle");
|
|
@@ -46,6 +47,7 @@ runner.load('task:download', download_1.download);
|
|
|
46
47
|
runner.load('task:replay', replay_1.replay);
|
|
47
48
|
runner.load('task:list', list_1.list);
|
|
48
49
|
runner.load('task:describe', describe_1.describe);
|
|
50
|
+
runner.load('task:fingerprint', fingerprint_1.fingerprint);
|
|
49
51
|
// Runner commands
|
|
50
52
|
runner.load('runner:create', create_1.create);
|
|
51
53
|
runner.load('runner:remove', remove_2.remove);
|
|
@@ -71,7 +73,7 @@ runner.setHandler(async (data) => {
|
|
|
71
73
|
}
|
|
72
74
|
try {
|
|
73
75
|
let result;
|
|
74
|
-
const commandsWithDescriptor = ['task:create', 'task:remove', 'task:publish', 'task:describe'];
|
|
76
|
+
const commandsWithDescriptor = ['task:create', 'task:remove', 'task:publish', 'task:describe', 'task:fingerprint'];
|
|
75
77
|
const commandsWithRunner = ['runner:create', 'runner:remove'];
|
|
76
78
|
if (commandsWithDescriptor.includes(taskName)) {
|
|
77
79
|
result = await task.run({ descriptorName: action });
|
package/dist/tasks/auth/add.js
CHANGED
|
@@ -27,24 +27,28 @@ const boundaries = {
|
|
|
27
27
|
await promises_1.default.writeFile(profilesPath, JSON.stringify(profiles, null, 2));
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
|
-
exports.add = (0, task_1.createTask)(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
//
|
|
36
|
-
profiles.profiles
|
|
30
|
+
exports.add = (0, task_1.createTask)({
|
|
31
|
+
schema,
|
|
32
|
+
boundaries,
|
|
33
|
+
fn: async function ({ name, apiKey, apiSecret, url }, { loadProfiles, persistProfiles }) {
|
|
34
|
+
const profiles = await loadProfiles({});
|
|
35
|
+
// Check if profile with same name already exists
|
|
36
|
+
const existingProfileIndex = profiles.profiles.findIndex(p => p.name === name);
|
|
37
|
+
if (existingProfileIndex >= 0) {
|
|
38
|
+
// Replace existing profile
|
|
39
|
+
profiles.profiles[existingProfileIndex] = { name, apiKey, apiSecret, url };
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// Add new profile
|
|
43
|
+
profiles.profiles.push({ name, apiKey, apiSecret, url });
|
|
44
|
+
}
|
|
45
|
+
// Set as default profile
|
|
46
|
+
profiles.default = name;
|
|
47
|
+
// Persist profiles
|
|
48
|
+
await persistProfiles(profiles);
|
|
49
|
+
return {
|
|
50
|
+
status: 'Ok',
|
|
51
|
+
message: `Profile '${name}' added and set as default`
|
|
52
|
+
};
|
|
37
53
|
}
|
|
38
|
-
else {
|
|
39
|
-
// Add new profile
|
|
40
|
-
profiles.profiles.push({ name, apiKey, apiSecret, url });
|
|
41
|
-
}
|
|
42
|
-
// Set as default profile
|
|
43
|
-
profiles.default = name;
|
|
44
|
-
// Persist profiles
|
|
45
|
-
await persistProfiles(profiles);
|
|
46
|
-
return {
|
|
47
|
-
status: 'Ok',
|
|
48
|
-
message: `Profile '${name}' added and set as default`
|
|
49
|
-
};
|
|
50
54
|
});
|
package/dist/tasks/auth/list.js
CHANGED
|
@@ -11,21 +11,25 @@ const schema = new schema_1.Schema({});
|
|
|
11
11
|
const boundaries = {
|
|
12
12
|
loadProfiles: load_1.load.asBoundary()
|
|
13
13
|
};
|
|
14
|
-
exports.list = (0, task_1.createTask)(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
exports.list = (0, task_1.createTask)({
|
|
15
|
+
schema,
|
|
16
|
+
boundaries,
|
|
17
|
+
fn: async function (_argv, { loadProfiles }) {
|
|
18
|
+
const profiles = await loadProfiles({});
|
|
19
|
+
if (profiles.profiles.length === 0) {
|
|
20
|
+
console.log('No profiles found. Use auth:add to create one.');
|
|
21
|
+
return { status: 'Ok', profiles: [] };
|
|
22
|
+
}
|
|
23
|
+
console.log('Available profiles:');
|
|
24
|
+
profiles.profiles.forEach(profile => {
|
|
25
|
+
const isDefault = profile.name === profiles.default;
|
|
26
|
+
const prefix = isDefault ? '* ' : ' ';
|
|
27
|
+
console.log(`${prefix}${profile.name} - API Key: ${profile.apiKey}`);
|
|
28
|
+
});
|
|
29
|
+
console.log('\nUse auth:add to create or update a profile');
|
|
30
|
+
console.log('\nUse auth:switch to switch to a profile');
|
|
31
|
+
return {
|
|
32
|
+
default: profiles.default
|
|
33
|
+
};
|
|
19
34
|
}
|
|
20
|
-
console.log('Available profiles:');
|
|
21
|
-
profiles.profiles.forEach(profile => {
|
|
22
|
-
const isDefault = profile.name === profiles.default;
|
|
23
|
-
const prefix = isDefault ? '* ' : ' ';
|
|
24
|
-
console.log(`${prefix}${profile.name} - API Key: ${profile.apiKey}`);
|
|
25
|
-
});
|
|
26
|
-
console.log('\nUse auth:add to create or update a profile');
|
|
27
|
-
console.log('\nUse auth:switch to switch to a profile');
|
|
28
|
-
return {
|
|
29
|
-
default: profiles.default
|
|
30
|
-
};
|
|
31
35
|
});
|
package/dist/tasks/auth/load.js
CHANGED
|
@@ -25,20 +25,24 @@ const boundaries = {
|
|
|
25
25
|
return buildsPath;
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
|
-
exports.load = (0, task_1.createTask)(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
28
|
+
exports.load = (0, task_1.createTask)({
|
|
29
|
+
schema,
|
|
30
|
+
boundaries,
|
|
31
|
+
fn: async function (argv, { ensureBuildsFolder }) {
|
|
32
|
+
const buildsPath = await ensureBuildsFolder();
|
|
33
|
+
let profiles = {
|
|
34
|
+
default: '',
|
|
35
|
+
profiles: []
|
|
36
|
+
};
|
|
37
|
+
const profilesPath = path_1.default.join(buildsPath, 'profiles.json');
|
|
38
|
+
try {
|
|
39
|
+
const content = await promises_1.default.readFile(profilesPath, 'utf-8');
|
|
40
|
+
profiles = JSON.parse(content);
|
|
41
|
+
}
|
|
42
|
+
catch (_error) {
|
|
43
|
+
console.log('Creating profiles.json');
|
|
44
|
+
await promises_1.default.writeFile(profilesPath, '{"profiles": [], "default": ""}');
|
|
45
|
+
}
|
|
46
|
+
return profiles;
|
|
42
47
|
}
|
|
43
|
-
return profiles;
|
|
44
48
|
});
|
|
@@ -11,14 +11,18 @@ const schema = new schema_1.Schema({});
|
|
|
11
11
|
const boundaries = {
|
|
12
12
|
loadProfiles: load_1.load.asBoundary()
|
|
13
13
|
};
|
|
14
|
-
exports.loadCurrent = (0, task_1.createTask)(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
exports.loadCurrent = (0, task_1.createTask)({
|
|
15
|
+
schema,
|
|
16
|
+
boundaries,
|
|
17
|
+
fn: async function (_argv, { loadProfiles }) {
|
|
18
|
+
const profiles = await loadProfiles({});
|
|
19
|
+
if (!profiles.default || profiles.default === '') {
|
|
20
|
+
throw new Error('No default profile set. Please run forge task:run auth:add to create a profile.');
|
|
21
|
+
}
|
|
22
|
+
const defaultProfile = profiles.profiles.find(profile => profile.name === profiles.default);
|
|
23
|
+
if (!defaultProfile) {
|
|
24
|
+
throw new Error(`Default profile "${profiles.default}" not found in profiles.`);
|
|
25
|
+
}
|
|
26
|
+
return { ...defaultProfile, name: profiles.default };
|
|
18
27
|
}
|
|
19
|
-
const defaultProfile = profiles.profiles.find(profile => profile.name === profiles.default);
|
|
20
|
-
if (!defaultProfile) {
|
|
21
|
-
throw new Error(`Default profile "${profiles.default}" not found in profiles.`);
|
|
22
|
-
}
|
|
23
|
-
return { ...defaultProfile, name: profiles.default };
|
|
24
28
|
});
|
|
@@ -24,33 +24,37 @@ const boundaries = {
|
|
|
24
24
|
await promises_1.default.writeFile(profilesPath, JSON.stringify(profiles, null, 2));
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
|
-
exports.remove = (0, task_1.createTask)(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// If the removed profile was the default, update the default
|
|
37
|
-
if (profiles.default === profileName) {
|
|
38
|
-
if (profiles.profiles.length > 0) {
|
|
39
|
-
// Set the first available profile as default
|
|
40
|
-
profiles.default = profiles.profiles[0].name;
|
|
41
|
-
console.log(`Default profile set to: ${profiles.default}`);
|
|
27
|
+
exports.remove = (0, task_1.createTask)({
|
|
28
|
+
schema,
|
|
29
|
+
boundaries,
|
|
30
|
+
fn: async function ({ profileName }, { loadProfiles, persistProfiles }) {
|
|
31
|
+
const profiles = await loadProfiles({});
|
|
32
|
+
// Check if profile exists
|
|
33
|
+
const profileExists = profiles.profiles.some(profile => profile.name === profileName);
|
|
34
|
+
if (!profileExists) {
|
|
35
|
+
throw new Error(`Profile "${profileName}" not found. Use auth:list to see available profiles.`);
|
|
42
36
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
// Remove the profile using filter
|
|
38
|
+
profiles.profiles = profiles.profiles.filter(profile => profile.name !== profileName);
|
|
39
|
+
// If the removed profile was the default, update the default
|
|
40
|
+
if (profiles.default === profileName) {
|
|
41
|
+
if (profiles.profiles.length > 0) {
|
|
42
|
+
// Set the first available profile as default
|
|
43
|
+
profiles.default = profiles.profiles[0].name;
|
|
44
|
+
console.log(`Default profile set to: ${profiles.default}`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// No profiles left, set default to empty
|
|
48
|
+
profiles.default = '';
|
|
49
|
+
console.log('No profiles left. Default set to empty.');
|
|
50
|
+
}
|
|
47
51
|
}
|
|
52
|
+
// Persist updated profiles
|
|
53
|
+
await persistProfiles(profiles);
|
|
54
|
+
console.log(`Profile "${profileName}" has been removed.`);
|
|
55
|
+
return {
|
|
56
|
+
status: 'Ok',
|
|
57
|
+
message: `Profile "${profileName}" has been removed.`
|
|
58
|
+
};
|
|
48
59
|
}
|
|
49
|
-
// Persist updated profiles
|
|
50
|
-
await persistProfiles(profiles);
|
|
51
|
-
console.log(`Profile "${profileName}" has been removed.`);
|
|
52
|
-
return {
|
|
53
|
-
status: 'Ok',
|
|
54
|
-
message: `Profile "${profileName}" has been removed.`
|
|
55
|
-
};
|
|
56
60
|
});
|
|
@@ -24,20 +24,24 @@ const boundaries = {
|
|
|
24
24
|
await promises_1.default.writeFile(profilesPath, JSON.stringify(profiles, null, 2));
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
|
-
exports.switchProfile = (0, task_1.createTask)(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
exports.switchProfile = (0, task_1.createTask)({
|
|
28
|
+
schema,
|
|
29
|
+
boundaries,
|
|
30
|
+
fn: async function ({ profileName }, { loadProfiles, persistProfiles }) {
|
|
31
|
+
// Load profiles
|
|
32
|
+
const profiles = await loadProfiles({});
|
|
33
|
+
// Check if profile exists
|
|
34
|
+
const profileExists = profiles.profiles.some(profile => profile.name === profileName);
|
|
35
|
+
if (!profileExists) {
|
|
36
|
+
throw new Error(`Profile "${profileName}" not found. Use auth:list to see available profiles.`);
|
|
37
|
+
}
|
|
38
|
+
// Update default profile
|
|
39
|
+
profiles.default = profileName;
|
|
40
|
+
// Save updated profiles
|
|
41
|
+
await persistProfiles(profiles);
|
|
42
|
+
console.log(`Switched to profile: ${profileName}`);
|
|
43
|
+
return {
|
|
44
|
+
default: profileName
|
|
45
|
+
};
|
|
34
46
|
}
|
|
35
|
-
// Update default profile
|
|
36
|
-
profiles.default = profileName;
|
|
37
|
-
// Save updated profiles
|
|
38
|
-
await persistProfiles(profiles);
|
|
39
|
-
console.log(`Switched to profile: ${profileName}`);
|
|
40
|
-
return {
|
|
41
|
-
default: profileName
|
|
42
|
-
};
|
|
43
47
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// TASK: create
|
|
3
3
|
// Run this task with:
|
|
4
|
-
//
|
|
4
|
+
// forge task:run bundle:create
|
|
5
5
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
6
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
7
|
};
|
|
@@ -15,15 +15,19 @@ const schema = new schema_1.Schema({
|
|
|
15
15
|
outputFile: schema_1.Schema.string()
|
|
16
16
|
});
|
|
17
17
|
const boundaries = {};
|
|
18
|
-
exports.create = (0, task_1.createTask)(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
exports.create = (0, task_1.createTask)({
|
|
19
|
+
schema,
|
|
20
|
+
boundaries,
|
|
21
|
+
fn: async function ({ entryPoint, outputFile }) {
|
|
22
|
+
// Build using esbuild
|
|
23
|
+
await esbuild_1.default.build({
|
|
24
|
+
entryPoints: [entryPoint],
|
|
25
|
+
outfile: outputFile,
|
|
26
|
+
bundle: true,
|
|
27
|
+
minify: true,
|
|
28
|
+
platform: 'node',
|
|
29
|
+
sourcemap: true
|
|
30
|
+
});
|
|
31
|
+
return { outputFile };
|
|
32
|
+
}
|
|
29
33
|
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { TaskFingerprintOutput } from '../../utils/taskAnalysis';
|
|
2
|
+
export declare const fingerprint: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
3
|
+
descriptorName: string;
|
|
4
|
+
filePath?: string | undefined;
|
|
5
|
+
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
6
|
+
getCwd: () => Promise<string>;
|
|
7
|
+
loadConf: (args: {}) => Promise<Promise<import("../types").ForgeConf>>;
|
|
8
|
+
readFile: (filePath: string) => Promise<string>;
|
|
9
|
+
writeFile: (filePath: string, content: string) => Promise<void>;
|
|
10
|
+
ensureForgeFolder: () => Promise<string>;
|
|
11
|
+
}>) => Promise<{
|
|
12
|
+
taskFingerprint: TaskFingerprintOutput;
|
|
13
|
+
outputFile?: undefined;
|
|
14
|
+
fingerprintsFile?: undefined;
|
|
15
|
+
taskFingerprints?: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
outputFile: string;
|
|
18
|
+
fingerprintsFile: string;
|
|
19
|
+
taskFingerprints: {
|
|
20
|
+
totalTasks: number;
|
|
21
|
+
tasks: {
|
|
22
|
+
name: string;
|
|
23
|
+
inputType: string;
|
|
24
|
+
outputType: string;
|
|
25
|
+
boundaryCount: number;
|
|
26
|
+
hash: string;
|
|
27
|
+
}[];
|
|
28
|
+
};
|
|
29
|
+
taskFingerprint?: undefined;
|
|
30
|
+
}>, {
|
|
31
|
+
getCwd: () => Promise<string>;
|
|
32
|
+
loadConf: (args: {}) => Promise<Promise<import("../types").ForgeConf>>;
|
|
33
|
+
readFile: (filePath: string) => Promise<string>;
|
|
34
|
+
writeFile: (filePath: string, content: string) => Promise<void>;
|
|
35
|
+
ensureForgeFolder: () => Promise<string>;
|
|
36
|
+
}>;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// TASK: fingerprint
|
|
3
|
+
// Run this task with:
|
|
4
|
+
// forge task:run bundle:fingerprint --descriptorName task-name
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.fingerprint = void 0;
|
|
10
|
+
const task_1 = require("@forgehive/task");
|
|
11
|
+
const schema_1 = require("@forgehive/schema");
|
|
12
|
+
const esbuild_1 = __importDefault(require("esbuild"));
|
|
13
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
14
|
+
const path_1 = __importDefault(require("path"));
|
|
15
|
+
const os_1 = __importDefault(require("os"));
|
|
16
|
+
const load_1 = require("../conf/load");
|
|
17
|
+
const taskAnalysis_1 = require("../../utils/taskAnalysis");
|
|
18
|
+
const description = 'Generate task bundle with comprehensive fingerprinting and type extraction';
|
|
19
|
+
const schema = new schema_1.Schema({
|
|
20
|
+
descriptorName: schema_1.Schema.string(),
|
|
21
|
+
filePath: schema_1.Schema.string().optional()
|
|
22
|
+
});
|
|
23
|
+
const boundaries = {
|
|
24
|
+
getCwd: async () => {
|
|
25
|
+
return process.cwd();
|
|
26
|
+
},
|
|
27
|
+
loadConf: load_1.load.asBoundary(),
|
|
28
|
+
readFile: async (filePath) => {
|
|
29
|
+
return promises_1.default.readFile(filePath, 'utf-8');
|
|
30
|
+
},
|
|
31
|
+
writeFile: async (filePath, content) => {
|
|
32
|
+
return promises_1.default.writeFile(filePath, content);
|
|
33
|
+
},
|
|
34
|
+
ensureForgeFolder: async () => {
|
|
35
|
+
const forgePath = path_1.default.join(os_1.default.homedir(), '.forge');
|
|
36
|
+
try {
|
|
37
|
+
await promises_1.default.access(forgePath);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
await promises_1.default.mkdir(forgePath, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
return forgePath;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
// esbuild plugin for fingerprinting
|
|
46
|
+
function taskFingerprintPlugin() {
|
|
47
|
+
return {
|
|
48
|
+
name: 'task-fingerprint',
|
|
49
|
+
setup(build) {
|
|
50
|
+
const fingerprints = [];
|
|
51
|
+
build.onLoad({ filter: /\.ts$/ }, async (args) => {
|
|
52
|
+
const sourceCode = await promises_1.default.readFile(args.path, 'utf-8');
|
|
53
|
+
// Only analyze files that contain createTask
|
|
54
|
+
if (sourceCode.includes('createTask')) {
|
|
55
|
+
const taskFingerprint = (0, taskAnalysis_1.analyzeTaskFile)(sourceCode, args.path);
|
|
56
|
+
if (taskFingerprint) {
|
|
57
|
+
// Convert to full TaskFingerprint for plugin compatibility
|
|
58
|
+
const fullFingerprint = {
|
|
59
|
+
name: path_1.default.basename(args.path, '.ts'),
|
|
60
|
+
description: taskFingerprint.description,
|
|
61
|
+
location: {
|
|
62
|
+
file: args.path,
|
|
63
|
+
line: 1,
|
|
64
|
+
column: 1
|
|
65
|
+
},
|
|
66
|
+
inputSchema: taskFingerprint.inputSchema,
|
|
67
|
+
outputType: taskFingerprint.outputType,
|
|
68
|
+
boundaries: taskFingerprint.boundaries,
|
|
69
|
+
hash: 'generated-hash'
|
|
70
|
+
};
|
|
71
|
+
fingerprints.push(fullFingerprint);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null; // Let esbuild handle the file normally
|
|
75
|
+
});
|
|
76
|
+
build.onEnd((result) => {
|
|
77
|
+
// Store fingerprints for later use
|
|
78
|
+
result.fingerprints = fingerprints;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
exports.fingerprint = (0, task_1.createTask)({
|
|
84
|
+
schema,
|
|
85
|
+
boundaries,
|
|
86
|
+
fn: async function ({ descriptorName, filePath }, { getCwd, loadConf, readFile, writeFile, ensureForgeFolder }) {
|
|
87
|
+
// If filePath is provided, analyze that file directly and return JSON
|
|
88
|
+
if (filePath) {
|
|
89
|
+
console.log(`Analyzing task file: ${filePath}`);
|
|
90
|
+
const sourceCode = await readFile(filePath);
|
|
91
|
+
const fingerprintOutput = (0, taskAnalysis_1.analyzeTaskFile)(sourceCode, filePath);
|
|
92
|
+
if (!fingerprintOutput) {
|
|
93
|
+
throw new Error('Could not extract fingerprint from task file: ' + filePath);
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
taskFingerprint: fingerprintOutput
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// Original bundle logic when no filePath is provided
|
|
100
|
+
const cwd = await getCwd();
|
|
101
|
+
const forgeJson = await loadConf({});
|
|
102
|
+
const taskDescriptor = forgeJson.tasks[descriptorName];
|
|
103
|
+
if (taskDescriptor === undefined) {
|
|
104
|
+
throw new Error(`Task "${descriptorName}" is not defined in forge.json`);
|
|
105
|
+
}
|
|
106
|
+
const entryPoint = path_1.default.join(cwd, taskDescriptor.path);
|
|
107
|
+
const forgePath = await ensureForgeFolder();
|
|
108
|
+
const outputFile = path_1.default.join(forgePath, `${descriptorName}.js`);
|
|
109
|
+
const fingerprintsFile = path_1.default.join(forgePath, `${descriptorName}.fingerprints.json`);
|
|
110
|
+
console.log(`Generating bundle with fingerprints for task: ${descriptorName}`);
|
|
111
|
+
console.log(`Entry point: ${entryPoint}`);
|
|
112
|
+
console.log(`Output: ${outputFile}`);
|
|
113
|
+
// Build with fingerprinting plugin
|
|
114
|
+
const result = await esbuild_1.default.build({
|
|
115
|
+
entryPoints: [entryPoint],
|
|
116
|
+
outfile: outputFile,
|
|
117
|
+
bundle: true,
|
|
118
|
+
minify: true,
|
|
119
|
+
platform: 'node',
|
|
120
|
+
sourcemap: true,
|
|
121
|
+
plugins: [taskFingerprintPlugin()],
|
|
122
|
+
metafile: true
|
|
123
|
+
});
|
|
124
|
+
// Extract fingerprints from build result
|
|
125
|
+
const taskFingerprints = result.fingerprints || [];
|
|
126
|
+
// Convert to simplified output format (remove name, location, hash)
|
|
127
|
+
const simplifiedFingerprints = taskFingerprints.map((fp) => ({
|
|
128
|
+
description: fp.description,
|
|
129
|
+
inputSchema: fp.inputSchema,
|
|
130
|
+
outputType: fp.outputType,
|
|
131
|
+
boundaries: fp.boundaries
|
|
132
|
+
}));
|
|
133
|
+
// Create fingerprint result
|
|
134
|
+
const fingerprintResult = {
|
|
135
|
+
tasks: simplifiedFingerprints,
|
|
136
|
+
buildInfo: {
|
|
137
|
+
entryPoint,
|
|
138
|
+
outputFile,
|
|
139
|
+
fingerprintsFile,
|
|
140
|
+
totalTasks: simplifiedFingerprints.length,
|
|
141
|
+
buildTimestamp: new Date().toISOString()
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
// Write fingerprints to file
|
|
145
|
+
await writeFile(fingerprintsFile, JSON.stringify(fingerprintResult, null, 2));
|
|
146
|
+
console.log(`Generated ${taskFingerprints.length} task fingerprints`);
|
|
147
|
+
console.log(`Fingerprints saved to: ${fingerprintsFile}`);
|
|
148
|
+
return {
|
|
149
|
+
outputFile,
|
|
150
|
+
fingerprintsFile,
|
|
151
|
+
taskFingerprints: {
|
|
152
|
+
totalTasks: taskFingerprints.length,
|
|
153
|
+
tasks: taskFingerprints.map((fp) => ({
|
|
154
|
+
name: fp.name,
|
|
155
|
+
inputType: fp.inputSchema.type,
|
|
156
|
+
outputType: fp.outputType.type,
|
|
157
|
+
boundaryCount: fp.boundaries.length,
|
|
158
|
+
hash: fp.hash
|
|
159
|
+
}))
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
exports.fingerprint.setDescription(description);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// TASK: load
|
|
3
3
|
// Run this task with:
|
|
4
|
-
//
|
|
4
|
+
// forge task:run bundle:load
|
|
5
5
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
6
|
if (k2 === undefined) k2 = k;
|
|
7
7
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -43,8 +43,12 @@ const schema = new schema_1.Schema({
|
|
|
43
43
|
bundlePath: schema_1.Schema.string()
|
|
44
44
|
});
|
|
45
45
|
const boundaries = {};
|
|
46
|
-
exports.load = (0, task_1.createTask)(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
exports.load = (0, task_1.createTask)({
|
|
47
|
+
schema,
|
|
48
|
+
boundaries,
|
|
49
|
+
fn: async function ({ bundlePath }) {
|
|
50
|
+
// Dynamically import the bundle from the specified path
|
|
51
|
+
const bundle = await Promise.resolve(`${bundlePath}`).then(s => __importStar(require(s)));
|
|
52
|
+
return bundle;
|
|
53
|
+
}
|
|
50
54
|
});
|