@synergenius/flow-weaver 0.23.5 → 0.24.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 (37) hide show
  1. package/dist/api/generate-in-place.d.ts +0 -9
  2. package/dist/api/generate-in-place.js +6 -54
  3. package/dist/api/generate.d.ts +4 -5
  4. package/dist/api/generate.js +6 -26
  5. package/dist/cli/commands/compile.d.ts +0 -5
  6. package/dist/cli/commands/compile.js +36 -8
  7. package/dist/cli/commands/context.js +4 -6
  8. package/dist/cli/commands/create.js +6 -14
  9. package/dist/cli/commands/describe.js +6 -10
  10. package/dist/cli/commands/diagram.js +18 -25
  11. package/dist/cli/commands/diff.js +7 -14
  12. package/dist/cli/commands/docs.js +3 -6
  13. package/dist/cli/commands/doctor.js +1 -1
  14. package/dist/cli/commands/export.js +1 -1
  15. package/dist/cli/commands/grammar.js +3 -4
  16. package/dist/cli/commands/implement.js +8 -13
  17. package/dist/cli/commands/market.js +4 -8
  18. package/dist/cli/commands/migrate.js +2 -1
  19. package/dist/cli/commands/modify.js +2 -1
  20. package/dist/cli/commands/openapi.js +2 -1
  21. package/dist/cli/commands/pattern.js +3 -2
  22. package/dist/cli/commands/strip.js +3 -6
  23. package/dist/cli/commands/validate.js +6 -1
  24. package/dist/cli/flow-weaver.mjs +780 -790
  25. package/dist/cli/index.js +10 -12
  26. package/dist/cli/postinstall.d.ts +16 -0
  27. package/dist/cli/postinstall.js +119 -0
  28. package/dist/cli/utils/parse-int-strict.d.ts +7 -0
  29. package/dist/cli/utils/parse-int-strict.js +17 -0
  30. package/dist/cli/utils/safe-write.d.ts +18 -0
  31. package/dist/cli/utils/safe-write.js +54 -0
  32. package/dist/generated-version.d.ts +1 -1
  33. package/dist/generated-version.js +1 -1
  34. package/docs/reference/cli-reference.md +0 -1
  35. package/docs/reference/compilation.md +2 -10
  36. package/package.json +4 -2
  37. package/scripts/postinstall.cjs +86 -0
@@ -7,6 +7,7 @@ import { parseWorkflow } from '../../api/index.js';
7
7
  import { generateFunctionSignature } from '../../annotation-generator.js';
8
8
  import { logger } from '../utils/logger.js';
9
9
  import { getErrorMessage } from '../../utils/error-utils.js';
10
+ import { safeWriteFile } from '../utils/safe-write.js';
10
11
  /**
11
12
  * Find a `declare function <name>(...): ...;` declaration in source text,
12
13
  * handling multiline signatures. Returns the full matched text and its
@@ -37,14 +38,11 @@ export async function implementCommand(input, nodeName, options = {}) {
37
38
  try {
38
39
  const filePath = path.resolve(input);
39
40
  if (!fs.existsSync(filePath)) {
40
- logger.error(`File not found: ${input}`);
41
- process.exit(1);
41
+ throw new Error(`File not found: ${input}`);
42
42
  }
43
43
  const parseResult = await parseWorkflow(filePath, { workflowName });
44
44
  if (parseResult.errors.length > 0) {
45
- logger.error('Parse errors:');
46
- parseResult.errors.forEach((e) => logger.error(` ${e}`));
47
- process.exit(1);
45
+ throw new Error(`Parse errors:\n${parseResult.errors.map((e) => ` ${e}`).join('\n')}`);
48
46
  }
49
47
  const ast = parseResult.ast;
50
48
  // Find the stub node type
@@ -59,18 +57,16 @@ export async function implementCommand(input, nodeName, options = {}) {
59
57
  .filter((nt) => nt.variant === 'STUB')
60
58
  .map((nt) => nt.functionName);
61
59
  if (available.length === 0) {
62
- logger.error('No stub nodes found in this workflow.');
60
+ throw new Error('No stub nodes found in this workflow.');
63
61
  }
64
62
  else {
65
- logger.error(`Stub node "${nodeName}" not found. Available stubs: ${available.join(', ')}`);
63
+ throw new Error(`Stub node "${nodeName}" not found. Available stubs: ${available.join(', ')}`);
66
64
  }
67
- process.exit(1);
68
65
  }
69
66
  const source = fs.readFileSync(filePath, 'utf8');
70
67
  const found = findDeclareFunction(source, stubNodeType.functionName);
71
68
  if (!found) {
72
- logger.error(`Could not find "declare function ${stubNodeType.functionName}" in source file.`);
73
- process.exit(1);
69
+ throw new Error(`Could not find "declare function ${stubNodeType.functionName}" in source file.`);
74
70
  }
75
71
  // Generate the real function signature
76
72
  const implementedType = { ...stubNodeType, variant: 'FUNCTION' };
@@ -84,13 +80,12 @@ export async function implementCommand(input, nodeName, options = {}) {
84
80
  }
85
81
  else {
86
82
  const updated = source.replace(found.match, replacement);
87
- fs.writeFileSync(filePath, updated, 'utf8');
83
+ safeWriteFile(filePath, updated);
88
84
  logger.success(`Implemented ${stubNodeType.functionName} in ${path.basename(filePath)}`);
89
85
  }
90
86
  }
91
87
  catch (error) {
92
- logger.error(`Implement failed: ${getErrorMessage(error)}`);
93
- process.exit(1);
88
+ throw new Error(`Implement failed: ${getErrorMessage(error)}`);
94
89
  }
95
90
  }
96
91
  //# sourceMappingURL=implement.js.map
@@ -24,13 +24,11 @@ export async function marketInitCommand(name, options = {}) {
24
24
  if (stat.isDirectory()) {
25
25
  const contents = fs.readdirSync(targetDir);
26
26
  if (contents.length > 0) {
27
- logger.error(`Directory "${name}" already exists and is not empty`);
28
- process.exit(1);
27
+ throw new Error(`Directory "${name}" already exists and is not empty`);
29
28
  }
30
29
  }
31
30
  else {
32
- logger.error(`"${name}" already exists and is not a directory`);
33
- process.exit(1);
31
+ throw new Error(`"${name}" already exists and is not a directory`);
34
32
  }
35
33
  }
36
34
  logger.section('Creating Marketplace Package');
@@ -211,8 +209,7 @@ export async function marketPackCommand(directory, options = {}) {
211
209
  }
212
210
  if (!validation.valid) {
213
211
  logger.newline();
214
- logger.error('Package validation failed. Fix errors above before publishing.');
215
- process.exit(1);
212
+ throw new Error('Package validation failed. Fix errors above before publishing.');
216
213
  }
217
214
  // 3. Write manifest
218
215
  const outPath = writeManifest(dir, manifest);
@@ -253,8 +250,7 @@ export async function marketPublishCommand(directory, options = {}) {
253
250
  }
254
251
  }
255
252
  catch (err) {
256
- logger.error(`npm publish failed: ${getErrorMessage(err)}`);
257
- process.exit(1);
253
+ throw new Error(`npm publish failed: ${getErrorMessage(err)}`);
258
254
  }
259
255
  }
260
256
  /**
@@ -13,6 +13,7 @@ import { generateInPlace } from '../../api/generate-in-place.js';
13
13
  import { WorkflowDiffer, formatDiff } from '../../diff/index.js';
14
14
  import { applyMigrations, getRegisteredMigrations } from '../../migration/registry.js';
15
15
  import { logger } from '../utils/logger.js';
16
+ import { safeWriteFile } from '../utils/safe-write.js';
16
17
  import { getErrorMessage } from '../../utils/error-utils.js';
17
18
  export async function migrateCommand(globPattern, options = {}) {
18
19
  const { dryRun = false, diff = false } = options;
@@ -69,7 +70,7 @@ export async function migrateCommand(globPattern, options = {}) {
69
70
  migratedCount++;
70
71
  continue;
71
72
  }
72
- fs.writeFileSync(filePath, genResult.code, 'utf8');
73
+ safeWriteFile(filePath, genResult.code);
73
74
  logger.success(` ${file}: migrated`);
74
75
  migratedCount++;
75
76
  }
@@ -4,6 +4,7 @@ import { parseWorkflow } from '../../api/index.js';
4
4
  import { generateInPlace } from '../../api/generate-in-place.js';
5
5
  import { applyModifyOperation, validateModifyParams } from '../../api/modify-operation.js';
6
6
  import { logger } from '../utils/logger.js';
7
+ import { safeWriteFile } from '../utils/safe-write.js';
7
8
  async function readParseModifyWrite(file, operation, params) {
8
9
  const validation = validateModifyParams(operation, params);
9
10
  if (!validation.success) {
@@ -17,7 +18,7 @@ async function readParseModifyWrite(file, operation, params) {
17
18
  }
18
19
  const { ast: modifiedAST, warnings } = applyModifyOperation(parseResult.ast, operation, params);
19
20
  const result = generateInPlace(source, modifiedAST);
20
- fs.writeFileSync(filePath, result.code, 'utf-8');
21
+ safeWriteFile(filePath, result.code);
21
22
  for (const w of warnings) {
22
23
  logger.warn(w);
23
24
  }
@@ -6,6 +6,7 @@ import * as fs from 'fs';
6
6
  import { WorkflowRegistry } from '../../server/workflow-registry.js';
7
7
  import { generateOpenAPIJson, generateOpenAPIYaml } from '../../deployment/openapi/generator.js';
8
8
  import { logger } from '../utils/logger.js';
9
+ import { safeWriteFile } from '../utils/safe-write.js';
9
10
  /**
10
11
  * Generate OpenAPI specification from workflows in a directory.
11
12
  *
@@ -59,7 +60,7 @@ export async function openapiCommand(dir, options) {
59
60
  // Output
60
61
  if (options.output) {
61
62
  const outputPath = path.resolve(options.output);
62
- fs.writeFileSync(outputPath, spec);
63
+ safeWriteFile(outputPath, spec);
63
64
  logger.success(`OpenAPI specification written to ${outputPath}`);
64
65
  }
65
66
  else {
@@ -10,6 +10,7 @@ import * as path from 'path';
10
10
  import { glob } from 'glob';
11
11
  import { AnnotationParser } from '../../parser.js';
12
12
  import { logger } from '../utils/logger.js';
13
+ import { safeWriteFile } from '../utils/safe-write.js';
13
14
  import { listPatterns, applyPattern, extractPattern } from '../../api/patterns.js';
14
15
  const parser = new AnnotationParser();
15
16
  /**
@@ -132,7 +133,7 @@ export async function patternApplyCommand(patternFile, targetFile, options) {
132
133
  return;
133
134
  }
134
135
  // Write modified content
135
- fs.writeFileSync(targetFile, result.modifiedContent);
136
+ safeWriteFile(targetFile, result.modifiedContent);
136
137
  logger.success(`Applied pattern "${pattern.name}" to ${targetFile}`);
137
138
  if (result.nodeTypesAdded.length > 0) {
138
139
  logger.info(`Added node types: ${result.nodeTypesAdded.join(', ')}`);
@@ -176,7 +177,7 @@ export async function patternExtractCommand(sourceFile, options) {
176
177
  return;
177
178
  }
178
179
  // Write to output file
179
- fs.writeFileSync(options.output, result.patternCode);
180
+ safeWriteFile(options.output, result.patternCode);
180
181
  logger.success(`Extracted pattern "${result.patternName}" to ${options.output}`);
181
182
  logger.info(`Included nodes: ${result.nodes.join(', ')}`);
182
183
  logger.info(`Input ports: ${result.inputPorts.join(', ') || 'none'}`);
@@ -3,6 +3,7 @@ import * as path from 'path';
3
3
  import { glob } from 'glob';
4
4
  import { hasInPlaceMarkers, stripGeneratedSections } from '../../api/generate-in-place.js';
5
5
  import { logger } from '../utils/logger.js';
6
+ import { safeWriteFile } from '../utils/safe-write.js';
6
7
  export async function stripCommand(input, options = {}) {
7
8
  const { output, dryRun = false, verbose = false } = options;
8
9
  // If input is a directory, expand to all .ts files recursively
@@ -25,8 +26,7 @@ export async function stripCommand(input, options = {}) {
25
26
  }
26
27
  });
27
28
  if (files.length === 0) {
28
- logger.error(`No files found matching pattern: ${input}`);
29
- process.exit(1);
29
+ throw new Error(`No files found matching pattern: ${input}`);
30
30
  }
31
31
  const t = logger.timer();
32
32
  let stripped = 0;
@@ -49,10 +49,7 @@ export async function stripCommand(input, options = {}) {
49
49
  const outPath = output
50
50
  ? path.join(path.resolve(output), path.basename(filePath))
51
51
  : filePath;
52
- if (output) {
53
- fs.mkdirSync(path.dirname(outPath), { recursive: true });
54
- }
55
- fs.writeFileSync(outPath, result);
52
+ safeWriteFile(outPath, result);
56
53
  stripped++;
57
54
  if (verbose) {
58
55
  logger.success(`Stripped: ${path.relative(process.cwd(), outPath)}`);
@@ -247,7 +247,12 @@ export async function validateCommand(input, options = {}) {
247
247
  }
248
248
  }
249
249
  if (totalErrors > 0) {
250
- process.exit(1);
250
+ if (json) {
251
+ // JSON output already emitted above — just signal failure via exit code
252
+ process.exitCode = 1;
253
+ return;
254
+ }
255
+ throw new Error(`Validation failed with ${totalErrors} error${totalErrors !== 1 ? 's' : ''}`);
251
256
  }
252
257
  }
253
258
  catch (error) {