@synergenius/flow-weaver 0.17.7 → 0.17.8

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 (52) hide show
  1. package/dist/api/parse.d.ts +5 -0
  2. package/dist/api/parse.js +4 -0
  3. package/dist/ast/types.d.ts +2 -0
  4. package/dist/cli/commands/compile.js +2 -1
  5. package/dist/cli/commands/init.js +15 -9
  6. package/dist/cli/commands/validate.js +1 -1
  7. package/dist/cli/exports.d.ts +17 -0
  8. package/dist/cli/exports.js +23 -0
  9. package/dist/cli/flow-weaver.mjs +59021 -62127
  10. package/dist/cli/templates/index.js +8 -1
  11. package/dist/extensions/index.d.ts +10 -6
  12. package/dist/extensions/index.js +11 -6
  13. package/dist/generated-version.d.ts +1 -1
  14. package/dist/generated-version.js +1 -1
  15. package/dist/generator/index.d.ts +11 -0
  16. package/dist/generator/index.js +11 -0
  17. package/dist/parser.d.ts +7 -0
  18. package/dist/parser.js +29 -0
  19. package/package.json +11 -7
  20. package/dist/extensions/cicd/base-target.d.ts +0 -110
  21. package/dist/extensions/cicd/base-target.js +0 -397
  22. package/dist/extensions/cicd/detection.d.ts +0 -33
  23. package/dist/extensions/cicd/detection.js +0 -88
  24. package/dist/extensions/cicd/docs/cicd.md +0 -395
  25. package/dist/extensions/cicd/index.d.ts +0 -15
  26. package/dist/extensions/cicd/index.js +0 -15
  27. package/dist/extensions/cicd/register.d.ts +0 -11
  28. package/dist/extensions/cicd/register.js +0 -62
  29. package/dist/extensions/cicd/rules.d.ts +0 -30
  30. package/dist/extensions/cicd/rules.js +0 -288
  31. package/dist/extensions/cicd/tag-handler.d.ts +0 -14
  32. package/dist/extensions/cicd/tag-handler.js +0 -504
  33. package/dist/extensions/cicd/templates/cicd-docker.d.ts +0 -9
  34. package/dist/extensions/cicd/templates/cicd-docker.js +0 -110
  35. package/dist/extensions/cicd/templates/cicd-matrix.d.ts +0 -9
  36. package/dist/extensions/cicd/templates/cicd-matrix.js +0 -112
  37. package/dist/extensions/cicd/templates/cicd-multi-env.d.ts +0 -9
  38. package/dist/extensions/cicd/templates/cicd-multi-env.js +0 -126
  39. package/dist/extensions/cicd/templates/cicd-test-deploy.d.ts +0 -11
  40. package/dist/extensions/cicd/templates/cicd-test-deploy.js +0 -156
  41. package/dist/extensions/inngest/dev-mode.d.ts +0 -9
  42. package/dist/extensions/inngest/dev-mode.js +0 -213
  43. package/dist/extensions/inngest/generator.d.ts +0 -53
  44. package/dist/extensions/inngest/generator.js +0 -1176
  45. package/dist/extensions/inngest/index.d.ts +0 -2
  46. package/dist/extensions/inngest/index.js +0 -2
  47. package/dist/extensions/inngest/register.d.ts +0 -6
  48. package/dist/extensions/inngest/register.js +0 -23
  49. package/dist/extensions/inngest/templates/ai-agent-durable.d.ts +0 -8
  50. package/dist/extensions/inngest/templates/ai-agent-durable.js +0 -334
  51. package/dist/extensions/inngest/templates/ai-pipeline-durable.d.ts +0 -8
  52. package/dist/extensions/inngest/templates/ai-pipeline-durable.js +0 -326
@@ -1,397 +0,0 @@
1
- /**
2
- * Base CI/CD Export Target
3
- *
4
- * Shared logic for generating CI/CD pipeline files (GitHub Actions, GitLab CI).
5
- * Unlike serverless targets, CI/CD targets produce native YAML that runs without
6
- * any FW runtime dependency.
7
- *
8
- * Key responsibilities:
9
- * - Build job graph from AST (group nodes by @job, compute dependencies)
10
- * - Resolve secret wiring (secret: pseudo-node connections -> job env vars)
11
- * - Inject artifact upload/download steps between jobs
12
- * - Generate SECRETS_SETUP.md documentation
13
- */
14
- import { BaseExportTarget, } from '../../deployment/targets/base.js';
15
- export const NODE_ACTION_MAP = {
16
- checkout: {
17
- githubAction: 'actions/checkout@v4',
18
- gitlabScript: ['echo "Checkout handled by GitLab CI runner"'],
19
- label: 'Checkout code',
20
- },
21
- 'setup-node': {
22
- githubAction: 'actions/setup-node@v4',
23
- githubWith: { 'node-version': '20' },
24
- gitlabImage: 'node:20',
25
- label: 'Setup Node.js',
26
- },
27
- 'setup-python': {
28
- githubAction: 'actions/setup-python@v5',
29
- githubWith: { 'python-version': '3.12' },
30
- gitlabImage: 'python:3.12',
31
- label: 'Setup Python',
32
- },
33
- 'npm-install': {
34
- githubAction: undefined,
35
- gitlabScript: ['npm ci'],
36
- label: 'Install dependencies',
37
- },
38
- 'npm-test': {
39
- githubAction: undefined,
40
- gitlabScript: ['npm test'],
41
- label: 'Run tests',
42
- },
43
- 'npm-build': {
44
- githubAction: undefined,
45
- gitlabScript: ['npm run build'],
46
- label: 'Build',
47
- },
48
- 'docker-build': {
49
- githubAction: 'docker/build-push-action@v6',
50
- githubWith: { push: 'false' },
51
- gitlabScript: ['docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .'],
52
- label: 'Build Docker image',
53
- },
54
- 'docker-push': {
55
- githubAction: 'docker/build-push-action@v6',
56
- githubWith: { push: 'true' },
57
- gitlabScript: ['docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA'],
58
- label: 'Push Docker image',
59
- },
60
- 'docker-login': {
61
- githubAction: 'docker/login-action@v3',
62
- gitlabScript: ['echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY'],
63
- label: 'Docker login',
64
- },
65
- 'shell-command': {
66
- githubAction: undefined,
67
- gitlabScript: ['echo "TODO: Add shell command"'],
68
- label: 'Run command',
69
- },
70
- 'deploy-ssh': {
71
- githubAction: undefined,
72
- gitlabScript: ['echo "TODO: Configure SSH deployment"'],
73
- label: 'Deploy via SSH',
74
- },
75
- 'deploy-s3': {
76
- githubAction: 'aws-actions/configure-aws-credentials@v4',
77
- gitlabScript: ['aws s3 sync dist/ s3://$S3_BUCKET/'],
78
- label: 'Deploy to S3',
79
- },
80
- 'slack-notify': {
81
- githubAction: 'slackapi/slack-github-action@v1',
82
- gitlabScript: ["curl -X POST -H 'Content-type: application/json' --data '{\"text\":\"Pipeline complete\"}' $SLACK_WEBHOOK_URL"],
83
- label: 'Send Slack notification',
84
- },
85
- 'health-check': {
86
- githubAction: undefined,
87
- gitlabScript: ['curl --retry 10 --retry-delay 5 --retry-all-errors $HEALTH_CHECK_URL'],
88
- label: 'Health check',
89
- },
90
- 'wait-for-url': {
91
- githubAction: undefined,
92
- gitlabScript: ['for i in $(seq 1 30); do curl -sf $WAIT_URL && exit 0; sleep 10; done; exit 1'],
93
- label: 'Wait for URL',
94
- },
95
- };
96
- // ---------------------------------------------------------------------------
97
- // Base CI/CD Target
98
- // ---------------------------------------------------------------------------
99
- export class BaseCICDTarget extends BaseExportTarget {
100
- async generateMultiWorkflow(_workflows, _options) {
101
- throw new Error('CI/CD targets use generate() with AST, not generateMultiWorkflow()');
102
- }
103
- async generateNodeTypeService(_nodeTypes, _options) {
104
- throw new Error('CI/CD targets do not export node types as services');
105
- }
106
- async generateBundle(_workflows, _nodeTypes, _options) {
107
- throw new Error('CI/CD targets use generate() with AST, not generateBundle()');
108
- }
109
- // ---------------------------------------------------------------------------
110
- // Shared CI/CD Logic
111
- // ---------------------------------------------------------------------------
112
- resolveActionMapping(step, targetName) {
113
- const deployConfig = step.nodeTypeDeploy?.[targetName];
114
- if (deployConfig) {
115
- return {
116
- githubAction: deployConfig.action,
117
- githubWith: deployConfig.with
118
- ? (typeof deployConfig.with === 'string'
119
- ? JSON.parse(deployConfig.with)
120
- : deployConfig.with)
121
- : undefined,
122
- gitlabScript: deployConfig.script
123
- ? (Array.isArray(deployConfig.script)
124
- ? deployConfig.script
125
- : deployConfig.script.split('\n'))
126
- : undefined,
127
- gitlabImage: deployConfig.image,
128
- label: deployConfig.label || step.name,
129
- };
130
- }
131
- return NODE_ACTION_MAP[step.nodeType]
132
- || NODE_ACTION_MAP[step.nodeType.replace(/([A-Z])/g, '-$1').toLowerCase()];
133
- }
134
- buildJobGraph(ast) {
135
- const nodeTypeLookup = new Map();
136
- for (const nt of ast.nodeTypes) {
137
- nodeTypeLookup.set(nt.name, nt);
138
- if (nt.functionName !== nt.name)
139
- nodeTypeLookup.set(nt.functionName, nt);
140
- }
141
- const jobMap = new Map();
142
- const defaultRunner = ast.options?.cicd?.runner;
143
- for (const inst of ast.instances) {
144
- const jobName = inst.job || 'default';
145
- if (!jobMap.has(jobName))
146
- jobMap.set(jobName, []);
147
- jobMap.get(jobName).push(inst);
148
- }
149
- const nodeJob = new Map();
150
- for (const inst of ast.instances) {
151
- nodeJob.set(inst.id, inst.job || 'default');
152
- }
153
- const jobDeps = new Map();
154
- for (const conn of ast.connections) {
155
- if (conn.from.node.startsWith('secret:'))
156
- continue;
157
- if (conn.from.node === 'Start' || conn.to.node === 'Exit')
158
- continue;
159
- const fromJob = nodeJob.get(conn.from.node);
160
- const toJob = nodeJob.get(conn.to.node);
161
- if (fromJob && toJob && fromJob !== toJob) {
162
- if (!jobDeps.has(toJob))
163
- jobDeps.set(toJob, new Set());
164
- jobDeps.get(toJob).add(fromJob);
165
- }
166
- }
167
- const jobs = [];
168
- for (const [jobId, instances] of jobMap) {
169
- const environment = instances.find((i) => i.environment)?.environment;
170
- const steps = instances.map((inst) => {
171
- const nt = nodeTypeLookup.get(inst.nodeType);
172
- return {
173
- id: inst.id,
174
- name: inst.config?.label || inst.id,
175
- nodeType: inst.nodeType,
176
- ...(nt?.deploy && { nodeTypeDeploy: nt.deploy }),
177
- };
178
- });
179
- const needs = jobDeps.get(jobId)
180
- ? Array.from(jobDeps.get(jobId))
181
- : [];
182
- jobs.push({
183
- id: jobId,
184
- name: jobId,
185
- runner: defaultRunner,
186
- needs,
187
- steps,
188
- environment,
189
- secrets: [],
190
- });
191
- }
192
- // Apply @job configs
193
- const jobConfigs = ast.options?.cicd?.jobs;
194
- if (jobConfigs) {
195
- for (const jc of jobConfigs) {
196
- const job = jobs.find(j => j.id === jc.id);
197
- if (!job)
198
- continue;
199
- if (jc.retry !== undefined)
200
- job.retry = jc.retry;
201
- if (jc.allowFailure !== undefined)
202
- job.allowFailure = jc.allowFailure;
203
- if (jc.timeout)
204
- job.timeout = jc.timeout;
205
- if (jc.variables)
206
- job.variables = { ...job.variables, ...jc.variables };
207
- if (jc.tags)
208
- job.tags = jc.tags;
209
- if (jc.beforeScript)
210
- job.beforeScript = jc.beforeScript;
211
- if (jc.rules)
212
- job.rules = jc.rules;
213
- if (jc.coverage)
214
- job.coverage = jc.coverage;
215
- if (jc.reports)
216
- job.reports = jc.reports;
217
- if (jc.runner)
218
- job.runner = jc.runner;
219
- if (jc.extends)
220
- job.extends = jc.extends;
221
- }
222
- }
223
- // Apply @stage assignments
224
- const stages = ast.options?.cicd?.stages;
225
- if (stages && stages.length > 0) {
226
- const depthMap = this.computeJobDepths(jobs);
227
- // Match ALL jobs by name prefix to stages, not just configured ones
228
- for (const job of jobs) {
229
- if (!job.stage) {
230
- for (const s of stages) {
231
- if (job.id === s.name || job.id.startsWith(s.name + '-') || job.id.startsWith(s.name + '_')) {
232
- job.stage = s.name;
233
- break;
234
- }
235
- }
236
- }
237
- }
238
- for (const job of jobs) {
239
- if (!job.stage) {
240
- const depth = depthMap.get(job.id) || 0;
241
- job.stage = stages[Math.min(depth, stages.length - 1)].name;
242
- }
243
- }
244
- }
245
- // Apply workflow-level defaults
246
- const cicd = ast.options?.cicd;
247
- if (cicd) {
248
- for (const job of jobs) {
249
- if (cicd.variables && !job.variables) {
250
- job.variables = { ...cicd.variables };
251
- }
252
- if (cicd.beforeScript && !job.beforeScript) {
253
- job.beforeScript = [...cicd.beforeScript];
254
- }
255
- if (cicd.tags && !job.tags) {
256
- job.tags = [...cicd.tags];
257
- }
258
- }
259
- }
260
- return this.topoSortJobs(jobs);
261
- }
262
- topoSortJobs(jobs) {
263
- const jobMap = new Map(jobs.map((j) => [j.id, j]));
264
- const visited = new Set();
265
- const sorted = [];
266
- function visit(id) {
267
- if (visited.has(id))
268
- return;
269
- visited.add(id);
270
- const job = jobMap.get(id);
271
- if (!job)
272
- return;
273
- for (const dep of job.needs) {
274
- visit(dep);
275
- }
276
- sorted.push(job);
277
- }
278
- for (const job of jobs) {
279
- visit(job.id);
280
- }
281
- return sorted;
282
- }
283
- computeJobDepths(jobs) {
284
- const depths = new Map();
285
- function depth(jobId, visited) {
286
- if (depths.has(jobId))
287
- return depths.get(jobId);
288
- if (visited.has(jobId))
289
- return 0;
290
- visited.add(jobId);
291
- const job = jobs.find(j => j.id === jobId);
292
- if (!job || job.needs.length === 0) {
293
- depths.set(jobId, 0);
294
- return 0;
295
- }
296
- const maxDep = Math.max(...job.needs.map(n => depth(n, visited)));
297
- const d = maxDep + 1;
298
- depths.set(jobId, d);
299
- return d;
300
- }
301
- for (const job of jobs) {
302
- depth(job.id, new Set());
303
- }
304
- return depths;
305
- }
306
- resolveJobSecrets(jobs, ast, renderSecretRef) {
307
- const nodeJob = new Map();
308
- for (const inst of ast.instances) {
309
- nodeJob.set(inst.id, inst.job || 'default');
310
- }
311
- const stepMap = new Map();
312
- for (const job of jobs) {
313
- for (const step of job.steps) {
314
- stepMap.set(step.id, step);
315
- }
316
- }
317
- for (const conn of ast.connections) {
318
- if (!conn.from.node.startsWith('secret:'))
319
- continue;
320
- const secretName = conn.from.node.substring(7);
321
- const targetNode = conn.to.node;
322
- const targetPort = conn.to.port;
323
- const jobId = nodeJob.get(targetNode);
324
- if (!jobId)
325
- continue;
326
- const job = jobs.find((j) => j.id === jobId);
327
- if (!job)
328
- continue;
329
- if (!job.secrets.includes(secretName)) {
330
- job.secrets.push(secretName);
331
- }
332
- const step = stepMap.get(targetNode);
333
- if (step) {
334
- step.env = step.env || {};
335
- step.env[targetPort.replace(/([A-Z])/g, '_$1').toUpperCase().replace(/^_/, '')] =
336
- renderSecretRef(secretName);
337
- }
338
- }
339
- }
340
- injectArtifactSteps(jobs, artifacts) {
341
- if (artifacts.length === 0)
342
- return;
343
- for (const job of jobs) {
344
- if (job.needs.length === 0)
345
- continue;
346
- const neededJobs = jobs.filter((j) => job.needs.includes(j.id));
347
- for (const needed of neededJobs) {
348
- const jobArtifacts = artifacts.filter((a) => !a.name || needed.steps.some((s) => s.nodeType === a.name));
349
- if (jobArtifacts.length > 0) {
350
- needed.uploadArtifacts = (needed.uploadArtifacts || []).concat(jobArtifacts);
351
- job.downloadArtifacts = (job.downloadArtifacts || []).concat(jobArtifacts.map((a) => a.name));
352
- }
353
- }
354
- }
355
- }
356
- generateSecretsDoc(secrets, platform) {
357
- if (secrets.length === 0)
358
- return '';
359
- const lines = [
360
- '# Secrets Setup Guide',
361
- '',
362
- `This workflow requires ${secrets.length} secret(s) to be configured.`,
363
- '',
364
- ];
365
- for (const secret of secrets) {
366
- lines.push(`## ${secret.name}`);
367
- if (secret.description) {
368
- lines.push(`> ${secret.description}`);
369
- }
370
- lines.push('');
371
- if (platform === 'github-actions' || secret.platform === 'all' || secret.platform === 'github' || !secret.platform) {
372
- lines.push('**GitHub Actions:**');
373
- lines.push('1. Go to your repository on GitHub');
374
- lines.push('2. Navigate to Settings > Secrets and variables > Actions');
375
- lines.push('3. Click "New repository secret"');
376
- lines.push(`4. Name: \`${secret.name}\``);
377
- lines.push('5. Paste your secret value and click "Add secret"');
378
- lines.push('');
379
- }
380
- if (platform === 'gitlab-ci' || secret.platform === 'all' || secret.platform === 'gitlab' || !secret.platform) {
381
- lines.push('**GitLab CI:**');
382
- lines.push('1. Go to your project on GitLab');
383
- lines.push('2. Navigate to Settings > CI/CD > Variables');
384
- lines.push('3. Click "Add variable"');
385
- lines.push(`4. Key: \`${secret.name}\``);
386
- lines.push('5. Paste your secret value');
387
- lines.push('6. Check "Mask variable" and optionally "Protect variable"');
388
- lines.push('7. Click "Add variable"');
389
- lines.push('');
390
- }
391
- lines.push('---');
392
- lines.push('');
393
- }
394
- return lines.join('\n');
395
- }
396
- }
397
- //# sourceMappingURL=base-target.js.map
@@ -1,33 +0,0 @@
1
- /**
2
- * CI/CD Workflow Detection
3
- *
4
- * Determines whether a workflow is a CI/CD pipeline based on annotations.
5
- * A workflow is CI/CD if it has any CI/CD-specific annotations:
6
- * @secret, @runner, @cache, @artifact, @environment, @matrix, @service,
7
- * @concurrency, [job: "..."], or CI/CD trigger types (push, pull_request, etc.)
8
- */
9
- import type { TWorkflowAST } from '../../ast/types.js';
10
- /**
11
- * Check if a workflow is a CI/CD pipeline.
12
- *
13
- * Detection signals (any one is sufficient):
14
- * 1. Workflow options contain CI/CD fields (secrets, runner, caches, etc.)
15
- * 2. Any node instance has a `job` attribute
16
- * 3. Workflow has cicdTriggers
17
- */
18
- export declare function isCICDWorkflow(ast: TWorkflowAST): boolean;
19
- /**
20
- * Get all unique job names from a CI/CD workflow.
21
- * Returns empty array if no jobs are defined.
22
- */
23
- export declare function getJobNames(ast: TWorkflowAST): string[];
24
- /**
25
- * Get all declared secret names from a CI/CD workflow.
26
- */
27
- export declare function getDeclaredSecrets(ast: TWorkflowAST): string[];
28
- /**
29
- * Get all secret:NAME references from connections.
30
- * Returns array of secret names that are wired via @connect.
31
- */
32
- export declare function getReferencedSecrets(ast: TWorkflowAST): string[];
33
- //# sourceMappingURL=detection.d.ts.map
@@ -1,88 +0,0 @@
1
- /**
2
- * CI/CD Workflow Detection
3
- *
4
- * Determines whether a workflow is a CI/CD pipeline based on annotations.
5
- * A workflow is CI/CD if it has any CI/CD-specific annotations:
6
- * @secret, @runner, @cache, @artifact, @environment, @matrix, @service,
7
- * @concurrency, [job: "..."], or CI/CD trigger types (push, pull_request, etc.)
8
- */
9
- /**
10
- * Check if a workflow is a CI/CD pipeline.
11
- *
12
- * Detection signals (any one is sufficient):
13
- * 1. Workflow options contain CI/CD fields (secrets, runner, caches, etc.)
14
- * 2. Any node instance has a `job` attribute
15
- * 3. Workflow has cicdTriggers
16
- */
17
- export function isCICDWorkflow(ast) {
18
- // Check CI/CD domain annotations
19
- const cicd = ast.options?.cicd;
20
- if (cicd) {
21
- if (cicd.secrets && cicd.secrets.length > 0)
22
- return true;
23
- if (cicd.runner)
24
- return true;
25
- if (cicd.caches && cicd.caches.length > 0)
26
- return true;
27
- if (cicd.artifacts && cicd.artifacts.length > 0)
28
- return true;
29
- if (cicd.environments && cicd.environments.length > 0)
30
- return true;
31
- if (cicd.matrix)
32
- return true;
33
- if (cicd.services && cicd.services.length > 0)
34
- return true;
35
- if (cicd.concurrency)
36
- return true;
37
- if (cicd.triggers && cicd.triggers.length > 0)
38
- return true;
39
- if (cicd.jobs && cicd.jobs.length > 0)
40
- return true;
41
- if (cicd.variables && Object.keys(cicd.variables).length > 0)
42
- return true;
43
- if (cicd.beforeScript && cicd.beforeScript.length > 0)
44
- return true;
45
- if (cicd.tags && cicd.tags.length > 0)
46
- return true;
47
- if (cicd.includes && cicd.includes.length > 0)
48
- return true;
49
- if (cicd.stages && cicd.stages.length > 0)
50
- return true;
51
- }
52
- // Check node-level CI/CD annotations
53
- if (ast.instances.some((inst) => inst.job))
54
- return true;
55
- return false;
56
- }
57
- /**
58
- * Get all unique job names from a CI/CD workflow.
59
- * Returns empty array if no jobs are defined.
60
- */
61
- export function getJobNames(ast) {
62
- const jobs = new Set();
63
- for (const inst of ast.instances) {
64
- if (inst.job)
65
- jobs.add(inst.job);
66
- }
67
- return Array.from(jobs);
68
- }
69
- /**
70
- * Get all declared secret names from a CI/CD workflow.
71
- */
72
- export function getDeclaredSecrets(ast) {
73
- return (ast.options?.cicd?.secrets || []).map((s) => s.name);
74
- }
75
- /**
76
- * Get all secret:NAME references from connections.
77
- * Returns array of secret names that are wired via @connect.
78
- */
79
- export function getReferencedSecrets(ast) {
80
- const secrets = new Set();
81
- for (const conn of ast.connections) {
82
- if (conn.from.node.startsWith('secret:')) {
83
- secrets.add(conn.from.node.substring(7)); // strip "secret:" prefix
84
- }
85
- }
86
- return Array.from(secrets);
87
- }
88
- //# sourceMappingURL=detection.js.map