@forgehive/forge-cli 0.3.18 → 0.5.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 +68 -0
- package/dist/tasks/auth/add.d.ts +2 -2
- package/dist/tasks/auth/add.js +4 -4
- package/dist/tasks/auth/clear.d.ts +3 -3
- package/dist/tasks/auth/list.d.ts +3 -3
- package/dist/tasks/auth/load.d.ts +1 -1
- package/dist/tasks/auth/loadCurrent.d.ts +3 -3
- package/dist/tasks/auth/remove.d.ts +2 -2
- package/dist/tasks/auth/remove.js +1 -1
- package/dist/tasks/auth/switch.d.ts +2 -2
- package/dist/tasks/auth/switch.js +1 -1
- package/dist/tasks/bundle/create.d.ts +2 -2
- package/dist/tasks/bundle/create.js +2 -2
- package/dist/tasks/bundle/fingerprint.d.ts +2 -2
- package/dist/tasks/bundle/fingerprint.js +2 -2
- package/dist/tasks/bundle/load.js +1 -1
- package/dist/tasks/bundle/zip.js +4 -4
- package/dist/tasks/conf/info.d.ts +5 -5
- package/dist/tasks/conf/load.d.ts +1 -1
- package/dist/tasks/docs/download.js +2 -2
- package/dist/tasks/fixture/download.d.ts +4 -4
- package/dist/tasks/fixture/download.js +1 -1
- package/dist/tasks/init.js +1 -1
- package/dist/tasks/project/create.d.ts +4 -4
- package/dist/tasks/project/create.js +2 -2
- package/dist/tasks/project/link.d.ts +4 -4
- package/dist/tasks/project/link.js +1 -1
- package/dist/tasks/project/sync.d.ts +5 -5
- package/dist/tasks/project/unlink.d.ts +3 -3
- package/dist/tasks/runner/bundle.d.ts +2 -2
- package/dist/tasks/runner/bundle.js +2 -2
- package/dist/tasks/runner/create.d.ts +2 -2
- package/dist/tasks/runner/create.js +1 -1
- package/dist/tasks/runner/remove.d.ts +2 -2
- package/dist/tasks/runner/remove.js +1 -1
- package/dist/tasks/task/createTask.d.ts +4 -4
- package/dist/tasks/task/createTask.js +3 -2
- package/dist/tasks/task/describe.d.ts +2 -2
- package/dist/tasks/task/describe.js +1 -1
- package/dist/tasks/task/download.d.ts +4 -4
- package/dist/tasks/task/download.js +2 -2
- package/dist/tasks/task/fingerprint.d.ts +2 -2
- package/dist/tasks/task/fingerprint.js +1 -1
- package/dist/tasks/task/invoke.d.ts +4 -4
- package/dist/tasks/task/invoke.js +2 -2
- package/dist/tasks/task/list.d.ts +3 -3
- package/dist/tasks/task/publish.d.ts +4 -4
- package/dist/tasks/task/publish.js +1 -1
- package/dist/tasks/task/remove.d.ts +2 -2
- package/dist/tasks/task/remove.js +1 -1
- package/dist/tasks/task/replay.d.ts +5 -5
- package/dist/tasks/task/replay.js +3 -3
- package/dist/tasks/task/run.d.ts +4 -4
- package/dist/tasks/task/run.js +2 -2
- package/dist/test/tasks/create.test.js +3 -2
- package/dist/utils/taskAnalysis.d.ts +6 -0
- package/dist/utils/taskAnalysis.js +82 -41
- package/package.json +11 -11
- package/pnpm-workspace.yaml +2 -0
- package/src/runner.ts +77 -0
- package/src/tasks/auth/add.ts +4 -4
- package/src/tasks/auth/remove.ts +1 -1
- package/src/tasks/auth/switch.ts +1 -1
- package/src/tasks/bundle/create.ts +2 -2
- package/src/tasks/bundle/fingerprint.ts +2 -2
- package/src/tasks/bundle/load.ts +1 -1
- package/src/tasks/bundle/zip.ts +4 -4
- package/src/tasks/docs/download.ts +2 -2
- package/src/tasks/fixture/download.ts +1 -1
- package/src/tasks/init.ts +1 -1
- package/src/tasks/project/create.ts +2 -2
- package/src/tasks/project/link.ts +1 -1
- package/src/tasks/runner/bundle.ts +2 -2
- package/src/tasks/runner/create.ts +1 -1
- package/src/tasks/runner/remove.ts +1 -1
- package/src/tasks/task/createTask.ts +3 -2
- package/src/tasks/task/describe.ts +1 -1
- package/src/tasks/task/download.ts +2 -2
- package/src/tasks/task/fingerprint.ts +1 -1
- package/src/tasks/task/invoke.ts +2 -2
- package/src/tasks/task/publish.ts +1 -1
- package/src/tasks/task/remove.ts +1 -1
- package/src/tasks/task/replay.ts +3 -3
- package/src/tasks/task/run.ts +2 -2
- package/src/test/tasks/create.test.ts +3 -2
- package/src/utils/taskAnalysis.ts +90 -41
- package/logs/bundle:fingerprint.log +0 -1
- package/logs/task:fingerprint.log +0 -10
- package/logs/task:list.log +0 -1
- package/logs/test:guidance.log +0 -1
- package/logs/test:uuid.log +0 -1
- package/logs/test:uuidCheck.log +0 -1
|
@@ -2,7 +2,7 @@ import { type ForgeConf } from '../types';
|
|
|
2
2
|
export declare const describe: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
3
3
|
descriptorName: string;
|
|
4
4
|
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
5
|
-
loadConf: (args:
|
|
5
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
6
6
|
bundleCreate: (args: {
|
|
7
7
|
entryPoint: string;
|
|
8
8
|
outputFile: string;
|
|
@@ -21,7 +21,7 @@ export declare const describe: import("@forgehive/task").TaskInstanceType<(argv:
|
|
|
21
21
|
schema: any;
|
|
22
22
|
boundaries: string[];
|
|
23
23
|
}>, {
|
|
24
|
-
loadConf: (args:
|
|
24
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
25
25
|
bundleCreate: (args: {
|
|
26
26
|
entryPoint: string;
|
|
27
27
|
outputFile: string;
|
|
@@ -17,7 +17,7 @@ const load_1 = require("../bundle/load");
|
|
|
17
17
|
const load_2 = require("../conf/load");
|
|
18
18
|
const description = 'Describe a task with detailed information about its schema, boundaries and configuration';
|
|
19
19
|
const schema = new schema_1.Schema({
|
|
20
|
-
descriptorName: schema_1.Schema.string()
|
|
20
|
+
descriptorName: schema_1.Schema.string().describe('The task descriptor name to describe (e.g. domain:taskName)')
|
|
21
21
|
});
|
|
22
22
|
const boundaries = {
|
|
23
23
|
loadConf: load_2.load.asBoundary(),
|
|
@@ -3,9 +3,9 @@ export declare const download: import("@forgehive/task").TaskInstanceType<(argv:
|
|
|
3
3
|
descriptorName: string;
|
|
4
4
|
uuid: string;
|
|
5
5
|
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
6
|
-
loadCurrentProfile: (args:
|
|
6
|
+
loadCurrentProfile: (args: Record<string, unknown>) => Promise<Promise<Profile>>;
|
|
7
7
|
downloadTask: (uuid: string, profile: Profile) => Promise<any>;
|
|
8
|
-
loadConf: (args:
|
|
8
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
9
9
|
getCwd: () => Promise<string>;
|
|
10
10
|
parseTaskName: (taskDescriptor: string) => Promise<{
|
|
11
11
|
descriptor: string;
|
|
@@ -40,9 +40,9 @@ export declare const download: import("@forgehive/task").TaskInstanceType<(argv:
|
|
|
40
40
|
error?: undefined;
|
|
41
41
|
message?: undefined;
|
|
42
42
|
}>, {
|
|
43
|
-
loadCurrentProfile: (args:
|
|
43
|
+
loadCurrentProfile: (args: Record<string, unknown>) => Promise<Promise<Profile>>;
|
|
44
44
|
downloadTask: (uuid: string, profile: Profile) => Promise<any>;
|
|
45
|
-
loadConf: (args:
|
|
45
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
46
46
|
getCwd: () => Promise<string>;
|
|
47
47
|
parseTaskName: (taskDescriptor: string) => Promise<{
|
|
48
48
|
descriptor: string;
|
|
@@ -16,8 +16,8 @@ const camelCase_1 = require("../../utils/camelCase");
|
|
|
16
16
|
const load_1 = require("../conf/load");
|
|
17
17
|
const loadCurrent_1 = require("../auth/loadCurrent");
|
|
18
18
|
const schema = new schema_1.Schema({
|
|
19
|
-
descriptorName: schema_1.Schema.string(),
|
|
20
|
-
uuid: schema_1.Schema.string()
|
|
19
|
+
descriptorName: schema_1.Schema.string().describe('The task descriptor name (e.g. domain:taskName)'),
|
|
20
|
+
uuid: schema_1.Schema.string().describe('The UUID of the task version to download')
|
|
21
21
|
});
|
|
22
22
|
const boundaries = {
|
|
23
23
|
loadCurrentProfile: loadCurrent_1.loadCurrent.asBoundary(),
|
|
@@ -2,7 +2,7 @@ export declare const fingerprint: import("@forgehive/task").TaskInstanceType<(ar
|
|
|
2
2
|
descriptorName: string;
|
|
3
3
|
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
4
4
|
getCwd: () => Promise<string>;
|
|
5
|
-
loadConf: (args:
|
|
5
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<import("../types").ForgeConf>>;
|
|
6
6
|
bundleFingerprint: (args: {
|
|
7
7
|
descriptorName: string;
|
|
8
8
|
filePath?: string | undefined;
|
|
@@ -40,7 +40,7 @@ export declare const fingerprint: import("@forgehive/task").TaskInstanceType<(ar
|
|
|
40
40
|
};
|
|
41
41
|
}>, {
|
|
42
42
|
getCwd: () => Promise<string>;
|
|
43
|
-
loadConf: (args:
|
|
43
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<import("../types").ForgeConf>>;
|
|
44
44
|
bundleFingerprint: (args: {
|
|
45
45
|
descriptorName: string;
|
|
46
46
|
filePath?: string | undefined;
|
|
@@ -14,7 +14,7 @@ const load_1 = require("../conf/load");
|
|
|
14
14
|
const fingerprint_1 = require("../bundle/fingerprint");
|
|
15
15
|
const description = 'Analyze a specific task and generate detailed fingerprint without bundling';
|
|
16
16
|
const schema = new schema_1.Schema({
|
|
17
|
-
descriptorName: schema_1.Schema.string()
|
|
17
|
+
descriptorName: schema_1.Schema.string().describe('The task descriptor name to fingerprint (e.g. domain:taskName)')
|
|
18
18
|
});
|
|
19
19
|
const boundaries = {
|
|
20
20
|
getCwd: async () => {
|
|
@@ -4,13 +4,13 @@ export declare const invoke: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
|
4
4
|
descriptorName: string;
|
|
5
5
|
json: string;
|
|
6
6
|
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
7
|
-
loadConf: (args:
|
|
8
|
-
loadCurrentProfile: (args:
|
|
7
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
8
|
+
loadCurrentProfile: (args: Record<string, unknown>) => Promise<Promise<Profile>>;
|
|
9
9
|
parseJSON: (jsonString: string) => Promise<unknown>;
|
|
10
10
|
invokeTask: (projectUuid: string, taskUuid: string, profile: Profile, taskName: string, payload: unknown) => Promise<InvokeResult | null>;
|
|
11
11
|
}>) => Promise<unknown>, {
|
|
12
|
-
loadConf: (args:
|
|
13
|
-
loadCurrentProfile: (args:
|
|
12
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
13
|
+
loadCurrentProfile: (args: Record<string, unknown>) => Promise<Promise<Profile>>;
|
|
14
14
|
parseJSON: (jsonString: string) => Promise<unknown>;
|
|
15
15
|
invokeTask: (projectUuid: string, taskUuid: string, profile: Profile, taskName: string, payload: unknown) => Promise<InvokeResult | null>;
|
|
16
16
|
}>;
|
|
@@ -12,8 +12,8 @@ const loadCurrent_1 = require("../auth/loadCurrent");
|
|
|
12
12
|
const name = 'task:invoke';
|
|
13
13
|
const description = 'Invoke a deployed task remotely using the Hive API';
|
|
14
14
|
const schema = new schema_1.Schema({
|
|
15
|
-
descriptorName: schema_1.Schema.string(),
|
|
16
|
-
json: schema_1.Schema.string()
|
|
15
|
+
descriptorName: schema_1.Schema.string().describe('The task descriptor name (e.g. domain:taskName)'),
|
|
16
|
+
json: schema_1.Schema.string().describe('JSON string of arguments to pass to the task')
|
|
17
17
|
});
|
|
18
18
|
const boundaries = {
|
|
19
19
|
loadConf: load_1.load.asBoundary(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ForgeConf } from '../types';
|
|
2
|
-
export declare const list: import("@forgehive/task").TaskInstanceType<(argv:
|
|
3
|
-
loadConf: (args:
|
|
2
|
+
export declare const list: import("@forgehive/task").TaskInstanceType<(argv: Record<string, unknown>, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
3
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
4
4
|
}>) => Promise<{
|
|
5
5
|
taskCount: number;
|
|
6
6
|
tasks: never[];
|
|
@@ -8,5 +8,5 @@ export declare const list: import("@forgehive/task").TaskInstanceType<(argv: {},
|
|
|
8
8
|
taskCount: number;
|
|
9
9
|
tasks?: undefined;
|
|
10
10
|
}>, {
|
|
11
|
-
loadConf: (args:
|
|
11
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
12
12
|
}>;
|
|
@@ -4,8 +4,8 @@ export declare const publish: import("@forgehive/task").TaskInstanceType<(argv:
|
|
|
4
4
|
descriptorName: string;
|
|
5
5
|
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
6
6
|
getCwd: () => Promise<string>;
|
|
7
|
-
loadConf: (args:
|
|
8
|
-
loadCurrentProfile: (args:
|
|
7
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<import("../types").ForgeConf>>;
|
|
8
|
+
loadCurrentProfile: (args: Record<string, unknown>) => Promise<Promise<Profile>>;
|
|
9
9
|
bundleCreate: (args: {
|
|
10
10
|
entryPoint: string;
|
|
11
11
|
outputFile: string;
|
|
@@ -59,8 +59,8 @@ export declare const publish: import("@forgehive/task").TaskInstanceType<(argv:
|
|
|
59
59
|
fingerprint: boolean;
|
|
60
60
|
}>, {
|
|
61
61
|
getCwd: () => Promise<string>;
|
|
62
|
-
loadConf: (args:
|
|
63
|
-
loadCurrentProfile: (args:
|
|
62
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<import("../types").ForgeConf>>;
|
|
63
|
+
loadCurrentProfile: (args: Record<string, unknown>) => Promise<Promise<Profile>>;
|
|
64
64
|
bundleCreate: (args: {
|
|
65
65
|
entryPoint: string;
|
|
66
66
|
outputFile: string;
|
|
@@ -20,7 +20,7 @@ const zip_1 = require("../bundle/zip");
|
|
|
20
20
|
const fingerprint_1 = require("../bundle/fingerprint");
|
|
21
21
|
const loadCurrent_1 = require("../auth/loadCurrent");
|
|
22
22
|
const schema = new schema_1.Schema({
|
|
23
|
-
descriptorName: schema_1.Schema.string()
|
|
23
|
+
descriptorName: schema_1.Schema.string().describe('The task descriptor name to publish (e.g. domain:taskName)')
|
|
24
24
|
});
|
|
25
25
|
const boundaries = {
|
|
26
26
|
getCwd: async () => {
|
|
@@ -2,14 +2,14 @@ import { type ForgeConf } from '../types';
|
|
|
2
2
|
export declare const remove: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
3
3
|
descriptorName: string;
|
|
4
4
|
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
5
|
-
loadConf: (args:
|
|
5
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
6
6
|
persistConf: (forge: ForgeConf) => Promise<void>;
|
|
7
7
|
deleteFile: (filePath: string) => Promise<void>;
|
|
8
8
|
}>) => Promise<{
|
|
9
9
|
status: string;
|
|
10
10
|
message: string;
|
|
11
11
|
}>, {
|
|
12
|
-
loadConf: (args:
|
|
12
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
13
13
|
persistConf: (forge: ForgeConf) => Promise<void>;
|
|
14
14
|
deleteFile: (filePath: string) => Promise<void>;
|
|
15
15
|
}>;
|
|
@@ -13,7 +13,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
13
13
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
14
14
|
const load_1 = require("../conf/load");
|
|
15
15
|
const schema = new schema_1.Schema({
|
|
16
|
-
descriptorName: schema_1.Schema.string()
|
|
16
|
+
descriptorName: schema_1.Schema.string().describe('The task descriptor name to remove (e.g. domain:taskName)')
|
|
17
17
|
});
|
|
18
18
|
const boundaries = {
|
|
19
19
|
loadConf: load_1.load.asBoundary(),
|
|
@@ -11,13 +11,13 @@ interface Fixture {
|
|
|
11
11
|
context: Record<string, unknown>;
|
|
12
12
|
}
|
|
13
13
|
export declare const replay: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
14
|
-
path: string;
|
|
15
14
|
descriptorName: string;
|
|
15
|
+
path: string;
|
|
16
16
|
cache?: string | undefined;
|
|
17
17
|
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
18
18
|
readFixture: (filePath: string) => Promise<Fixture>;
|
|
19
|
-
loadConf: (args:
|
|
20
|
-
loadCurrentProfile: (args:
|
|
19
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
20
|
+
loadCurrentProfile: (args: Record<string, unknown>) => Promise<Promise<Profile>>;
|
|
21
21
|
bundleCreate: (args: {
|
|
22
22
|
entryPoint: string;
|
|
23
23
|
outputFile: string;
|
|
@@ -35,8 +35,8 @@ export declare const replay: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
|
35
35
|
}>;
|
|
36
36
|
}>) => Promise<any>, {
|
|
37
37
|
readFixture: (filePath: string) => Promise<Fixture>;
|
|
38
|
-
loadConf: (args:
|
|
39
|
-
loadCurrentProfile: (args:
|
|
38
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
39
|
+
loadCurrentProfile: (args: Record<string, unknown>) => Promise<Promise<Profile>>;
|
|
40
40
|
bundleCreate: (args: {
|
|
41
41
|
entryPoint: string;
|
|
42
42
|
outputFile: string;
|
|
@@ -19,9 +19,9 @@ const load_2 = require("../conf/load");
|
|
|
19
19
|
const loadCurrent_1 = require("../auth/loadCurrent");
|
|
20
20
|
const description = 'Replay a task execution from a specified path';
|
|
21
21
|
const schema = new schema_1.Schema({
|
|
22
|
-
descriptorName: schema_1.Schema.string(),
|
|
23
|
-
path: schema_1.Schema.string(),
|
|
24
|
-
cache: schema_1.Schema.string().optional()
|
|
22
|
+
descriptorName: schema_1.Schema.string().describe('The task descriptor name to replay (e.g. domain:taskName)'),
|
|
23
|
+
path: schema_1.Schema.string().describe('Path to the execution log fixture to replay'),
|
|
24
|
+
cache: schema_1.Schema.string().describe('Cache mode for boundaries during replay').optional()
|
|
25
25
|
});
|
|
26
26
|
const boundaries = {
|
|
27
27
|
readFixture: async (filePath) => {
|
package/dist/tasks/task/run.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ export declare const run: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
|
4
4
|
descriptorName: string;
|
|
5
5
|
args: Record<string, string | number | boolean>;
|
|
6
6
|
}, boundaries: import("@forgehive/task").WrappedBoundaries<{
|
|
7
|
-
loadConf: (args:
|
|
8
|
-
loadCurrentProfile: (args:
|
|
7
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
8
|
+
loadCurrentProfile: (args: Record<string, unknown>) => Promise<Promise<Profile>>;
|
|
9
9
|
bundleCreate: (args: {
|
|
10
10
|
entryPoint: string;
|
|
11
11
|
outputFile: string;
|
|
@@ -24,8 +24,8 @@ export declare const run: import("@forgehive/task").TaskInstanceType<(argv: {
|
|
|
24
24
|
skipRemoteLog?: boolean;
|
|
25
25
|
}>;
|
|
26
26
|
}>) => Promise<any>, {
|
|
27
|
-
loadConf: (args:
|
|
28
|
-
loadCurrentProfile: (args:
|
|
27
|
+
loadConf: (args: Record<string, unknown>) => Promise<Promise<ForgeConf>>;
|
|
28
|
+
loadCurrentProfile: (args: Record<string, unknown>) => Promise<Promise<Profile>>;
|
|
29
29
|
bundleCreate: (args: {
|
|
30
30
|
entryPoint: string;
|
|
31
31
|
outputFile: string;
|
package/dist/tasks/task/run.js
CHANGED
|
@@ -22,8 +22,8 @@ const loadCurrent_1 = require("../auth/loadCurrent");
|
|
|
22
22
|
// For now, we'll use a simple schema without the record type
|
|
23
23
|
// TODO: Use Schema.record once it's properly built and available
|
|
24
24
|
const schema = new schema_1.Schema({
|
|
25
|
-
descriptorName: schema_1.Schema.string(),
|
|
26
|
-
args: schema_1.Schema.mixedRecord()
|
|
25
|
+
descriptorName: schema_1.Schema.string().describe('The task descriptor name to run (e.g. domain:taskName)'),
|
|
26
|
+
args: schema_1.Schema.mixedRecord().describe('Arguments to pass to the task')
|
|
27
27
|
// args will be passed directly without schema validation for now
|
|
28
28
|
});
|
|
29
29
|
const boundaries = {
|
|
@@ -19,8 +19,9 @@ const name = 'sample:newTask'
|
|
|
19
19
|
const description = 'Add task description here'
|
|
20
20
|
|
|
21
21
|
const schema = new Schema({
|
|
22
|
-
// Add your schema definitions here
|
|
23
|
-
//
|
|
22
|
+
// Add your schema definitions here.
|
|
23
|
+
// Use .describe() so the field shows up in \`forge sample:newTask --help\`.
|
|
24
|
+
// example: myParam: Schema.string().describe('What this parameter is for')
|
|
24
25
|
})
|
|
25
26
|
|
|
26
27
|
const boundaries = {
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
interface SchemaProperty {
|
|
2
2
|
name?: string;
|
|
3
3
|
type: string;
|
|
4
|
+
format?: string;
|
|
5
|
+
description?: string;
|
|
4
6
|
optional?: boolean;
|
|
5
7
|
default?: string;
|
|
6
8
|
properties?: Record<string, SchemaProperty>;
|
|
9
|
+
additionalProperties?: SchemaProperty | {
|
|
10
|
+
anyOf: SchemaProperty[];
|
|
11
|
+
};
|
|
7
12
|
}
|
|
8
13
|
interface InputSchema {
|
|
9
14
|
type: string;
|
|
10
15
|
properties: Record<string, SchemaProperty>;
|
|
16
|
+
required?: string[];
|
|
11
17
|
}
|
|
12
18
|
interface OutputType {
|
|
13
19
|
type: string;
|
|
@@ -502,64 +502,105 @@ function analyzeSchemaArg(node, sourceFile) {
|
|
|
502
502
|
const arg = node.arguments?.[0];
|
|
503
503
|
if (arg && ts.isObjectLiteralExpression(arg)) {
|
|
504
504
|
const properties = {};
|
|
505
|
+
const required = [];
|
|
505
506
|
arg.properties.forEach(prop => {
|
|
506
507
|
if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
|
|
507
508
|
const propName = prop.name.text;
|
|
508
509
|
const propValue = analyzeSchemaProp(prop.initializer, sourceFile);
|
|
510
|
+
// Optionality is expressed by absence from `required` (JSON Schema)
|
|
511
|
+
const isOptional = propValue.optional === true;
|
|
512
|
+
delete propValue.optional;
|
|
509
513
|
properties[propName] = propValue;
|
|
514
|
+
if (!isOptional) {
|
|
515
|
+
required.push(propName);
|
|
516
|
+
}
|
|
510
517
|
}
|
|
511
518
|
});
|
|
512
|
-
|
|
519
|
+
const result = { type: 'object', properties };
|
|
520
|
+
if (required.length > 0) {
|
|
521
|
+
result.required = required;
|
|
522
|
+
}
|
|
523
|
+
return result;
|
|
513
524
|
}
|
|
514
525
|
}
|
|
515
526
|
return { type: 'object', properties: {} };
|
|
516
527
|
}
|
|
517
|
-
//
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
const chainedMethod = node.expression.name.text;
|
|
533
|
-
if (chainedMethod === 'optional') {
|
|
534
|
-
// This is a .optional() call, get the base type
|
|
535
|
-
const baseCall = node.expression.expression;
|
|
536
|
-
if (ts.isCallExpression(baseCall)) {
|
|
537
|
-
const baseType = analyzeSchemaProp(baseCall, sourceFile);
|
|
538
|
-
return { ...baseType, optional: true };
|
|
539
|
-
}
|
|
528
|
+
// Analyze a single schema field, unwrapping the call chain
|
|
529
|
+
// (e.g. Schema.string().describe('...').optional()) into a JSON Schema property.
|
|
530
|
+
function analyzeSchemaProp(node, _sourceFile) {
|
|
531
|
+
let optional = false;
|
|
532
|
+
let description;
|
|
533
|
+
let defaultValue;
|
|
534
|
+
let current = node;
|
|
535
|
+
while (ts.isCallExpression(current) && ts.isPropertyAccessExpression(current.expression)) {
|
|
536
|
+
const methodName = current.expression.name.text;
|
|
537
|
+
const inner = current.expression.expression;
|
|
538
|
+
// Base call: Schema.<type>(...)
|
|
539
|
+
if (ts.isIdentifier(inner) && inner.text === 'Schema') {
|
|
540
|
+
const prop = mapSchemaMethod(methodName);
|
|
541
|
+
if (description !== undefined) {
|
|
542
|
+
prop.description = description;
|
|
540
543
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
const defaultValue = node.arguments[0]?.getText() || 'undefined';
|
|
547
|
-
return { ...baseType, default: defaultValue };
|
|
548
|
-
}
|
|
544
|
+
if (defaultValue !== undefined) {
|
|
545
|
+
prop.default = defaultValue;
|
|
546
|
+
}
|
|
547
|
+
if (optional) {
|
|
548
|
+
prop.optional = true;
|
|
549
549
|
}
|
|
550
|
+
return prop;
|
|
550
551
|
}
|
|
552
|
+
// Chained modifiers
|
|
553
|
+
if (methodName === 'optional') {
|
|
554
|
+
optional = true;
|
|
555
|
+
}
|
|
556
|
+
else if (methodName === 'describe') {
|
|
557
|
+
const arg = current.arguments[0];
|
|
558
|
+
if (arg && ts.isStringLiteral(arg)) {
|
|
559
|
+
description = arg.text;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
else if (methodName === 'default') {
|
|
563
|
+
defaultValue = current.arguments[0]?.getText() ?? 'undefined';
|
|
564
|
+
}
|
|
565
|
+
// Other modifiers (min/max/regex/...) don't change the JSON Schema type, so
|
|
566
|
+
// we keep unwrapping until we reach the base Schema.<type>() call.
|
|
567
|
+
current = inner;
|
|
551
568
|
}
|
|
552
569
|
return { type: 'unknown' };
|
|
553
570
|
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
571
|
+
// Map a Schema.* helper name to its JSON Schema representation, matching what
|
|
572
|
+
// Schema.describe() emits at runtime.
|
|
573
|
+
function mapSchemaMethod(methodName) {
|
|
574
|
+
switch (methodName) {
|
|
575
|
+
case 'string':
|
|
576
|
+
return { type: 'string' };
|
|
577
|
+
case 'number':
|
|
578
|
+
return { type: 'number' };
|
|
579
|
+
case 'boolean':
|
|
580
|
+
return { type: 'boolean' };
|
|
581
|
+
case 'date':
|
|
582
|
+
return { type: 'string', format: 'date-time' };
|
|
583
|
+
case 'email':
|
|
584
|
+
return { type: 'string', format: 'email' };
|
|
585
|
+
case 'uuid':
|
|
586
|
+
return { type: 'string', format: 'uuid' };
|
|
587
|
+
case 'url':
|
|
588
|
+
return { type: 'string', format: 'uri' };
|
|
589
|
+
case 'array':
|
|
590
|
+
return { type: 'array' };
|
|
591
|
+
case 'object':
|
|
592
|
+
return { type: 'object' };
|
|
593
|
+
case 'stringRecord':
|
|
594
|
+
return { type: 'object', additionalProperties: { type: 'string' } };
|
|
595
|
+
case 'numberRecord':
|
|
596
|
+
return { type: 'object', additionalProperties: { type: 'number' } };
|
|
597
|
+
case 'booleanRecord':
|
|
598
|
+
return { type: 'object', additionalProperties: { type: 'boolean' } };
|
|
599
|
+
case 'mixedRecord':
|
|
600
|
+
return { type: 'object', additionalProperties: { anyOf: [{ type: 'string' }, { type: 'number' }, { type: 'boolean' }] } };
|
|
601
|
+
default:
|
|
602
|
+
return { type: 'unknown' };
|
|
603
|
+
}
|
|
563
604
|
}
|
|
564
605
|
// Enhanced boundary analysis that extracts detailed boundary information
|
|
565
606
|
function analyzeBoundariesWithTypes(node, sourceFile) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgehive/forge-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "TypeScript CLI application",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@forgehive/hive-sdk": "^0.
|
|
14
|
-
"@forgehive/record-tape": "^0.
|
|
15
|
-
"@forgehive/runner": "^0.
|
|
16
|
-
"@forgehive/schema": "^0.
|
|
17
|
-
"@forgehive/task": "^0.
|
|
13
|
+
"@forgehive/hive-sdk": "^0.3.0",
|
|
14
|
+
"@forgehive/record-tape": "^0.3.0",
|
|
15
|
+
"@forgehive/runner": "^0.3.0",
|
|
16
|
+
"@forgehive/schema": "^0.2.0",
|
|
17
|
+
"@forgehive/task": "^0.3.0",
|
|
18
18
|
"esbuild": "^0.25.0",
|
|
19
19
|
"handlebars": "^4.7.8",
|
|
20
20
|
"minimist": "^1.2.8",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"minimist": "^1.2.8",
|
|
31
31
|
"typescript": "^5.3.3",
|
|
32
32
|
"uuid": "^11.1.0",
|
|
33
|
-
"@forgehive/
|
|
34
|
-
"@forgehive/
|
|
35
|
-
"@forgehive/
|
|
36
|
-
"@forgehive/schema": "0.
|
|
37
|
-
"@forgehive/runner": "0.
|
|
33
|
+
"@forgehive/hive-sdk": "0.3.0",
|
|
34
|
+
"@forgehive/record-tape": "0.3.0",
|
|
35
|
+
"@forgehive/task": "0.3.0",
|
|
36
|
+
"@forgehive/schema": "0.2.0",
|
|
37
|
+
"@forgehive/runner": "0.3.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/archiver": "^6.0.3",
|
package/src/runner.ts
CHANGED
|
@@ -93,11 +93,88 @@ runner.load('project:link', linkProject)
|
|
|
93
93
|
runner.load('project:unlink', unlinkProject)
|
|
94
94
|
runner.load('project:sync', syncProject)
|
|
95
95
|
|
|
96
|
+
function printAllHelp(): void {
|
|
97
|
+
const tasks = runner.describe()
|
|
98
|
+
console.log('Usage: forge <command> [options]')
|
|
99
|
+
console.log('')
|
|
100
|
+
console.log('Commands:')
|
|
101
|
+
|
|
102
|
+
const groups: Record<string, string[]> = {}
|
|
103
|
+
for (const name of Object.keys(tasks).sort()) {
|
|
104
|
+
const group = name.includes(':') ? name.split(':')[0] : name
|
|
105
|
+
if (!groups[group]) {
|
|
106
|
+
groups[group] = []
|
|
107
|
+
}
|
|
108
|
+
groups[group].push(name)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
for (const [group, commands] of Object.entries(groups)) {
|
|
112
|
+
console.log(`\n ${group}:`)
|
|
113
|
+
for (const cmd of commands) {
|
|
114
|
+
const desc = tasks[cmd].description || ''
|
|
115
|
+
console.log(` ${cmd.padEnd(26)} ${desc}`)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
console.log('')
|
|
120
|
+
console.log('Run "forge <command> --help" for more information on a specific command.')
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function printTaskHelp(taskName: string): void {
|
|
124
|
+
const task = runner.getTask(taskName)
|
|
125
|
+
if (!task) {
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// `describe()` returns JSON Schema: fields live under `properties`, optionality
|
|
130
|
+
// is the absence from `required`, and `description` carries the help text.
|
|
131
|
+
const schema = task.describe()
|
|
132
|
+
const properties = (schema.properties ?? {}) as Record<string, { type?: string; format?: string; description?: string }>
|
|
133
|
+
const required = new Set((schema.required ?? []) as string[])
|
|
134
|
+
const keys = Object.keys(properties)
|
|
135
|
+
|
|
136
|
+
console.log(`Usage: forge ${taskName}${keys.length > 0 ? ' [options]' : ''}`)
|
|
137
|
+
console.log('')
|
|
138
|
+
|
|
139
|
+
const desc = task.getDescription()
|
|
140
|
+
if (desc) {
|
|
141
|
+
console.log(desc)
|
|
142
|
+
console.log('')
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (keys.length > 0) {
|
|
146
|
+
console.log('Options:')
|
|
147
|
+
for (const key of keys) {
|
|
148
|
+
const field = properties[key]
|
|
149
|
+
const type = field.format ?? field.type ?? 'unknown'
|
|
150
|
+
const optional = required.has(key) ? '' : ' (optional)'
|
|
151
|
+
const description = field.description ? ` - ${field.description}` : ''
|
|
152
|
+
console.log(` --${key.padEnd(20)} ${`${type}${optional}`.padEnd(20)}${description}`)
|
|
153
|
+
}
|
|
154
|
+
console.log('')
|
|
155
|
+
} else {
|
|
156
|
+
console.log('This command takes no options.')
|
|
157
|
+
console.log('')
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
96
161
|
// Set handler
|
|
97
162
|
runner.setHandler(async (data: ParsedArgs): Promise<unknown> => {
|
|
98
163
|
const parsedArgs = runner.parseArguments(data)
|
|
99
164
|
const { taskName, action, args } = parsedArgs
|
|
100
165
|
|
|
166
|
+
const helpRequested = (args as Record<string, unknown>)?.help === true
|
|
167
|
+
|
|
168
|
+
if (helpRequested || taskName === 'undefined' || !taskName) {
|
|
169
|
+
if (helpRequested && runner.getTask(taskName)) {
|
|
170
|
+
printTaskHelp(taskName)
|
|
171
|
+
} else {
|
|
172
|
+
printAllHelp()
|
|
173
|
+
}
|
|
174
|
+
setTimeout(() => { process.exit(0) }, 100)
|
|
175
|
+
return { silent: true, outcome: 'Success', taskName, result: null }
|
|
176
|
+
}
|
|
177
|
+
|
|
101
178
|
console.log('===============================================')
|
|
102
179
|
console.log(`Running: ${taskName} ${action ? action : ''} ${JSON.stringify(args)}`)
|
|
103
180
|
console.log('===============================================')
|
package/src/tasks/auth/add.ts
CHANGED
|
@@ -12,10 +12,10 @@ import { load as loadProfiles } from './load'
|
|
|
12
12
|
import { type Profiles } from '../types'
|
|
13
13
|
|
|
14
14
|
const schema = new Schema({
|
|
15
|
-
name: Schema.string(),
|
|
16
|
-
apiKey: Schema.string(),
|
|
17
|
-
apiSecret: Schema.string(),
|
|
18
|
-
url: Schema.string()
|
|
15
|
+
name: Schema.string().describe('The name of the profile'),
|
|
16
|
+
apiKey: Schema.string().describe('The API key for the profile'),
|
|
17
|
+
apiSecret: Schema.string().describe('The API secret for the profile'),
|
|
18
|
+
url: Schema.string().describe('The URL for the profile')
|
|
19
19
|
})
|
|
20
20
|
|
|
21
21
|
const boundaries = {
|
package/src/tasks/auth/remove.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { load as loadProfiles } from './load'
|
|
|
12
12
|
import { type Profiles } from '../types'
|
|
13
13
|
|
|
14
14
|
const schema = new Schema({
|
|
15
|
-
profileName: Schema.string()
|
|
15
|
+
profileName: Schema.string().describe('The name of the auth profile to remove')
|
|
16
16
|
})
|
|
17
17
|
|
|
18
18
|
const boundaries = {
|
package/src/tasks/auth/switch.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { load as loadProfiles } from './load'
|
|
|
12
12
|
import { type Profiles } from '../types'
|
|
13
13
|
|
|
14
14
|
const schema = new Schema({
|
|
15
|
-
profileName: Schema.string()
|
|
15
|
+
profileName: Schema.string().describe('The name of the auth profile to switch to')
|
|
16
16
|
})
|
|
17
17
|
|
|
18
18
|
const boundaries = {
|