@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
package/README.md CHANGED
@@ -12,10 +12,49 @@
12
12
 
13
13
  Design agent workflows in the Studio, in TypeScript, or let AI build them for you. The compiler validates everything with 20+ rule categories. The output is standalone TypeScript you deploy anywhere, zero runtime dependency on Flow Weaver.
14
14
 
15
+ *Got an AGENTS.md or runbook? [Convert it to a typed workflow →](https://flowweaver.ai/services/md-converter)*
16
+
15
17
  [**flowweaver.ai**](https://flowweaver.ai) · [**Open the Studio**](https://flowweaver.ai/studio) · [**Docs**](https://flowweaver.ai/docs) · [**Discord**](https://discord.gg/6Byh3ur2bk) · [**npm**](https://www.npmjs.com/package/@synergenius/flow-weaver)
16
18
 
17
19
  ---
18
20
 
21
+ ## Your AGENTS.md is a workflow waiting to happen
22
+
23
+ You already wrote the steps, the branching logic, the edge cases. But it's a markdown file. It doesn't run, doesn't validate, and you can't see the full flow at a glance.
24
+
25
+ **Paste this:**
26
+
27
+ ```markdown
28
+ # Code Review Agent
29
+
30
+ ### 1. Analyze diff
31
+ Send the PR diff to an LLM for security, quality, and style review.
32
+
33
+ ### 2. Classify severity
34
+ Critical (must fix) · Warning (should fix) · Suggestion (nice to have).
35
+
36
+ ### 3. Route
37
+ Critical issues → request changes. Otherwise → approve with comments.
38
+ ```
39
+
40
+ **Get this:**
41
+
42
+ <a href="https://htmlpreview.github.io/?https://github.com/synergenius-fw/flow-weaver/blob/main/docs/images/code-review-agent.html">
43
+ <picture>
44
+ <source media="(prefers-color-scheme: dark)" srcset="docs/images/code-review-agent-dark.svg">
45
+ <source media="(prefers-color-scheme: light)" srcset="docs/images/code-review-agent-light.svg">
46
+ <img alt="Code Review Agent workflow diagram generated from AGENTS.md" src="docs/images/code-review-agent-dark.svg" width="100%">
47
+ </picture>
48
+ </a>
49
+
50
+ <sup>Click the diagram to open the interactive version (zoom, pan, inspect nodes).</sup>
51
+
52
+ The converter extracts the steps and decision points from your markdown and produces typed TypeScript plus a visual diagram. You can run it, test it, deploy it.
53
+
54
+ [**Try the converter →**](https://flowweaver.ai/services/md-converter) &ensp; Works with AGENTS.md, CLAUDE.md, Cursor rules, runbooks, SOPs, and any process doc.
55
+
56
+ ---
57
+
19
58
  ## Try It
20
59
 
21
60
  **In the browser.** Open the [Cloud Studio](https://flowweaver.ai/studio), sign up, and start building. No install required.
@@ -31,7 +70,7 @@ npx flow-weaver run workflows/example.ts --params '{"input": "value"}'
31
70
 
32
71
  ## How It Works
33
72
 
34
- **Generate.** AI agents build workflows via 48 MCP tools, or you build visually in the Studio, or you write annotated TypeScript by hand. All three stay in sync.
73
+ **Generate.** Let AI build it for you, design visually in the Studio, or write annotated TypeScript by hand. All three stay in sync.
35
74
 
36
75
  **Validate.** The compiler catches wiring errors, type mismatches, missing handlers, unreachable paths, and agent-specific mistakes before anything runs. Not at runtime, not in production.
37
76
 
@@ -43,7 +82,7 @@ npx flow-weaver run workflows/example.ts --params '{"input": "value"}'
43
82
 
44
83
  **TypeScript.** Define workflows in plain TypeScript by annotating functions with JSDoc. The compiler derives an executable workflow graph with static typing and compile-time validation. No YAML, no JSON configuration, no runtime layer. Remove the annotations and you keep a clean TypeScript file with zero dependencies.
45
84
 
46
- **AI Agents.** Connect Claude Code, Cursor, or OpenClaw and let agents scaffold implementations, run the compiler, interpret validation errors, apply corrections, and iterate until the workflow compiles. Agents then test with deterministic mock providers and generate diagrams for human review.
85
+ **AI Agents.** Connect Claude Code, Cursor, or OpenClaw and let agents scaffold, compile, fix validation errors, and iterate until the workflow works. Agents can also test with mock AI responses and generate diagrams for review.
47
86
 
48
87
  ## Quick Start
49
88
 
@@ -6,6 +6,8 @@
6
6
  */
7
7
  import { validator } from "../validator.js";
8
8
  import { getAgentValidationRules } from "../validation/agent-rules.js";
9
+ import { getCICDValidationRules } from "../validation/cicd-rules.js";
10
+ import { isCICDWorkflow } from "../validation/cicd-detection.js";
9
11
  /**
10
12
  * Validates a workflow AST
11
13
  *
@@ -19,8 +21,12 @@ import { getAgentValidationRules } from "../validation/agent-rules.js";
19
21
  export function validateWorkflow(ast, options) {
20
22
  // Use the consolidated validator
21
23
  const result = validator.validate(ast, { mode: options?.mode });
22
- // Apply agent-specific rules + any custom rules
23
- const allRules = [...getAgentValidationRules(), ...(options?.customRules || [])];
24
+ // Apply agent-specific rules, CI/CD rules (only if workflow is CI/CD), and custom rules
25
+ const allRules = [
26
+ ...getAgentValidationRules(),
27
+ ...(isCICDWorkflow(ast) ? getCICDValidationRules() : []),
28
+ ...(options?.customRules || []),
29
+ ];
24
30
  for (const rule of allRules) {
25
31
  const ruleResults = rule.validate(ast);
26
32
  for (const err of ruleResults) {
@@ -277,6 +277,8 @@ export type TNodeTypeAST = {
277
277
  declarationKind?: 'const' | 'let' | 'var';
278
278
  /** npm package specifier this node type was resolved from (e.g., 'date-fns') */
279
279
  importSource?: string;
280
+ /** Per-target deploy config from @deploy annotations (e.g., deploy['github-actions'].action) */
281
+ deploy?: Record<string, Record<string, unknown>>;
280
282
  };
281
283
  /**
282
284
  * Port configuration for instance-level overrides
@@ -395,6 +397,10 @@ export type TNodeInstanceAST = {
395
397
  sourceLocation?: TSourceLocation;
396
398
  /** Reserved for plugin extensibility */
397
399
  metadata?: TNodeMetadata;
400
+ /** CI/CD job group this node belongs to (from [job: "name"] attribute) */
401
+ job?: string;
402
+ /** CI/CD environment for this node's job (from [environment: "name"] attribute) */
403
+ environment?: string;
398
404
  };
399
405
  /**
400
406
  * Type compatibility result for a connection.
@@ -440,6 +446,120 @@ export type TWorkflowOptions = {
440
446
  limit: number;
441
447
  period?: string;
442
448
  };
449
+ /** CI/CD pipeline configuration from @secret, @cache, @artifact, etc. */
450
+ cicd?: TCICDOptions;
451
+ /** Target-specific config (e.g., deploy['github-actions'].runner) */
452
+ deploy?: Record<string, Record<string, unknown>>;
453
+ };
454
+ /**
455
+ * CI/CD domain options — shared across all CI/CD export targets.
456
+ * Populated from @secret, @runner, @cache, @artifact, @environment,
457
+ * @matrix, @service, @concurrency annotations.
458
+ */
459
+ export type TCICDOptions = {
460
+ /** Secret declarations for CI/CD pipelines */
461
+ secrets?: TCICDSecret[];
462
+ /** Default runner environment for CI/CD jobs */
463
+ runner?: string;
464
+ /** Cache configurations for CI/CD */
465
+ caches?: TCICDCache[];
466
+ /** Artifact declarations for CI/CD */
467
+ artifacts?: TCICDArtifact[];
468
+ /** Deployment environment configurations */
469
+ environments?: TCICDEnvironment[];
470
+ /** Matrix strategy for multi-version/OS testing */
471
+ matrix?: TCICDMatrix;
472
+ /** Sidecar service containers */
473
+ services?: TCICDService[];
474
+ /** Concurrency control */
475
+ concurrency?: {
476
+ group: string;
477
+ cancelInProgress?: boolean;
478
+ };
479
+ /** Extended CI/CD triggers (push, PR, dispatch, tag) */
480
+ triggers?: TCICDTrigger[];
481
+ };
482
+ /** Secret declaration from @secret annotation */
483
+ export type TCICDSecret = {
484
+ /** Secret name (e.g., NPM_TOKEN) */
485
+ name: string;
486
+ /** Human-readable description */
487
+ description?: string;
488
+ /** Platform restriction (default: all) */
489
+ platform?: 'github' | 'gitlab' | 'all';
490
+ /** Which job scope uses this secret */
491
+ scope?: string;
492
+ };
493
+ /** Cache configuration from @cache annotation */
494
+ export type TCICDCache = {
495
+ /** Cache strategy name (e.g., npm, pip, custom) */
496
+ strategy: string;
497
+ /** Cache path override */
498
+ path?: string;
499
+ /** Cache key file (e.g., package-lock.json) */
500
+ key?: string;
501
+ };
502
+ /** Artifact declaration from @artifact annotation */
503
+ export type TCICDArtifact = {
504
+ /** Artifact name */
505
+ name: string;
506
+ /** Path(s) to include */
507
+ path: string;
508
+ /** Retention in days */
509
+ retention?: number;
510
+ };
511
+ /** Deployment environment from @environment annotation */
512
+ export type TCICDEnvironment = {
513
+ /** Environment name (e.g., production, staging) */
514
+ name: string;
515
+ /** Environment URL */
516
+ url?: string;
517
+ /** Number of required reviewers */
518
+ reviewers?: number;
519
+ };
520
+ /** Matrix strategy from @matrix annotation */
521
+ export type TCICDMatrix = {
522
+ /** Dimension name → values (e.g., { "node": ["18","20","22"] }) */
523
+ dimensions: Record<string, string[]>;
524
+ /** Explicit include entries */
525
+ include?: Record<string, string>[];
526
+ /** Explicit exclude entries */
527
+ exclude?: Record<string, string>[];
528
+ };
529
+ /** Service container from @service annotation */
530
+ export type TCICDService = {
531
+ /** Service name */
532
+ name: string;
533
+ /** Docker image */
534
+ image: string;
535
+ /** Environment variables */
536
+ env?: Record<string, string>;
537
+ /** Port mappings (host:container) */
538
+ ports?: string[];
539
+ };
540
+ /** CI/CD trigger from extended @trigger annotation */
541
+ export type TCICDTrigger = {
542
+ /** Trigger type */
543
+ type: 'push' | 'pull_request' | 'schedule' | 'dispatch' | 'tag';
544
+ /** Branch filters */
545
+ branches?: string[];
546
+ /** Path filters */
547
+ paths?: string[];
548
+ /** Path ignore filters */
549
+ pathsIgnore?: string[];
550
+ /** Tag pattern (for tag triggers) */
551
+ pattern?: string;
552
+ /** PR event types (e.g., opened, synchronize) */
553
+ types?: string[];
554
+ /** Cron expression (for schedule triggers) */
555
+ cron?: string;
556
+ /** Dispatch inputs */
557
+ inputs?: Record<string, {
558
+ description?: string;
559
+ required?: boolean;
560
+ default?: string;
561
+ type?: string;
562
+ }>;
443
563
  };
444
564
  /**
445
565
  * Connection AST - A link between two ports.
@@ -27,6 +27,10 @@ export interface NodeParseResult {
27
27
  label: string;
28
28
  tooltip?: string;
29
29
  }>;
30
+ /** CI/CD job group */
31
+ job?: string;
32
+ /** CI/CD deployment environment */
33
+ environment?: string;
30
34
  }
31
35
  /**
32
36
  * Parse a @node line and return structured result.
@@ -4,7 +4,7 @@
4
4
  * Parser for @node declarations using Chevrotain.
5
5
  */
6
6
  import { CstParser } from 'chevrotain';
7
- import { JSDocLexer, NodeTag, Identifier, Dot, Integer, LabelPrefix, ExprPrefix, PortOrderPrefix, PortLabelPrefix, MinimizedKeyword, PullExecutionPrefix, SizePrefix, PositionPrefix, ColorPrefix, IconPrefix, TagsPrefix, StringLiteral, LBracket, RBracket, Comma, Equals, EventEq, CronEq, MatchEq, TimeoutEq, LimitEq, PeriodEq, allTokens, } from './tokens.js';
7
+ import { JSDocLexer, NodeTag, Identifier, Dot, Integer, LabelPrefix, ExprPrefix, PortOrderPrefix, PortLabelPrefix, MinimizedKeyword, PullExecutionPrefix, SizePrefix, PositionPrefix, ColorPrefix, IconPrefix, JobPrefix, EnvironmentAttrPrefix, TagsPrefix, StringLiteral, LBracket, RBracket, Comma, Equals, EventEq, CronEq, MatchEq, TimeoutEq, LimitEq, PeriodEq, allTokens, } from './tokens.js';
8
8
  // =============================================================================
9
9
  // Parser Definition
10
10
  // =============================================================================
@@ -51,6 +51,8 @@ class NodeParser extends CstParser {
51
51
  { ALT: () => this.SUBRULE(this.positionAttr) },
52
52
  { ALT: () => this.SUBRULE(this.colorAttr) },
53
53
  { ALT: () => this.SUBRULE(this.iconAttr) },
54
+ { ALT: () => this.SUBRULE(this.jobAttr) },
55
+ { ALT: () => this.SUBRULE(this.environmentAttr) },
54
56
  { ALT: () => this.SUBRULE(this.tagsAttr) },
55
57
  ]);
56
58
  },
@@ -157,6 +159,16 @@ class NodeParser extends CstParser {
157
159
  this.CONSUME(IconPrefix);
158
160
  this.CONSUME(StringLiteral, { LABEL: 'iconValue' });
159
161
  });
162
+ // job: "value" — CI/CD job group
163
+ jobAttr = this.RULE('jobAttr', () => {
164
+ this.CONSUME(JobPrefix);
165
+ this.CONSUME(StringLiteral, { LABEL: 'jobValue' });
166
+ });
167
+ // environment: "value" — CI/CD deployment environment
168
+ environmentAttr = this.RULE('environmentAttr', () => {
169
+ this.CONSUME(EnvironmentAttrPrefix);
170
+ this.CONSUME(StringLiteral, { LABEL: 'environmentValue' });
171
+ });
160
172
  // tags: "label" "tooltip", "label2"
161
173
  tagsAttr = this.RULE('tagsAttr', () => {
162
174
  this.CONSUME(TagsPrefix);
@@ -203,6 +215,8 @@ class NodeVisitor extends BaseVisitor {
203
215
  let color;
204
216
  let icon;
205
217
  let tags;
218
+ let job;
219
+ let environment;
206
220
  if (ctx.parentScopeRef) {
207
221
  parentScope = this.visit(ctx.parentScopeRef);
208
222
  }
@@ -231,6 +245,10 @@ class NodeVisitor extends BaseVisitor {
231
245
  icon = attrs.icon;
232
246
  if (attrs.tags)
233
247
  tags = [...(tags || []), ...attrs.tags];
248
+ if (attrs.job)
249
+ job = attrs.job;
250
+ if (attrs.environment)
251
+ environment = attrs.environment;
234
252
  }
235
253
  }
236
254
  return {
@@ -248,6 +266,8 @@ class NodeVisitor extends BaseVisitor {
248
266
  ...(color && { color }),
249
267
  ...(icon && { icon }),
250
268
  ...(tags && { tags }),
269
+ ...(job && { job }),
270
+ ...(environment && { environment }),
251
271
  };
252
272
  }
253
273
  parentScopeRef(ctx) {
@@ -267,6 +287,8 @@ class NodeVisitor extends BaseVisitor {
267
287
  let color;
268
288
  let icon;
269
289
  let tags;
290
+ let job;
291
+ let environment;
270
292
  if (ctx.labelAttr) {
271
293
  for (const attr of ctx.labelAttr) {
272
294
  label = this.visit(attr);
@@ -324,6 +346,16 @@ class NodeVisitor extends BaseVisitor {
324
346
  tags = [...(tags || []), ...parsed];
325
347
  }
326
348
  }
349
+ if (ctx.jobAttr) {
350
+ for (const attr of ctx.jobAttr) {
351
+ job = this.visit(attr);
352
+ }
353
+ }
354
+ if (ctx.environmentAttr) {
355
+ for (const attr of ctx.environmentAttr) {
356
+ environment = this.visit(attr);
357
+ }
358
+ }
327
359
  return {
328
360
  label,
329
361
  expressions,
@@ -336,6 +368,8 @@ class NodeVisitor extends BaseVisitor {
336
368
  color,
337
369
  icon,
338
370
  tags,
371
+ job,
372
+ environment,
339
373
  };
340
374
  }
341
375
  labelAttr(ctx) {
@@ -426,6 +460,12 @@ class NodeVisitor extends BaseVisitor {
426
460
  iconAttr(ctx) {
427
461
  return this.unescapeString(ctx.iconValue[0].image);
428
462
  }
463
+ jobAttr(ctx) {
464
+ return this.unescapeString(ctx.jobValue[0].image);
465
+ }
466
+ environmentAttr(ctx) {
467
+ return this.unescapeString(ctx.environmentValue[0].image);
468
+ }
429
469
  tagsAttr(ctx) {
430
470
  const result = [];
431
471
  if (ctx.tagEntry) {
@@ -13,6 +13,7 @@ export interface PortParseResult {
13
13
  placement?: 'TOP' | 'BOTTOM';
14
14
  dataType?: string;
15
15
  mergeStrategy?: string;
16
+ hidden?: boolean;
16
17
  description?: string;
17
18
  }
18
19
  /**
@@ -4,7 +4,7 @@
4
4
  * Parser for @input/@output/@step port declarations using Chevrotain.
5
5
  */
6
6
  import { CstParser } from 'chevrotain';
7
- import { JSDocLexer, InputTag, OutputTag, StepTag, Identifier, ScopePrefix, OrderPrefix, PlacementPrefix, TypePrefix, MergeStrategyPrefix, TopKeyword, BottomKeyword, TrueKeyword, FalseKeyword, OverKeyword, AsKeyword, MinimizedKeyword, Integer, StringLiteral, DescriptionText, LBracket, RBracket, LParen, RParen, Comma, Colon, Dot, Dash, Equals, GreaterThan, LessThan, Pipe, Ampersand, LBrace, RBrace, Asterisk, allTokens, } from './tokens.js';
7
+ import { JSDocLexer, InputTag, OutputTag, StepTag, Identifier, ScopePrefix, OrderPrefix, PlacementPrefix, TypePrefix, MergeStrategyPrefix, TopKeyword, BottomKeyword, TrueKeyword, FalseKeyword, OverKeyword, AsKeyword, MinimizedKeyword, HiddenKeyword, Integer, StringLiteral, DescriptionText, LBracket, RBracket, LParen, RParen, Comma, Colon, Dot, Dash, Equals, GreaterThan, LessThan, Pipe, Ampersand, LBrace, RBrace, Asterisk, allTokens, } from './tokens.js';
8
8
  // =============================================================================
9
9
  // Parser Definition
10
10
  // =============================================================================
@@ -97,6 +97,7 @@ class PortParser extends CstParser {
97
97
  { ALT: () => this.SUBRULE(this.placementAttr) },
98
98
  { ALT: () => this.SUBRULE(this.typeAttr) },
99
99
  { ALT: () => this.SUBRULE(this.mergeStrategyAttr) },
100
+ { ALT: () => this.SUBRULE(this.hiddenAttr) },
100
101
  ]);
101
102
  },
102
103
  });
@@ -126,6 +127,10 @@ class PortParser extends CstParser {
126
127
  this.CONSUME(MergeStrategyPrefix);
127
128
  this.CONSUME(Identifier, { LABEL: 'mergeStrategyValue' });
128
129
  });
130
+ // hidden (standalone keyword, no value needed)
131
+ hiddenAttr = this.RULE('hiddenAttr', () => {
132
+ this.CONSUME(HiddenKeyword);
133
+ });
129
134
  // - description text
130
135
  // Note: We just consume the dash here. The actual description text is extracted
131
136
  // from the raw input in parsePortLine() to handle special characters like &, :, etc.
@@ -226,6 +231,7 @@ class PortVisitor extends BaseVisitor {
226
231
  if (ctx.scopeClause) {
227
232
  scope = this.visit(ctx.scopeClause);
228
233
  }
234
+ let hidden;
229
235
  if (ctx.metadataBracket) {
230
236
  // Handle multiple metadata brackets (e.g., [order:1] [placement:TOP])
231
237
  for (const bracket of ctx.metadataBracket) {
@@ -238,6 +244,8 @@ class PortVisitor extends BaseVisitor {
238
244
  dataType = metadata.dataType;
239
245
  if (metadata.mergeStrategy !== undefined)
240
246
  mergeStrategy = metadata.mergeStrategy;
247
+ if (metadata.hidden)
248
+ hidden = true;
241
249
  }
242
250
  }
243
251
  if (ctx.descriptionClause) {
@@ -253,6 +261,7 @@ class PortVisitor extends BaseVisitor {
253
261
  ...(placement && { placement }),
254
262
  ...(dataType && { dataType }),
255
263
  ...(mergeStrategy && { mergeStrategy }),
264
+ ...(hidden && { hidden }),
256
265
  ...(description && { description }),
257
266
  };
258
267
  }
@@ -266,6 +275,7 @@ class PortVisitor extends BaseVisitor {
266
275
  if (ctx.scopeClause) {
267
276
  scope = this.visit(ctx.scopeClause);
268
277
  }
278
+ let hidden;
269
279
  if (ctx.metadataBracket) {
270
280
  // Handle multiple metadata brackets (e.g., [order:1] [placement:TOP])
271
281
  for (const bracket of ctx.metadataBracket) {
@@ -276,6 +286,8 @@ class PortVisitor extends BaseVisitor {
276
286
  placement = metadata.placement;
277
287
  if (metadata.dataType !== undefined)
278
288
  dataType = metadata.dataType;
289
+ if (metadata.hidden)
290
+ hidden = true;
279
291
  }
280
292
  }
281
293
  if (ctx.descriptionClause) {
@@ -288,6 +300,7 @@ class PortVisitor extends BaseVisitor {
288
300
  ...(order !== undefined && { order }),
289
301
  ...(placement && { placement }),
290
302
  ...(dataType && { dataType }),
303
+ ...(hidden && { hidden }),
291
304
  ...(description && { description }),
292
305
  };
293
306
  }
@@ -311,6 +324,7 @@ class PortVisitor extends BaseVisitor {
311
324
  let placement;
312
325
  let dataType;
313
326
  let mergeStrategy;
327
+ let hidden;
314
328
  if (ctx.orderAttr) {
315
329
  for (const attr of ctx.orderAttr) {
316
330
  order = this.visit(attr);
@@ -331,7 +345,10 @@ class PortVisitor extends BaseVisitor {
331
345
  mergeStrategy = this.visit(attr);
332
346
  }
333
347
  }
334
- return { order, placement, dataType, mergeStrategy };
348
+ if (ctx.hiddenAttr) {
349
+ hidden = true;
350
+ }
351
+ return { order, placement, dataType, mergeStrategy, hidden };
335
352
  }
336
353
  orderAttr(ctx) {
337
354
  return parseInt(ctx.orderValue[0].image, 10);
@@ -342,6 +359,9 @@ class PortVisitor extends BaseVisitor {
342
359
  typeAttr(ctx) {
343
360
  return ctx.typeValue[0].image;
344
361
  }
362
+ hiddenAttr(_ctx) {
363
+ return true;
364
+ }
345
365
  mergeStrategyAttr(ctx) {
346
366
  return ctx.mergeStrategyValue[0].image;
347
367
  }
@@ -43,10 +43,13 @@ export declare const ExprPrefix: import("chevrotain").TokenType;
43
43
  export declare const MergeStrategyPrefix: import("chevrotain").TokenType;
44
44
  export declare const PullExecutionPrefix: import("chevrotain").TokenType;
45
45
  export declare const MinimizedKeyword: import("chevrotain").TokenType;
46
+ export declare const HiddenKeyword: import("chevrotain").TokenType;
46
47
  export declare const SizePrefix: import("chevrotain").TokenType;
47
48
  export declare const PositionPrefix: import("chevrotain").TokenType;
48
49
  export declare const ColorPrefix: import("chevrotain").TokenType;
49
50
  export declare const IconPrefix: import("chevrotain").TokenType;
51
+ export declare const JobPrefix: import("chevrotain").TokenType;
52
+ export declare const EnvironmentAttrPrefix: import("chevrotain").TokenType;
50
53
  export declare const TagsPrefix: import("chevrotain").TokenType;
51
54
  export declare const EventEq: import("chevrotain").TokenType;
52
55
  export declare const CronEq: import("chevrotain").TokenType;
@@ -168,6 +168,10 @@ export const MinimizedKeyword = createToken({
168
168
  name: 'MinimizedKeyword',
169
169
  pattern: /minimized\b/,
170
170
  });
171
+ export const HiddenKeyword = createToken({
172
+ name: 'HiddenKeyword',
173
+ pattern: /hidden\b/,
174
+ });
171
175
  export const SizePrefix = createToken({
172
176
  name: 'SizePrefix',
173
177
  pattern: /size:/,
@@ -184,6 +188,14 @@ export const IconPrefix = createToken({
184
188
  name: 'IconPrefix',
185
189
  pattern: /icon:/,
186
190
  });
191
+ export const JobPrefix = createToken({
192
+ name: 'JobPrefix',
193
+ pattern: /job:/,
194
+ });
195
+ export const EnvironmentAttrPrefix = createToken({
196
+ name: 'EnvironmentAttrPrefix',
197
+ pattern: /environment:/,
198
+ });
187
199
  export const TagsPrefix = createToken({
188
200
  name: 'TagsPrefix',
189
201
  pattern: /tags:/,
@@ -363,6 +375,8 @@ export const allTokens = [
363
375
  PositionPrefix,
364
376
  ColorPrefix,
365
377
  IconPrefix,
378
+ JobPrefix,
379
+ EnvironmentAttrPrefix,
366
380
  TagsPrefix,
367
381
  EventEq,
368
382
  CronEq,
@@ -374,6 +388,7 @@ export const allTokens = [
374
388
  OverKeyword,
375
389
  AsKeyword,
376
390
  MinimizedKeyword,
391
+ HiddenKeyword,
377
392
  TopKeyword,
378
393
  BottomKeyword,
379
394
  TrueKeyword,
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Export command - generate serverless function handlers for deployment
3
3
  */
4
- import { exportWorkflow, getSupportedTargets } from '../../export/index.js';
4
+ import { exportWorkflow } from '../../export/index.js';
5
5
  import { logger } from '../utils/logger.js';
6
6
  /**
7
7
  * Export a workflow as a serverless function.
@@ -34,10 +34,9 @@ import { logger } from '../utils/logger.js';
34
34
  * ```
35
35
  */
36
36
  export async function exportCommand(input, options) {
37
- const validTargets = getSupportedTargets();
38
- // Validate target
39
- if (!validTargets.includes(options.target)) {
40
- throw new Error(`Invalid target "${options.target}". Valid targets: ${validTargets.join(', ')}`);
37
+ // Validate target is provided
38
+ if (!options.target) {
39
+ throw new Error('--target is required. Install a target pack (e.g. npm install flowweaver-pack-lambda)');
41
40
  }
42
41
  const isDryRun = options.dryRun ?? false;
43
42
  const isMulti = options.multi ?? false;
@@ -122,42 +121,30 @@ export async function exportCommand(input, options) {
122
121
  }
123
122
  }
124
123
  }
124
+ // Get deploy instructions from the target
125
125
  logger.newline();
126
126
  logger.section('Next Steps');
127
- switch (result.target) {
128
- case 'lambda':
129
- logger.log(' 1. cd ' + options.output);
130
- logger.log(' 2. npm install');
131
- logger.log(' 3. npm run build');
132
- logger.log(' 4. sam build && sam deploy --guided');
133
- logger.newline();
134
- logger.info('Requires: AWS SAM CLI (https://aws.amazon.com/serverless/sam/)');
135
- break;
136
- case 'vercel':
137
- logger.log(" 1. Move files to your Vercel project's api/ directory:");
138
- logger.log(` mv ${options.output}/*.ts your-project/api/`);
139
- logger.log(' 2. vercel deploy');
140
- logger.newline();
141
- logger.info('Requires: Vercel CLI (npm install -g vercel)');
142
- logger.info(`Endpoint will be: https://your-project.vercel.app/api/${result.workflow}`);
143
- break;
144
- case 'cloudflare':
145
- logger.log(' 1. cd ' + options.output);
146
- logger.log(' 2. npm install');
147
- logger.log(' 3. npm run deploy');
148
- logger.newline();
149
- logger.info('Requires: Wrangler CLI (npm install -g wrangler)');
150
- logger.info('First run: wrangler login');
151
- break;
152
- case 'inngest':
153
- logger.log(' 1. cd ' + options.output);
154
- logger.log(' 2. npm install');
155
- logger.log(' 3. npm run dev');
127
+ const { createTargetRegistry } = await import('../../deployment/index.js');
128
+ const registry = await createTargetRegistry(process.cwd());
129
+ const target = registry.get(result.target);
130
+ if (target) {
131
+ // Use the target's own deploy instructions
132
+ const instructions = target.getDeployInstructions({
133
+ files: [],
134
+ target: result.target,
135
+ workflowName: result.workflow,
136
+ entryPoint: '',
137
+ });
138
+ for (let i = 0; i < instructions.steps.length; i++) {
139
+ logger.log(` ${i + 1}. ${instructions.steps[i]}`);
140
+ }
141
+ if (instructions.prerequisites.length > 0) {
156
142
  logger.newline();
157
- logger.info('Inngest Dev Server will start at http://localhost:8288');
158
- logger.info('Send test events from the Inngest Dev Server UI');
159
- logger.info('Docs: https://www.inngest.com/docs');
160
- break;
143
+ logger.info(`Requires: ${instructions.prerequisites.join(', ')}`);
144
+ }
145
+ }
146
+ else {
147
+ logger.log(' See target documentation for deployment instructions.');
161
148
  }
162
149
  }
163
150
  //# sourceMappingURL=export.js.map