@synergenius/flow-weaver 0.13.2 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +41 -2
  2. package/dist/api/validate.js +8 -2
  3. package/dist/ast/types.d.ts +120 -0
  4. package/dist/chevrotain-parser/node-parser.d.ts +4 -0
  5. package/dist/chevrotain-parser/node-parser.js +41 -1
  6. package/dist/chevrotain-parser/port-parser.d.ts +1 -0
  7. package/dist/chevrotain-parser/port-parser.js +22 -2
  8. package/dist/chevrotain-parser/tokens.d.ts +3 -0
  9. package/dist/chevrotain-parser/tokens.js +15 -0
  10. package/dist/cli/commands/export.js +25 -38
  11. package/dist/cli/flow-weaver.mjs +63703 -54297
  12. package/dist/cli/templates/index.js +9 -0
  13. package/dist/cli/templates/workflows/cicd-docker.d.ts +9 -0
  14. package/dist/cli/templates/workflows/cicd-docker.js +110 -0
  15. package/dist/cli/templates/workflows/cicd-matrix.d.ts +9 -0
  16. package/dist/cli/templates/workflows/cicd-matrix.js +112 -0
  17. package/dist/cli/templates/workflows/cicd-multi-env.d.ts +9 -0
  18. package/dist/cli/templates/workflows/cicd-multi-env.js +118 -0
  19. package/dist/cli/templates/workflows/cicd-test-deploy.d.ts +11 -0
  20. package/dist/cli/templates/workflows/cicd-test-deploy.js +149 -0
  21. package/dist/constants.js +7 -0
  22. package/dist/deployment/index.d.ts +14 -7
  23. package/dist/deployment/index.js +29 -17
  24. package/dist/deployment/targets/base.d.ts +27 -2
  25. package/dist/deployment/targets/base.js +38 -6
  26. package/dist/deployment/targets/cicd-base.d.ts +111 -0
  27. package/dist/deployment/targets/cicd-base.js +357 -0
  28. package/dist/deployment/targets/cloudflare.d.ts +6 -0
  29. package/dist/deployment/targets/cloudflare.js +3 -0
  30. package/dist/deployment/targets/github-actions.d.ts +54 -0
  31. package/dist/deployment/targets/github-actions.js +366 -0
  32. package/dist/deployment/targets/gitlab-ci.d.ts +65 -0
  33. package/dist/deployment/targets/gitlab-ci.js +374 -0
  34. package/dist/deployment/targets/inngest.d.ts +25 -0
  35. package/dist/deployment/targets/inngest.js +10 -1
  36. package/dist/deployment/targets/lambda.d.ts +17 -0
  37. package/dist/deployment/targets/lambda.js +5 -0
  38. package/dist/deployment/targets/vercel.d.ts +16 -0
  39. package/dist/deployment/targets/vercel.js +5 -0
  40. package/dist/diagram/geometry.js +13 -5
  41. package/dist/export/index.d.ts +13 -9
  42. package/dist/export/index.js +129 -997
  43. package/dist/generated-version.d.ts +1 -1
  44. package/dist/generated-version.js +1 -1
  45. package/dist/jsdoc-parser.d.ts +130 -0
  46. package/dist/jsdoc-parser.js +408 -4
  47. package/dist/marketplace/index.d.ts +1 -1
  48. package/dist/marketplace/types.d.ts +13 -0
  49. package/dist/marketplace/validator.js +21 -2
  50. package/dist/mcp/tools-export.js +56 -14
  51. package/dist/parser.js +28 -1
  52. package/dist/validation/cicd-detection.d.ts +33 -0
  53. package/dist/validation/cicd-detection.js +76 -0
  54. package/dist/validation/cicd-rules.d.ts +62 -0
  55. package/dist/validation/cicd-rules.js +284 -0
  56. package/docs/reference/scaffold.md +4 -0
  57. package/package.json +4 -3
@@ -0,0 +1,374 @@
1
+ /**
2
+ * GitLab CI Export Target
3
+ *
4
+ * Generates .gitlab-ci.yml from a Flow Weaver CI/CD workflow.
5
+ * No FW runtime dependency — outputs native GitLab CI YAML.
6
+ *
7
+ * Key differences from GitHub Actions:
8
+ * - `stage:` instead of job `needs:` (generates `stages:` list)
9
+ * - `$CI_VARIABLE` instead of `${{ secrets.NAME }}`
10
+ * - `cache:` and `artifacts:` as native YAML keywords (no separate actions)
11
+ * - `services:` as native keyword
12
+ * - `rules:` for conditional execution
13
+ * - `environment:` as native keyword with `url:` and `when: manual` for approval
14
+ */
15
+ import { stringify as yamlStringify } from 'yaml';
16
+ import { isCICDWorkflow } from '../../validation/cicd-detection.js';
17
+ import { BaseCICDTarget, } from './cicd-base.js';
18
+ import { parseWorkflow } from '../../api/index.js';
19
+ import * as path from 'path';
20
+ export class GitLabCITarget extends BaseCICDTarget {
21
+ name = 'gitlab-ci';
22
+ description = 'GitLab CI/CD pipeline (.gitlab-ci.yml)';
23
+ deploySchema = {
24
+ runner: { type: 'string', description: 'Default Docker image', default: 'ubuntu:latest' },
25
+ };
26
+ nodeTypeDeploySchema = {
27
+ script: { type: 'string[]', description: 'GitLab CI script commands' },
28
+ image: { type: 'string', description: 'Docker image override' },
29
+ label: { type: 'string', description: 'Step display name' },
30
+ };
31
+ async generate(options) {
32
+ const filePath = path.resolve(options.sourceFile);
33
+ const outputDir = path.resolve(options.outputDir);
34
+ // Parse the workflow file to get AST
35
+ const parseResult = await parseWorkflow(filePath, { nodeTypesOnly: false });
36
+ if (parseResult.errors.length > 0) {
37
+ throw new Error(`Parse errors: ${parseResult.errors.join('; ')}`);
38
+ }
39
+ const allWorkflows = parseResult.allWorkflows || [];
40
+ const targetWorkflows = options.workflowName
41
+ ? allWorkflows.filter((w) => w.name === options.workflowName || w.functionName === options.workflowName)
42
+ : allWorkflows.filter((w) => isCICDWorkflow(w));
43
+ if (targetWorkflows.length === 0) {
44
+ throw new Error('No CI/CD workflows found. Ensure workflow has CI/CD annotations (@secret, @runner, @trigger, [job:], etc.)');
45
+ }
46
+ const files = [];
47
+ for (const ast of targetWorkflows) {
48
+ // Build job graph
49
+ const jobs = this.buildJobGraph(ast);
50
+ // Resolve secrets
51
+ this.resolveJobSecrets(jobs, ast, (name) => `$${name}`);
52
+ // Inject artifacts
53
+ const artifacts = ast.options?.cicd?.artifacts || [];
54
+ this.injectArtifactSteps(jobs, artifacts);
55
+ // Apply workflow options
56
+ this.applyWorkflowOptions(jobs, ast);
57
+ // Generate YAML
58
+ const yamlContent = this.renderPipelineYAML(ast, jobs);
59
+ files.push(this.createFile(outputDir, '.gitlab-ci.yml', yamlContent, 'config'));
60
+ // Generate secrets doc if secrets exist
61
+ const secrets = ast.options?.cicd?.secrets || [];
62
+ if (secrets.length > 0) {
63
+ const secretsDoc = this.generateSecretsDoc(secrets, 'gitlab-ci');
64
+ files.push(this.createFile(outputDir, 'SECRETS_SETUP.md', secretsDoc, 'other'));
65
+ }
66
+ }
67
+ return {
68
+ files,
69
+ target: this.name,
70
+ workflowName: options.displayName || targetWorkflows[0].name,
71
+ entryPoint: files[0].relativePath,
72
+ };
73
+ }
74
+ getDeployInstructions(_artifacts) {
75
+ return {
76
+ title: 'Deploy GitLab CI Pipeline',
77
+ prerequisites: [
78
+ 'GitLab repository',
79
+ 'CI/CD variables configured (see SECRETS_SETUP.md)',
80
+ 'GitLab Runner available (shared or project-specific)',
81
+ ],
82
+ steps: [
83
+ 'Copy .gitlab-ci.yml to your repository root',
84
+ 'Configure required variables in GitLab (Settings > CI/CD > Variables)',
85
+ 'Push to trigger the pipeline',
86
+ ],
87
+ localTestSteps: [
88
+ 'Install gitlab-runner: brew install gitlab-runner',
89
+ 'Run locally: gitlab-runner exec docker <job-name>',
90
+ ],
91
+ links: [
92
+ { label: 'GitLab CI/CD Docs', url: 'https://docs.gitlab.com/ee/ci/' },
93
+ { label: 'GitLab CI Lint', url: 'https://docs.gitlab.com/ee/ci/lint.html' },
94
+ ],
95
+ };
96
+ }
97
+ // ---------------------------------------------------------------------------
98
+ // Private: YAML Rendering
99
+ // ---------------------------------------------------------------------------
100
+ renderPipelineYAML(ast, jobs) {
101
+ const doc = {};
102
+ // stages (derived from job dependency order)
103
+ const stages = this.deriveStages(jobs);
104
+ doc.stages = stages;
105
+ // Default image
106
+ const defaultImage = this.deriveDefaultImage(ast, jobs);
107
+ if (defaultImage) {
108
+ doc.default = { image: defaultImage };
109
+ }
110
+ // Workflow-level rules (from triggers)
111
+ const rules = this.renderWorkflowRules(ast.options?.cicd?.triggers || []);
112
+ if (rules.length > 0) {
113
+ doc.workflow = { rules };
114
+ }
115
+ // Job definitions
116
+ for (const job of jobs) {
117
+ doc[job.id] = this.renderJob(job, ast, stages);
118
+ }
119
+ return yamlStringify(doc, {
120
+ lineWidth: 120,
121
+ defaultStringType: 'PLAIN',
122
+ defaultKeyType: 'PLAIN',
123
+ });
124
+ }
125
+ /**
126
+ * Derive stages from job dependency order.
127
+ * Jobs with no deps → stage 1, jobs depending on stage 1 → stage 2, etc.
128
+ */
129
+ deriveStages(jobs) {
130
+ const stages = [];
131
+ const assigned = new Map();
132
+ // Assign stages based on dependency depth
133
+ function getStage(jobId, jobs) {
134
+ if (assigned.has(jobId))
135
+ return assigned.get(jobId);
136
+ const job = jobs.find((j) => j.id === jobId);
137
+ if (!job || job.needs.length === 0) {
138
+ assigned.set(jobId, jobId);
139
+ return jobId;
140
+ }
141
+ // Stage is one after the latest dependency
142
+ const depStages = job.needs.map((dep) => getStage(dep, jobs));
143
+ assigned.set(jobId, jobId);
144
+ return jobId;
145
+ }
146
+ // Simple: use job IDs as stage names, ordered by dependency
147
+ for (const job of jobs) {
148
+ getStage(job.id, jobs);
149
+ if (!stages.includes(job.id)) {
150
+ stages.push(job.id);
151
+ }
152
+ }
153
+ return stages;
154
+ }
155
+ /**
156
+ * Derive default image from @deploy annotations or built-in mappings.
157
+ */
158
+ deriveDefaultImage(_ast, jobs) {
159
+ // Check steps for @deploy gitlab-ci image or built-in mapping
160
+ for (const job of jobs) {
161
+ for (const step of job.steps) {
162
+ const mapping = this.resolveActionMapping(step, 'gitlab-ci');
163
+ if (mapping?.gitlabImage)
164
+ return mapping.gitlabImage;
165
+ }
166
+ }
167
+ return undefined;
168
+ }
169
+ /**
170
+ * Convert CI/CD triggers to GitLab CI workflow rules.
171
+ */
172
+ renderWorkflowRules(triggers) {
173
+ if (triggers.length === 0)
174
+ return [];
175
+ const rules = [];
176
+ for (const trigger of triggers) {
177
+ switch (trigger.type) {
178
+ case 'push':
179
+ if (trigger.branches) {
180
+ for (const branch of trigger.branches) {
181
+ rules.push({
182
+ if: `$CI_COMMIT_BRANCH == "${branch}"`,
183
+ when: 'always',
184
+ });
185
+ }
186
+ }
187
+ else {
188
+ rules.push({ if: '$CI_PIPELINE_SOURCE == "push"', when: 'always' });
189
+ }
190
+ break;
191
+ case 'pull_request':
192
+ rules.push({
193
+ if: '$CI_PIPELINE_SOURCE == "merge_request_event"',
194
+ when: 'always',
195
+ });
196
+ break;
197
+ case 'schedule':
198
+ rules.push({
199
+ if: '$CI_PIPELINE_SOURCE == "schedule"',
200
+ when: 'always',
201
+ });
202
+ break;
203
+ case 'dispatch':
204
+ rules.push({
205
+ if: '$CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "api"',
206
+ when: 'always',
207
+ });
208
+ break;
209
+ case 'tag':
210
+ rules.push({ if: '$CI_COMMIT_TAG', when: 'always' });
211
+ break;
212
+ }
213
+ }
214
+ return rules;
215
+ }
216
+ renderJob(job, ast, stages) {
217
+ const jobObj = {};
218
+ // stage
219
+ jobObj.stage = job.id;
220
+ // image (from runner or default)
221
+ if (job.runner && job.runner !== 'ubuntu-latest') {
222
+ // GitLab uses Docker images, not runner labels
223
+ // Map common GitHub runners to Docker images
224
+ const imageMap = {
225
+ 'ubuntu-latest': 'ubuntu:latest',
226
+ 'ubuntu-22.04': 'ubuntu:22.04',
227
+ 'ubuntu-20.04': 'ubuntu:20.04',
228
+ };
229
+ const image = imageMap[job.runner] || job.runner;
230
+ jobObj.image = image;
231
+ }
232
+ // needs (for DAG mode instead of stage-based ordering)
233
+ if (job.needs.length > 0) {
234
+ jobObj.needs = job.needs;
235
+ }
236
+ // environment
237
+ if (job.environment) {
238
+ const envConfig = ast.options?.cicd?.environments?.find((e) => e.name === job.environment);
239
+ const envObj = { name: job.environment };
240
+ if (envConfig?.url)
241
+ envObj.url = envConfig.url;
242
+ if (envConfig?.reviewers)
243
+ envObj.deployment_tier = 'production';
244
+ jobObj.environment = envObj;
245
+ // Protected environments require manual approval in GitLab
246
+ if (envConfig?.reviewers) {
247
+ jobObj.when = 'manual';
248
+ }
249
+ }
250
+ // services
251
+ if (job.services && job.services.length > 0) {
252
+ jobObj.services = job.services.map((svc) => {
253
+ const svcObj = { name: svc.image };
254
+ if (svc.ports) {
255
+ // GitLab services expose the first port automatically
256
+ // Additional port mapping needs alias
257
+ }
258
+ return svcObj;
259
+ });
260
+ }
261
+ // variables (from secrets)
262
+ if (job.secrets.length > 0) {
263
+ // In GitLab, CI/CD variables are automatically available
264
+ // But we document them for clarity
265
+ const variables = {};
266
+ for (const secret of job.secrets) {
267
+ variables[secret] = `$${secret}`;
268
+ }
269
+ jobObj.variables = variables;
270
+ }
271
+ // cache
272
+ if (job.cache) {
273
+ jobObj.cache = this.renderCache(job.cache);
274
+ }
275
+ // artifacts (upload)
276
+ if (job.uploadArtifacts && job.uploadArtifacts.length > 0) {
277
+ const paths = job.uploadArtifacts.map((a) => a.path);
278
+ const expiry = job.uploadArtifacts[0].retention
279
+ ? `${job.uploadArtifacts[0].retention} days`
280
+ : '1 week';
281
+ jobObj.artifacts = {
282
+ paths,
283
+ expire_in: expiry,
284
+ };
285
+ }
286
+ // script (the actual steps)
287
+ const script = [];
288
+ // Download artifacts (GitLab handles this automatically via `needs:`)
289
+ // but we add a comment for clarity if explicit artifacts are expected
290
+ if (job.downloadArtifacts && job.downloadArtifacts.length > 0) {
291
+ script.push(`# Artifacts from: ${job.downloadArtifacts.join(', ')} (downloaded automatically via needs:)`);
292
+ }
293
+ // Step scripts
294
+ for (const step of job.steps) {
295
+ const stepScript = this.renderStepScript(step);
296
+ script.push(...stepScript);
297
+ }
298
+ jobObj.script = script;
299
+ return jobObj;
300
+ }
301
+ renderStepScript(step) {
302
+ const mapping = this.resolveActionMapping(step, 'gitlab-ci');
303
+ const lines = [];
304
+ // Add env vars as export statements if present
305
+ if (step.env) {
306
+ for (const [key, value] of Object.entries(step.env)) {
307
+ lines.push(`export ${key}="${value}"`);
308
+ }
309
+ }
310
+ if (mapping?.gitlabScript) {
311
+ lines.push(`# ${mapping.label || step.name}`);
312
+ lines.push(...mapping.gitlabScript);
313
+ }
314
+ else {
315
+ // Unknown node type — generate TODO
316
+ lines.push(`# TODO: Implement '${step.id}' (node type: ${step.nodeType})`);
317
+ lines.push(`echo "Step: ${step.name}"`);
318
+ }
319
+ return lines;
320
+ }
321
+ renderCache(cache) {
322
+ const cacheObj = {};
323
+ switch (cache.strategy) {
324
+ case 'npm':
325
+ cacheObj.key = {
326
+ files: [cache.key || 'package-lock.json'],
327
+ };
328
+ cacheObj.paths = [cache.path || 'node_modules/'];
329
+ break;
330
+ case 'pip':
331
+ cacheObj.key = {
332
+ files: [cache.key || 'requirements.txt'],
333
+ };
334
+ cacheObj.paths = [cache.path || '.pip-cache/'];
335
+ break;
336
+ default:
337
+ cacheObj.key = cache.key || '$CI_COMMIT_REF_SLUG';
338
+ cacheObj.paths = [cache.path || '.cache/'];
339
+ }
340
+ return cacheObj;
341
+ }
342
+ /**
343
+ * Apply workflow-level options to jobs.
344
+ */
345
+ applyWorkflowOptions(jobs, ast) {
346
+ const cicd = ast.options?.cicd;
347
+ if (!cicd)
348
+ return;
349
+ // Apply cache to all jobs
350
+ if (cicd.caches && cicd.caches.length > 0) {
351
+ for (const job of jobs) {
352
+ if (!job.cache) {
353
+ job.cache = cicd.caches[0];
354
+ }
355
+ }
356
+ }
357
+ // Apply services to all jobs
358
+ if (cicd.services && cicd.services.length > 0) {
359
+ for (const job of jobs) {
360
+ if (!job.services) {
361
+ job.services = cicd.services;
362
+ }
363
+ }
364
+ }
365
+ // Apply matrix (GitLab uses `parallel: matrix:`)
366
+ if (cicd.matrix) {
367
+ const rootJobs = jobs.filter((j) => j.needs.length === 0);
368
+ for (const job of rootJobs) {
369
+ job.matrix = cicd.matrix;
370
+ }
371
+ }
372
+ }
373
+ }
374
+ //# sourceMappingURL=gitlab-ci.js.map
@@ -12,6 +12,31 @@ import { BaseExportTarget, type ExportOptions, type ExportArtifacts, type Deploy
12
12
  export declare class InngestTarget extends BaseExportTarget {
13
13
  readonly name = "inngest";
14
14
  readonly description = "Inngest \u2014 durable, event-driven workflow functions";
15
+ readonly deploySchema: {
16
+ durableSteps: {
17
+ type: "boolean";
18
+ description: string;
19
+ default: boolean;
20
+ };
21
+ framework: {
22
+ type: "string";
23
+ description: string;
24
+ };
25
+ serve: {
26
+ type: "boolean";
27
+ description: string;
28
+ default: boolean;
29
+ };
30
+ retries: {
31
+ type: "number";
32
+ description: string;
33
+ default: number;
34
+ };
35
+ triggerEvent: {
36
+ type: "string";
37
+ description: string;
38
+ };
39
+ };
15
40
  /**
16
41
  * Sanitize a name into a valid Inngest ID (lowercase, alphanumeric + hyphens)
17
42
  */
@@ -394,6 +394,13 @@ export default app;
394
394
  export class InngestTarget extends BaseExportTarget {
395
395
  name = 'inngest';
396
396
  description = 'Inngest — durable, event-driven workflow functions';
397
+ deploySchema = {
398
+ durableSteps: { type: 'boolean', description: 'Per-node step.run() for durability', default: false },
399
+ framework: { type: 'string', description: 'Framework adapter: next, express, hono, fastify, remix' },
400
+ serve: { type: 'boolean', description: 'Generate serve() handler export', default: false },
401
+ retries: { type: 'number', description: 'Retries per function', default: 3 },
402
+ triggerEvent: { type: 'string', description: 'Custom trigger event name' },
403
+ };
397
404
  /**
398
405
  * Sanitize a name into a valid Inngest ID (lowercase, alphanumeric + hyphens)
399
406
  */
@@ -413,7 +420,9 @@ export class InngestTarget extends BaseExportTarget {
413
420
  async generate(options) {
414
421
  const files = [];
415
422
  const includeDocs = options.includeDocs ?? false;
416
- const durableSteps = options.targetOptions?.durableSteps === true;
423
+ // @deploy inngest annotations take precedence over CLI flags
424
+ const deployConfig = options.targetOptions?.deploy?.inngest;
425
+ const durableSteps = deployConfig?.durableSteps === true || options.targetOptions?.durableSteps === true;
417
426
  const serviceId = this.toInngestId(options.displayName);
418
427
  const functionId = this.toInngestId(options.workflowName);
419
428
  const functionVar = `fn_${this.toVarName(options.workflowName)}`;
@@ -10,6 +10,23 @@ import { BaseExportTarget, type ExportOptions, type ExportArtifacts, type Deploy
10
10
  export declare class LambdaTarget extends BaseExportTarget {
11
11
  readonly name = "lambda";
12
12
  readonly description = "AWS Lambda with SAM (Serverless Application Model)";
13
+ readonly deploySchema: {
14
+ memory: {
15
+ type: "number";
16
+ description: string;
17
+ default: number;
18
+ };
19
+ runtime: {
20
+ type: "string";
21
+ description: string;
22
+ default: string;
23
+ };
24
+ timeout: {
25
+ type: "number";
26
+ description: string;
27
+ default: number;
28
+ };
29
+ };
13
30
  generate(options: ExportOptions): Promise<ExportArtifacts>;
14
31
  /**
15
32
  * Generate OpenAPI specification for the workflow
@@ -873,6 +873,11 @@ Outputs:
873
873
  export class LambdaTarget extends BaseExportTarget {
874
874
  name = 'lambda';
875
875
  description = 'AWS Lambda with SAM (Serverless Application Model)';
876
+ deploySchema = {
877
+ memory: { type: 'number', description: 'Lambda memory in MB', default: 256 },
878
+ runtime: { type: 'string', description: 'Lambda runtime', default: 'nodejs20.x' },
879
+ timeout: { type: 'number', description: 'Function timeout in seconds', default: 30 },
880
+ };
876
881
  async generate(options) {
877
882
  const files = [];
878
883
  const includeDocs = options.includeDocs ?? false;
@@ -10,6 +10,22 @@ import { BaseExportTarget, type ExportOptions, type ExportArtifacts, type Deploy
10
10
  export declare class VercelTarget extends BaseExportTarget {
11
11
  readonly name = "vercel";
12
12
  readonly description = "Vercel Serverless Functions";
13
+ readonly deploySchema: {
14
+ maxDuration: {
15
+ type: "number";
16
+ description: string;
17
+ default: number;
18
+ };
19
+ memory: {
20
+ type: "number";
21
+ description: string;
22
+ default: number;
23
+ };
24
+ regions: {
25
+ type: "string[]";
26
+ description: string;
27
+ };
28
+ };
13
29
  generate(options: ExportOptions): Promise<ExportArtifacts>;
14
30
  /**
15
31
  * Generate OpenAPI specification for the workflow
@@ -519,6 +519,11 @@ export default async function handler(req: VercelRequest, res: VercelResponse) {
519
519
  export class VercelTarget extends BaseExportTarget {
520
520
  name = 'vercel';
521
521
  description = 'Vercel Serverless Functions';
522
+ deploySchema = {
523
+ maxDuration: { type: 'number', description: 'Max function duration in seconds', default: 60 },
524
+ memory: { type: 'number', description: 'Memory in MB', default: 1024 },
525
+ regions: { type: 'string[]', description: 'Deployment regions' },
526
+ };
522
527
  async generate(options) {
523
528
  const files = [];
524
529
  const maxDuration = options.targetOptions?.maxDuration || 60;
@@ -176,19 +176,19 @@ function orderedPorts(ports, direction) {
176
176
  function buildInstanceNode(instId, instNodeType, instConfig, nodeTypeMap, theme = 'dark') {
177
177
  const nt = nodeTypeMap.get(instNodeType);
178
178
  const allInputs = nt
179
- ? { ...filterNonScopedPorts(nt.inputs) }
179
+ ? filterHiddenPorts(filterNonScopedPorts(nt.inputs))
180
180
  : {};
181
181
  const allOutputs = nt
182
- ? { ...filterNonScopedPorts(nt.outputs) }
182
+ ? filterHiddenPorts(filterNonScopedPorts(nt.outputs))
183
183
  : {};
184
184
  if (nt && !nt.expression) {
185
- if (!allInputs.execute)
185
+ if (!allInputs.execute && !nt.inputs.execute?.hidden)
186
186
  allInputs.execute = { dataType: 'STEP' };
187
187
  }
188
- if (nt && nt.hasSuccessPort && !allOutputs.onSuccess) {
188
+ if (nt && nt.hasSuccessPort && !allOutputs.onSuccess && !nt.outputs.onSuccess?.hidden) {
189
189
  allOutputs.onSuccess = { dataType: 'STEP', isControlFlow: true };
190
190
  }
191
- if (nt && nt.hasFailurePort && !allOutputs.onFailure) {
191
+ if (nt && nt.hasFailurePort && !allOutputs.onFailure && !nt.outputs.onFailure?.hidden) {
192
192
  allOutputs.onFailure = { dataType: 'STEP', isControlFlow: true, failure: true };
193
193
  }
194
194
  // Resolve icon: instance config → node type visuals → auto-detection
@@ -1084,6 +1084,14 @@ function findScopeParent(childId, diagramNodes) {
1084
1084
  }
1085
1085
  return undefined;
1086
1086
  }
1087
+ function filterHiddenPorts(ports) {
1088
+ const result = {};
1089
+ for (const [name, def] of Object.entries(ports)) {
1090
+ if (!def.hidden)
1091
+ result[name] = def;
1092
+ }
1093
+ return result;
1094
+ }
1087
1095
  function filterNonScopedPorts(ports) {
1088
1096
  const result = {};
1089
1097
  for (const [name, def] of Object.entries(ports)) {
@@ -3,9 +3,13 @@
3
3
  * Generates deployment-ready handlers for various platforms
4
4
  */
5
5
  /**
6
- * Supported export targets
6
+ * Export target identifier.
7
+ *
8
+ * Widened to `string` so marketplace packs can register arbitrary targets
9
+ * without modifying core. Well-known built-in names (when packs are installed):
10
+ * 'lambda', 'vercel', 'cloudflare', 'inngest', 'github-actions', 'gitlab-ci'
7
11
  */
8
- export type ExportTarget = 'lambda' | 'vercel' | 'cloudflare' | 'inngest';
12
+ export type ExportTarget = string;
9
13
  /**
10
14
  * Options for exporting a workflow
11
15
  */
@@ -54,15 +58,15 @@ export interface ExportResult {
54
58
  openApiSpec?: object;
55
59
  }
56
60
  /**
57
- * Export multiple workflows as a single service
58
- */
59
- export declare function exportMultiWorkflow(options: ExportOptions): Promise<ExportResult>;
60
- /**
61
- * Export a workflow for serverless deployment
61
+ * Export a workflow for deployment.
62
+ *
63
+ * Delegates to the target registry — every target is a plugin discovered
64
+ * from installed marketplace packs. The legacy template system has been
65
+ * replaced by target classes that generate their own handler + config.
62
66
  */
63
67
  export declare function exportWorkflow(options: ExportOptions): Promise<ExportResult>;
64
68
  /**
65
- * List supported export targets
69
+ * List installed export targets by querying the registry.
66
70
  */
67
- export declare function getSupportedTargets(): ExportTarget[];
71
+ export declare function getSupportedTargets(projectDir?: string): Promise<string[]>;
68
72
  //# sourceMappingURL=index.d.ts.map