@forgehive/forge-cli 0.3.17 → 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 +71 -3
- 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 +4 -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 +5 -5
- package/dist/tasks/project/create.js +21 -25
- package/dist/tasks/project/link.d.ts +4 -4
- package/dist/tasks/project/link.js +1 -1
- package/dist/tasks/project/sync.d.ts +7 -7
- package/dist/tasks/project/sync.js +7 -3
- 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 +14 -7
- package/dist/tasks/task/replay.js +33 -23
- package/dist/tasks/task/run.d.ts +6 -6
- package/dist/tasks/task/run.js +18 -23
- package/dist/tasks/types.d.ts +1 -0
- 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 +80 -3
- 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 +5 -2
- package/src/tasks/fixture/download.ts +1 -1
- package/src/tasks/init.ts +1 -1
- package/src/tasks/project/create.ts +21 -27
- package/src/tasks/project/link.ts +1 -1
- package/src/tasks/project/sync.ts +9 -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 +38 -24
- package/src/tasks/task/run.ts +19 -26
- package/src/tasks/types.ts +1 -0
- 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
package/dist/tasks/types.d.ts
CHANGED
|
@@ -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/task": "0.
|
|
36
|
-
"@forgehive/
|
|
37
|
-
"@forgehive/
|
|
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('===============================================')
|
|
@@ -114,7 +191,7 @@ runner.setHandler(async (data: ParsedArgs): Promise<unknown> => {
|
|
|
114
191
|
const commandsWithDescriptor = ['task:create', 'task:remove', 'task:publish', 'task:describe', 'task:fingerprint']
|
|
115
192
|
const commandsWithRunner = ['runner:create', 'runner:remove']
|
|
116
193
|
const commandsWithoutParams = ['project:unlink', 'project:sync', 'auth:clear']
|
|
117
|
-
const silentCommands = ['task:describe', 'task:list', 'auth:list', 'info']
|
|
194
|
+
const silentCommands = ['task:describe', 'task:list', 'auth:list', 'info', 'docs:download']
|
|
118
195
|
|
|
119
196
|
if (commandsWithDescriptor.includes(taskName)) {
|
|
120
197
|
result = await task.run({ descriptorName: action })
|
|
@@ -191,10 +268,10 @@ runner.setHandler(async (data: ParsedArgs): Promise<unknown> => {
|
|
|
191
268
|
logs
|
|
192
269
|
})
|
|
193
270
|
} else if (taskName === 'project:create') {
|
|
194
|
-
const {
|
|
271
|
+
const { name, description } = args as { name: string, description?: string }
|
|
195
272
|
|
|
196
273
|
result = await task.run({
|
|
197
|
-
|
|
274
|
+
name,
|
|
198
275
|
description
|
|
199
276
|
})
|
|
200
277
|
} else if (taskName === 'project:link') {
|
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 = {
|
|
@@ -9,8 +9,8 @@ import { load as loadConf } from '../conf/load'
|
|
|
9
9
|
import { type ForgeConf } from '../types'
|
|
10
10
|
|
|
11
11
|
const schema = new Schema({
|
|
12
|
-
entryPoint: Schema.string(),
|
|
13
|
-
outputFile: Schema.string()
|
|
12
|
+
entryPoint: Schema.string().describe('Path to the task entry point file'),
|
|
13
|
+
outputFile: Schema.string().describe('Path for the bundled output file')
|
|
14
14
|
})
|
|
15
15
|
|
|
16
16
|
const boundaries = {
|
|
@@ -45,8 +45,8 @@ interface FingerprintResult {
|
|
|
45
45
|
const description = 'Generate task bundle with comprehensive fingerprinting and type extraction'
|
|
46
46
|
|
|
47
47
|
const schema = new Schema({
|
|
48
|
-
descriptorName: Schema.string(),
|
|
49
|
-
filePath: Schema.string().optional()
|
|
48
|
+
descriptorName: Schema.string().describe('The task descriptor name (e.g. domain:taskName)'),
|
|
49
|
+
filePath: Schema.string().describe('Optional path to the task source file').optional()
|
|
50
50
|
})
|
|
51
51
|
|
|
52
52
|
const boundaries = {
|
package/src/tasks/bundle/load.ts
CHANGED
package/src/tasks/bundle/zip.ts
CHANGED
|
@@ -11,10 +11,10 @@ import path from 'path'
|
|
|
11
11
|
const description = 'Zip a bundle file for distribution'
|
|
12
12
|
|
|
13
13
|
const schema = new Schema({
|
|
14
|
-
dir: Schema.string(),
|
|
15
|
-
input: Schema.string(),
|
|
16
|
-
output: Schema.string(),
|
|
17
|
-
forgeJsonPath: Schema.string().optional() // Optional path to forge.json - if provided, it will be included
|
|
14
|
+
dir: Schema.string().describe('Directory that will contain the generated zip'),
|
|
15
|
+
input: Schema.string().describe('Path to the file or folder to add to the zip'),
|
|
16
|
+
output: Schema.string().describe('Output path for the generated zip file'),
|
|
17
|
+
forgeJsonPath: Schema.string().describe('Optional path to forge.json to include in the bundle').optional() // Optional path to forge.json - if provided, it will be included
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
const boundaries = {
|
|
@@ -16,8 +16,8 @@ const LLM_GUIDE_URL = 'https://raw.githubusercontent.com/forge-and-hive/forge-mo
|
|
|
16
16
|
const LLM_HIVE_LOGGING_URL = 'https://raw.githubusercontent.com/forge-and-hive/forge-mono-repo/refs/heads/main/docs/llm-hive-logging.md'
|
|
17
17
|
|
|
18
18
|
const schema = new Schema({
|
|
19
|
-
path: Schema.string().optional(),
|
|
20
|
-
logs: Schema.boolean().optional()
|
|
19
|
+
path: Schema.string().describe('Optional output path for the downloaded docs').optional(),
|
|
20
|
+
logs: Schema.boolean().describe('Include execution logs in the downloaded docs').optional()
|
|
21
21
|
})
|
|
22
22
|
|
|
23
23
|
const boundaries = {
|
|
@@ -92,6 +92,7 @@ export const download = createTask({
|
|
|
92
92
|
|
|
93
93
|
// Download Hive logging guide if --logs flag is provided
|
|
94
94
|
if (logs) {
|
|
95
|
+
console.log('===============================================')
|
|
95
96
|
const logsTargetPath = customPath
|
|
96
97
|
? path.join(path.dirname(customPath), 'hive-logging.md')
|
|
97
98
|
: 'docs/hive-logging.md'
|
|
@@ -125,6 +126,8 @@ export const download = createTask({
|
|
|
125
126
|
})
|
|
126
127
|
}
|
|
127
128
|
|
|
129
|
+
console.log('===============================================')
|
|
130
|
+
|
|
128
131
|
return {
|
|
129
132
|
success: true,
|
|
130
133
|
downloads: results,
|
|
@@ -26,7 +26,7 @@ interface FixtureResponse {
|
|
|
26
26
|
const description = 'Download a fixture by UUID to a path based on task descriptor returned from API'
|
|
27
27
|
|
|
28
28
|
const schema = new Schema({
|
|
29
|
-
uuid: Schema.string()
|
|
29
|
+
uuid: Schema.string().describe('The UUID of the fixture to download')
|
|
30
30
|
})
|
|
31
31
|
|
|
32
32
|
const boundaries = {
|
package/src/tasks/init.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { Schema } from '@forgehive/schema'
|
|
|
7
7
|
import { type ForgeConf } from './types'
|
|
8
8
|
|
|
9
9
|
const schema = new Schema({
|
|
10
|
-
dryRun: Schema.boolean().optional()
|
|
10
|
+
dryRun: Schema.boolean().describe('Preview the changes without writing any files').optional()
|
|
11
11
|
})
|
|
12
12
|
|
|
13
13
|
const boundaries = {
|
|
@@ -12,12 +12,12 @@ import { load as loadConf } from '../conf/load'
|
|
|
12
12
|
import { loadCurrent as loadCurrentProfile } from '../auth/loadCurrent'
|
|
13
13
|
import { type ForgeConf, type Profile } from '../types'
|
|
14
14
|
|
|
15
|
-
const
|
|
16
|
-
const
|
|
15
|
+
const taskName = 'project:create'
|
|
16
|
+
const taskDescription = 'Create a new project in ForgeHive'
|
|
17
17
|
|
|
18
18
|
const schema = new Schema({
|
|
19
|
-
|
|
20
|
-
description: Schema.string().optional()
|
|
19
|
+
name: Schema.string().describe('The name of the project'),
|
|
20
|
+
description: Schema.string().describe('Optional description of the project').optional()
|
|
21
21
|
})
|
|
22
22
|
|
|
23
23
|
const boundaries = {
|
|
@@ -40,39 +40,33 @@ const boundaries = {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export const create = createTask({
|
|
43
|
-
name,
|
|
44
|
-
description,
|
|
43
|
+
name: taskName,
|
|
44
|
+
description: taskDescription,
|
|
45
45
|
schema,
|
|
46
46
|
boundaries,
|
|
47
47
|
fn: async function (argv, { loadConf, loadCurrentProfile, writeFile, createProject }) {
|
|
48
|
-
const {
|
|
48
|
+
const { name: projectName, description } = argv
|
|
49
49
|
|
|
50
50
|
// Load current configuration
|
|
51
51
|
const conf = await loadConf({})
|
|
52
52
|
|
|
53
|
-
// Use provided projectName or fall back to forge.json project name
|
|
54
|
-
const projectName = inputProjectName || conf.project.name
|
|
55
|
-
|
|
56
|
-
if (!projectName) {
|
|
57
|
-
throw new Error('Project name is required. Provide --projectName or ensure forge.json has a project name.')
|
|
58
|
-
}
|
|
59
|
-
|
|
60
53
|
// Check if project already has a UUID, generate one if not
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
...conf,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
uuid: projectUuid
|
|
72
|
-
}
|
|
54
|
+
const projectUuid = conf.project.uuid || uuidv4()
|
|
55
|
+
|
|
56
|
+
// Update forge.json with the project name and UUID
|
|
57
|
+
const forgePath = path.join(process.cwd(), 'forge.json')
|
|
58
|
+
const updatedConf: ForgeConf = {
|
|
59
|
+
...conf,
|
|
60
|
+
project: {
|
|
61
|
+
...conf.project,
|
|
62
|
+
name: projectName,
|
|
63
|
+
uuid: projectUuid
|
|
73
64
|
}
|
|
65
|
+
}
|
|
74
66
|
|
|
75
|
-
|
|
67
|
+
await writeFile(forgePath, JSON.stringify(updatedConf, null, 2))
|
|
68
|
+
console.log(`Updated forge.json with project name: ${projectName}`)
|
|
69
|
+
if (!conf.project.uuid) {
|
|
76
70
|
console.log(`Generated and saved project UUID: ${projectUuid}`)
|
|
77
71
|
}
|
|
78
72
|
|
|
@@ -15,7 +15,7 @@ const name = 'project:link'
|
|
|
15
15
|
const description = 'Link an existing remote project to the local project by UUID'
|
|
16
16
|
|
|
17
17
|
const schema = new Schema({
|
|
18
|
-
uuid: Schema.string()
|
|
18
|
+
uuid: Schema.string().describe('The UUID of the project to link')
|
|
19
19
|
})
|
|
20
20
|
|
|
21
21
|
const boundaries = {
|
|
@@ -26,6 +26,8 @@ const boundaries = {
|
|
|
26
26
|
},
|
|
27
27
|
syncTasksToHive: async (
|
|
28
28
|
projectUuid: string,
|
|
29
|
+
projectName: string,
|
|
30
|
+
projectDescription: string | undefined,
|
|
29
31
|
tasks: Array<{ uuid: string; name: string }>,
|
|
30
32
|
apiKey: string,
|
|
31
33
|
apiSecret: string,
|
|
@@ -57,7 +59,7 @@ const boundaries = {
|
|
|
57
59
|
'Content-Type': 'application/json',
|
|
58
60
|
'Authorization': `Bearer ${apiKey}:${apiSecret}`
|
|
59
61
|
},
|
|
60
|
-
body: JSON.stringify({ tasks })
|
|
62
|
+
body: JSON.stringify({ projectName, description: projectDescription, tasks })
|
|
61
63
|
})
|
|
62
64
|
|
|
63
65
|
if (response.ok) {
|
|
@@ -134,11 +136,17 @@ export const sync = createTask({
|
|
|
134
136
|
}
|
|
135
137
|
|
|
136
138
|
console.log(` 📊 Found ${tasksToSync.length} tasks to sync`)
|
|
139
|
+
console.log(` 📝 Project name: ${forge.project.name}`)
|
|
140
|
+
if (forge.project.description) {
|
|
141
|
+
console.log(` 📝 Project description: ${forge.project.description}`)
|
|
142
|
+
}
|
|
137
143
|
|
|
138
144
|
try {
|
|
139
145
|
const profile = await loadCurrentProfile({})
|
|
140
146
|
const result = await syncTasksToHive(
|
|
141
147
|
forge.project.uuid,
|
|
148
|
+
forge.project.name,
|
|
149
|
+
forge.project.description,
|
|
142
150
|
tasksToSync,
|
|
143
151
|
profile.apiKey,
|
|
144
152
|
profile.apiSecret,
|
|
@@ -11,8 +11,8 @@ import { load as loadConf } from '../conf/load'
|
|
|
11
11
|
import { type ForgeConf } from '../types'
|
|
12
12
|
|
|
13
13
|
const schema = new Schema({
|
|
14
|
-
runnerName: Schema.string(),
|
|
15
|
-
targetPath: Schema.string()
|
|
14
|
+
runnerName: Schema.string().describe('The name of the runner to bundle'),
|
|
15
|
+
targetPath: Schema.string().describe('Target path for the bundled runner')
|
|
16
16
|
})
|
|
17
17
|
|
|
18
18
|
const boundaries = {
|
|
@@ -24,8 +24,9 @@ const name = '{{ taskDescriptor }}'
|
|
|
24
24
|
const description = 'Add task description here'
|
|
25
25
|
|
|
26
26
|
const schema = new Schema({
|
|
27
|
-
// Add your schema definitions here
|
|
28
|
-
//
|
|
27
|
+
// Add your schema definitions here.
|
|
28
|
+
// Use .describe() so the field shows up in \`forge {{ taskDescriptor }} --help\`.
|
|
29
|
+
// example: myParam: Schema.string().describe('What this parameter is for')
|
|
29
30
|
})
|
|
30
31
|
|
|
31
32
|
const boundaries = {
|