entitymodeler 0.1.0 → 0.1.1

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/bin/em.mjs +14 -3
  2. package/package.json +1 -1
package/bin/em.mjs CHANGED
@@ -12729,6 +12729,10 @@ function relationalPlan(m) {
12729
12729
  if (!child || !parent || !pk) continue;
12730
12730
  let fk = resolveForeignKey(m, r, byName);
12731
12731
  if (!fk) fk = addColumn(child, ends.child === ends.parent ? `parent_${pk.name}` : keyColumnName(parent, pk), pk, `${parent.display_name} (${r.forward_label})`, `relationship ${r.name}`);
12732
+ if (r.required) {
12733
+ const column = child.columns.find((c) => c.name === fk);
12734
+ if (column) column.notNull = true;
12735
+ }
12732
12736
  if (r.cardinality === "1:1" && !child.pk.includes(fk)) child.unique.push(fk);
12733
12737
  for (const ra of r.attributes || []) addRelationshipColumn(child, ra, r, false);
12734
12738
  foreignKeys.push({ name: fkName(`fk_${r.name}`), table: child.name, column: fk, refTable: parent.name, refColumn: pk.name, kind: "relationship", relationship: r.name });
@@ -13224,6 +13228,7 @@ function deriveLogical(src, o) {
13224
13228
  }
13225
13229
  delete r.foreign_key;
13226
13230
  if (!child || !a) continue;
13231
+ if (a.required) r.required = true;
13227
13232
  child.attributes = child.attributes.filter((x) => x !== a);
13228
13233
  rep.droppedColumns.push(`${child.name}.${a.name} (foreign key \u2192 ${r.name})`);
13229
13234
  }
@@ -13388,14 +13393,18 @@ function derivePhysical(src, o) {
13388
13393
  child.attributes.push({ ...rest, name: uniqueName(ra.name, child.attributes.map((a) => a.name)), is_primary_key: false, is_label: false, description: ra.description || `${r.forward_label || r.name}: ${ra.label || ra.name}` });
13389
13394
  }
13390
13395
  if (r.attributes?.length) r.attributes = [];
13396
+ const required = r.required;
13397
+ delete r.required;
13391
13398
  const existing = r.foreign_key && child.attributes.some((a) => a.name === r.foreign_key) ? r.foreign_key : inferForeignKey(m, r);
13392
13399
  if (existing) {
13393
13400
  r.foreign_key = existing;
13401
+ const column = child.attributes.find((a) => a.name === existing);
13402
+ if (required && column) column.required = true;
13394
13403
  continue;
13395
13404
  }
13396
13405
  const name = uniqueName(ends.child === ends.parent ? `parent_${pk.name}` : keyColumnName(parent, pk), child.attributes.map((a) => a.name));
13397
13406
  const at = child.attributes.findIndex((a) => !a.is_primary_key);
13398
- const col = { name, label: toLabel(name), type: pk.type, description: `${parent.display_name} (${r.forward_label || r.name})` };
13407
+ const col = { name, label: toLabel(name), type: pk.type, ...required ? { required } : {}, description: `${parent.display_name} (${r.forward_label || r.name})` };
13399
13408
  child.attributes.splice(at === -1 ? child.attributes.length : at, 0, col);
13400
13409
  r.foreign_key = name;
13401
13410
  fkAdded++;
@@ -14928,6 +14937,7 @@ function validateModel(m) {
14928
14937
  for (const end of ["source", "target"])
14929
14938
  if (!entityByName.has(r[end])) push("error", "rel.endpoint", `Relationship "${r.name}" ${end} entity "${r[end]}" does not exist.`, t);
14930
14939
  if (!r.forward_label) push("warning", "rel.fwd", `Relationship "${r.name}" has no forward label.`, t);
14940
+ if (r.required && !relationshipEnds(r)) push("warning", "rel.reqnn", `Relationship "${r.name}" is N:N, so "required" is ignored (a junction table is used).`, t);
14931
14941
  if (r.foreign_key) {
14932
14942
  const ends = relationshipEnds(r);
14933
14943
  if (!ends) push("warning", "rel.fknn", `Relationship "${r.name}" is N:N, so its foreign key "${r.foreign_key}" is ignored (a junction table is used).`, t);
@@ -16522,6 +16532,7 @@ function diffViews(A, B, dir, a = { id: "a", name: "Before" }, b = { id: "b", na
16522
16532
  if (relKey(ra, "a") !== relKey(rb, "b")) d.push(`ends ${ra.source} \u2192 ${ra.target} became ${rb.source} \u2192 ${rb.target}`);
16523
16533
  if (ra.cardinality !== rb.cardinality) d.push(`cardinality ${ra.cardinality} \u2192 ${rb.cardinality}`);
16524
16534
  if ((ra.foreign_key || "") !== (rb.foreign_key || "")) d.push(`foreign key ${ra.foreign_key || "(none)"} \u2192 ${rb.foreign_key || "(none)"}`);
16535
+ if (!!ra.required !== !!rb.required) d.push(rb.required ? "optional \u2192 required" : "required \u2192 optional");
16525
16536
  if (ra.forward_label !== rb.forward_label) d.push(`label "${ra.forward_label}" \u2192 "${rb.forward_label}"`);
16526
16537
  const raAttrs = new Map((ra.attributes || []).map((x) => [x.name, x]));
16527
16538
  const rbAttrs = new Map((rb.attributes || []).map((x) => [x.name, x]));
@@ -17076,8 +17087,8 @@ update_entity {entity, set:{display_name?, description?, entity_type?, color_cod
17076
17087
  rename_entity {entity, to} delete_entity {entity}
17077
17088
  add_attribute {entity, attribute:{name, type?, label?, description?, is_primary_key?, is_label?, required?, pii?, example?, is_array?, reference?:{entity, output_attribute}, struct_type?}, after?}
17078
17089
  update_attribute {entity, attribute, set:{\u2026}} rename_attribute {entity, attribute, to} delete_attribute {entity, attribute} move_attribute {entity, attribute, after: name|null}
17079
- add_relationship {relationship:{source, target, name?, cardinality?: "1:1"|"1:N"|"N:1"|"N:N", forward_label?, reverse_label?, bidirectional?, foreign_key?, description?, attributes?: Attribute[]}}
17080
- update_relationship {relationship, set:{\u2026}} \u2014 set.attributes replaces the relationship's own attributes (facts about the link, e.g. an enrollment's grade; simple types only): junction-table columns for N:N, child-table columns otherwise rename_relationship {relationship, to} delete_relationship {relationship}
17090
+ add_relationship {relationship:{source, target, name?, cardinality?: "1:1"|"1:N"|"N:1"|"N:N", forward_label?, reverse_label?, bidirectional?, foreign_key?, required?, description?, attributes?: Attribute[]}}
17091
+ update_relationship {relationship, set:{\u2026}} \u2014 set.required: true means the child can't exist without the parent (NOT NULL foreign key); set.attributes replaces the relationship's own attributes (facts about the link, e.g. an enrollment's grade; simple types only): junction-table columns for N:N, child-table columns otherwise rename_relationship {relationship, to} delete_relationship {relationship}
17081
17092
  set_reference_values {entity, values:[{attr: "value"}\u2026], source?}
17082
17093
  add_note {text} set_hidden {entities:[\u2026], hidden} update_model {set:{title?, description?, organization?, version?, author?, status?}}
17083
17094
  update_tab {tab, set:{name?, kind?, dialect?, description?}} make_primary {tab} delete_tab {tab}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "entitymodeler",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "EntityModel.com: data modeling CLI and MCP server for Claude and other agents.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://entitymodel.com",