@matserdam/prisma-neighborhood 0.2.0 → 0.3.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # prisma-neighbourhood
2
2
 
3
- Generate focused ERD diagrams from a Prisma schema by starting from one model and traversing relationships up to a configurable depth.
3
+ Generate focused ERD diagrams from a Prisma schema by starting from any entity (model, view, or enum) and traversing relationships up to a configurable depth.
4
4
 
5
5
  The npm package is **`@matserdam/prisma-neighborhood`** and it exposes two CLI commands:
6
6
 
@@ -20,6 +20,12 @@ bunx @matserdam/prisma-neighborhood -s ./prisma/schema.prisma -m User
20
20
  # Limit to direct relationships only (depth 1)
21
21
  bunx @matserdam/prisma-neighborhood -s ./prisma/schema.prisma -m User -d 1
22
22
 
23
+ # Start from a view (shows view + related enums/models)
24
+ bunx @matserdam/prisma-neighborhood -s ./prisma/schema.prisma -m UserSummary -d 2
25
+
26
+ # Start from an enum (shows enum + all models/views using it)
27
+ bunx @matserdam/prisma-neighborhood -s ./prisma/schema.prisma -m UserRole -d 2
28
+
23
29
  # Write Mermaid to a file (use .mmd or .md)
24
30
  bunx @matserdam/prisma-neighborhood -s ./prisma/schema.prisma -m User -o erd.mmd
25
31
 
@@ -50,7 +56,7 @@ prisma-hood -s ./prisma/schema.prisma -m User
50
56
  | Option | Alias | Description | Default |
51
57
  |--------|-------|-------------|---------|
52
58
  | `--schema <path>` | `-s` | Path to the Prisma schema file | required |
53
- | `--model <name>` | `-m` | Model to start traversal from | required |
59
+ | `--model <name>` | `-m` | Entity to start traversal from (model, view, or enum) | required |
54
60
  | `--depth <n>` | `-d` | Relationship levels to traverse | `3` |
55
61
  | `--renderer <name>` | `-r` | Renderer to use | `vector` |
56
62
  | `--output <file>` | `-o` | Write to a file instead of stdout | stdout |
@@ -69,6 +75,32 @@ The output format is determined by the file extension:
69
75
  | `.png` | PNG image |
70
76
  | `.pdf` | PDF |
71
77
 
72
- ## No Puppeteer / Chromium
78
+ ## Entity types
79
+
80
+ ### Models
81
+ Standard Prisma models are rendered as plain ERD entities.
82
+
83
+ ### Views
84
+ Views (requires `previewFeatures = ["views"]`) are rendered with a `[view]` prefix:
85
+ ```
86
+ "[view] UserSummary" {
87
+ Int id UK
88
+ String email
89
+ }
90
+ ```
91
+
92
+ ### Enums
93
+ Enums are rendered with an `[enum]` prefix, with the enum name as the type for each value:
94
+ ```
95
+ "[enum] UserRole" {
96
+ UserRole ADMIN
97
+ UserRole USER
98
+ UserRole GUEST
99
+ }
100
+ ```
101
+
102
+ ## Traversal behavior
73
103
 
74
- SVG/PNG/PDF export is implemented without headless Chromium, so you no longer need to install OS-level Chromium dependencies.
104
+ - **From a model**: Traverses relations to other models/views, and enum fields to enums
105
+ - **From a view**: Traverses relations to models/views, and enum fields to enums
106
+ - **From an enum**: Finds all models/views using this enum, then traverses their relations
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @fileoverview Tests for the model traverser.
3
- * Tests cover BFS traversal, depth limiting, and cycle detection.
2
+ * @fileoverview Tests for the entity traverser.
3
+ * Tests cover BFS traversal of models, views, and enums with depth limiting.
4
4
  */
5
5
  export {};
6
6
  //# sourceMappingURL=traverser.test.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmCpC;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,OAAO,CA2BvC;AAqID;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1D"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmCpC;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,OAAO,CA8BvC;AAqID;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1D"}
package/dist/cli.js CHANGED
@@ -2155,6 +2155,48 @@ function isPrimaryKeyField(field) {
2155
2155
  function isUniqueField(field) {
2156
2156
  return field.isUnique;
2157
2157
  }
2158
+ function extractViewNames(schemaContent) {
2159
+ const viewNames = new Set;
2160
+ const viewRegex = /^\s*view\s+(\w+)\s*\{/gm;
2161
+ const matches = schemaContent.matchAll(viewRegex);
2162
+ for (const match of matches) {
2163
+ viewNames.add(match[1]);
2164
+ }
2165
+ return viewNames;
2166
+ }
2167
+ function parseFieldsAndRelations(dmmfEntity, entityLookup) {
2168
+ const fields = [];
2169
+ const relations = [];
2170
+ for (const dmmfField of dmmfEntity.fields) {
2171
+ const field = {
2172
+ name: dmmfField.name,
2173
+ type: dmmfField.type,
2174
+ isRequired: dmmfField.isRequired,
2175
+ isList: dmmfField.isList,
2176
+ isPrimaryKey: isPrimaryKeyField(dmmfField),
2177
+ isUnique: isUniqueField(dmmfField),
2178
+ isRelation: isRelationField(dmmfField)
2179
+ };
2180
+ fields.push(field);
2181
+ if (isRelationField(dmmfField)) {
2182
+ const relatedEntity = entityLookup.get(dmmfField.type);
2183
+ const relatedField = relatedEntity?.fields.find((f) => f.relationName === dmmfField.relationName && f.name !== dmmfField.name);
2184
+ const relationType = determineRelationType({ isList: dmmfField.isList, isRequired: dmmfField.isRequired }, relatedField ? {
2185
+ isList: relatedField.isList,
2186
+ isRequired: relatedField.isRequired
2187
+ } : undefined);
2188
+ const isOwner = dmmfField.relationFromFields !== undefined && dmmfField.relationFromFields.length > 0;
2189
+ const relation = {
2190
+ relatedModel: dmmfField.type,
2191
+ type: relationType,
2192
+ fieldName: dmmfField.name,
2193
+ isOwner
2194
+ };
2195
+ relations.push(relation);
2196
+ }
2197
+ }
2198
+ return { fields, relations };
2199
+ }
2158
2200
  async function parseSchema(options) {
2159
2201
  const { schemaPath } = options;
2160
2202
  try {
@@ -2168,53 +2210,44 @@ async function parseSchema(options) {
2168
2210
  };
2169
2211
  }
2170
2212
  const dmmf = await import_internals.getDMMF({ datamodel: schemaContent });
2213
+ const viewNamesFromSchema = extractViewNames(schemaContent);
2171
2214
  const dmmfModels = dmmf.datamodel.models;
2172
- const modelMap = new Map;
2215
+ const dmmfEnums = dmmf.datamodel.enums ?? [];
2216
+ const entityLookup = new Map;
2173
2217
  for (const model of dmmfModels) {
2174
- modelMap.set(model.name, model);
2218
+ entityLookup.set(model.name, model);
2175
2219
  }
2176
2220
  const models = new Map;
2221
+ const views = new Map;
2177
2222
  for (const dmmfModel of dmmfModels) {
2178
- const fields = [];
2179
- const relations = [];
2180
- for (const dmmfField of dmmfModel.fields) {
2181
- const field = {
2182
- name: dmmfField.name,
2183
- type: dmmfField.type,
2184
- isRequired: dmmfField.isRequired,
2185
- isList: dmmfField.isList,
2186
- isPrimaryKey: isPrimaryKeyField(dmmfField),
2187
- isUnique: isUniqueField(dmmfField),
2188
- isRelation: isRelationField(dmmfField)
2223
+ const { fields, relations } = parseFieldsAndRelations(dmmfModel, entityLookup);
2224
+ if (viewNamesFromSchema.has(dmmfModel.name)) {
2225
+ const view = {
2226
+ name: dmmfModel.name,
2227
+ fields,
2228
+ relations
2189
2229
  };
2190
- fields.push(field);
2191
- if (isRelationField(dmmfField)) {
2192
- const relatedModel = modelMap.get(dmmfField.type);
2193
- const relatedField = relatedModel?.fields.find((f) => f.relationName === dmmfField.relationName && f.name !== dmmfField.name);
2194
- const relationType = determineRelationType({ isList: dmmfField.isList, isRequired: dmmfField.isRequired }, relatedField ? {
2195
- isList: relatedField.isList,
2196
- isRequired: relatedField.isRequired
2197
- } : undefined);
2198
- const isOwner = dmmfField.relationFromFields !== undefined && dmmfField.relationFromFields.length > 0;
2199
- const relation = {
2200
- relatedModel: dmmfField.type,
2201
- type: relationType,
2202
- fieldName: dmmfField.name,
2203
- isOwner
2204
- };
2205
- relations.push(relation);
2206
- }
2230
+ views.set(view.name, view);
2231
+ } else {
2232
+ const model = {
2233
+ name: dmmfModel.name,
2234
+ fields,
2235
+ relations
2236
+ };
2237
+ models.set(model.name, model);
2207
2238
  }
2208
- const model = {
2209
- name: dmmfModel.name,
2210
- fields,
2211
- relations
2239
+ }
2240
+ const enums = new Map;
2241
+ for (const dmmfEnum of dmmfEnums) {
2242
+ const enumDef = {
2243
+ name: dmmfEnum.name,
2244
+ values: dmmfEnum.values.map((v) => v.name)
2212
2245
  };
2213
- models.set(model.name, model);
2246
+ enums.set(enumDef.name, enumDef);
2214
2247
  }
2215
2248
  return {
2216
2249
  success: true,
2217
- schema: { models }
2250
+ schema: { models, views, enums }
2218
2251
  };
2219
2252
  } catch (error) {
2220
2253
  const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
@@ -2230,43 +2263,88 @@ var RELATION_SYMBOLS = {
2230
2263
  ONE_TO_MANY: "||--o{",
2231
2264
  MANY_TO_MANY: "}o--o{"
2232
2265
  };
2233
- function renderMermaidErd(models) {
2266
+ var ENUM_USAGE_SYMBOL = "}o--||";
2267
+ function renderModelOrView(entity, isView, lines) {
2268
+ const displayName = isView ? `"[view] ${entity.name}"` : entity.name;
2269
+ lines.push(` ${displayName} {`);
2270
+ for (const field of entity.fields) {
2271
+ if (field.isRelation) {
2272
+ continue;
2273
+ }
2274
+ const modifiers = [];
2275
+ if (field.isPrimaryKey) {
2276
+ modifiers.push("PK");
2277
+ }
2278
+ if (field.isUnique && !field.isPrimaryKey) {
2279
+ modifiers.push("UK");
2280
+ }
2281
+ const modifierStr = modifiers.length > 0 ? ` ${modifiers.join(",")}` : "";
2282
+ lines.push(` ${field.type} ${field.name}${modifierStr}`);
2283
+ }
2284
+ lines.push(" }");
2285
+ }
2286
+ function renderEnum(enumDef, lines) {
2287
+ lines.push(` "[enum] ${enumDef.name}" {`);
2288
+ for (const value of enumDef.values) {
2289
+ lines.push(` ${enumDef.name} ${value}`);
2290
+ }
2291
+ lines.push(" }");
2292
+ }
2293
+ function renderMermaidErd(entities) {
2234
2294
  const lines = ["erDiagram"];
2235
2295
  const renderedRelations = new Set;
2236
- for (const { model } of models) {
2237
- lines.push(` ${model.name} {`);
2238
- for (const field of model.fields) {
2239
- if (field.isRelation) {
2240
- continue;
2241
- }
2242
- const modifiers = [];
2243
- if (field.isPrimaryKey) {
2244
- modifiers.push("PK");
2245
- }
2246
- if (field.isUnique && !field.isPrimaryKey) {
2247
- modifiers.push("UK");
2248
- }
2249
- const modifierStr = modifiers.length > 0 ? ` ${modifiers.join(",")}` : "";
2250
- lines.push(` ${field.type} ${field.name}${modifierStr}`);
2296
+ const modelViewNames = new Set;
2297
+ const enumNames = new Set;
2298
+ const displayNames = new Map;
2299
+ for (const { entity, kind } of entities) {
2300
+ if (kind === "enum") {
2301
+ enumNames.add(entity.name);
2302
+ displayNames.set(entity.name, `"[enum] ${entity.name}"`);
2303
+ } else if (kind === "view") {
2304
+ modelViewNames.add(entity.name);
2305
+ displayNames.set(entity.name, `"[view] ${entity.name}"`);
2306
+ } else {
2307
+ modelViewNames.add(entity.name);
2308
+ displayNames.set(entity.name, entity.name);
2251
2309
  }
2252
- lines.push(" }");
2253
2310
  }
2254
- const modelNames = new Set(models.map((m) => m.model.name));
2255
- for (const { model } of models) {
2256
- for (const relation of model.relations) {
2257
- if (!modelNames.has(relation.relatedModel)) {
2311
+ const getDisplayName = (name) => displayNames.get(name) ?? name;
2312
+ for (const { entity, kind } of entities) {
2313
+ if (kind === "enum") {
2314
+ renderEnum(entity, lines);
2315
+ } else {
2316
+ renderModelOrView(entity, kind === "view", lines);
2317
+ }
2318
+ }
2319
+ for (const { entity, kind } of entities) {
2320
+ if (kind === "enum") {
2321
+ continue;
2322
+ }
2323
+ const modelOrView = entity;
2324
+ for (const relation of modelOrView.relations) {
2325
+ if (!modelViewNames.has(relation.relatedModel)) {
2258
2326
  continue;
2259
2327
  }
2260
- const sortedNames = [model.name, relation.relatedModel].sort();
2261
- const relationKey = `${sortedNames[0]}-${sortedNames[1]}`;
2328
+ const sortedNames = [entity.name, relation.relatedModel].sort();
2329
+ const relationKey = `model:${sortedNames[0]}-${sortedNames[1]}`;
2262
2330
  if (renderedRelations.has(relationKey)) {
2263
2331
  continue;
2264
2332
  }
2265
2333
  const symbol = RELATION_SYMBOLS[relation.type];
2266
- const label = relation.fieldName;
2267
- lines.push(` ${model.name} ${symbol} ${relation.relatedModel} : "${label}"`);
2334
+ lines.push(` ${getDisplayName(entity.name)} ${symbol} ${getDisplayName(relation.relatedModel)} : "${relation.fieldName}"`);
2268
2335
  renderedRelations.add(relationKey);
2269
2336
  }
2337
+ for (const field of modelOrView.fields) {
2338
+ if (!enumNames.has(field.type)) {
2339
+ continue;
2340
+ }
2341
+ const enumRelationKey = `enum:${entity.name}-${field.type}-${field.name}`;
2342
+ if (renderedRelations.has(enumRelationKey)) {
2343
+ continue;
2344
+ }
2345
+ lines.push(` ${getDisplayName(entity.name)} ${ENUM_USAGE_SYMBOL} ${getDisplayName(field.type)} : "${field.name}"`);
2346
+ renderedRelations.add(enumRelationKey);
2347
+ }
2270
2348
  }
2271
2349
  return lines.join(`
2272
2350
  `);
@@ -2328,8 +2406,8 @@ async function runMermaidCli(mermaidContent, options) {
2328
2406
  class MermaidRenderer {
2329
2407
  name = "mermaid";
2330
2408
  description = "Mermaid ERD syntax (text). Supports export via mermaid-cli.";
2331
- render(models) {
2332
- return renderMermaidErd(models);
2409
+ render(entities) {
2410
+ return renderMermaidErd(entities);
2333
2411
  }
2334
2412
  async export(content, outputPath, format) {
2335
2413
  await runMermaidCli(content, { outputFormat: format, outputPath });
@@ -2385,8 +2463,8 @@ var import_sharp = __toESM(require("sharp"));
2385
2463
  class VectorRenderer {
2386
2464
  name = "vector";
2387
2465
  description = "Vector-first Mermaid ERD renderer (default). Exports SVG/PNG/PDF using mermaid-cli with sharp for high-DPI output.";
2388
- render(models) {
2389
- return renderMermaidErd(models);
2466
+ render(entities) {
2467
+ return renderMermaidErd(entities);
2390
2468
  }
2391
2469
  async export(content, outputPath, format) {
2392
2470
  const svg = await runMermaidCli(content, {
@@ -2443,47 +2521,127 @@ if (!rendererRegistry.has("mermaid")) {
2443
2521
  });
2444
2522
  }
2445
2523
 
2446
- // src/traversal/model-traverser.ts
2524
+ // src/traversal/entity-traverser.ts
2447
2525
  var DEFAULT_MAX_DEPTH = 3;
2448
- function traverseModels(schema, options) {
2449
- const { startModel: startModelName, maxDepth = DEFAULT_MAX_DEPTH } = options;
2450
- const startModel = schema.models.get(startModelName);
2451
- if (!startModel) {
2526
+ function entityKey(kind, name) {
2527
+ return `${kind}:${name}`;
2528
+ }
2529
+ function findEntity(schema, name) {
2530
+ const model = schema.models.get(name);
2531
+ if (model) {
2532
+ return { entity: model, kind: "model" };
2533
+ }
2534
+ const view = schema.views.get(name);
2535
+ if (view) {
2536
+ return { entity: view, kind: "view" };
2537
+ }
2538
+ const enumDef = schema.enums.get(name);
2539
+ if (enumDef) {
2540
+ return { entity: enumDef, kind: "enum" };
2541
+ }
2542
+ return;
2543
+ }
2544
+ function findEntitiesUsingEnum(schema, enumName) {
2545
+ const result = [];
2546
+ for (const model of schema.models.values()) {
2547
+ const usesEnum = model.fields.some((f) => f.type === enumName);
2548
+ if (usesEnum) {
2549
+ result.push({ entity: model, kind: "model" });
2550
+ }
2551
+ }
2552
+ for (const view of schema.views.values()) {
2553
+ const usesEnum = view.fields.some((f) => f.type === enumName);
2554
+ if (usesEnum) {
2555
+ result.push({ entity: view, kind: "view" });
2556
+ }
2557
+ }
2558
+ return result;
2559
+ }
2560
+ function getReferencedEnums(entity, schema) {
2561
+ const enums = [];
2562
+ for (const field of entity.fields) {
2563
+ const enumDef = schema.enums.get(field.type);
2564
+ if (enumDef) {
2565
+ enums.push(enumDef);
2566
+ }
2567
+ }
2568
+ return enums;
2569
+ }
2570
+ function getRelatedEntities(entity, schema) {
2571
+ const result = [];
2572
+ for (const relation of entity.relations) {
2573
+ const relatedModel = schema.models.get(relation.relatedModel);
2574
+ if (relatedModel) {
2575
+ result.push({ entity: relatedModel, kind: "model" });
2576
+ continue;
2577
+ }
2578
+ const relatedView = schema.views.get(relation.relatedModel);
2579
+ if (relatedView) {
2580
+ result.push({ entity: relatedView, kind: "view" });
2581
+ }
2582
+ }
2583
+ return result;
2584
+ }
2585
+ function traverseEntities(schema, options) {
2586
+ const { startEntity: startEntityName, maxDepth = DEFAULT_MAX_DEPTH } = options;
2587
+ const startFound = findEntity(schema, startEntityName);
2588
+ if (!startFound) {
2452
2589
  return {
2453
2590
  success: false,
2454
- error: `Start model "${startModelName}" not found in schema`
2591
+ error: `Entity "${startEntityName}" not found in schema (searched models, views, and enums)`
2455
2592
  };
2456
2593
  }
2594
+ const { entity: startEntity, kind: startKind } = startFound;
2457
2595
  const visited = new Set;
2458
2596
  const result = [];
2459
2597
  const queue = [];
2460
- queue.push({ model: startModel, depth: 0 });
2461
- visited.add(startModelName);
2598
+ queue.push({ entity: startEntity, kind: startKind, depth: 0 });
2599
+ visited.add(entityKey(startKind, startEntity.name));
2462
2600
  while (queue.length > 0) {
2463
2601
  const current = queue.shift();
2464
2602
  if (!current)
2465
2603
  break;
2466
- const { model, depth } = current;
2467
- result.push({ model, depth });
2604
+ const { entity, kind, depth } = current;
2605
+ result.push({ entity, kind, depth });
2468
2606
  if (depth >= maxDepth) {
2469
2607
  continue;
2470
2608
  }
2471
- for (const relation of model.relations) {
2472
- const relatedModelName = relation.relatedModel;
2473
- if (visited.has(relatedModelName)) {
2474
- continue;
2609
+ if (kind === "enum") {
2610
+ const users = findEntitiesUsingEnum(schema, entity.name);
2611
+ for (const { entity: user, kind: userKind } of users) {
2612
+ const key = entityKey(userKind, user.name);
2613
+ if (!visited.has(key)) {
2614
+ visited.add(key);
2615
+ queue.push({ entity: user, kind: userKind, depth: depth + 1 });
2616
+ }
2475
2617
  }
2476
- const relatedModel = schema.models.get(relatedModelName);
2477
- if (!relatedModel) {
2478
- continue;
2618
+ } else {
2619
+ const modelOrView = entity;
2620
+ const related = getRelatedEntities(modelOrView, schema);
2621
+ for (const { entity: relatedEntity, kind: relatedKind } of related) {
2622
+ const key = entityKey(relatedKind, relatedEntity.name);
2623
+ if (!visited.has(key)) {
2624
+ visited.add(key);
2625
+ queue.push({
2626
+ entity: relatedEntity,
2627
+ kind: relatedKind,
2628
+ depth: depth + 1
2629
+ });
2630
+ }
2631
+ }
2632
+ const enums = getReferencedEnums(modelOrView, schema);
2633
+ for (const enumDef of enums) {
2634
+ const key = entityKey("enum", enumDef.name);
2635
+ if (!visited.has(key)) {
2636
+ visited.add(key);
2637
+ queue.push({ entity: enumDef, kind: "enum", depth: depth + 1 });
2638
+ }
2479
2639
  }
2480
- visited.add(relatedModelName);
2481
- queue.push({ model: relatedModel, depth: depth + 1 });
2482
2640
  }
2483
2641
  }
2484
2642
  return {
2485
2643
  success: true,
2486
- models: result
2644
+ entities: result
2487
2645
  };
2488
2646
  }
2489
2647
  // src/cli/types.ts
@@ -2509,7 +2667,7 @@ function isSupportedExtension(ext) {
2509
2667
  }
2510
2668
  function createProgram() {
2511
2669
  const program2 = new Command;
2512
- program2.name("prisma-neighborhood").description("Generate Entity-Relationship Diagrams from Prisma schemas").version("0.1.0").option("-s, --schema <path>", "Path to the Prisma schema file").option("-m, --model <name>", "Name of the model to start traversal from").option("-d, --depth <n>", "Traversal depth", String(DEFAULT_CLI_OPTIONS.depth)).option("-r, --renderer <name>", "Diagram renderer", DEFAULT_CLI_OPTIONS.renderer).option("-o, --output <file>", "Output file: .mmd, .md (text), .svg, .png, .pdf (export)").option("--list-renderers", "Show available renderers").action(runCommand);
2670
+ program2.name("prisma-neighborhood").description("Generate Entity-Relationship Diagrams from Prisma schemas").version("0.3.0").option("-s, --schema <path>", "Path to the Prisma schema file").option("-m, --model <name>", "Name of the entity (model, view, or enum) to start traversal from").option("-d, --depth <n>", "Traversal depth", String(DEFAULT_CLI_OPTIONS.depth)).option("-r, --renderer <name>", "Diagram renderer", DEFAULT_CLI_OPTIONS.renderer).option("-o, --output <file>", "Output file: .mmd, .md (text), .svg, .png, .pdf (export)").option("--list-renderers", "Show available renderers").action(runCommand);
2513
2671
  return program2;
2514
2672
  }
2515
2673
  function listRenderers() {
@@ -2565,15 +2723,15 @@ async function runCommand(options) {
2565
2723
  process.exit(1);
2566
2724
  }
2567
2725
  const depth = parseInt(options.depth, 10);
2568
- const traversalResult = traverseModels(parseResult.schema, {
2569
- startModel: options.model,
2726
+ const traversalResult = traverseEntities(parseResult.schema, {
2727
+ startEntity: options.model,
2570
2728
  maxDepth: depth
2571
2729
  });
2572
2730
  if (!traversalResult.success) {
2573
2731
  console.error(`Error: ${traversalResult.error}`);
2574
2732
  process.exit(1);
2575
2733
  }
2576
- const output = renderer.render(traversalResult.models);
2734
+ const output = renderer.render(traversalResult.entities);
2577
2735
  if (options.output) {
2578
2736
  if (format && renderer.export) {
2579
2737
  await renderer.export(output, options.output, format);