@bpmnkit/cli 0.0.37 → 0.1.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.
- package/README.md +1 -1
- package/dist/commands/generate.js +79 -16
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://github.com/bpmnkit/monorepo)
|
|
10
10
|
[](https://github.com/bpmnkit/monorepo)
|
|
11
11
|
|
|
12
|
-
[Website](https://bpmnkit.com) · [Documentation](https://
|
|
12
|
+
[Website](https://bpmnkit.com) · [Documentation](https://bpmnkit.com/docs) · [GitHub](https://github.com/bpmnkit/monorepo) · [Changelog](https://github.com/bpmnkit/monorepo/blob/main/apps/cli/CHANGELOG.md)
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
15
|
---
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import {
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { Bpmn, applyAutoLayout, applyBpmnOperations, compactify, expand } from "@bpmnkit/core";
|
|
3
4
|
// ── JSON schema reference ─────────────────────────────────────────────────────
|
|
4
5
|
const SCHEMA_HELP = `CompactDiagram JSON schema — for --definition and stdin input
|
|
5
6
|
==============================================================
|
|
@@ -455,6 +456,35 @@ async function readStdin() {
|
|
|
455
456
|
}
|
|
456
457
|
return Buffer.concat(chunks).toString("utf-8").trim();
|
|
457
458
|
}
|
|
459
|
+
// ── Output path guard ─────────────────────────────────────────────────────────
|
|
460
|
+
/**
|
|
461
|
+
* Decide where `--input` mode writes, refusing to replace the input file unless
|
|
462
|
+
* the caller asked for it explicitly.
|
|
463
|
+
*
|
|
464
|
+
* The patch itself is applied to the full model, so nothing outside it is lost.
|
|
465
|
+
* Replacing the source is still destructive — the diagram is re-laid out, and a
|
|
466
|
+
* mistaken patch has nowhere to be compared against — so in-place replacement
|
|
467
|
+
* has to be asked for by name.
|
|
468
|
+
*
|
|
469
|
+
* @param inputFile - The `--input` path.
|
|
470
|
+
* @param outputFlag - The `--output` path, if any. `-` (stdout) is handled by the caller.
|
|
471
|
+
* @param force - Whether `--force` was passed.
|
|
472
|
+
* @returns The path to write to.
|
|
473
|
+
* @throws If the write would replace `inputFile` and `force` is false.
|
|
474
|
+
*/
|
|
475
|
+
export function resolveModifyOutputPath({ inputFile, outputFlag, force, }) {
|
|
476
|
+
const output = typeof outputFlag === "string" && outputFlag.length > 0 ? outputFlag : undefined;
|
|
477
|
+
const inPlace = output === undefined || resolve(output) === resolve(inputFile);
|
|
478
|
+
if (inPlace && !force) {
|
|
479
|
+
throw new Error([
|
|
480
|
+
`Refusing to overwrite ${inputFile}.`,
|
|
481
|
+
"The patch applies to the full model, so nothing is dropped, but the diagram is " +
|
|
482
|
+
"re-laid out and the original is gone once it is replaced.",
|
|
483
|
+
`Write elsewhere with --output <file>, or pass --force to replace ${inputFile} anyway.`,
|
|
484
|
+
].join("\n"));
|
|
485
|
+
}
|
|
486
|
+
return output ?? inputFile;
|
|
487
|
+
}
|
|
458
488
|
// ── Command ───────────────────────────────────────────────────────────────────
|
|
459
489
|
const generateBpmnCmd = {
|
|
460
490
|
name: "bpmn",
|
|
@@ -500,7 +530,9 @@ const generateBpmnCmd = {
|
|
|
500
530
|
{
|
|
501
531
|
name: "input",
|
|
502
532
|
short: "f",
|
|
503
|
-
description: "Existing .bpmn file to load and modify"
|
|
533
|
+
description: "Existing .bpmn file to load and modify. The patch is applied to the full model, so " +
|
|
534
|
+
"pools, lanes, data wiring and Zeebe detail are preserved; the diagram is re-laid " +
|
|
535
|
+
"out. Requires --output, or --force to replace it in place.",
|
|
504
536
|
type: "string",
|
|
505
537
|
},
|
|
506
538
|
{
|
|
@@ -513,6 +545,11 @@ const generateBpmnCmd = {
|
|
|
513
545
|
description: "Print the CompactDiagram JSON of --input and exit (for AI inspection of existing files)",
|
|
514
546
|
type: "boolean",
|
|
515
547
|
},
|
|
548
|
+
{
|
|
549
|
+
name: "force",
|
|
550
|
+
description: "Allow --input to be replaced in place. Prefer --output <file>.",
|
|
551
|
+
type: "boolean",
|
|
552
|
+
},
|
|
516
553
|
],
|
|
517
554
|
examples: [
|
|
518
555
|
{
|
|
@@ -553,11 +590,11 @@ const generateBpmnCmd = {
|
|
|
553
590
|
},
|
|
554
591
|
{
|
|
555
592
|
description: "Add a new gateway path to an existing file",
|
|
556
|
-
command: 'casen generate bpmn --input order.bpmn --patch \'{"elements":[{"id":"notify","type":"serviceTask","name":"Notify","jobType":"notify-worker"},{"id":"end2","type":"endEvent","name":"Notified"}],"flows":[{"id":"fn1","from":"gw","to":"notify","condition":"= urgent"},{"id":"fn2","from":"notify","to":"end2"}]}\'',
|
|
593
|
+
command: 'casen generate bpmn --input order.bpmn --output order.patched.bpmn --patch \'{"elements":[{"id":"notify","type":"serviceTask","name":"Notify","jobType":"notify-worker"},{"id":"end2","type":"endEvent","name":"Notified"}],"flows":[{"id":"fn1","from":"gw","to":"notify","condition":"= urgent"},{"id":"fn2","from":"notify","to":"end2"}]}\'',
|
|
557
594
|
},
|
|
558
595
|
{
|
|
559
596
|
description: "Pipe a patch from AI output",
|
|
560
|
-
command: 'echo \'{"elements":[...],"flows":[...]}\' | casen generate bpmn --input order.bpmn',
|
|
597
|
+
command: 'echo \'{"elements":[...],"flows":[...]}\' | casen generate bpmn --input order.bpmn --output order.patched.bpmn',
|
|
561
598
|
},
|
|
562
599
|
{
|
|
563
600
|
description: "Re-apply auto-layout to an existing file",
|
|
@@ -580,12 +617,20 @@ const generateBpmnCmd = {
|
|
|
580
617
|
if (inputFile) {
|
|
581
618
|
const xml = await readFile(inputFile, "utf-8");
|
|
582
619
|
const defs = Bpmn.parse(xml);
|
|
583
|
-
const compact = compactify(defs);
|
|
584
620
|
// --dump-compact: print JSON for AI inspection and exit
|
|
585
621
|
if (ctx.flags["dump-compact"]) {
|
|
586
|
-
process.stdout.write(`${JSON.stringify(
|
|
622
|
+
process.stdout.write(`${JSON.stringify(compactify(defs), null, 2)}\n`);
|
|
587
623
|
return;
|
|
588
624
|
}
|
|
625
|
+
// Settle the destination before reading stdin or building the patch, so an
|
|
626
|
+
// unwritable target fails immediately instead of after the work is done.
|
|
627
|
+
const outputPath = outputFlag === "-"
|
|
628
|
+
? null
|
|
629
|
+
: resolveModifyOutputPath({
|
|
630
|
+
inputFile,
|
|
631
|
+
outputFlag,
|
|
632
|
+
force: ctx.flags.force === true,
|
|
633
|
+
});
|
|
589
634
|
// Resolve patch from --patch flag or stdin
|
|
590
635
|
let patch = null;
|
|
591
636
|
if (patchFlag) {
|
|
@@ -607,22 +652,40 @@ const generateBpmnCmd = {
|
|
|
607
652
|
}
|
|
608
653
|
}
|
|
609
654
|
}
|
|
610
|
-
// Apply patch to
|
|
655
|
+
// Apply the patch to the full model, not to the compact view of it: an
|
|
656
|
+
// element added this way leaves the document's pools, lanes, data
|
|
657
|
+
// wiring and Zeebe detail exactly where they were.
|
|
658
|
+
let edited = defs;
|
|
611
659
|
if (patch) {
|
|
612
|
-
const
|
|
613
|
-
if (!
|
|
660
|
+
const process = defs.processes[0];
|
|
661
|
+
if (!process)
|
|
614
662
|
throw new Error("Input BPMN has no processes");
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
663
|
+
const operations = [
|
|
664
|
+
...(patch.elements ?? []).map((element) => ({ op: "insert", element, parent: process.id })),
|
|
665
|
+
...(patch.flows ?? []).map((flow) => ({
|
|
666
|
+
op: "add_flow",
|
|
667
|
+
id: flow.id,
|
|
668
|
+
parent: process.id,
|
|
669
|
+
from: flow.from,
|
|
670
|
+
to: flow.to,
|
|
671
|
+
name: flow.name,
|
|
672
|
+
condition: flow.condition,
|
|
673
|
+
})),
|
|
674
|
+
];
|
|
675
|
+
try {
|
|
676
|
+
edited = applyBpmnOperations(defs, operations).definitions;
|
|
677
|
+
}
|
|
678
|
+
catch (error) {
|
|
679
|
+
// Unresolved ids used to be skipped in silence, so a patch naming a
|
|
680
|
+
// misspelled element reported success and changed nothing.
|
|
681
|
+
throw new Error(`Patch could not be applied: ${error instanceof Error ? error.message : String(error)}`);
|
|
682
|
+
}
|
|
619
683
|
}
|
|
620
|
-
const patched = Bpmn.export(
|
|
621
|
-
if (
|
|
684
|
+
const patched = Bpmn.export(applyAutoLayout(edited));
|
|
685
|
+
if (outputPath === null) {
|
|
622
686
|
process.stdout.write(patched);
|
|
623
687
|
return;
|
|
624
688
|
}
|
|
625
|
-
const outputPath = typeof outputFlag === "string" && outputFlag.length > 0 ? outputFlag : inputFile;
|
|
626
689
|
await writeFile(outputPath, patched, "utf-8");
|
|
627
690
|
ctx.output.ok(patch ? `Patched and written to ${outputPath}` : `Re-laid-out and written to ${outputPath}`);
|
|
628
691
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bpmnkit/cli",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Command-line interface for Camunda 8 — deploy, manage, and monitor processes from the terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@bpmnkit/api": "0.0.20",
|
|
20
|
-
"@bpmnkit/ascii": "0.0.
|
|
20
|
+
"@bpmnkit/ascii": "0.0.31",
|
|
21
21
|
"@bpmnkit/connector-gen": "0.0.15",
|
|
22
|
-
"@bpmnkit/connectors": "0.0.
|
|
23
|
-
"@bpmnkit/core": "0.
|
|
24
|
-
"@bpmnkit/engine": "0.1.
|
|
22
|
+
"@bpmnkit/connectors": "0.0.3",
|
|
23
|
+
"@bpmnkit/core": "0.2.0",
|
|
24
|
+
"@bpmnkit/engine": "0.1.31",
|
|
25
25
|
"@bpmnkit/patterns": "0.0.5",
|
|
26
26
|
"@bpmnkit/profiles": "0.0.18",
|
|
27
|
-
"@bpmnkit/proxy": "0.0
|
|
27
|
+
"@bpmnkit/proxy": "0.1.0"
|
|
28
28
|
},
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public"
|