@synergenius/flow-weaver 0.17.0 → 0.17.2

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 (123) hide show
  1. package/dist/api/index.d.ts +4 -1
  2. package/dist/api/index.js +4 -1
  3. package/dist/api/templates.js +2 -2
  4. package/dist/api/validate.d.ts +2 -2
  5. package/dist/api/validate.js +6 -6
  6. package/dist/api/validation-registry.d.ts +10 -0
  7. package/dist/api/validation-registry.js +10 -0
  8. package/dist/ast/types.d.ts +91 -4
  9. package/dist/built-in-nodes/invoke-workflow.d.ts +1 -1
  10. package/dist/built-in-nodes/invoke-workflow.js +1 -1
  11. package/dist/chevrotain-parser/connect-parser.js +25 -7
  12. package/dist/cli/commands/compile.d.ts +5 -9
  13. package/dist/cli/commands/compile.js +21 -14
  14. package/dist/cli/commands/dev.d.ts +2 -13
  15. package/dist/cli/commands/dev.js +10 -204
  16. package/dist/cli/commands/doctor.js +6 -3
  17. package/dist/cli/commands/export.d.ts +8 -17
  18. package/dist/cli/commands/export.js +8 -17
  19. package/dist/cli/commands/init-personas.d.ts +17 -6
  20. package/dist/cli/commands/init-personas.js +73 -24
  21. package/dist/cli/commands/init.d.ts +5 -2
  22. package/dist/cli/commands/init.js +73 -42
  23. package/dist/cli/commands/mcp-setup.d.ts +7 -0
  24. package/dist/cli/commands/mcp-setup.js +16 -1
  25. package/dist/cli/flow-weaver.mjs +71002 -70385
  26. package/dist/cli/index.d.ts +1 -0
  27. package/dist/cli/index.js +9 -7
  28. package/dist/cli/templates/index.d.ts +20 -1
  29. package/dist/cli/templates/index.js +66 -15
  30. package/dist/cli/templates/nodes/human-approval.js +2 -3
  31. package/dist/cli/templates/nodes/rag-retriever.js +1 -1
  32. package/dist/constants.d.ts +7 -0
  33. package/dist/constants.js +13 -3
  34. package/dist/context/index.js +13 -3
  35. package/dist/deployment/config/loader.js +2 -1
  36. package/dist/deployment/core/adapters.d.ts +1 -25
  37. package/dist/deployment/core/adapters.js +0 -95
  38. package/dist/deployment/core/formatters.d.ts +0 -15
  39. package/dist/deployment/core/formatters.js +0 -24
  40. package/dist/deployment/index.d.ts +7 -5
  41. package/dist/deployment/index.js +8 -5
  42. package/dist/deployment/types.d.ts +2 -45
  43. package/dist/diagram/html-viewer.js +65 -32
  44. package/dist/diagram/renderer.js +9 -6
  45. package/dist/diagram/theme.js +4 -0
  46. package/dist/diagram/types.d.ts +2 -0
  47. package/dist/doc-metadata/extractors/annotations.js +5 -5
  48. package/dist/doc-metadata/extractors/cli-commands.js +1 -1
  49. package/dist/doc-metadata/extractors/mcp-tools.js +1 -2
  50. package/dist/docs/index.d.ts +28 -1
  51. package/dist/docs/index.js +95 -28
  52. package/dist/export/index.d.ts +2 -3
  53. package/dist/{deployment/targets/cicd-base.d.ts → extensions/cicd/base-target.d.ts} +35 -36
  54. package/dist/{deployment/targets/cicd-base.js → extensions/cicd/base-target.js} +97 -57
  55. package/dist/{validation/cicd-detection.d.ts → extensions/cicd/detection.d.ts} +2 -2
  56. package/dist/{validation/cicd-detection.js → extensions/cicd/detection.js} +13 -1
  57. package/dist/extensions/cicd/docs/cicd.md +395 -0
  58. package/dist/extensions/cicd/index.d.ts +10 -0
  59. package/dist/extensions/cicd/index.js +10 -0
  60. package/dist/extensions/cicd/register.d.ts +11 -0
  61. package/dist/extensions/cicd/register.js +62 -0
  62. package/dist/extensions/cicd/rules.d.ts +30 -0
  63. package/dist/{validation/cicd-rules.js → extensions/cicd/rules.js} +60 -56
  64. package/dist/extensions/cicd/tag-handler.d.ts +14 -0
  65. package/dist/extensions/cicd/tag-handler.js +488 -0
  66. package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-docker.d.ts +1 -1
  67. package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-matrix.d.ts +1 -1
  68. package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-multi-env.d.ts +1 -1
  69. package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-test-deploy.d.ts +1 -1
  70. package/dist/extensions/index.d.ts +12 -0
  71. package/dist/extensions/index.js +12 -0
  72. package/dist/extensions/inngest/dev-mode.d.ts +9 -0
  73. package/dist/extensions/inngest/dev-mode.js +213 -0
  74. package/dist/{generator/inngest.d.ts → extensions/inngest/generator.d.ts} +2 -2
  75. package/dist/{generator/inngest.js → extensions/inngest/generator.js} +4 -4
  76. package/dist/extensions/inngest/index.d.ts +2 -0
  77. package/dist/extensions/inngest/index.js +2 -0
  78. package/dist/extensions/inngest/register.d.ts +6 -0
  79. package/dist/extensions/inngest/register.js +23 -0
  80. package/dist/extensions/inngest/templates/ai-agent-durable.d.ts +8 -0
  81. package/dist/{cli/templates/workflows → extensions/inngest/templates}/ai-agent-durable.js +8 -8
  82. package/dist/{cli/templates/workflows → extensions/inngest/templates}/ai-pipeline-durable.d.ts +2 -2
  83. package/dist/{cli/templates/workflows → extensions/inngest/templates}/ai-pipeline-durable.js +7 -7
  84. package/dist/generated-version.d.ts +1 -1
  85. package/dist/generated-version.js +1 -1
  86. package/dist/generator/compile-target-registry.d.ts +20 -0
  87. package/dist/generator/compile-target-registry.js +20 -0
  88. package/dist/generator/dev-mode-registry.d.ts +27 -0
  89. package/dist/generator/dev-mode-registry.js +20 -0
  90. package/dist/index.d.ts +4 -0
  91. package/dist/index.js +3 -0
  92. package/dist/jsdoc-parser.d.ts +12 -114
  93. package/dist/jsdoc-parser.js +57 -362
  94. package/dist/marketplace/index.d.ts +2 -2
  95. package/dist/marketplace/index.js +1 -1
  96. package/dist/marketplace/registry.d.ts +39 -1
  97. package/dist/marketplace/registry.js +77 -0
  98. package/dist/marketplace/types.d.ts +76 -3
  99. package/dist/mcp/server.d.ts +1 -0
  100. package/dist/mcp/server.js +2 -0
  101. package/dist/mcp/tools-export.js +3 -3
  102. package/dist/mcp/tools-query.js +17 -11
  103. package/dist/mcp/tools-template.js +1 -1
  104. package/dist/parser/tag-registry.d.ts +47 -0
  105. package/dist/parser/tag-registry.js +57 -0
  106. package/dist/parser.d.ts +3 -0
  107. package/dist/parser.js +10 -23
  108. package/dist/validation/rule-registry.d.ts +36 -0
  109. package/dist/validation/rule-registry.js +37 -0
  110. package/dist/validator.js +3 -3
  111. package/docs/reference/concepts.md +2 -1
  112. package/docs/reference/deployment.md +21 -0
  113. package/docs/reference/jsdoc-grammar.md +242 -1
  114. package/docs/reference/scaffold.md +0 -6
  115. package/package.json +9 -1
  116. package/dist/cli/templates/workflows/ai-agent-durable.d.ts +0 -8
  117. package/dist/export/templates.d.ts +0 -24
  118. package/dist/export/templates.js +0 -186
  119. package/dist/validation/cicd-rules.d.ts +0 -62
  120. /package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-docker.js +0 -0
  121. /package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-matrix.js +0 -0
  122. /package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-multi-env.js +0 -0
  123. /package/dist/{cli/templates/workflows → extensions/cicd/templates}/cicd-test-deploy.js +0 -0
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Parses @flowWeaver annotations from JSDoc comments.
5
5
  */
6
- import { isExecutePort, isSuccessPort, isFailurePort, isScopedMandatoryPort, KNOWN_NODETYPE_TAGS, KNOWN_WORKFLOW_TAGS, KNOWN_PATTERN_TAGS, STANDARD_JSDOC_TAGS, } from './constants.js';
6
+ import { isExecutePort, isSuccessPort, isFailurePort, isScopedMandatoryPort, KNOWN_NODETYPE_TAGS, KNOWN_PATTERN_TAGS, STANDARD_JSDOC_TAGS, getKnownWorkflowTags, } from './constants.js';
7
7
  import { inferDataTypeFromTS } from './type-mappings.js';
8
8
  import { findClosestMatches } from './utils/string-distance.js';
9
9
  import { parsePortLine, parseNodeLine, parseConnectLine, parsePositionLine, parseScopeLine, parseMapLine, parsePathLine, parseFanOutLine, parseFanInLine, parseCoerceLine, parseTriggerLine, parseCancelOnLine, parseThrottleLine, } from './chevrotain-parser/index.js';
@@ -99,9 +99,11 @@ function extractCallbackParamType(callbackType, paramName) {
99
99
  }
100
100
  export class JSDocParser {
101
101
  /**
102
- * Parse @flowWeaver nodeType from JSDoc comments
102
+ * Parse @flowWeaver nodeType from JSDoc comments.
103
+ * When a TagHandlerRegistry is provided, unknown tags are checked against it
104
+ * before being reported as warnings.
103
105
  */
104
- parseNodeType(func, warnings) {
106
+ parseNodeType(func, warnings, tagRegistry) {
105
107
  const jsdocs = func.getJsDocs();
106
108
  if (jsdocs.length === 0)
107
109
  return null;
@@ -199,11 +201,17 @@ export class JSDocParser {
199
201
  config.deploy = config.deploy || {};
200
202
  this.parseDeployTag(tag, config.deploy);
201
203
  break;
202
- default:
204
+ default: {
203
205
  // D: Context validation - tags that belong to other block types
204
206
  if (tagName === 'param' || tagName === 'returns' || tagName === 'return') {
205
207
  warnings.push(`@${tagName} is for workflows, not node types. Use @input/@output instead.`);
206
208
  }
209
+ else if (tagRegistry && tagRegistry.has(tagName)) {
210
+ // Delegate to pack-contributed tag handler
211
+ if (!config.deploy)
212
+ config.deploy = {};
213
+ tagRegistry.handle(tagName, comment, 'nodeType', config.deploy, warnings);
214
+ }
207
215
  else if (!KNOWN_NODETYPE_TAGS.has(tagName) && !STANDARD_JSDOC_TAGS.has(tagName)) {
208
216
  // C: Unknown tag detection with suggestions
209
217
  const suggestions = findClosestMatches(tagName, [...KNOWN_NODETYPE_TAGS]);
@@ -211,14 +219,17 @@ export class JSDocParser {
211
219
  warnings.push(`Unknown annotation @${tagName} in nodeType block.${hint}`);
212
220
  }
213
221
  break;
222
+ }
214
223
  }
215
224
  });
216
225
  return config;
217
226
  }
218
227
  /**
219
- * Parse @flowWeaver workflow from JSDoc comments
228
+ * Parse @flowWeaver workflow from JSDoc comments.
229
+ * When a TagHandlerRegistry is provided, unknown tags are checked against it
230
+ * before being reported as warnings.
220
231
  */
221
- parseWorkflow(func, warnings) {
232
+ parseWorkflow(func, warnings, tagRegistry) {
222
233
  const jsdocs = func.getJsDocs();
223
234
  if (jsdocs.length === 0)
224
235
  return null;
@@ -298,7 +309,7 @@ export class JSDocParser {
298
309
  this.parseCoerceTag(tag, config, warnings);
299
310
  break;
300
311
  case 'trigger':
301
- this.parseTriggerTag(tag, config, warnings);
312
+ this.parseTriggerTag(tag, config, warnings, tagRegistry);
302
313
  break;
303
314
  case 'cancelOn':
304
315
  this.parseCancelOnTag(tag, config, warnings);
@@ -320,17 +331,9 @@ export class JSDocParser {
320
331
  case 'throttle':
321
332
  this.parseThrottleTag(tag, config, warnings);
322
333
  break;
323
- // ── CI/CD + deployment annotations (delegated to helper) ──
324
334
  case 'deploy':
325
- case 'secret':
326
- case 'runner':
327
- case 'cache':
328
- case 'artifact':
329
- case 'environment':
330
- case 'matrix':
331
- case 'service':
332
- case 'concurrency':
333
- this.handleDeploymentTag(tagName, tag, config, warnings);
335
+ config.deploy = config.deploy || {};
336
+ this.parseDeployTag(tag, config.deploy);
334
337
  break;
335
338
  case 'param':
336
339
  this.parseParamTag(tag, config, func, warnings);
@@ -339,7 +342,7 @@ export class JSDocParser {
339
342
  case 'returns':
340
343
  this.parseReturnTag(tag, config, func, warnings);
341
344
  break;
342
- default:
345
+ default: {
343
346
  // D: Context validation - tags that belong to other block types
344
347
  if (tagName === 'color' || tagName === 'icon' || tagName === 'tag') {
345
348
  warnings.push(`@${tagName} is for node types, not workflows. Use it on @flowWeaver nodeType instead.`);
@@ -347,13 +350,23 @@ export class JSDocParser {
347
350
  else if (tagName === 'input' || tagName === 'output' || tagName === 'step') {
348
351
  warnings.push(`@${tagName} is for node types, not workflows. Use @param/@returns for workflows.`);
349
352
  }
350
- else if (!KNOWN_WORKFLOW_TAGS.has(tagName) && !STANDARD_JSDOC_TAGS.has(tagName)) {
351
- // C: Unknown tag detection with suggestions
352
- const suggestions = findClosestMatches(tagName, [...KNOWN_WORKFLOW_TAGS]);
353
- const hint = suggestions.length > 0 ? ` Did you mean @${suggestions[0]}?` : '';
354
- warnings.push(`Unknown annotation @${tagName} in workflow block.${hint}`);
353
+ else if (tagRegistry && tagRegistry.has(tagName)) {
354
+ // Delegate to pack-contributed tag handler
355
+ if (!config.deploy)
356
+ config.deploy = {};
357
+ tagRegistry.handle(tagName, comment, 'workflow', config.deploy, warnings);
358
+ }
359
+ else {
360
+ const knownTags = getKnownWorkflowTags(tagRegistry?.getRegisteredTags());
361
+ if (!knownTags.has(tagName) && !STANDARD_JSDOC_TAGS.has(tagName)) {
362
+ // C: Unknown tag detection with suggestions
363
+ const suggestions = findClosestMatches(tagName, [...knownTags]);
364
+ const hint = suggestions.length > 0 ? ` Did you mean @${suggestions[0]}?` : '';
365
+ warnings.push(`Unknown annotation @${tagName} in workflow block.${hint}`);
366
+ }
355
367
  }
356
368
  break;
369
+ }
357
370
  }
358
371
  });
359
372
  return config;
@@ -1035,74 +1048,29 @@ export class JSDocParser {
1035
1048
  }
1036
1049
  /**
1037
1050
  * Parse @trigger tag using Chevrotain parser.
1051
+ * Delegates unrecognized trigger formats to the tag registry (e.g. CI/CD triggers).
1038
1052
  */
1039
- parseTriggerTag(tag, config, warnings) {
1053
+ parseTriggerTag(tag, config, warnings, tagRegistry) {
1040
1054
  const comment = (tag.getCommentText() || '').trim();
1041
- // Check for CI/CD trigger types first (push, pull_request, dispatch, tag, schedule)
1042
- const cicdTriggerMatch = comment.match(/^(push|pull_request|dispatch|tag|schedule)\b(.*)?$/);
1043
- if (cicdTriggerMatch) {
1044
- this.parseCICDTrigger(cicdTriggerMatch[1], cicdTriggerMatch[2]?.trim() || '', config, warnings);
1045
- return;
1046
- }
1047
- // Also detect cron="..." as a schedule trigger for CI/CD
1048
- const cronOnlyMatch = comment.match(/^cron\s*=\s*"([^"]+)"/);
1049
- if (cronOnlyMatch && !comment.includes('event=')) {
1050
- // Could be CI/CD schedule or existing FW cron — store both
1051
- config.cicdTriggers = config.cicdTriggers || [];
1052
- config.cicdTriggers.push({ type: 'schedule', cron: cronOnlyMatch[1] });
1053
- }
1054
- // Existing FW trigger parsing (event= and/or cron=)
1055
+ // Try core FW trigger parsing first (event= and/or cron=)
1055
1056
  const result = parseTriggerLine(`@trigger ${comment}`, warnings);
1056
- if (!result) {
1057
- // If it was a CI/CD trigger we already handled, don't warn
1058
- if (cicdTriggerMatch)
1059
- return;
1060
- warnings.push(`Invalid @trigger format: @trigger ${comment}`);
1057
+ if (result) {
1058
+ // Merge: multiple @trigger tags accumulate (event + cron can be separate tags)
1059
+ config.trigger = config.trigger || {};
1060
+ if (result.event)
1061
+ config.trigger.event = result.event;
1062
+ if (result.cron)
1063
+ config.trigger.cron = result.cron;
1061
1064
  return;
1062
1065
  }
1063
- // Merge: multiple @trigger tags accumulate (event + cron can be separate tags)
1064
- config.trigger = config.trigger || {};
1065
- if (result.event)
1066
- config.trigger.event = result.event;
1067
- if (result.cron)
1068
- config.trigger.cron = result.cron;
1069
- }
1070
- /**
1071
- * Parse a CI/CD-specific trigger type (push, pull_request, dispatch, tag, schedule).
1072
- */
1073
- parseCICDTrigger(type, rest, config, _warnings) {
1074
- config.cicdTriggers = config.cicdTriggers || [];
1075
- const triggerType = type;
1076
- const trigger = { type: triggerType };
1077
- // Parse key="value" pairs from rest
1078
- const branchesMatch = rest.match(/branches\s*=\s*"([^"]+)"/);
1079
- if (branchesMatch)
1080
- trigger.branches = branchesMatch[1].split(',').map(b => b.trim());
1081
- const pathsMatch = rest.match(/(?<![a-z])paths\s*=\s*"([^"]+)"/);
1082
- if (pathsMatch)
1083
- trigger.paths = pathsMatch[1].split(',').map(p => p.trim());
1084
- const pathsIgnoreMatch = rest.match(/paths-ignore\s*=\s*"([^"]+)"/);
1085
- if (pathsIgnoreMatch)
1086
- trigger.pathsIgnore = pathsIgnoreMatch[1].split(',').map(p => p.trim());
1087
- const typesMatch = rest.match(/types\s*=\s*"([^"]+)"/);
1088
- if (typesMatch)
1089
- trigger.types = typesMatch[1].split(',').map(t => t.trim());
1090
- const patternMatch = rest.match(/pattern\s*=\s*"([^"]+)"/);
1091
- if (patternMatch)
1092
- trigger.pattern = patternMatch[1];
1093
- const cronMatch = rest.match(/cron\s*=\s*"([^"]+)"/);
1094
- if (cronMatch)
1095
- trigger.cron = cronMatch[1];
1096
- const inputsMatch = rest.match(/inputs\s*=\s*"([^"]+)"/);
1097
- if (inputsMatch) {
1098
- trigger.inputs = {};
1099
- for (const input of inputsMatch[1].split(',')) {
1100
- const name = input.trim();
1101
- if (name)
1102
- trigger.inputs[name] = {};
1103
- }
1066
+ // Not a core trigger. Delegate to domain-specific handlers (e.g. CI/CD).
1067
+ if (tagRegistry && tagRegistry.has('_cicdTrigger')) {
1068
+ if (!config.deploy)
1069
+ config.deploy = {};
1070
+ tagRegistry.handle('_cicdTrigger', comment, 'workflow', config.deploy, warnings);
1071
+ return;
1104
1072
  }
1105
- config.cicdTriggers.push(trigger);
1073
+ warnings.push(`Invalid @trigger format: @trigger ${comment}`);
1106
1074
  }
1107
1075
  /**
1108
1076
  * Parse @cancelOn tag using Chevrotain parser.
@@ -1128,54 +1096,14 @@ export class JSDocParser {
1128
1096
  }
1129
1097
  config.throttle = result;
1130
1098
  }
1131
- // ── Deployment dispatch + @deploy parser ───────────────────────────
1132
- /**
1133
- * Dispatch a CI/CD or @deploy tag to the appropriate parser.
1134
- * Consolidates all deployment-related cases from the main switch.
1135
- */
1136
- handleDeploymentTag(tagName, tag, config, warnings) {
1137
- switch (tagName) {
1138
- case 'deploy':
1139
- config.deploy = config.deploy || {};
1140
- this.parseDeployTag(tag, config.deploy);
1141
- break;
1142
- case 'secret':
1143
- this.parseSecretTag(tag, config, warnings);
1144
- break;
1145
- case 'runner': {
1146
- const comment = (tag.getCommentText() || '').trim().replace(/^["']|["']$/g, '');
1147
- if (comment)
1148
- config.runner = comment;
1149
- break;
1150
- }
1151
- case 'cache':
1152
- this.parseCacheTag(tag, config, warnings);
1153
- break;
1154
- case 'artifact':
1155
- this.parseArtifactTag(tag, config, warnings);
1156
- break;
1157
- case 'environment':
1158
- this.parseEnvironmentTag(tag, config, warnings);
1159
- break;
1160
- case 'matrix':
1161
- this.parseMatrixTag(tag, config, warnings);
1162
- break;
1163
- case 'service':
1164
- this.parseServiceTag(tag, config, warnings);
1165
- break;
1166
- case 'concurrency':
1167
- this.parseConcurrencyTag(tag, config, warnings);
1168
- break;
1169
- }
1170
- }
1171
1099
  /**
1172
1100
  * Parse @deploy tag.
1173
1101
  * Format: @deploy <target> key=value key2="value with spaces" key3=123 key4=true
1174
1102
  *
1175
1103
  * Examples:
1176
1104
  * @deploy github-actions action="actions/checkout@v4"
1177
- * @deploy inngest durableSteps=true framework="next" retries=3
1178
- * @deploy lambda memory=256 timeout=30
1105
+ * @deploy my-target durableSteps=true framework="next" retries=3
1106
+ * @deploy another-target memory=256 timeout=30
1179
1107
  *
1180
1108
  * Values are auto-coerced: "true"/"false" → boolean, numeric strings → number.
1181
1109
  */
@@ -1194,7 +1122,8 @@ export class JSDocParser {
1194
1122
  if (!rest)
1195
1123
  return;
1196
1124
  // Parse key=value and key="value with spaces" pairs
1197
- const kvRegex = /(\w[\w-]*)\s*=\s*(?:"([^"]*)"|([\S]+))/g;
1125
+ // The quoted value pattern handles escaped quotes: "echo \"hello\""
1126
+ const kvRegex = /(\w[\w-]*)\s*=\s*(?:"((?:[^"\\]|\\.)*)"|([\S]+))/g;
1198
1127
  let match;
1199
1128
  while ((match = kvRegex.exec(rest)) !== null) {
1200
1129
  const key = match[1];
@@ -1224,240 +1153,6 @@ export class JSDocParser {
1224
1153
  }
1225
1154
  }
1226
1155
  }
1227
- // ── CI/CD annotation parsers ───────────────────────────────────────
1228
- /**
1229
- * Parse @secret tag.
1230
- * Format: @secret NAME - description
1231
- * Optional: @secret NAME scope="deploy" platform="github" - description
1232
- */
1233
- parseSecretTag(_tag, config, warnings) {
1234
- const comment = (_tag.getCommentText() || '').trim();
1235
- if (!comment) {
1236
- warnings.push('Empty @secret tag. Expected: @secret SECRET_NAME - description');
1237
- return;
1238
- }
1239
- // Parse: NAME [key=value ...] [- description]
1240
- const match = comment.match(/^(\S+)(.*?)(?:\s+-\s+(.*))?$/);
1241
- if (!match) {
1242
- warnings.push(`Invalid @secret format: @secret ${comment}`);
1243
- return;
1244
- }
1245
- const name = match[1];
1246
- const attrs = match[2] || '';
1247
- const description = match[3]?.trim();
1248
- const secret = { name };
1249
- if (description)
1250
- secret.description = description;
1251
- // Parse optional key=value attributes
1252
- const scopeMatch = attrs.match(/scope\s*=\s*"([^"]+)"/);
1253
- if (scopeMatch)
1254
- secret.scope = scopeMatch[1];
1255
- const platformMatch = attrs.match(/platform\s*=\s*"([^"]+)"/);
1256
- if (platformMatch) {
1257
- const validPlatforms = ['github', 'gitlab', 'all'];
1258
- const p = platformMatch[1];
1259
- if (validPlatforms.includes(p)) {
1260
- secret.platform = p;
1261
- }
1262
- else {
1263
- warnings.push(`Invalid @secret platform "${platformMatch[1]}". Must be: github, gitlab, or all`);
1264
- }
1265
- }
1266
- config.secrets = config.secrets || [];
1267
- config.secrets.push(secret);
1268
- }
1269
- /**
1270
- * Parse @cache tag.
1271
- * Format: @cache strategy [key="file"] [path="dir"]
1272
- */
1273
- parseCacheTag(_tag, config, warnings) {
1274
- const comment = (_tag.getCommentText() || '').trim();
1275
- if (!comment) {
1276
- warnings.push('Empty @cache tag. Expected: @cache npm key="package-lock.json"');
1277
- return;
1278
- }
1279
- const parts = comment.match(/^(\S+)(.*)?$/);
1280
- if (!parts) {
1281
- warnings.push(`Invalid @cache format: @cache ${comment}`);
1282
- return;
1283
- }
1284
- const cache = { strategy: parts[1] };
1285
- const rest = parts[2] || '';
1286
- const keyMatch = rest.match(/key\s*=\s*"([^"]+)"/);
1287
- if (keyMatch)
1288
- cache.key = keyMatch[1];
1289
- const pathMatch = rest.match(/path\s*=\s*"([^"]+)"/);
1290
- if (pathMatch)
1291
- cache.path = pathMatch[1];
1292
- config.caches = config.caches || [];
1293
- config.caches.push(cache);
1294
- }
1295
- /**
1296
- * Parse @artifact tag.
1297
- * Format: @artifact name path="dist/" [retention=5]
1298
- */
1299
- parseArtifactTag(_tag, config, warnings) {
1300
- const comment = (_tag.getCommentText() || '').trim();
1301
- if (!comment) {
1302
- warnings.push('Empty @artifact tag. Expected: @artifact name path="dist/"');
1303
- return;
1304
- }
1305
- const nameMatch = comment.match(/^(\S+)/);
1306
- if (!nameMatch) {
1307
- warnings.push(`Invalid @artifact format: @artifact ${comment}`);
1308
- return;
1309
- }
1310
- const pathMatch = comment.match(/path\s*=\s*"([^"]+)"/);
1311
- if (!pathMatch) {
1312
- warnings.push(`@artifact requires path="...": @artifact ${comment}`);
1313
- return;
1314
- }
1315
- const artifact = {
1316
- name: nameMatch[1],
1317
- path: pathMatch[1],
1318
- };
1319
- const retentionMatch = comment.match(/retention\s*=\s*(\d+)/);
1320
- if (retentionMatch)
1321
- artifact.retention = parseInt(retentionMatch[1], 10);
1322
- config.artifacts = config.artifacts || [];
1323
- config.artifacts.push(artifact);
1324
- }
1325
- /**
1326
- * Parse @environment tag.
1327
- * Format: @environment name [url="..."] [reviewers=N]
1328
- */
1329
- parseEnvironmentTag(_tag, config, warnings) {
1330
- const comment = (_tag.getCommentText() || '').trim();
1331
- if (!comment) {
1332
- warnings.push('Empty @environment tag. Expected: @environment production url="https://app.com"');
1333
- return;
1334
- }
1335
- const nameMatch = comment.match(/^(\S+)/);
1336
- if (!nameMatch) {
1337
- warnings.push(`Invalid @environment format: @environment ${comment}`);
1338
- return;
1339
- }
1340
- const env = { name: nameMatch[1] };
1341
- const urlMatch = comment.match(/url\s*=\s*"([^"]+)"/);
1342
- if (urlMatch)
1343
- env.url = urlMatch[1];
1344
- const reviewersMatch = comment.match(/reviewers\s*=\s*(\d+)/);
1345
- if (reviewersMatch)
1346
- env.reviewers = parseInt(reviewersMatch[1], 10);
1347
- config.environments = config.environments || [];
1348
- config.environments.push(env);
1349
- }
1350
- /**
1351
- * Parse @matrix tag.
1352
- * Format: @matrix dim1="val1,val2" dim2="val3,val4"
1353
- * Or: @matrix include dim1="val1" dim2="val2"
1354
- * Or: @matrix exclude dim1="val1" dim2="val2"
1355
- */
1356
- parseMatrixTag(_tag, config, warnings) {
1357
- const comment = (_tag.getCommentText() || '').trim();
1358
- if (!comment) {
1359
- warnings.push('Empty @matrix tag. Expected: @matrix node="18,20,22" os="ubuntu-latest"');
1360
- return;
1361
- }
1362
- config.matrix = config.matrix || { dimensions: {} };
1363
- // Check for include/exclude prefix
1364
- const isInclude = comment.startsWith('include ');
1365
- const isExclude = comment.startsWith('exclude ');
1366
- if (isInclude || isExclude) {
1367
- const rest = comment.slice(isInclude ? 8 : 8);
1368
- const entry = {};
1369
- const kvRegex = /(\w[\w-]*)\s*=\s*"([^"]+)"/g;
1370
- let m;
1371
- while ((m = kvRegex.exec(rest)) !== null) {
1372
- entry[m[1]] = m[2];
1373
- }
1374
- if (Object.keys(entry).length > 0) {
1375
- if (isInclude) {
1376
- config.matrix.include = config.matrix.include || [];
1377
- config.matrix.include.push(entry);
1378
- }
1379
- else {
1380
- config.matrix.exclude = config.matrix.exclude || [];
1381
- config.matrix.exclude.push(entry);
1382
- }
1383
- }
1384
- return;
1385
- }
1386
- // Regular dimensions: key="val1,val2"
1387
- const kvRegex = /(\w[\w-]*)\s*=\s*"([^"]+)"/g;
1388
- let m;
1389
- while ((m = kvRegex.exec(comment)) !== null) {
1390
- config.matrix.dimensions[m[1]] = m[2].split(',').map(v => v.trim());
1391
- }
1392
- }
1393
- /**
1394
- * Parse @service tag.
1395
- * Format: @service name image="..." [env="K=V,K2=V2"] [ports="5432:5432"]
1396
- */
1397
- parseServiceTag(_tag, config, warnings) {
1398
- const comment = (_tag.getCommentText() || '').trim();
1399
- if (!comment) {
1400
- warnings.push('Empty @service tag. Expected: @service postgres image="postgres:16"');
1401
- return;
1402
- }
1403
- const nameMatch = comment.match(/^(\S+)/);
1404
- if (!nameMatch) {
1405
- warnings.push(`Invalid @service format: @service ${comment}`);
1406
- return;
1407
- }
1408
- const imageMatch = comment.match(/image\s*=\s*"([^"]+)"/);
1409
- if (!imageMatch) {
1410
- warnings.push(`@service requires image="...": @service ${comment}`);
1411
- return;
1412
- }
1413
- const svc = {
1414
- name: nameMatch[1],
1415
- image: imageMatch[1],
1416
- };
1417
- const envMatch = comment.match(/env\s*=\s*"([^"]+)"/);
1418
- if (envMatch) {
1419
- svc.env = {};
1420
- for (const pair of envMatch[1].split(',')) {
1421
- const [k, ...vParts] = pair.split('=');
1422
- if (k && vParts.length > 0)
1423
- svc.env[k.trim()] = vParts.join('=').trim();
1424
- }
1425
- }
1426
- const portsMatch = comment.match(/ports\s*=\s*"([^"]+)"/);
1427
- if (portsMatch) {
1428
- svc.ports = portsMatch[1].split(',').map(p => p.trim());
1429
- }
1430
- config.services = config.services || [];
1431
- config.services.push(svc);
1432
- }
1433
- /**
1434
- * Parse @concurrency tag.
1435
- * Format: @concurrency group="name" [cancel-in-progress=true]
1436
- */
1437
- parseConcurrencyTag(_tag, config, warnings) {
1438
- const comment = (_tag.getCommentText() || '').trim();
1439
- if (!comment) {
1440
- warnings.push('Empty @concurrency tag. Expected: @concurrency group="deploy"');
1441
- return;
1442
- }
1443
- const groupMatch = comment.match(/group\s*=\s*"([^"]+)"/);
1444
- if (!groupMatch) {
1445
- // Try bare word: @concurrency deploy
1446
- const bareMatch = comment.match(/^(\S+)/);
1447
- if (bareMatch) {
1448
- config.concurrency = { group: bareMatch[1], cancelInProgress: false };
1449
- }
1450
- else {
1451
- warnings.push(`Invalid @concurrency format: @concurrency ${comment}`);
1452
- }
1453
- return;
1454
- }
1455
- const cancelMatch = comment.match(/cancel-in-progress\s*=\s*(true|false)/);
1456
- config.concurrency = {
1457
- group: groupMatch[1],
1458
- cancelInProgress: cancelMatch ? cancelMatch[1] === 'true' : false,
1459
- };
1460
- }
1461
1156
  /**
1462
1157
  * Parse default value from string
1463
1158
  */
@@ -4,8 +4,8 @@
4
4
  * Flow Weaver Marketplace — discover, install, and publish reusable
5
5
  * node types, workflows, and patterns via npm.
6
6
  */
7
- export type { TMarketplaceManifest, TManifestNodeType, TManifestWorkflow, TManifestPattern, TManifestExportTarget, TManifestPort, TValidationIssue, TValidationSeverity, TPackageValidationResult, TMarketplacePackageInfo, TInstalledPackage, TMarketInitConfig, } from './types.js';
7
+ export type { TMarketplaceManifest, TManifestNodeType, TManifestWorkflow, TManifestPattern, TManifestExportTarget, TManifestPort, TValidationIssue, TValidationSeverity, TPackageValidationResult, TMarketplacePackageInfo, TInstalledPackage, TMarketInitConfig, TManifestTagHandler, TManifestValidationRuleSet, TManifestDocTopic, TManifestInitContribution, } from './types.js';
8
8
  export { generateManifest, writeManifest, readManifest, type GenerateManifestOptions, type GenerateManifestResult, } from './manifest.js';
9
9
  export { validatePackage } from './validator.js';
10
- export { searchPackages, listInstalledPackages, getInstalledPackageManifest, type SearchOptions, } from './registry.js';
10
+ export { searchPackages, listInstalledPackages, getInstalledPackageManifest, discoverTagHandlers, discoverValidationRuleSets, discoverDocTopics, discoverInitContributions, type SearchOptions, type TDiscoveredTagHandler, type TDiscoveredValidationRuleSet, type TDiscoveredDocTopic, type TDiscoveredInitContribution, } from './registry.js';
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -6,5 +6,5 @@
6
6
  */
7
7
  export { generateManifest, writeManifest, readManifest, } from './manifest.js';
8
8
  export { validatePackage } from './validator.js';
9
- export { searchPackages, listInstalledPackages, getInstalledPackageManifest, } from './registry.js';
9
+ export { searchPackages, listInstalledPackages, getInstalledPackageManifest, discoverTagHandlers, discoverValidationRuleSets, discoverDocTopics, discoverInitContributions, } from './registry.js';
10
10
  //# sourceMappingURL=index.js.map
@@ -5,7 +5,7 @@
5
5
  * `flowweaver-marketplace-pack` keyword for discovery, and scans
6
6
  * `node_modules/` for locally installed packages.
7
7
  */
8
- import type { TMarketplaceManifest, TMarketplacePackageInfo, TInstalledPackage } from './types.js';
8
+ import type { TMarketplaceManifest, TMarketplacePackageInfo, TInstalledPackage, TManifestTagHandler, TManifestValidationRuleSet, TManifestDocTopic, TManifestInitContribution } from './types.js';
9
9
  export interface SearchOptions {
10
10
  /** Search query text */
11
11
  query?: string;
@@ -27,4 +27,42 @@ export declare function listInstalledPackages(projectDir: string): Promise<TInst
27
27
  * Read the manifest for a specific installed package.
28
28
  */
29
29
  export declare function getInstalledPackageManifest(projectDir: string, packageName: string): TMarketplaceManifest | null;
30
+ export type TDiscoveredTagHandler = TManifestTagHandler & {
31
+ /** Absolute path to the handler module */
32
+ absoluteFile: string;
33
+ /** Package name this handler belongs to */
34
+ packageName: string;
35
+ };
36
+ export type TDiscoveredValidationRuleSet = TManifestValidationRuleSet & {
37
+ /** Absolute path to the rule set module */
38
+ absoluteFile: string;
39
+ /** Package name this rule set belongs to */
40
+ packageName: string;
41
+ };
42
+ export type TDiscoveredDocTopic = TManifestDocTopic & {
43
+ /** Absolute path to the markdown file */
44
+ absoluteFile: string;
45
+ /** Package name this doc belongs to */
46
+ packageName: string;
47
+ };
48
+ export type TDiscoveredInitContribution = TManifestInitContribution & {
49
+ /** Package name this contribution belongs to */
50
+ packageName: string;
51
+ };
52
+ /**
53
+ * Discover all tag handlers from installed pack manifests.
54
+ */
55
+ export declare function discoverTagHandlers(projectDir: string): Promise<TDiscoveredTagHandler[]>;
56
+ /**
57
+ * Discover all validation rule sets from installed pack manifests.
58
+ */
59
+ export declare function discoverValidationRuleSets(projectDir: string): Promise<TDiscoveredValidationRuleSet[]>;
60
+ /**
61
+ * Discover all doc topics from installed pack manifests.
62
+ */
63
+ export declare function discoverDocTopics(projectDir: string): Promise<TDiscoveredDocTopic[]>;
64
+ /**
65
+ * Discover all init contributions from installed pack manifests.
66
+ */
67
+ export declare function discoverInitContributions(projectDir: string): Promise<TDiscoveredInitContribution[]>;
30
68
  //# sourceMappingURL=registry.d.ts.map