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.
Files changed (2) hide show
  1. package/dist/index.js +117 -15
  2. 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().optional(),
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 cannot be updated. They share the original's name and
3826
- fields by design edit the original and all copies pick up the change. The
3827
- CLI refuses both name-based updates (ambiguous with the original) and
3828
- --id <copy-uuid> updates (would diverge from the original).
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
- const validation = validateEntry(meta.scope, parsed);
3878
- if (!validation.ok) {
3879
- console.error(`Validation failed for ${meta.type}:`);
3880
- for (const issue of validation.issues)
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 originalId = meta.originalIdKey ? entry[meta.originalIdKey] : undefined;
3892
- console.error(`Cannot update ${meta.type} ${id} — it is a linked copy. ` + `Linked copies share their original's name and fields; edit the original instead` + (originalId ? ` (--id ${originalId}).` : "."));
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eventmodeler",
3
- "version": "0.6.8",
3
+ "version": "0.6.10",
4
4
  "description": "CLI tool for event modeling - explore, design, and generate code from your event models",
5
5
  "type": "module",
6
6
  "repository": {