@synergenius/flow-weaver 0.17.1 → 0.17.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/api/index.d.ts +4 -1
- package/dist/api/index.js +4 -1
- package/dist/api/templates.js +2 -2
- package/dist/api/validate.d.ts +2 -2
- package/dist/api/validate.js +6 -6
- package/dist/api/validation-registry.d.ts +10 -0
- package/dist/api/validation-registry.js +10 -0
- package/dist/ast/types.d.ts +91 -4
- package/dist/built-in-nodes/invoke-workflow.d.ts +1 -1
- package/dist/built-in-nodes/invoke-workflow.js +1 -1
- package/dist/chevrotain-parser/connect-parser.js +25 -7
- package/dist/cli/commands/compile.d.ts +5 -9
- package/dist/cli/commands/compile.js +21 -14
- package/dist/cli/commands/dev.d.ts +2 -13
- package/dist/cli/commands/dev.js +10 -204
- package/dist/cli/commands/doctor.js +6 -3
- package/dist/cli/commands/export.d.ts +8 -17
- package/dist/cli/commands/export.js +8 -17
- package/dist/cli/commands/init-personas.d.ts +12 -3
- package/dist/cli/commands/init-personas.js +27 -4
- package/dist/cli/commands/init.d.ts +2 -2
- package/dist/cli/commands/init.js +5 -11
- package/dist/cli/flow-weaver.mjs +61463 -60910
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +9 -7
- package/dist/cli/templates/index.d.ts +20 -1
- package/dist/cli/templates/index.js +66 -15
- package/dist/cli/templates/nodes/human-approval.js +2 -3
- package/dist/cli/templates/nodes/rag-retriever.js +1 -1
- package/dist/constants.d.ts +7 -0
- package/dist/constants.js +13 -3
- package/dist/context/index.js +13 -3
- package/dist/deployment/config/loader.js +2 -1
- package/dist/deployment/core/adapters.d.ts +1 -25
- package/dist/deployment/core/adapters.js +0 -95
- package/dist/deployment/core/formatters.d.ts +0 -15
- package/dist/deployment/core/formatters.js +0 -24
- package/dist/deployment/index.d.ts +7 -5
- package/dist/deployment/index.js +8 -5
- package/dist/deployment/types.d.ts +2 -45
- package/dist/diagram/html-viewer.js +65 -32
- package/dist/diagram/renderer.js +9 -6
- package/dist/diagram/theme.js +4 -0
- package/dist/diagram/types.d.ts +2 -0
- package/dist/doc-metadata/extractors/annotations.js +5 -5
- package/dist/doc-metadata/extractors/cli-commands.js +1 -1
- package/dist/doc-metadata/extractors/mcp-tools.js +1 -2
- package/dist/docs/index.d.ts +28 -1
- package/dist/docs/index.js +95 -28
- package/dist/export/index.d.ts +2 -3
- package/dist/{deployment/targets/cicd-base.d.ts → extensions/cicd/base-target.d.ts} +35 -36
- package/dist/{deployment/targets/cicd-base.js → extensions/cicd/base-target.js} +97 -57
- package/dist/{validation/cicd-detection.d.ts → extensions/cicd/detection.d.ts} +2 -2
- package/dist/{validation/cicd-detection.js → extensions/cicd/detection.js} +13 -1
- package/dist/extensions/cicd/docs/cicd.md +395 -0
- package/dist/extensions/cicd/index.d.ts +10 -0
- package/dist/extensions/cicd/index.js +10 -0
- package/dist/extensions/cicd/register.d.ts +11 -0
- package/dist/extensions/cicd/register.js +62 -0
- package/dist/extensions/cicd/rules.d.ts +30 -0
- package/dist/{validation/cicd-rules.js → extensions/cicd/rules.js} +60 -56
- package/dist/extensions/cicd/tag-handler.d.ts +14 -0
- package/dist/extensions/cicd/tag-handler.js +488 -0
- package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-docker.d.ts +1 -1
- package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-matrix.d.ts +1 -1
- package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-multi-env.d.ts +1 -1
- package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-test-deploy.d.ts +1 -1
- package/dist/extensions/index.d.ts +12 -0
- package/dist/extensions/index.js +12 -0
- package/dist/extensions/inngest/dev-mode.d.ts +9 -0
- package/dist/extensions/inngest/dev-mode.js +213 -0
- package/dist/{generator/inngest.d.ts → extensions/inngest/generator.d.ts} +2 -2
- package/dist/{generator/inngest.js → extensions/inngest/generator.js} +4 -4
- package/dist/extensions/inngest/index.d.ts +2 -0
- package/dist/extensions/inngest/index.js +2 -0
- package/dist/extensions/inngest/register.d.ts +6 -0
- package/dist/extensions/inngest/register.js +23 -0
- package/dist/extensions/inngest/templates/ai-agent-durable.d.ts +8 -0
- package/dist/{cli/templates/workflows → extensions/inngest/templates}/ai-agent-durable.js +8 -8
- package/dist/{cli/templates/workflows → extensions/inngest/templates}/ai-pipeline-durable.d.ts +2 -2
- package/dist/{cli/templates/workflows → extensions/inngest/templates}/ai-pipeline-durable.js +7 -7
- package/dist/generated-version.d.ts +1 -1
- package/dist/generated-version.js +1 -1
- package/dist/generator/compile-target-registry.d.ts +20 -0
- package/dist/generator/compile-target-registry.js +20 -0
- package/dist/generator/dev-mode-registry.d.ts +27 -0
- package/dist/generator/dev-mode-registry.js +20 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/jsdoc-parser.d.ts +12 -114
- package/dist/jsdoc-parser.js +57 -362
- package/dist/marketplace/index.d.ts +2 -2
- package/dist/marketplace/index.js +1 -1
- package/dist/marketplace/registry.d.ts +39 -1
- package/dist/marketplace/registry.js +77 -0
- package/dist/marketplace/types.d.ts +76 -3
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +2 -0
- package/dist/mcp/tools-export.js +3 -3
- package/dist/mcp/tools-query.js +17 -11
- package/dist/mcp/tools-template.js +1 -1
- package/dist/parser/tag-registry.d.ts +47 -0
- package/dist/parser/tag-registry.js +57 -0
- package/dist/parser.d.ts +3 -0
- package/dist/parser.js +10 -23
- package/dist/validation/rule-registry.d.ts +36 -0
- package/dist/validation/rule-registry.js +37 -0
- package/dist/validator.js +3 -3
- package/docs/reference/concepts.md +2 -1
- package/docs/reference/deployment.md +21 -0
- package/docs/reference/jsdoc-grammar.md +242 -1
- package/docs/reference/scaffold.md +0 -6
- package/package.json +9 -1
- package/dist/cli/templates/workflows/ai-agent-durable.d.ts +0 -8
- package/dist/export/templates.d.ts +0 -24
- package/dist/export/templates.js +0 -186
- package/dist/validation/cicd-rules.d.ts +0 -62
- /package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-docker.js +0 -0
- /package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-matrix.js +0 -0
- /package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-multi-env.js +0 -0
- /package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-test-deploy.js +0 -0
package/dist/cli/commands/dev.js
CHANGED
|
@@ -3,14 +3,13 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import * as path from 'path';
|
|
5
5
|
import * as fs from 'fs';
|
|
6
|
-
import * as os from 'os';
|
|
7
6
|
import { glob } from 'glob';
|
|
8
|
-
import {
|
|
9
|
-
import { compileCommand, compileInngestTarget } from './compile.js';
|
|
7
|
+
import { compileCommand } from './compile.js';
|
|
10
8
|
import { executeWorkflowFromFile } from '../../mcp/workflow-executor.js';
|
|
11
9
|
import { logger } from '../utils/logger.js';
|
|
12
10
|
import { getErrorMessage } from '../../utils/error-utils.js';
|
|
13
11
|
import { getFriendlyError } from '../../friendly-errors.js';
|
|
12
|
+
import { devModeRegistry } from '../../generator/dev-mode-registry.js';
|
|
14
13
|
function timestamp() {
|
|
15
14
|
const now = new Date();
|
|
16
15
|
const h = String(now.getHours()).padStart(2, '0');
|
|
@@ -124,204 +123,6 @@ async function compileAndRun(filePath, params, options) {
|
|
|
124
123
|
}
|
|
125
124
|
}
|
|
126
125
|
// ---------------------------------------------------------------------------
|
|
127
|
-
// Inngest Dev Mode
|
|
128
|
-
// ---------------------------------------------------------------------------
|
|
129
|
-
/**
|
|
130
|
-
* Check that required packages are installed.
|
|
131
|
-
*/
|
|
132
|
-
function checkDependency(pkg, cwd) {
|
|
133
|
-
try {
|
|
134
|
-
require.resolve(pkg, { paths: [cwd] });
|
|
135
|
-
return true;
|
|
136
|
-
}
|
|
137
|
-
catch {
|
|
138
|
-
return false;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Generate the dev server entry file for Inngest.
|
|
143
|
-
*/
|
|
144
|
-
function generateDevServerEntry(inngestOutputPath, framework, port) {
|
|
145
|
-
const relImport = `./${path.basename(inngestOutputPath).replace(/\.ts$/, '.js')}`;
|
|
146
|
-
if (framework === 'express') {
|
|
147
|
-
return `import express from 'express';
|
|
148
|
-
import { handler } from '${relImport}';
|
|
149
|
-
|
|
150
|
-
const app = express();
|
|
151
|
-
app.use(express.json());
|
|
152
|
-
app.use('/api/inngest', handler);
|
|
153
|
-
app.listen(${port}, () => {
|
|
154
|
-
console.log('Inngest dev server running on http://localhost:${port}');
|
|
155
|
-
console.log('Inngest endpoint: http://localhost:${port}/api/inngest');
|
|
156
|
-
console.log('');
|
|
157
|
-
console.log('Connect Inngest Dev Server:');
|
|
158
|
-
console.log(' npx inngest-cli@latest dev -u http://localhost:${port}/api/inngest');
|
|
159
|
-
});
|
|
160
|
-
`;
|
|
161
|
-
}
|
|
162
|
-
if (framework === 'hono') {
|
|
163
|
-
return `import { Hono } from 'hono';
|
|
164
|
-
import { serve } from '@hono/node-server';
|
|
165
|
-
import { handler } from '${relImport}';
|
|
166
|
-
|
|
167
|
-
const app = new Hono();
|
|
168
|
-
app.route('/api/inngest', handler);
|
|
169
|
-
|
|
170
|
-
serve({ fetch: app.fetch, port: ${port} }, () => {
|
|
171
|
-
console.log('Inngest dev server running on http://localhost:${port}');
|
|
172
|
-
console.log('Inngest endpoint: http://localhost:${port}/api/inngest');
|
|
173
|
-
console.log('');
|
|
174
|
-
console.log('Connect Inngest Dev Server:');
|
|
175
|
-
console.log(' npx inngest-cli@latest dev -u http://localhost:${port}/api/inngest');
|
|
176
|
-
});
|
|
177
|
-
`;
|
|
178
|
-
}
|
|
179
|
-
// Default: express (most common for dev)
|
|
180
|
-
return generateDevServerEntry(inngestOutputPath, 'express', port);
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Compile workflow to Inngest and start a local dev server.
|
|
184
|
-
*/
|
|
185
|
-
async function runInngestDevMode(filePath, options) {
|
|
186
|
-
const framework = options.framework ?? 'express';
|
|
187
|
-
const port = options.port ?? 3000;
|
|
188
|
-
const cwd = path.dirname(filePath);
|
|
189
|
-
// Check dependencies
|
|
190
|
-
const missingDeps = [];
|
|
191
|
-
if (!checkDependency('inngest', cwd))
|
|
192
|
-
missingDeps.push('inngest');
|
|
193
|
-
if (framework === 'express' && !checkDependency('express', cwd))
|
|
194
|
-
missingDeps.push('express');
|
|
195
|
-
if (framework === 'hono') {
|
|
196
|
-
if (!checkDependency('hono', cwd))
|
|
197
|
-
missingDeps.push('hono');
|
|
198
|
-
if (!checkDependency('@hono/node-server', cwd))
|
|
199
|
-
missingDeps.push('@hono/node-server');
|
|
200
|
-
}
|
|
201
|
-
if (missingDeps.length > 0) {
|
|
202
|
-
throw new Error(`Missing dependencies: ${missingDeps.join(', ')}. Install them with: npm install ${missingDeps.join(' ')}`);
|
|
203
|
-
}
|
|
204
|
-
// Set up temp directory for generated files
|
|
205
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'fw-inngest-dev-'));
|
|
206
|
-
const inngestOutputPath = path.join(tmpDir, path.basename(filePath).replace(/\.ts$/, '.inngest.ts'));
|
|
207
|
-
let serverProcess = null;
|
|
208
|
-
const compileInngest = async () => {
|
|
209
|
-
try {
|
|
210
|
-
await compileInngestTarget(filePath, {
|
|
211
|
-
production: false,
|
|
212
|
-
workflowName: options.workflow,
|
|
213
|
-
serve: true,
|
|
214
|
-
framework: framework,
|
|
215
|
-
typedEvents: true,
|
|
216
|
-
});
|
|
217
|
-
// compileInngestTarget writes to filePath.replace(.ts, .inngest.ts)
|
|
218
|
-
// Copy it to our temp dir, then remove the source-adjacent file
|
|
219
|
-
const sourceOutput = filePath.replace(/\.ts$/, '.inngest.ts');
|
|
220
|
-
if (fs.existsSync(sourceOutput)) {
|
|
221
|
-
fs.copyFileSync(sourceOutput, inngestOutputPath);
|
|
222
|
-
try {
|
|
223
|
-
fs.unlinkSync(sourceOutput);
|
|
224
|
-
}
|
|
225
|
-
catch { /* ignore */ }
|
|
226
|
-
}
|
|
227
|
-
return true;
|
|
228
|
-
}
|
|
229
|
-
catch (error) {
|
|
230
|
-
logger.error(`Inngest compilation failed: ${getErrorMessage(error)}`);
|
|
231
|
-
return false;
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
const startServer = () => {
|
|
235
|
-
// Generate dev server entry
|
|
236
|
-
const entryPath = path.join(tmpDir, 'dev-server.ts');
|
|
237
|
-
const entryCode = generateDevServerEntry(inngestOutputPath, framework, port);
|
|
238
|
-
fs.writeFileSync(entryPath, entryCode, 'utf8');
|
|
239
|
-
// Spawn tsx to run the server
|
|
240
|
-
serverProcess = spawn('npx', ['tsx', entryPath], {
|
|
241
|
-
cwd: path.dirname(filePath),
|
|
242
|
-
stdio: 'inherit',
|
|
243
|
-
shell: true,
|
|
244
|
-
});
|
|
245
|
-
serverProcess.on('error', (err) => {
|
|
246
|
-
logger.error(`Server process error: ${err.message}`);
|
|
247
|
-
});
|
|
248
|
-
serverProcess.on('exit', (code) => {
|
|
249
|
-
if (code !== null && code !== 0) {
|
|
250
|
-
logger.error(`Server exited with code ${code}`);
|
|
251
|
-
}
|
|
252
|
-
serverProcess = null;
|
|
253
|
-
});
|
|
254
|
-
};
|
|
255
|
-
const stopServer = () => {
|
|
256
|
-
if (serverProcess && !serverProcess.killed) {
|
|
257
|
-
serverProcess.kill();
|
|
258
|
-
serverProcess = null;
|
|
259
|
-
}
|
|
260
|
-
};
|
|
261
|
-
const restartServer = async () => {
|
|
262
|
-
stopServer();
|
|
263
|
-
const ok = await compileInngest();
|
|
264
|
-
if (ok) {
|
|
265
|
-
startServer();
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
|
-
// Header
|
|
269
|
-
logger.section('Inngest Dev Mode');
|
|
270
|
-
logger.info(`File: ${path.basename(filePath)}`);
|
|
271
|
-
logger.info(`Framework: ${framework}`);
|
|
272
|
-
logger.info(`Port: ${port}`);
|
|
273
|
-
logger.newline();
|
|
274
|
-
// Initial compile + start
|
|
275
|
-
const ok = await compileInngest();
|
|
276
|
-
if (!ok) {
|
|
277
|
-
if (options.once)
|
|
278
|
-
return;
|
|
279
|
-
logger.info('Fix the errors above, then save the file to retry.');
|
|
280
|
-
}
|
|
281
|
-
else {
|
|
282
|
-
if (options.once)
|
|
283
|
-
return;
|
|
284
|
-
startServer();
|
|
285
|
-
}
|
|
286
|
-
// Watch for changes
|
|
287
|
-
logger.newline();
|
|
288
|
-
logger.success('Watching for file changes... (Ctrl+C to stop)');
|
|
289
|
-
const files = await glob(path.resolve(filePath), { absolute: true });
|
|
290
|
-
const chokidar = await import('chokidar');
|
|
291
|
-
const watcher = chokidar.watch(files, {
|
|
292
|
-
persistent: true,
|
|
293
|
-
ignoreInitial: true,
|
|
294
|
-
});
|
|
295
|
-
watcher.on('change', async (file) => {
|
|
296
|
-
cycleSeparator(file);
|
|
297
|
-
logger.info('Recompiling and restarting server...');
|
|
298
|
-
await restartServer();
|
|
299
|
-
});
|
|
300
|
-
// Cleanup
|
|
301
|
-
const sourceOutput = filePath.replace(/\.ts$/, '.inngest.ts');
|
|
302
|
-
const cleanup = () => {
|
|
303
|
-
logger.newline();
|
|
304
|
-
logger.info('Stopping Inngest dev mode...');
|
|
305
|
-
stopServer();
|
|
306
|
-
watcher.close();
|
|
307
|
-
// Clean up temp files and source-adjacent .inngest.ts
|
|
308
|
-
try {
|
|
309
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
310
|
-
}
|
|
311
|
-
catch { /* ignore */ }
|
|
312
|
-
try {
|
|
313
|
-
fs.unlinkSync(sourceOutput);
|
|
314
|
-
}
|
|
315
|
-
catch { /* ignore */ }
|
|
316
|
-
process.exit(0);
|
|
317
|
-
};
|
|
318
|
-
process.on('SIGINT', cleanup);
|
|
319
|
-
if (process.platform !== 'win32')
|
|
320
|
-
process.on('SIGTERM', cleanup);
|
|
321
|
-
// Keep process alive
|
|
322
|
-
await new Promise(() => { });
|
|
323
|
-
}
|
|
324
|
-
// ---------------------------------------------------------------------------
|
|
325
126
|
// Main Command
|
|
326
127
|
// ---------------------------------------------------------------------------
|
|
327
128
|
/**
|
|
@@ -332,9 +133,14 @@ export async function devCommand(input, options = {}) {
|
|
|
332
133
|
if (!fs.existsSync(filePath)) {
|
|
333
134
|
throw new Error(`File not found: ${filePath}`);
|
|
334
135
|
}
|
|
335
|
-
//
|
|
336
|
-
if (options.target
|
|
337
|
-
|
|
136
|
+
// Delegate to a registered dev mode provider if one exists for the target
|
|
137
|
+
if (options.target) {
|
|
138
|
+
const provider = devModeRegistry.get(options.target);
|
|
139
|
+
if (provider) {
|
|
140
|
+
return provider.run(filePath, options);
|
|
141
|
+
}
|
|
142
|
+
const available = devModeRegistry.getNames();
|
|
143
|
+
throw new Error(`Unknown dev target "${options.target}". ${available.length ? `Available: ${available.join(', ')}` : 'No dev mode providers registered. Install a pack that provides one.'}`);
|
|
338
144
|
}
|
|
339
145
|
const params = parseParams(options);
|
|
340
146
|
if (!options.json) {
|
|
@@ -455,7 +455,8 @@ export function checkTsxAvailable(cwd) {
|
|
|
455
455
|
}
|
|
456
456
|
// ── Config health checks ─────────────────────────────────────────────────────
|
|
457
457
|
const VALID_FILE_TYPES = ['ts', 'tsx', 'js', 'jsx'];
|
|
458
|
-
|
|
458
|
+
// Target validation is skipped — valid targets are discovered dynamically
|
|
459
|
+
// from installed packs at export time.
|
|
459
460
|
function readYaml(filePath) {
|
|
460
461
|
try {
|
|
461
462
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
@@ -606,8 +607,10 @@ export function checkDeploymentProfiles(cwd) {
|
|
|
606
607
|
continue;
|
|
607
608
|
}
|
|
608
609
|
const config = data;
|
|
609
|
-
|
|
610
|
-
|
|
610
|
+
// Target names are validated at export time via the target registry.
|
|
611
|
+
// We only check that the value is a non-empty string here.
|
|
612
|
+
if (config.target && typeof config.target !== 'string') {
|
|
613
|
+
invalid.push(`${profile} (target must be a string)`);
|
|
611
614
|
}
|
|
612
615
|
}
|
|
613
616
|
if (invalid.length > 0) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Export command - generate serverless function handlers for deployment
|
|
3
3
|
*/
|
|
4
4
|
export interface ExportOptions {
|
|
5
|
-
/** Target platform (
|
|
5
|
+
/** Target platform (provided by installed packs) */
|
|
6
6
|
target: string;
|
|
7
7
|
/** Output directory */
|
|
8
8
|
output: string;
|
|
@@ -20,7 +20,7 @@ export interface ExportOptions {
|
|
|
20
20
|
workflows?: string;
|
|
21
21
|
/** Include API documentation routes (/docs and /openapi.json) */
|
|
22
22
|
docs?: boolean;
|
|
23
|
-
/** Use deep generator with per-node
|
|
23
|
+
/** Use deep generator with per-node durable steps */
|
|
24
24
|
durableSteps?: boolean;
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
@@ -31,26 +31,17 @@ export interface ExportOptions {
|
|
|
31
31
|
*
|
|
32
32
|
* @example
|
|
33
33
|
* ```bash
|
|
34
|
-
* # Export for
|
|
35
|
-
* flow-weaver export workflow.ts --target
|
|
36
|
-
*
|
|
37
|
-
* # Export for AWS Lambda
|
|
38
|
-
* flow-weaver export workflow.ts --target lambda --output dist/lambda/
|
|
39
|
-
*
|
|
40
|
-
* # Export for Cloudflare Workers
|
|
41
|
-
* flow-weaver export workflow.ts --target cloudflare --output workers/
|
|
34
|
+
* # Export for a target (install the corresponding pack first)
|
|
35
|
+
* flow-weaver export workflow.ts --target <target> --output dist/
|
|
42
36
|
*
|
|
43
37
|
* # Export specific workflow from multi-workflow file
|
|
44
|
-
* flow-weaver export multi-workflow.ts --target
|
|
45
|
-
*
|
|
46
|
-
* # Export all workflows as a single service (multi-workflow mode)
|
|
47
|
-
* flow-weaver export workflows.ts --target lambda --output dist/ --multi
|
|
38
|
+
* flow-weaver export multi-workflow.ts --target <target> --output api/ --workflow calculate
|
|
48
39
|
*
|
|
49
|
-
* # Export
|
|
50
|
-
* flow-weaver export workflows.ts --target
|
|
40
|
+
* # Export all workflows as a single service
|
|
41
|
+
* flow-weaver export workflows.ts --target <target> --output dist/ --multi
|
|
51
42
|
*
|
|
52
43
|
* # Export with API documentation routes
|
|
53
|
-
* flow-weaver export workflow.ts --target
|
|
44
|
+
* flow-weaver export workflow.ts --target <target> --output dist/ --docs
|
|
54
45
|
* ```
|
|
55
46
|
*/
|
|
56
47
|
export declare function exportCommand(input: string, options: ExportOptions): Promise<void>;
|
|
@@ -11,32 +11,23 @@ import { logger } from '../utils/logger.js';
|
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```bash
|
|
14
|
-
* # Export for
|
|
15
|
-
* flow-weaver export workflow.ts --target
|
|
16
|
-
*
|
|
17
|
-
* # Export for AWS Lambda
|
|
18
|
-
* flow-weaver export workflow.ts --target lambda --output dist/lambda/
|
|
19
|
-
*
|
|
20
|
-
* # Export for Cloudflare Workers
|
|
21
|
-
* flow-weaver export workflow.ts --target cloudflare --output workers/
|
|
14
|
+
* # Export for a target (install the corresponding pack first)
|
|
15
|
+
* flow-weaver export workflow.ts --target <target> --output dist/
|
|
22
16
|
*
|
|
23
17
|
* # Export specific workflow from multi-workflow file
|
|
24
|
-
* flow-weaver export multi-workflow.ts --target
|
|
25
|
-
*
|
|
26
|
-
* # Export all workflows as a single service (multi-workflow mode)
|
|
27
|
-
* flow-weaver export workflows.ts --target lambda --output dist/ --multi
|
|
18
|
+
* flow-weaver export multi-workflow.ts --target <target> --output api/ --workflow calculate
|
|
28
19
|
*
|
|
29
|
-
* # Export
|
|
30
|
-
* flow-weaver export workflows.ts --target
|
|
20
|
+
* # Export all workflows as a single service
|
|
21
|
+
* flow-weaver export workflows.ts --target <target> --output dist/ --multi
|
|
31
22
|
*
|
|
32
23
|
* # Export with API documentation routes
|
|
33
|
-
* flow-weaver export workflow.ts --target
|
|
24
|
+
* flow-weaver export workflow.ts --target <target> --output dist/ --docs
|
|
34
25
|
* ```
|
|
35
26
|
*/
|
|
36
27
|
export async function exportCommand(input, options) {
|
|
37
28
|
// Validate target is provided
|
|
38
29
|
if (!options.target) {
|
|
39
|
-
throw new Error('--target is required. Install a target pack
|
|
30
|
+
throw new Error('--target is required. Install a target pack first.');
|
|
40
31
|
}
|
|
41
32
|
const isDryRun = options.dryRun ?? false;
|
|
42
33
|
const t = logger.timer();
|
|
@@ -64,7 +55,7 @@ export async function exportCommand(input, options) {
|
|
|
64
55
|
logger.info('Include docs: Yes (/docs and /openapi.json routes)');
|
|
65
56
|
}
|
|
66
57
|
if (options.durableSteps) {
|
|
67
|
-
logger.info('Durable steps: Yes
|
|
58
|
+
logger.info('Durable steps: Yes');
|
|
68
59
|
}
|
|
69
60
|
if (isDryRun) {
|
|
70
61
|
logger.info('Mode: DRY RUN (no files will be written)');
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Types, use-case mappings, template selection, and post-scaffold output.
|
|
4
4
|
*/
|
|
5
5
|
export type PersonaId = 'nocode' | 'vibecoder' | 'lowcode' | 'expert';
|
|
6
|
-
export type UseCaseId = 'data' | 'ai' | 'api' | 'automation' | '
|
|
6
|
+
export type UseCaseId = 'data' | 'ai' | 'api' | 'automation' | 'minimal';
|
|
7
7
|
export declare const PERSONA_CHOICES: {
|
|
8
8
|
value: PersonaId;
|
|
9
9
|
name: string;
|
|
@@ -20,13 +20,22 @@ export interface UseCaseMapping {
|
|
|
20
20
|
default: string;
|
|
21
21
|
all: string[];
|
|
22
22
|
}
|
|
23
|
-
export declare const USE_CASE_TEMPLATES: Record<
|
|
23
|
+
export declare const USE_CASE_TEMPLATES: Record<string, UseCaseMapping>;
|
|
24
|
+
/**
|
|
25
|
+
* Register a use case contributed by a pack.
|
|
26
|
+
* Adds the use case choice and template mapping so it appears in fw init.
|
|
27
|
+
*/
|
|
28
|
+
export declare function registerPackUseCase(useCase: {
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
description: string;
|
|
32
|
+
}, templates: string[]): void;
|
|
24
33
|
/**
|
|
25
34
|
* Select the template for a given persona and use-case.
|
|
26
35
|
* For lowcode, returns the full list when the category has multiple templates.
|
|
27
36
|
* For nocode/vibecoder, always returns the single default.
|
|
28
37
|
*/
|
|
29
|
-
export declare function selectTemplateForPersona(persona: PersonaId, useCase: UseCaseId): {
|
|
38
|
+
export declare function selectTemplateForPersona(persona: PersonaId, useCase: UseCaseId | string): {
|
|
30
39
|
template: string;
|
|
31
40
|
choices?: string[];
|
|
32
41
|
};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { execSync } from 'child_process';
|
|
6
6
|
import { logger } from '../utils/logger.js';
|
|
7
|
-
import {
|
|
7
|
+
import { getAllWorkflowTemplates } from '../templates/index.js';
|
|
8
8
|
import { buildContext } from '../../context/index.js';
|
|
9
9
|
// ── Prompt choices ───────────────────────────────────────────────────────────
|
|
10
10
|
export const PERSONA_CHOICES = [
|
|
@@ -25,7 +25,6 @@ export const USE_CASE_CHOICES = [
|
|
|
25
25
|
{ value: 'ai', name: 'AI agent', description: 'LLM with tools, reasoning, or retrieval' },
|
|
26
26
|
{ value: 'api', name: 'API / webhook', description: 'HTTP endpoints and integrations' },
|
|
27
27
|
{ value: 'automation', name: 'Automation', description: 'Conditional logic, error handling, routing' },
|
|
28
|
-
{ value: 'cicd', name: 'CI/CD pipeline', description: 'Test, build, and deploy workflows' },
|
|
29
28
|
{ value: 'minimal', name: 'Something else', description: 'Start with a minimal template' },
|
|
30
29
|
];
|
|
31
30
|
export const USE_CASE_TEMPLATES = {
|
|
@@ -33,9 +32,33 @@ export const USE_CASE_TEMPLATES = {
|
|
|
33
32
|
ai: { default: 'ai-agent', all: ['ai-agent', 'ai-react', 'ai-rag', 'ai-chat'] },
|
|
34
33
|
api: { default: 'webhook', all: ['webhook'] },
|
|
35
34
|
automation: { default: 'conditional', all: ['conditional', 'error-handler'] },
|
|
36
|
-
cicd: { default: 'cicd-test-deploy', all: ['cicd-test-deploy', 'cicd-docker', 'cicd-multi-env', 'cicd-matrix'] },
|
|
37
35
|
minimal: { default: 'sequential', all: ['sequential'] },
|
|
38
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* Register a use case contributed by a pack.
|
|
39
|
+
* Adds the use case choice and template mapping so it appears in fw init.
|
|
40
|
+
*/
|
|
41
|
+
export function registerPackUseCase(useCase, templates) {
|
|
42
|
+
// Add to choices if not already present
|
|
43
|
+
if (!USE_CASE_CHOICES.some((c) => c.value === useCase.id)) {
|
|
44
|
+
// Insert before "minimal" (last entry)
|
|
45
|
+
const minimalIdx = USE_CASE_CHOICES.findIndex((c) => c.value === 'minimal');
|
|
46
|
+
const entry = { value: useCase.id, name: useCase.name, description: useCase.description };
|
|
47
|
+
if (minimalIdx >= 0) {
|
|
48
|
+
USE_CASE_CHOICES.splice(minimalIdx, 0, entry);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
USE_CASE_CHOICES.push(entry);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Add template mapping
|
|
55
|
+
if (!USE_CASE_TEMPLATES[useCase.id] && templates.length > 0) {
|
|
56
|
+
USE_CASE_TEMPLATES[useCase.id] = {
|
|
57
|
+
default: templates[0],
|
|
58
|
+
all: templates,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
39
62
|
/**
|
|
40
63
|
* Select the template for a given persona and use-case.
|
|
41
64
|
* For lowcode, returns the full list when the category has multiple templates.
|
|
@@ -57,7 +80,7 @@ export function selectTemplateForPersona(persona, useCase) {
|
|
|
57
80
|
*/
|
|
58
81
|
export function getTemplateSubChoices(templateIds) {
|
|
59
82
|
return templateIds.map((id) => {
|
|
60
|
-
const tmpl =
|
|
83
|
+
const tmpl = getAllWorkflowTemplates().find((t) => t.id === id);
|
|
61
84
|
return {
|
|
62
85
|
value: id,
|
|
63
86
|
name: id,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { ToolId } from './mcp-setup.js';
|
|
6
6
|
import type { TModuleFormat } from '../../ast/types.js';
|
|
7
|
-
import type { PersonaId
|
|
7
|
+
import type { PersonaId } from './init-personas.js';
|
|
8
8
|
export interface InitOptions {
|
|
9
9
|
name?: string;
|
|
10
10
|
template?: string;
|
|
@@ -28,7 +28,7 @@ export interface InitConfig {
|
|
|
28
28
|
git: boolean;
|
|
29
29
|
force: boolean;
|
|
30
30
|
persona: PersonaId;
|
|
31
|
-
useCase?:
|
|
31
|
+
useCase?: string;
|
|
32
32
|
/** Free-text description when user picked "Something else" */
|
|
33
33
|
useCaseDescription?: string;
|
|
34
34
|
mcp: boolean;
|
|
@@ -10,7 +10,7 @@ import input from '@inquirer/input';
|
|
|
10
10
|
import select, { Separator } from '@inquirer/select';
|
|
11
11
|
import confirm from '@inquirer/confirm';
|
|
12
12
|
import { ExitPromptError } from '@inquirer/core';
|
|
13
|
-
import { getWorkflowTemplate,
|
|
13
|
+
import { getWorkflowTemplate, getAllWorkflowTemplates } from '../templates/index.js';
|
|
14
14
|
import { logger } from '../utils/logger.js';
|
|
15
15
|
import { compileCommand } from './compile.js';
|
|
16
16
|
import { runMcpSetupFromInit, CLI_TOOL_BINARY, detectCliTools } from './mcp-setup.js';
|
|
@@ -37,9 +37,11 @@ export function toWorkflowName(projectName) {
|
|
|
37
37
|
export function isNonInteractive() {
|
|
38
38
|
return !process.stdin.isTTY;
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
// Dynamic: includes core templates plus any registered by extensions
|
|
41
|
+
const VALID_TEMPLATES = getAllWorkflowTemplates().map((t) => t.id);
|
|
41
42
|
const VALID_PERSONAS = ['nocode', 'vibecoder', 'lowcode', 'expert'];
|
|
42
|
-
|
|
43
|
+
// Dynamic: includes core use cases plus any registered by extensions
|
|
44
|
+
const VALID_USE_CASES = USE_CASE_CHOICES.map((c) => c.value);
|
|
43
45
|
// ── Config resolution (prompts) ──────────────────────────────────────────────
|
|
44
46
|
export async function resolveInitConfig(dirArg, options) {
|
|
45
47
|
const skipPrompts = options.yes || isNonInteractive();
|
|
@@ -124,18 +126,10 @@ export async function resolveInitConfig(dirArg, options) {
|
|
|
124
126
|
{ value: 'ai-react', name: 'ai-react', description: 'ReAct pattern' },
|
|
125
127
|
{ value: 'ai-rag', name: 'ai-rag', description: 'Retrieval-Augmented Generation' },
|
|
126
128
|
{ value: 'ai-chat', name: 'ai-chat', description: 'Conversational AI' },
|
|
127
|
-
new Separator('── Durable ──'),
|
|
128
|
-
{ value: 'ai-agent-durable', name: 'ai-agent-durable', description: 'Durable agent with approval gate' },
|
|
129
|
-
{ value: 'ai-pipeline-durable', name: 'ai-pipeline-durable', description: 'Durable data pipeline' },
|
|
130
129
|
new Separator('── Integration ──'),
|
|
131
130
|
{ value: 'webhook', name: 'webhook', description: 'HTTP webhook handler' },
|
|
132
131
|
new Separator('── Utility ──'),
|
|
133
132
|
{ value: 'error-handler', name: 'error-handler', description: 'Error handling and recovery' },
|
|
134
|
-
new Separator('── CI/CD ──'),
|
|
135
|
-
{ value: 'cicd-test-deploy', name: 'cicd-test-deploy', description: 'Test and deploy pipeline' },
|
|
136
|
-
{ value: 'cicd-docker', name: 'cicd-docker', description: 'Docker build and push' },
|
|
137
|
-
{ value: 'cicd-multi-env', name: 'cicd-multi-env', description: 'Multi-environment deploy' },
|
|
138
|
-
{ value: 'cicd-matrix', name: 'cicd-matrix', description: 'Matrix build strategy' },
|
|
139
133
|
],
|
|
140
134
|
default: 'sequential',
|
|
141
135
|
});
|