eventmodeler 0.6.8 → 0.6.10
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/dist/index.js +117 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2576,6 +2576,33 @@ function getEntry(doc, scope, id) {
|
|
|
2576
2576
|
return;
|
|
2577
2577
|
return entry instanceof Y4.AbstractType ? entry.toJSON() : entry;
|
|
2578
2578
|
}
|
|
2579
|
+
// ../packages/canvas-model/src/dimensions.ts
|
|
2580
|
+
var ELEMENT_DIMENSIONS = {
|
|
2581
|
+
commandSticky: { width: 160, height: 100 },
|
|
2582
|
+
eventSticky: { width: 160, height: 100 },
|
|
2583
|
+
readModelSticky: { width: 160, height: 100 },
|
|
2584
|
+
screen: { width: 180, height: 120 },
|
|
2585
|
+
processor: { width: 120, height: 120 },
|
|
2586
|
+
slice: { width: 300, height: 200 },
|
|
2587
|
+
aggregate: { width: 300, height: 200 },
|
|
2588
|
+
actor: { width: 300, height: 200 },
|
|
2589
|
+
chapter: { width: 800, height: 1200 },
|
|
2590
|
+
note: { width: 200, height: 150 },
|
|
2591
|
+
externalEvent: { width: 160, height: 100 },
|
|
2592
|
+
context: { width: 300, height: 200 },
|
|
2593
|
+
swimLane: { width: 300, height: 200 }
|
|
2594
|
+
};
|
|
2595
|
+
var FIXED_SIZE_SCOPE_DIMENSIONS = {
|
|
2596
|
+
commands: ELEMENT_DIMENSIONS.commandSticky,
|
|
2597
|
+
events: ELEMENT_DIMENSIONS.eventSticky,
|
|
2598
|
+
readModels: ELEMENT_DIMENSIONS.readModelSticky,
|
|
2599
|
+
screens: ELEMENT_DIMENSIONS.screen,
|
|
2600
|
+
processors: ELEMENT_DIMENSIONS.processor,
|
|
2601
|
+
externalEvents: ELEMENT_DIMENSIONS.externalEvent
|
|
2602
|
+
};
|
|
2603
|
+
function canonicalSizeForScope(scope) {
|
|
2604
|
+
return FIXED_SIZE_SCOPE_DIMENSIONS[scope];
|
|
2605
|
+
}
|
|
2579
2606
|
// ../packages/canvas-model/src/actions.ts
|
|
2580
2607
|
import * as Y5 from "yjs";
|
|
2581
2608
|
// ../packages/canvas-model/src/containment.ts
|
|
@@ -2705,7 +2732,7 @@ var FieldTypeSchema = z.enum([
|
|
|
2705
2732
|
"Custom"
|
|
2706
2733
|
]);
|
|
2707
2734
|
var FieldBase = z.object({
|
|
2708
|
-
id: z.string().uuid().
|
|
2735
|
+
id: z.string().uuid().default(() => crypto.randomUUID()),
|
|
2709
2736
|
name: z.string().min(1),
|
|
2710
2737
|
fieldType: FieldTypeSchema,
|
|
2711
2738
|
isList: z.boolean().optional(),
|
|
@@ -3704,6 +3731,22 @@ function knownTypeAliases() {
|
|
|
3704
3731
|
return TYPES.map((t) => t.type);
|
|
3705
3732
|
}
|
|
3706
3733
|
|
|
3734
|
+
// src/lib/enforce-size.ts
|
|
3735
|
+
function enforceCanonicalSize(meta, entry) {
|
|
3736
|
+
const dims = canonicalSizeForScope(meta.scope);
|
|
3737
|
+
if (!dims)
|
|
3738
|
+
return;
|
|
3739
|
+
const hadW = typeof entry.width === "number";
|
|
3740
|
+
const hadH = typeof entry.height === "number";
|
|
3741
|
+
const mismatched = hadW && entry.width !== dims.width || hadH && entry.height !== dims.height;
|
|
3742
|
+
entry.width = dims.width;
|
|
3743
|
+
entry.height = dims.height;
|
|
3744
|
+
if (mismatched) {
|
|
3745
|
+
return `${meta.type} is a fixed-size element; using canonical ${dims.width}x${dims.height}.`;
|
|
3746
|
+
}
|
|
3747
|
+
return;
|
|
3748
|
+
}
|
|
3749
|
+
|
|
3707
3750
|
// src/commands/create.ts
|
|
3708
3751
|
var CREATE_HELP = `
|
|
3709
3752
|
Place a new element described by a JSON shape. The JSON is validated against
|
|
@@ -3714,6 +3757,12 @@ type-specific fields (e.g. \`status\` on slices, \`fields\` on stickies).
|
|
|
3714
3757
|
Notes use \`title\` instead of \`name\`. The CLI fills in the id and modelId
|
|
3715
3758
|
automatically — agents do not need to supply them.
|
|
3716
3759
|
|
|
3760
|
+
Fixed-size elements (command, event, read-model, screen, processor,
|
|
3761
|
+
external-event) are not resizable in the editor: the CLI always writes their
|
|
3762
|
+
canonical dimensions, so width/height are optional and any supplied size is
|
|
3763
|
+
overridden (a note is printed when it differs). Containers (slice, chapter,
|
|
3764
|
+
context, …) are resizable — pass the size you want.
|
|
3765
|
+
|
|
3717
3766
|
Screens accept an optional \`design\` field — an Excalidraw scene as a JSON
|
|
3718
3767
|
array of elements. The CLI converts the array to the Y.Doc representation that
|
|
3719
3768
|
the canvas streams in realtime, so passing valid Excalidraw JSON is enough:
|
|
@@ -3745,6 +3794,11 @@ function registerCreateCommands(program) {
|
|
|
3745
3794
|
console.error(`Invalid JSON: ${err.message}`);
|
|
3746
3795
|
process.exit(2);
|
|
3747
3796
|
}
|
|
3797
|
+
if (parsed && typeof parsed === "object") {
|
|
3798
|
+
const note = enforceCanonicalSize(meta, parsed);
|
|
3799
|
+
if (note)
|
|
3800
|
+
console.error(note);
|
|
3801
|
+
}
|
|
3748
3802
|
const validation = validateEntry(meta.scope, parsed);
|
|
3749
3803
|
if (!validation.ok) {
|
|
3750
3804
|
console.error(`Validation failed for ${meta.type}:`);
|
|
@@ -3822,10 +3876,13 @@ Pattern (read-modify-write):
|
|
|
3822
3876
|
| jq '.fields += [{"name":"customerId","fieldType":"UUID","isList":false,"isGenerated":false}]')
|
|
3823
3877
|
eventmodeler update event "OrderPlaced" "$NEW"
|
|
3824
3878
|
|
|
3825
|
-
Linked-copy entries
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3879
|
+
Linked-copy entries can be repositioned/resized but never re-identified. A
|
|
3880
|
+
copy shares its original's name and fields by design, so an update to a copy
|
|
3881
|
+
writes geometry (x, y, width, height) only — any name/field keys in the
|
|
3882
|
+
payload are ignored. To change a copy's name or fields, edit the original and
|
|
3883
|
+
all copies pick up the change. Address a copy by uuid:
|
|
3884
|
+
|
|
3885
|
+
eventmodeler --id <copy-uuid> update event '{"x":120,"y":340}'
|
|
3829
3886
|
|
|
3830
3887
|
Flows have no addressable name and must be updated via uuid:
|
|
3831
3888
|
|
|
@@ -3840,6 +3897,33 @@ semantics); to preserve it, round-trip via \`show screen ... | jq\`.
|
|
|
3840
3897
|
This is a *replace*, not a patch: keys present in the previous entry but
|
|
3841
3898
|
absent in the new JSON are removed.
|
|
3842
3899
|
`;
|
|
3900
|
+
var GEOMETRY_KEYS = ["x", "y", "width", "height"];
|
|
3901
|
+
function extractGeometry(parsed) {
|
|
3902
|
+
if (!parsed || typeof parsed !== "object") {
|
|
3903
|
+
return { ok: false, values: {}, issues: ["payload must be a JSON object"] };
|
|
3904
|
+
}
|
|
3905
|
+
const obj = parsed;
|
|
3906
|
+
const values = {};
|
|
3907
|
+
const issues = [];
|
|
3908
|
+
for (const k of GEOMETRY_KEYS) {
|
|
3909
|
+
const v = obj[k];
|
|
3910
|
+
if (v === undefined)
|
|
3911
|
+
continue;
|
|
3912
|
+
if (typeof v !== "number" || !Number.isFinite(v)) {
|
|
3913
|
+
issues.push(`${k} must be a finite number`);
|
|
3914
|
+
continue;
|
|
3915
|
+
}
|
|
3916
|
+
if ((k === "width" || k === "height") && v <= 0) {
|
|
3917
|
+
issues.push(`${k} must be positive`);
|
|
3918
|
+
continue;
|
|
3919
|
+
}
|
|
3920
|
+
values[k] = v;
|
|
3921
|
+
}
|
|
3922
|
+
if (issues.length === 0 && Object.keys(values).length === 0) {
|
|
3923
|
+
issues.push("no geometry fields (x, y, width, height) present to update");
|
|
3924
|
+
}
|
|
3925
|
+
return { ok: issues.length === 0, values, issues };
|
|
3926
|
+
}
|
|
3843
3927
|
function registerUpdateCommands(program) {
|
|
3844
3928
|
program.command("update <type> <args...>").description(`Replace an element's shape with JSON. Types: ${knownTypeAliases().join(", ")}`).option("--model <id>", "Model id (defaults to .eventmodeler.json in cwd)").addHelpText("after", UPDATE_HELP).action(async (type, args, opts) => {
|
|
3845
3929
|
const meta = resolveType(type);
|
|
@@ -3874,12 +3958,10 @@ function registerUpdateCommands(program) {
|
|
|
3874
3958
|
console.error(`Invalid JSON: ${err.message}`);
|
|
3875
3959
|
process.exit(2);
|
|
3876
3960
|
}
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
console.error(` - ${issue}`);
|
|
3882
|
-
process.exit(2);
|
|
3961
|
+
if (parsed && typeof parsed === "object") {
|
|
3962
|
+
const note = enforceCanonicalSize(meta, parsed);
|
|
3963
|
+
if (note)
|
|
3964
|
+
console.error(note);
|
|
3883
3965
|
}
|
|
3884
3966
|
const modelId = resolveModelId(opts.model);
|
|
3885
3967
|
await withDoc(modelId, (doc) => {
|
|
@@ -3887,19 +3969,39 @@ function registerUpdateCommands(program) {
|
|
|
3887
3969
|
idOverride,
|
|
3888
3970
|
includeLinkedCopies: Boolean(idOverride)
|
|
3889
3971
|
});
|
|
3972
|
+
const map = getScopeMap(doc, meta.scope);
|
|
3890
3973
|
if (entry.isLinkedCopy) {
|
|
3891
|
-
const
|
|
3892
|
-
|
|
3974
|
+
const geom = extractGeometry(parsed);
|
|
3975
|
+
if (!geom.ok) {
|
|
3976
|
+
console.error(`Cannot update ${meta.type} ${id} (linked copy):`);
|
|
3977
|
+
for (const issue of geom.issues)
|
|
3978
|
+
console.error(` - ${issue}`);
|
|
3979
|
+
process.exit(2);
|
|
3980
|
+
}
|
|
3981
|
+
doc.transact(() => {
|
|
3982
|
+
const e = map.get(id);
|
|
3983
|
+
if (!e)
|
|
3984
|
+
return;
|
|
3985
|
+
for (const [k, v] of Object.entries(geom.values))
|
|
3986
|
+
e.set(k, v);
|
|
3987
|
+
});
|
|
3988
|
+
console.log(`Updated ${meta.type} geometry (linked copy — name and fields stay tied to the original).`);
|
|
3989
|
+
return;
|
|
3990
|
+
}
|
|
3991
|
+
const validation = validateEntry(meta.scope, parsed);
|
|
3992
|
+
if (!validation.ok) {
|
|
3993
|
+
console.error(`Validation failed for ${meta.type}:`);
|
|
3994
|
+
for (const issue of validation.issues)
|
|
3995
|
+
console.error(` - ${issue}`);
|
|
3893
3996
|
process.exit(2);
|
|
3894
3997
|
}
|
|
3895
|
-
const map = getScopeMap(doc, meta.scope);
|
|
3896
3998
|
const finalEntry = { ...validation.data, [meta.idKey]: id, modelId };
|
|
3897
3999
|
doc.transact(() => {
|
|
3898
4000
|
map.delete(id);
|
|
3899
4001
|
map.set(id, deepToY(finalEntry));
|
|
3900
4002
|
});
|
|
4003
|
+
console.log(`Updated ${meta.type}.`);
|
|
3901
4004
|
});
|
|
3902
|
-
console.log(`Updated ${meta.type}.`);
|
|
3903
4005
|
});
|
|
3904
4006
|
}
|
|
3905
4007
|
|