@forgehive/forge-cli 0.3.1 → 0.3.3
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/tasks/task/invoke.d.ts +16 -0
- package/dist/tasks/task/invoke.js +76 -0
- package/dist/tasks/task/run.d.ts +8 -2
- package/dist/tasks/task/run.js +21 -15
- package/forge.json +4 -0
- package/package.json +9 -7
- package/src/runner.ts +10 -0
- package/src/tasks/task/invoke.ts +93 -0
- package/src/tasks/task/run.ts +21 -17
- package/src/tasks/types.ts +1 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type InvokeResult } from '@forgehive/hive-sdk';
|
|
2
|
+
import { type ForgeConf, type Profile } from '../types';
|
|
3
|
+
export declare const invoke: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
4
|
+
descriptorName: string;
|
|
5
|
+
json: string;
|
|
6
|
+
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
7
|
+
loadConf: (args: {}) => Promise<Promise<ForgeConf>>;
|
|
8
|
+
loadCurrentProfile: (args: {}) => Promise<Promise<Profile>>;
|
|
9
|
+
parseJSON: (jsonString: string) => Promise<unknown>;
|
|
10
|
+
invokeTask: (projectUuid: string, profile: Profile, taskName: string, payload: unknown) => Promise<InvokeResult | null>;
|
|
11
|
+
}>) => Promise<unknown>, {
|
|
12
|
+
loadConf: (args: {}) => Promise<Promise<ForgeConf>>;
|
|
13
|
+
loadCurrentProfile: (args: {}) => Promise<Promise<Profile>>;
|
|
14
|
+
parseJSON: (jsonString: string) => Promise<unknown>;
|
|
15
|
+
invokeTask: (projectUuid: string, profile: Profile, taskName: string, payload: unknown) => Promise<InvokeResult | null>;
|
|
16
|
+
}>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// TASK: invoke
|
|
3
|
+
// Run this task with:
|
|
4
|
+
// forge task:run task:invoke
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.invoke = void 0;
|
|
7
|
+
const task_1 = require("@forgehive/task");
|
|
8
|
+
const schema_1 = require("@forgehive/schema");
|
|
9
|
+
const hive_sdk_1 = require("@forgehive/hive-sdk");
|
|
10
|
+
const load_1 = require("../conf/load");
|
|
11
|
+
const loadCurrent_1 = require("../auth/loadCurrent");
|
|
12
|
+
const name = 'task:invoke';
|
|
13
|
+
const description = 'Invoke a deployed task remotely using the Hive API';
|
|
14
|
+
const schema = new schema_1.Schema({
|
|
15
|
+
descriptorName: schema_1.Schema.string(),
|
|
16
|
+
json: schema_1.Schema.string()
|
|
17
|
+
});
|
|
18
|
+
const boundaries = {
|
|
19
|
+
loadConf: load_1.load.asBoundary(),
|
|
20
|
+
loadCurrentProfile: loadCurrent_1.loadCurrent.asBoundary(),
|
|
21
|
+
parseJSON: async (jsonString) => {
|
|
22
|
+
try {
|
|
23
|
+
return JSON.parse(jsonString);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
throw new Error(`Invalid JSON: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
invokeTask: async (projectUuid, profile, taskName, payload) => {
|
|
30
|
+
const client = (0, hive_sdk_1.createHiveClient)({
|
|
31
|
+
projectUuid,
|
|
32
|
+
apiKey: profile.apiKey,
|
|
33
|
+
apiSecret: profile.apiSecret,
|
|
34
|
+
host: profile.url
|
|
35
|
+
});
|
|
36
|
+
console.log(`Invoking task: ${taskName}`);
|
|
37
|
+
console.log('Payload:', payload);
|
|
38
|
+
console.log(`Using profile: ${profile.name} (${profile.url})`);
|
|
39
|
+
return await client.invoke(taskName, payload);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
exports.invoke = (0, task_1.createTask)({
|
|
43
|
+
name,
|
|
44
|
+
description,
|
|
45
|
+
schema,
|
|
46
|
+
boundaries,
|
|
47
|
+
fn: async function ({ descriptorName, json }, { loadConf, loadCurrentProfile, parseJSON, invokeTask }) {
|
|
48
|
+
// Load forge configuration
|
|
49
|
+
const forge = await loadConf({});
|
|
50
|
+
const taskDescriptor = forge.tasks[descriptorName];
|
|
51
|
+
if (taskDescriptor === undefined) {
|
|
52
|
+
throw new Error(`Task "${descriptorName}" is not defined in forge.json`);
|
|
53
|
+
}
|
|
54
|
+
// Check for project UUID
|
|
55
|
+
if (!forge.project.uuid) {
|
|
56
|
+
throw new Error('Project UUID is not defined in forge.json. Please ensure your project has a UUID.');
|
|
57
|
+
}
|
|
58
|
+
// Load profile (required for invoke)
|
|
59
|
+
let profile;
|
|
60
|
+
try {
|
|
61
|
+
profile = await loadCurrentProfile({});
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
throw new Error('No profile found. Please authenticate first using: forge auth:add');
|
|
65
|
+
}
|
|
66
|
+
// Parse the JSON payload
|
|
67
|
+
const payload = await parseJSON(json);
|
|
68
|
+
// Invoke the task using the boundary
|
|
69
|
+
const result = await invokeTask(forge.project.uuid, profile, descriptorName, payload);
|
|
70
|
+
if ((0, hive_sdk_1.isInvokeError)(result)) {
|
|
71
|
+
throw new Error(`Task invocation failed: ${result.error}`);
|
|
72
|
+
}
|
|
73
|
+
console.log('Success! Task invoked successfully.');
|
|
74
|
+
return result?.responsePayload;
|
|
75
|
+
}
|
|
76
|
+
});
|
package/dist/tasks/task/run.d.ts
CHANGED
|
@@ -16,7 +16,10 @@ export declare const run: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
|
16
16
|
}) => Promise<Promise<any>>;
|
|
17
17
|
verifyLogFolder: (logsPath: string) => Promise<boolean>;
|
|
18
18
|
ensureBuildsFolder: () => Promise<string>;
|
|
19
|
-
sendLogToAPI: (profile: Profile, projectName: string, taskName: string, logItem:
|
|
19
|
+
sendLogToAPI: (profile: Profile, projectName: string, taskName: string, logItem: {
|
|
20
|
+
input: unknown;
|
|
21
|
+
metadata?: Record<string, string>;
|
|
22
|
+
}) => Promise<boolean>;
|
|
20
23
|
}>) => Promise<any>, {
|
|
21
24
|
loadConf: (args: {}) => Promise<Promise<ForgeConf>>;
|
|
22
25
|
loadCurrentProfile: (args: {}) => Promise<Promise<Profile>>;
|
|
@@ -31,5 +34,8 @@ export declare const run: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
|
31
34
|
}) => Promise<Promise<any>>;
|
|
32
35
|
verifyLogFolder: (logsPath: string) => Promise<boolean>;
|
|
33
36
|
ensureBuildsFolder: () => Promise<string>;
|
|
34
|
-
sendLogToAPI: (profile: Profile, projectName: string, taskName: string, logItem:
|
|
37
|
+
sendLogToAPI: (profile: Profile, projectName: string, taskName: string, logItem: {
|
|
38
|
+
input: unknown;
|
|
39
|
+
metadata?: Record<string, string>;
|
|
40
|
+
}) => Promise<boolean>;
|
|
35
41
|
}>;
|
package/dist/tasks/task/run.js
CHANGED
|
@@ -11,10 +11,10 @@ exports.run = void 0;
|
|
|
11
11
|
const path_1 = __importDefault(require("path"));
|
|
12
12
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
13
13
|
const os_1 = __importDefault(require("os"));
|
|
14
|
-
const axios_1 = __importDefault(require("axios"));
|
|
15
14
|
const task_1 = require("@forgehive/task");
|
|
16
15
|
const schema_1 = require("@forgehive/schema");
|
|
17
16
|
const record_tape_1 = require("@forgehive/record-tape");
|
|
17
|
+
const hive_sdk_1 = require("@forgehive/hive-sdk");
|
|
18
18
|
const create_1 = require("../bundle/create");
|
|
19
19
|
const load_1 = require("../bundle/load");
|
|
20
20
|
const load_2 = require("../conf/load");
|
|
@@ -53,25 +53,31 @@ const boundaries = {
|
|
|
53
53
|
},
|
|
54
54
|
sendLogToAPI: async (profile, projectName, taskName, logItem) => {
|
|
55
55
|
try {
|
|
56
|
-
const
|
|
57
|
-
const authToken = `${profile.apiKey}:${profile.apiSecret}`;
|
|
58
|
-
await axios_1.default.post(logsUrl, {
|
|
56
|
+
const config = {
|
|
59
57
|
projectName,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
'Content-Type': 'application/json'
|
|
58
|
+
apiKey: profile.apiKey,
|
|
59
|
+
apiSecret: profile.apiSecret,
|
|
60
|
+
host: profile.url,
|
|
61
|
+
metadata: {
|
|
62
|
+
environment: 'cli'
|
|
66
63
|
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
};
|
|
65
|
+
const client = new hive_sdk_1.HiveLogClient(config);
|
|
66
|
+
const result = await client.sendLog(taskName, logItem);
|
|
67
|
+
if (result === 'success') {
|
|
68
|
+
console.log('===============================================');
|
|
69
|
+
console.log('Log sent to API... ', profile.name, profile.url);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
console.error('Failed to send log to API:', profile.url);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
71
76
|
}
|
|
72
77
|
catch (e) {
|
|
78
|
+
console.error('Failed to send log to API:', profile.url);
|
|
73
79
|
const error = e;
|
|
74
|
-
console.error('
|
|
80
|
+
console.error('Error:', error.message);
|
|
75
81
|
return false;
|
|
76
82
|
}
|
|
77
83
|
}
|
package/forge.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgehive/forge-cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "TypeScript CLI application",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@forgehive/
|
|
14
|
-
"@forgehive/
|
|
13
|
+
"@forgehive/hive-sdk": "^0.0.3",
|
|
14
|
+
"@forgehive/record-tape": "^0.2.2",
|
|
15
|
+
"@forgehive/runner": "^0.2.2",
|
|
15
16
|
"@forgehive/schema": "^0.1.4",
|
|
16
|
-
"@forgehive/task": "^0.2.
|
|
17
|
+
"@forgehive/task": "^0.2.2",
|
|
17
18
|
"esbuild": "^0.25.0",
|
|
18
19
|
"handlebars": "^4.7.8",
|
|
19
20
|
"minimist": "^1.2.8"
|
|
@@ -26,10 +27,11 @@
|
|
|
26
27
|
"esbuild": "^0.25.0",
|
|
27
28
|
"handlebars": "^4.7.8",
|
|
28
29
|
"minimist": "^1.2.8",
|
|
30
|
+
"@forgehive/hive-sdk": "0.0.3",
|
|
31
|
+
"@forgehive/runner": "0.2.2",
|
|
32
|
+
"@forgehive/record-tape": "0.2.2",
|
|
29
33
|
"@forgehive/schema": "0.1.4",
|
|
30
|
-
"@forgehive/
|
|
31
|
-
"@forgehive/record-tape": "0.2.1",
|
|
32
|
-
"@forgehive/task": "0.2.1"
|
|
34
|
+
"@forgehive/task": "0.2.2"
|
|
33
35
|
},
|
|
34
36
|
"devDependencies": {
|
|
35
37
|
"@types/archiver": "^6.0.3",
|
package/src/runner.ts
CHANGED
|
@@ -18,6 +18,8 @@ import { replay as replayTask } from './tasks/task/replay'
|
|
|
18
18
|
import { list as listTasks } from './tasks/task/list'
|
|
19
19
|
import { describe as describeTask } from './tasks/task/describe'
|
|
20
20
|
import { fingerprint as fingerprintTask } from './tasks/task/fingerprint'
|
|
21
|
+
import { invoke as invokeTask } from './tasks/task/invoke'
|
|
22
|
+
|
|
21
23
|
|
|
22
24
|
import { create as createRunner } from './tasks/runner/create'
|
|
23
25
|
import { remove as removeRunner } from './tasks/runner/remove'
|
|
@@ -58,6 +60,7 @@ runner.load('task:replay', replayTask)
|
|
|
58
60
|
runner.load('task:list', listTasks)
|
|
59
61
|
runner.load('task:describe', describeTask)
|
|
60
62
|
runner.load('task:fingerprint', fingerprintTask)
|
|
63
|
+
runner.load('task:invoke', invokeTask)
|
|
61
64
|
|
|
62
65
|
// Runner commands
|
|
63
66
|
runner.load('runner:create', createRunner)
|
|
@@ -114,6 +117,13 @@ runner.setHandler(async (data: ParsedArgs): Promise<unknown> => {
|
|
|
114
117
|
descriptorName: action,
|
|
115
118
|
uuid
|
|
116
119
|
})
|
|
120
|
+
} else if (taskName === 'task:invoke') {
|
|
121
|
+
const { json } = args as { json: string }
|
|
122
|
+
|
|
123
|
+
result = await task.run({
|
|
124
|
+
descriptorName: action,
|
|
125
|
+
json
|
|
126
|
+
})
|
|
117
127
|
} else if (taskName === 'task:replay') {
|
|
118
128
|
const { path, cache } = args as { path: string, cache: string }
|
|
119
129
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// TASK: invoke
|
|
2
|
+
// Run this task with:
|
|
3
|
+
// forge task:run task:invoke
|
|
4
|
+
|
|
5
|
+
import { createTask } from '@forgehive/task'
|
|
6
|
+
import { Schema } from '@forgehive/schema'
|
|
7
|
+
import { createHiveClient, isInvokeError, type InvokeResult } from '@forgehive/hive-sdk'
|
|
8
|
+
|
|
9
|
+
import { load as loadConf } from '../conf/load'
|
|
10
|
+
import { loadCurrent as loadCurrentProfile } from '../auth/loadCurrent'
|
|
11
|
+
import { type ForgeConf, type Profile } from '../types'
|
|
12
|
+
|
|
13
|
+
const name = 'task:invoke'
|
|
14
|
+
const description = 'Invoke a deployed task remotely using the Hive API'
|
|
15
|
+
|
|
16
|
+
const schema = new Schema({
|
|
17
|
+
descriptorName: Schema.string(),
|
|
18
|
+
json: Schema.string()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const boundaries = {
|
|
22
|
+
loadConf: loadConf.asBoundary(),
|
|
23
|
+
loadCurrentProfile: loadCurrentProfile.asBoundary(),
|
|
24
|
+
parseJSON: async (jsonString: string): Promise<unknown> => {
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(jsonString)
|
|
27
|
+
} catch (error) {
|
|
28
|
+
throw new Error(`Invalid JSON: ${error instanceof Error ? error.message : 'Unknown error'}`)
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
invokeTask: async (
|
|
32
|
+
projectUuid: string,
|
|
33
|
+
profile: Profile,
|
|
34
|
+
taskName: string,
|
|
35
|
+
payload: unknown
|
|
36
|
+
): Promise<InvokeResult | null> => {
|
|
37
|
+
const client = createHiveClient({
|
|
38
|
+
projectUuid,
|
|
39
|
+
apiKey: profile.apiKey,
|
|
40
|
+
apiSecret: profile.apiSecret,
|
|
41
|
+
host: profile.url
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
console.log(`Invoking task: ${taskName}`)
|
|
45
|
+
console.log('Payload:', payload)
|
|
46
|
+
console.log(`Using profile: ${profile.name} (${profile.url})`)
|
|
47
|
+
|
|
48
|
+
return await client.invoke(taskName, payload)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const invoke = createTask({
|
|
53
|
+
name,
|
|
54
|
+
description,
|
|
55
|
+
schema,
|
|
56
|
+
boundaries,
|
|
57
|
+
fn: async function ({ descriptorName, json }, { loadConf, loadCurrentProfile, parseJSON, invokeTask }) {
|
|
58
|
+
// Load forge configuration
|
|
59
|
+
const forge: ForgeConf = await loadConf({})
|
|
60
|
+
const taskDescriptor = forge.tasks[descriptorName as keyof typeof forge.tasks]
|
|
61
|
+
|
|
62
|
+
if (taskDescriptor === undefined) {
|
|
63
|
+
throw new Error(`Task "${descriptorName}" is not defined in forge.json`)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check for project UUID
|
|
67
|
+
if (!forge.project.uuid) {
|
|
68
|
+
throw new Error('Project UUID is not defined in forge.json. Please ensure your project has a UUID.')
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Load profile (required for invoke)
|
|
72
|
+
let profile: Profile
|
|
73
|
+
try {
|
|
74
|
+
profile = await loadCurrentProfile({})
|
|
75
|
+
} catch (error) {
|
|
76
|
+
throw new Error('No profile found. Please authenticate first using: forge auth:add')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Parse the JSON payload
|
|
80
|
+
const payload = await parseJSON(json)
|
|
81
|
+
|
|
82
|
+
// Invoke the task using the boundary
|
|
83
|
+
const result = await invokeTask(forge.project.uuid, profile, descriptorName, payload)
|
|
84
|
+
|
|
85
|
+
if (isInvokeError(result)) {
|
|
86
|
+
throw new Error(`Task invocation failed: ${result.error}`)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log('Success! Task invoked successfully.')
|
|
90
|
+
return result?.responsePayload
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
|
package/src/tasks/task/run.ts
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
import path from 'path'
|
|
7
7
|
import fs from 'fs/promises'
|
|
8
8
|
import os from 'os'
|
|
9
|
-
import axios from 'axios'
|
|
10
9
|
|
|
11
10
|
import { createTask } from '@forgehive/task'
|
|
12
11
|
import { Schema } from '@forgehive/schema'
|
|
13
12
|
import { RecordTape } from '@forgehive/record-tape'
|
|
13
|
+
import { HiveLogClient } from '@forgehive/hive-sdk'
|
|
14
14
|
|
|
15
15
|
import { create as bundleCreate } from '../bundle/create'
|
|
16
16
|
import { load as bundleLoad } from '../bundle/load'
|
|
@@ -51,29 +51,33 @@ const boundaries = {
|
|
|
51
51
|
|
|
52
52
|
return buildsPath
|
|
53
53
|
},
|
|
54
|
-
sendLogToAPI: async (profile: Profile, projectName: string, taskName: string, logItem: unknown): Promise<boolean> => {
|
|
54
|
+
sendLogToAPI: async (profile: Profile, projectName: string, taskName: string, logItem: { input: unknown; metadata?: Record<string, string> }): Promise<boolean> => {
|
|
55
55
|
try {
|
|
56
|
-
const
|
|
57
|
-
const authToken = `${profile.apiKey}:${profile.apiSecret}`
|
|
58
|
-
|
|
59
|
-
await axios.post(logsUrl, {
|
|
56
|
+
const config = {
|
|
60
57
|
projectName,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
'Content-Type': 'application/json'
|
|
58
|
+
apiKey: profile.apiKey,
|
|
59
|
+
apiSecret: profile.apiSecret,
|
|
60
|
+
host: profile.url,
|
|
61
|
+
metadata: {
|
|
62
|
+
environment: 'cli'
|
|
67
63
|
}
|
|
68
|
-
}
|
|
64
|
+
}
|
|
69
65
|
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
const client = new HiveLogClient(config)
|
|
67
|
+
const result = await client.sendLog(taskName, logItem)
|
|
72
68
|
|
|
73
|
-
|
|
69
|
+
if (result === 'success') {
|
|
70
|
+
console.log('===============================================')
|
|
71
|
+
console.log('Log sent to API... ', profile.name, profile.url)
|
|
72
|
+
return true
|
|
73
|
+
} else {
|
|
74
|
+
console.error('Failed to send log to API:', profile.url)
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
74
77
|
} catch (e) {
|
|
78
|
+
console.error('Failed to send log to API:', profile.url)
|
|
75
79
|
const error = e as Error
|
|
76
|
-
console.error('
|
|
80
|
+
console.error('Error:', error.message)
|
|
77
81
|
return false
|
|
78
82
|
}
|
|
79
83
|
}
|