@forgehive/forge-cli 0.2.14 → 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 +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 +84 -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 +5 -4
- package/src/test/tasks/create.test.ts +9 -9
- package/src/utils/taskAnalysis.ts +419 -0
|
@@ -25,29 +25,33 @@ const boundaries = {
|
|
|
25
25
|
await promises_1.default.unlink(filePath);
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
|
-
exports.remove = (0, task_1.createTask)(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
exports.remove = (0, task_1.createTask)({
|
|
29
|
+
schema,
|
|
30
|
+
boundaries,
|
|
31
|
+
fn: async function ({ descriptorName }, { loadConf, persistConf, deleteFile }) {
|
|
32
|
+
// Load shadow configuration
|
|
33
|
+
const forge = await loadConf({});
|
|
34
|
+
// Check if the task exists in shadow.json
|
|
35
|
+
if (!forge.tasks[descriptorName]) {
|
|
36
|
+
throw new Error(`Task '${descriptorName}' not found in forge.json`);
|
|
37
|
+
}
|
|
38
|
+
// Get the task file path
|
|
39
|
+
const taskFilePath = path_1.default.join(process.cwd(), forge.tasks[descriptorName].path);
|
|
40
|
+
console.log(`
|
|
38
41
|
==================================================
|
|
39
42
|
Removing task: ${descriptorName}
|
|
40
43
|
File path: ${taskFilePath}
|
|
41
44
|
==================================================
|
|
42
45
|
`);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
// Delete the task file
|
|
47
|
+
await deleteFile(taskFilePath);
|
|
48
|
+
// Remove the task from shadow.json
|
|
49
|
+
delete forge.tasks[descriptorName];
|
|
50
|
+
// Save the updated shadow.json
|
|
51
|
+
await persistConf(forge);
|
|
52
|
+
return {
|
|
53
|
+
status: 'Ok',
|
|
54
|
+
message: `Task '${descriptorName}' has been successfully removed`
|
|
55
|
+
};
|
|
56
|
+
}
|
|
53
57
|
});
|
|
@@ -80,100 +80,104 @@ const boundaries = {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
};
|
|
83
|
-
exports.replay = (0, task_1.createTask)(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
? fixturePath
|
|
97
|
-
: path_1.default.join(process.cwd(), forge.paths.fixtures, fixturePath);
|
|
98
|
-
// Read the file from the provided path
|
|
99
|
-
const fixture = await readFixture(resolvedFixturePath);
|
|
100
|
-
// Try to load profile, but continue if not found
|
|
101
|
-
let profile = null;
|
|
102
|
-
try {
|
|
103
|
-
profile = await loadCurrentProfile({});
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
// Profile not found or not configured, continue without it
|
|
107
|
-
console.log('No profile found, logs will not be sent to remote API');
|
|
108
|
-
}
|
|
109
|
-
// Verify if log folder exists
|
|
110
|
-
const logFolderPath = path_1.default.join(process.cwd(), forge.paths.logs);
|
|
111
|
-
const logFolderExists = await verifyLogFolder(logFolderPath);
|
|
112
|
-
if (!logFolderExists) {
|
|
113
|
-
throw new Error(`Log folder "${logFolderPath}" does not exist`);
|
|
114
|
-
}
|
|
115
|
-
// Prepare paths
|
|
116
|
-
const entryPoint = path_1.default.join(process.cwd(), taskDescriptor.path);
|
|
117
|
-
const buildsPath = await ensureBuildsFolder();
|
|
118
|
-
const outputFile = path_1.default.join(buildsPath, `${descriptorName}.js`);
|
|
119
|
-
// Bundle the task
|
|
120
|
-
await bundleCreate({
|
|
121
|
-
entryPoint,
|
|
122
|
-
outputFile
|
|
123
|
-
});
|
|
124
|
-
// Load the bundled task
|
|
125
|
-
const bundle = await bundleLoad({
|
|
126
|
-
bundlePath: outputFile
|
|
127
|
-
});
|
|
128
|
-
// Get the task handler
|
|
129
|
-
const task = bundle[taskDescriptor.handler];
|
|
130
|
-
if (!task) {
|
|
131
|
-
throw new Error(`Handler "${taskDescriptor.handler}" not found in bundle`);
|
|
132
|
-
}
|
|
133
|
-
// Configure boundaries based on cache parameter if provided
|
|
134
|
-
const boundaryConfig = {};
|
|
135
|
-
if (cache) {
|
|
136
|
-
// Parse the comma-separated list and trim each item
|
|
137
|
-
const cacheBoundaries = cache.split(',').map((b) => b.trim());
|
|
138
|
-
// Log which boundaries will use cache mode
|
|
139
|
-
if (cacheBoundaries.length > 0) {
|
|
140
|
-
// Set each specified boundary to 'replay' mode
|
|
141
|
-
cacheBoundaries.forEach((boundary) => {
|
|
142
|
-
boundaryConfig[boundary] = 'replay';
|
|
143
|
-
});
|
|
83
|
+
exports.replay = (0, task_1.createTask)({
|
|
84
|
+
schema,
|
|
85
|
+
boundaries,
|
|
86
|
+
fn: async function ({ descriptorName, path: fixturePath, cache }, { readFixture, loadConf, loadCurrentProfile, bundleCreate, bundleLoad, ensureBuildsFolder, verifyLogFolder, sendLogToAPI }) {
|
|
87
|
+
console.log('Input descriptorName:', descriptorName);
|
|
88
|
+
console.log('Input path:', fixturePath);
|
|
89
|
+
console.log('Input cache:', cache);
|
|
90
|
+
// Load forge configuration
|
|
91
|
+
const forge = await loadConf({});
|
|
92
|
+
const taskDescriptor = forge.tasks[descriptorName];
|
|
93
|
+
const projectName = forge.project.name;
|
|
94
|
+
if (taskDescriptor === undefined) {
|
|
95
|
+
throw new Error(`Task ${descriptorName} is not defined in forge.json`);
|
|
144
96
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
console.log('Boundaries:', JSON.stringify(fixture.boundaries, null, 2));
|
|
154
|
-
console.log('==================================================');
|
|
155
|
-
console.log('Boundary config:', boundaryConfig);
|
|
156
|
-
console.log('==================================================');
|
|
157
|
-
// Perform the replay
|
|
158
|
-
const [result, error, record] = await task.safeReplay({
|
|
159
|
-
input: fixture.input,
|
|
160
|
-
output: fixture.output,
|
|
161
|
-
boundaries: fixture.boundaries,
|
|
162
|
-
}, {
|
|
163
|
-
boundaries: boundaryConfig // Use configured boundary modes
|
|
164
|
-
});
|
|
165
|
-
// Send the log to API if profile is available
|
|
166
|
-
if (profile) {
|
|
97
|
+
// Resolve the fixture path (check if absolute, if not make it relative to logs folder)
|
|
98
|
+
const resolvedFixturePath = path_1.default.isAbsolute(fixturePath)
|
|
99
|
+
? fixturePath
|
|
100
|
+
: path_1.default.join(process.cwd(), forge.paths.fixtures, fixturePath);
|
|
101
|
+
// Read the file from the provided path
|
|
102
|
+
const fixture = await readFixture(resolvedFixturePath);
|
|
103
|
+
// Try to load profile, but continue if not found
|
|
104
|
+
let profile = null;
|
|
167
105
|
try {
|
|
168
|
-
|
|
106
|
+
profile = await loadCurrentProfile({});
|
|
169
107
|
}
|
|
170
|
-
catch (
|
|
171
|
-
|
|
108
|
+
catch (error) {
|
|
109
|
+
// Profile not found or not configured, continue without it
|
|
110
|
+
console.log('No profile found, logs will not be sent to remote API');
|
|
172
111
|
}
|
|
112
|
+
// Verify if log folder exists
|
|
113
|
+
const logFolderPath = path_1.default.join(process.cwd(), forge.paths.logs);
|
|
114
|
+
const logFolderExists = await verifyLogFolder(logFolderPath);
|
|
115
|
+
if (!logFolderExists) {
|
|
116
|
+
throw new Error(`Log folder "${logFolderPath}" does not exist`);
|
|
117
|
+
}
|
|
118
|
+
// Prepare paths
|
|
119
|
+
const entryPoint = path_1.default.join(process.cwd(), taskDescriptor.path);
|
|
120
|
+
const buildsPath = await ensureBuildsFolder();
|
|
121
|
+
const outputFile = path_1.default.join(buildsPath, `${descriptorName}.js`);
|
|
122
|
+
// Bundle the task
|
|
123
|
+
await bundleCreate({
|
|
124
|
+
entryPoint,
|
|
125
|
+
outputFile
|
|
126
|
+
});
|
|
127
|
+
// Load the bundled task
|
|
128
|
+
const bundle = await bundleLoad({
|
|
129
|
+
bundlePath: outputFile
|
|
130
|
+
});
|
|
131
|
+
// Get the task handler
|
|
132
|
+
const task = bundle[taskDescriptor.handler];
|
|
133
|
+
if (!task) {
|
|
134
|
+
throw new Error(`Handler "${taskDescriptor.handler}" not found in bundle`);
|
|
135
|
+
}
|
|
136
|
+
// Configure boundaries based on cache parameter if provided
|
|
137
|
+
const boundaryConfig = {};
|
|
138
|
+
if (cache) {
|
|
139
|
+
// Parse the comma-separated list and trim each item
|
|
140
|
+
const cacheBoundaries = cache.split(',').map((b) => b.trim());
|
|
141
|
+
// Log which boundaries will use cache mode
|
|
142
|
+
if (cacheBoundaries.length > 0) {
|
|
143
|
+
// Set each specified boundary to 'replay' mode
|
|
144
|
+
cacheBoundaries.forEach((boundary) => {
|
|
145
|
+
boundaryConfig[boundary] = 'replay';
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
console.log('==================================================');
|
|
150
|
+
console.log('UUID:', fixture.fixtureUUID);
|
|
151
|
+
console.log('Task name:', fixture.taskName);
|
|
152
|
+
console.log('Project name:', fixture.projectName);
|
|
153
|
+
console.log('Context:', fixture.context);
|
|
154
|
+
console.log('==================================================');
|
|
155
|
+
console.log('Replay:', fixture.input);
|
|
156
|
+
console.log('Boundaries:', JSON.stringify(fixture.boundaries, null, 2));
|
|
157
|
+
console.log('==================================================');
|
|
158
|
+
console.log('Boundary config:', boundaryConfig);
|
|
159
|
+
console.log('==================================================');
|
|
160
|
+
// Perform the replay
|
|
161
|
+
const [result, error, record] = await task.safeReplay({
|
|
162
|
+
input: fixture.input,
|
|
163
|
+
output: fixture.output,
|
|
164
|
+
boundaries: fixture.boundaries,
|
|
165
|
+
}, {
|
|
166
|
+
boundaries: boundaryConfig // Use configured boundary modes
|
|
167
|
+
});
|
|
168
|
+
// Send the log to API if profile is available
|
|
169
|
+
if (profile) {
|
|
170
|
+
try {
|
|
171
|
+
await sendLogToAPI(profile, projectName, descriptorName, record, fixture.fixtureUUID);
|
|
172
|
+
}
|
|
173
|
+
catch (e) {
|
|
174
|
+
console.error('Failed to send log to API:', e);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (error) {
|
|
178
|
+
throw new Error(error.message);
|
|
179
|
+
}
|
|
180
|
+
return result;
|
|
173
181
|
}
|
|
174
|
-
if (error) {
|
|
175
|
-
throw new Error(error.message);
|
|
176
|
-
}
|
|
177
|
-
return result;
|
|
178
182
|
});
|
|
179
183
|
exports.replay.setDescription(description);
|
package/dist/tasks/task/run.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// TASK: run
|
|
3
3
|
// Run this task with:
|
|
4
|
-
//
|
|
4
|
+
// most recursive call on the project
|
|
5
|
+
// forge task:run task:run
|
|
5
6
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
8
|
};
|
|
@@ -75,87 +76,91 @@ const boundaries = {
|
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
};
|
|
78
|
-
exports.run = (0, task_1.createTask)(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
profile = await loadCurrentProfile({});
|
|
90
|
-
}
|
|
91
|
-
catch (error) {
|
|
92
|
-
// Profile not found or not configured, continue without it
|
|
93
|
-
console.log('No profile found, logs will not be sent to remote API');
|
|
94
|
-
}
|
|
95
|
-
// Verify if log folder exists
|
|
96
|
-
const logFolderPath = path_1.default.join(process.cwd(), forge.paths.logs);
|
|
97
|
-
const logFolderExists = await verifyLogFolder(logFolderPath);
|
|
98
|
-
if (!logFolderExists) {
|
|
99
|
-
throw new Error(`Log folder "${logFolderPath}" does not exist`);
|
|
100
|
-
}
|
|
101
|
-
// Prepare paths
|
|
102
|
-
const logsPath = path_1.default.join(logFolderPath, descriptorName);
|
|
103
|
-
const entryPoint = path_1.default.join(process.cwd(), taskDescriptor.path);
|
|
104
|
-
const buildsPath = await ensureBuildsFolder();
|
|
105
|
-
const outputFile = path_1.default.join(buildsPath, `${descriptorName}.js`);
|
|
106
|
-
// Bundle the task
|
|
107
|
-
await bundleCreate({
|
|
108
|
-
entryPoint,
|
|
109
|
-
outputFile
|
|
110
|
-
});
|
|
111
|
-
// Load the bundled task
|
|
112
|
-
const bundle = await bundleLoad({
|
|
113
|
-
bundlePath: outputFile
|
|
114
|
-
});
|
|
115
|
-
// Get the task handler
|
|
116
|
-
const task = bundle[taskDescriptor.handler];
|
|
117
|
-
if (!task) {
|
|
118
|
-
throw new Error(`Handler "${taskDescriptor.handler}" not found in bundle`);
|
|
119
|
-
}
|
|
120
|
-
// Setup record tape
|
|
121
|
-
let tape = new record_tape_1.RecordTape({
|
|
122
|
-
path: logsPath
|
|
123
|
-
});
|
|
124
|
-
// load record tape
|
|
125
|
-
try {
|
|
126
|
-
await tape.load();
|
|
127
|
-
// Need to figure out how to handle the log length
|
|
128
|
-
// and other options for the RecordTape
|
|
129
|
-
// For now, we'll just keep the implementation simple
|
|
130
|
-
const maxLogLength = 9;
|
|
131
|
-
const log = tape.getLog();
|
|
132
|
-
if (log.length > maxLogLength) {
|
|
133
|
-
const newTape = new record_tape_1.RecordTape({
|
|
134
|
-
path: logsPath,
|
|
135
|
-
log: log.slice(-maxLogLength)
|
|
136
|
-
});
|
|
137
|
-
tape = newTape;
|
|
79
|
+
exports.run = (0, task_1.createTask)({
|
|
80
|
+
schema,
|
|
81
|
+
boundaries,
|
|
82
|
+
fn: async function ({ descriptorName, args }, { loadConf, bundleCreate, bundleLoad, verifyLogFolder, ensureBuildsFolder, loadCurrentProfile, sendLogToAPI }) {
|
|
83
|
+
// Load forge configuration
|
|
84
|
+
const forge = await loadConf({});
|
|
85
|
+
const taskDescriptor = forge.tasks[descriptorName];
|
|
86
|
+
const projectName = forge.project.name;
|
|
87
|
+
if (taskDescriptor === undefined) {
|
|
88
|
+
throw new Error('Task is not defined on forge.json');
|
|
138
89
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
// if the tape is not found, create a new one on saving
|
|
142
|
-
}
|
|
143
|
-
// Run the task with provided arguments
|
|
144
|
-
const [result, error, record] = await task.safeRun(args);
|
|
145
|
-
const logItem = tape.push(descriptorName, record, {
|
|
146
|
-
environment: 'cli'
|
|
147
|
-
});
|
|
148
|
-
await tape.save();
|
|
149
|
-
if (profile) {
|
|
90
|
+
// Try to load profile, but continue if not found
|
|
91
|
+
let profile = null;
|
|
150
92
|
try {
|
|
151
|
-
|
|
93
|
+
profile = await loadCurrentProfile({});
|
|
152
94
|
}
|
|
153
|
-
catch (
|
|
154
|
-
|
|
95
|
+
catch (error) {
|
|
96
|
+
// Profile not found or not configured, continue without it
|
|
97
|
+
console.log('No profile found, logs will not be sent to remote API');
|
|
155
98
|
}
|
|
99
|
+
// Verify if log folder exists
|
|
100
|
+
const logFolderPath = path_1.default.join(process.cwd(), forge.paths.logs);
|
|
101
|
+
const logFolderExists = await verifyLogFolder(logFolderPath);
|
|
102
|
+
if (!logFolderExists) {
|
|
103
|
+
throw new Error(`Log folder "${logFolderPath}" does not exist`);
|
|
104
|
+
}
|
|
105
|
+
// Prepare paths
|
|
106
|
+
const logsPath = path_1.default.join(logFolderPath, descriptorName);
|
|
107
|
+
const entryPoint = path_1.default.join(process.cwd(), taskDescriptor.path);
|
|
108
|
+
const buildsPath = await ensureBuildsFolder();
|
|
109
|
+
const outputFile = path_1.default.join(buildsPath, `${descriptorName}.js`);
|
|
110
|
+
// Bundle the task
|
|
111
|
+
await bundleCreate({
|
|
112
|
+
entryPoint,
|
|
113
|
+
outputFile
|
|
114
|
+
});
|
|
115
|
+
// Load the bundled task
|
|
116
|
+
const bundle = await bundleLoad({
|
|
117
|
+
bundlePath: outputFile
|
|
118
|
+
});
|
|
119
|
+
// Get the task handler
|
|
120
|
+
const task = bundle[taskDescriptor.handler];
|
|
121
|
+
if (!task) {
|
|
122
|
+
throw new Error(`Handler "${taskDescriptor.handler}" not found in bundle`);
|
|
123
|
+
}
|
|
124
|
+
// Setup record tape
|
|
125
|
+
let tape = new record_tape_1.RecordTape({
|
|
126
|
+
path: logsPath
|
|
127
|
+
});
|
|
128
|
+
// load record tape
|
|
129
|
+
try {
|
|
130
|
+
await tape.load();
|
|
131
|
+
// Need to figure out how to handle the log length
|
|
132
|
+
// and other options for the RecordTape
|
|
133
|
+
// For now, we'll just keep the implementation simple
|
|
134
|
+
const maxLogLength = 9;
|
|
135
|
+
const log = tape.getLog();
|
|
136
|
+
if (log.length > maxLogLength) {
|
|
137
|
+
const newTape = new record_tape_1.RecordTape({
|
|
138
|
+
path: logsPath,
|
|
139
|
+
log: log.slice(-maxLogLength)
|
|
140
|
+
});
|
|
141
|
+
tape = newTape;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (_error) {
|
|
145
|
+
// if the tape is not found, create a new one on saving
|
|
146
|
+
}
|
|
147
|
+
// Run the task with provided arguments
|
|
148
|
+
const [result, error, record] = await task.safeRun(args);
|
|
149
|
+
const logItem = tape.push(descriptorName, record, {
|
|
150
|
+
environment: 'cli'
|
|
151
|
+
});
|
|
152
|
+
await tape.save();
|
|
153
|
+
if (profile) {
|
|
154
|
+
try {
|
|
155
|
+
await sendLogToAPI(profile, projectName, descriptorName, logItem);
|
|
156
|
+
}
|
|
157
|
+
catch (e) {
|
|
158
|
+
console.error('Failed to send log to API:', e);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (error) {
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
156
165
|
}
|
|
157
|
-
if (error) {
|
|
158
|
-
throw error;
|
|
159
|
-
}
|
|
160
|
-
return result;
|
|
161
166
|
});
|
|
@@ -15,6 +15,7 @@ const expectedContent = `// TASK: newTask
|
|
|
15
15
|
import { createTask } from '@forgehive/task'
|
|
16
16
|
import { Schema } from '@forgehive/schema'
|
|
17
17
|
|
|
18
|
+
const name = 'sample:newTask'
|
|
18
19
|
const description = 'Add task description here'
|
|
19
20
|
|
|
20
21
|
const schema = new Schema({
|
|
@@ -27,10 +28,12 @@ const boundaries = {
|
|
|
27
28
|
// example: readFile: async (path: string) => fs.readFile(path, 'utf-8')
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
export const newTask = createTask(
|
|
31
|
+
export const newTask = createTask({
|
|
32
|
+
name,
|
|
33
|
+
description,
|
|
31
34
|
schema,
|
|
32
35
|
boundaries,
|
|
33
|
-
async function (argv, boundaries) {
|
|
36
|
+
fn: async function (argv, boundaries) {
|
|
34
37
|
console.log('input:', argv)
|
|
35
38
|
console.log('boundaries:', boundaries)
|
|
36
39
|
// Your task implementation goes here
|
|
@@ -38,13 +41,11 @@ export const newTask = createTask(
|
|
|
38
41
|
|
|
39
42
|
return status
|
|
40
43
|
}
|
|
41
|
-
)
|
|
44
|
+
})
|
|
42
45
|
|
|
43
|
-
newTask.setDescription(description)
|
|
44
46
|
`;
|
|
45
47
|
describe('Create task', () => {
|
|
46
48
|
let volume;
|
|
47
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
48
49
|
let fs;
|
|
49
50
|
let rootDir;
|
|
50
51
|
beforeEach(() => {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface SchemaProperty {
|
|
2
|
+
type: string;
|
|
3
|
+
optional?: boolean;
|
|
4
|
+
default?: string;
|
|
5
|
+
}
|
|
6
|
+
interface InputSchema {
|
|
7
|
+
type: string;
|
|
8
|
+
properties: Record<string, SchemaProperty>;
|
|
9
|
+
}
|
|
10
|
+
interface OutputType {
|
|
11
|
+
type: string;
|
|
12
|
+
properties?: Record<string, SchemaProperty>;
|
|
13
|
+
}
|
|
14
|
+
export interface TaskFingerprintOutput {
|
|
15
|
+
description?: string;
|
|
16
|
+
inputSchema: InputSchema;
|
|
17
|
+
outputType: OutputType;
|
|
18
|
+
boundaries: string[];
|
|
19
|
+
}
|
|
20
|
+
export declare function analyzeTaskFile(sourceCode: string, filePath: string, _expectedTaskName?: string): TaskFingerprintOutput | null;
|
|
21
|
+
export {};
|