@documentation-robotics/cli 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.
Files changed (169) hide show
  1. package/PYTHON_CLI_PARITY.md +265 -0
  2. package/PYTHON_CLI_STRUCTURE_UPDATE.md +246 -0
  3. package/README.md +926 -0
  4. package/biome.json +42 -0
  5. package/bunfig.toml +3 -0
  6. package/dist/ai/claude-client.js +71 -0
  7. package/dist/ai/claude-client.js.map +7 -0
  8. package/dist/ai/context-provider.js +129 -0
  9. package/dist/ai/context-provider.js.map +7 -0
  10. package/dist/ai/tools.js +231 -0
  11. package/dist/ai/tools.js.map +7 -0
  12. package/dist/cli.js +224 -0
  13. package/dist/cli.js.map +7 -0
  14. package/dist/commands/add.js +51 -0
  15. package/dist/commands/add.js.map +7 -0
  16. package/dist/commands/changeset.js +174 -0
  17. package/dist/commands/changeset.js.map +7 -0
  18. package/dist/commands/chat.js +111 -0
  19. package/dist/commands/chat.js.map +7 -0
  20. package/dist/commands/conformance.js +132 -0
  21. package/dist/commands/conformance.js.map +7 -0
  22. package/dist/commands/delete.js +31 -0
  23. package/dist/commands/delete.js.map +7 -0
  24. package/dist/commands/element.js +28 -0
  25. package/dist/commands/element.js.map +7 -0
  26. package/dist/commands/export.js +65 -0
  27. package/dist/commands/export.js.map +7 -0
  28. package/dist/commands/info.js +40 -0
  29. package/dist/commands/info.js.map +7 -0
  30. package/dist/commands/init.js +45 -0
  31. package/dist/commands/init.js.map +7 -0
  32. package/dist/commands/list.js +32 -0
  33. package/dist/commands/list.js.map +7 -0
  34. package/dist/commands/migrate.js +36 -0
  35. package/dist/commands/migrate.js.map +7 -0
  36. package/dist/commands/project.js +74 -0
  37. package/dist/commands/project.js.map +7 -0
  38. package/dist/commands/relationship.js +118 -0
  39. package/dist/commands/relationship.js.map +7 -0
  40. package/dist/commands/search.js +48 -0
  41. package/dist/commands/search.js.map +7 -0
  42. package/dist/commands/show.js +38 -0
  43. package/dist/commands/show.js.map +7 -0
  44. package/dist/commands/trace.js +60 -0
  45. package/dist/commands/trace.js.map +7 -0
  46. package/dist/commands/update.js +37 -0
  47. package/dist/commands/update.js.map +7 -0
  48. package/dist/commands/upgrade.js +152 -0
  49. package/dist/commands/upgrade.js.map +7 -0
  50. package/dist/commands/validate.js +71 -0
  51. package/dist/commands/validate.js.map +7 -0
  52. package/dist/commands/version.js +20 -0
  53. package/dist/commands/version.js.map +7 -0
  54. package/dist/commands/visualize.js +51 -0
  55. package/dist/commands/visualize.js.map +7 -0
  56. package/dist/core/active-changeset.js +52 -0
  57. package/dist/core/active-changeset.js.map +7 -0
  58. package/dist/core/changeset.js +244 -0
  59. package/dist/core/changeset.js.map +7 -0
  60. package/dist/core/dependency-tracker.js +322 -0
  61. package/dist/core/dependency-tracker.js.map +7 -0
  62. package/dist/core/element.js +65 -0
  63. package/dist/core/element.js.map +7 -0
  64. package/dist/core/layer.js +75 -0
  65. package/dist/core/layer.js.map +7 -0
  66. package/dist/core/manifest.js +57 -0
  67. package/dist/core/manifest.js.map +7 -0
  68. package/dist/core/migration-registry.js +131 -0
  69. package/dist/core/migration-registry.js.map +7 -0
  70. package/dist/core/model.js +455 -0
  71. package/dist/core/model.js.map +7 -0
  72. package/dist/core/projection-engine.js +288 -0
  73. package/dist/core/projection-engine.js.map +7 -0
  74. package/dist/core/reference-registry.js +188 -0
  75. package/dist/core/reference-registry.js.map +7 -0
  76. package/dist/core/relationship-registry.js +114 -0
  77. package/dist/core/relationship-registry.js.map +7 -0
  78. package/dist/core/relationships.js +78 -0
  79. package/dist/core/relationships.js.map +7 -0
  80. package/dist/export/archimate-exporter.js +111 -0
  81. package/dist/export/archimate-exporter.js.map +7 -0
  82. package/dist/export/export-manager.js +63 -0
  83. package/dist/export/export-manager.js.map +7 -0
  84. package/dist/export/graphml-exporter.js +39 -0
  85. package/dist/export/graphml-exporter.js.map +7 -0
  86. package/dist/export/index.js +17 -0
  87. package/dist/export/index.js.map +7 -0
  88. package/dist/export/json-schema-exporter.js +60 -0
  89. package/dist/export/json-schema-exporter.js.map +7 -0
  90. package/dist/export/markdown-exporter.js +99 -0
  91. package/dist/export/markdown-exporter.js.map +7 -0
  92. package/dist/export/openapi-exporter.js +85 -0
  93. package/dist/export/openapi-exporter.js.map +7 -0
  94. package/dist/export/plantuml-exporter.js +60 -0
  95. package/dist/export/plantuml-exporter.js.map +7 -0
  96. package/dist/export/types.js +36 -0
  97. package/dist/export/types.js.map +7 -0
  98. package/dist/schemas/bundled/01-motivation-layer.schema.json +942 -0
  99. package/dist/schemas/bundled/02-business-layer.schema.json +1293 -0
  100. package/dist/schemas/bundled/03-security-layer.schema.json +2177 -0
  101. package/dist/schemas/bundled/04-application-layer.schema.json +1328 -0
  102. package/dist/schemas/bundled/05-technology-layer.schema.json +1465 -0
  103. package/dist/schemas/bundled/06-api-layer.schema.json +1743 -0
  104. package/dist/schemas/bundled/07-data-model-layer.schema.json +1253 -0
  105. package/dist/schemas/bundled/08-datastore-layer.schema.json +892 -0
  106. package/dist/schemas/bundled/09-ux-layer.schema.json +1506 -0
  107. package/dist/schemas/bundled/10-navigation-layer.schema.json +843 -0
  108. package/dist/schemas/bundled/11-apm-observability-layer.schema.json +1430 -0
  109. package/dist/schemas/bundled/12-testing-layer.schema.json +1091 -0
  110. package/dist/schemas/bundled/common/layer-extensions.schema.json +266 -0
  111. package/dist/schemas/bundled/common/predicates.schema.json +493 -0
  112. package/dist/schemas/bundled/common/relationships.schema.json +791 -0
  113. package/dist/schemas/bundled/common/source-references.schema.json +71 -0
  114. package/dist/schemas/bundled/link-registry.json +1839 -0
  115. package/dist/schemas/bundled/link-registry.schema.json +339 -0
  116. package/dist/schemas/bundled/relationship-catalog.json +1302 -0
  117. package/dist/schemas/bundled/relationship-type.schema.json +221 -0
  118. package/dist/server/server.js +1207 -0
  119. package/dist/server/server.js.map +7 -0
  120. package/dist/server/telemetry-middleware.js +24 -0
  121. package/dist/server/telemetry-middleware.js.map +7 -0
  122. package/dist/telemetry/console-interceptor.js +34 -0
  123. package/dist/telemetry/console-interceptor.js.map +7 -0
  124. package/dist/telemetry/index.js +54 -0
  125. package/dist/telemetry/index.js.map +7 -0
  126. package/dist/telemetry/resilient-exporter.js +41 -0
  127. package/dist/telemetry/resilient-exporter.js.map +7 -0
  128. package/dist/telemetry/resilient-log-exporter.js +41 -0
  129. package/dist/telemetry/resilient-log-exporter.js.map +7 -0
  130. package/dist/telemetry/test-instrumentation.js +32 -0
  131. package/dist/telemetry/test-instrumentation.js.map +7 -0
  132. package/dist/types/index.js +1 -0
  133. package/dist/types/index.js.map +7 -0
  134. package/dist/utils/element-utils.js +11 -0
  135. package/dist/utils/element-utils.js.map +7 -0
  136. package/dist/utils/errors.js +105 -0
  137. package/dist/utils/errors.js.map +7 -0
  138. package/dist/utils/file-io.js +69 -0
  139. package/dist/utils/file-io.js.map +7 -0
  140. package/dist/utils/globals.js +28 -0
  141. package/dist/utils/globals.js.map +7 -0
  142. package/dist/utils/model-path.js +22 -0
  143. package/dist/utils/model-path.js.map +7 -0
  144. package/dist/utils/project-paths.js +45 -0
  145. package/dist/utils/project-paths.js.map +7 -0
  146. package/dist/utils/spec-installer.js +85 -0
  147. package/dist/utils/spec-installer.js.map +7 -0
  148. package/dist/utils/spec-version.js +33 -0
  149. package/dist/utils/spec-version.js.map +7 -0
  150. package/dist/validators/index.js +15 -0
  151. package/dist/validators/index.js.map +7 -0
  152. package/dist/validators/naming-validator.js +82 -0
  153. package/dist/validators/naming-validator.js.map +7 -0
  154. package/dist/validators/reference-validator.js +106 -0
  155. package/dist/validators/reference-validator.js.map +7 -0
  156. package/dist/validators/schema-validator.js +148 -0
  157. package/dist/validators/schema-validator.js.map +7 -0
  158. package/dist/validators/semantic-validator.js +80 -0
  159. package/dist/validators/semantic-validator.js.map +7 -0
  160. package/dist/validators/types.js +48 -0
  161. package/dist/validators/types.js.map +7 -0
  162. package/dist/validators/validator.js +67 -0
  163. package/dist/validators/validator.js.map +7 -0
  164. package/docs/TEST-INSTRUMENTATION.md +405 -0
  165. package/docs/telemetry.md +427 -0
  166. package/package.json +70 -0
  167. package/test-debug.js +33 -0
  168. package/test-special.mjs +46 -0
  169. package/test_runner.ts +7 -0
@@ -0,0 +1,32 @@
1
+ import ansis from "ansis";
2
+ import { Model } from "../core/model.js";
3
+ async function listCommand(layer, options) {
4
+ try {
5
+ const layerObj = await (await Model.load(options.model)).getLayer(layer);
6
+ layerObj || (console.error(ansis.red(`Error: Layer ${layer} not found`)), process.exit(1));
7
+ let elements = layerObj.listElements();
8
+ if (options.type && (elements = elements.filter((e) => e.type === options.type)), options.json) {
9
+ console.log(JSON.stringify(elements.map((e) => e.toJSON()), null, 2));
10
+ return;
11
+ }
12
+ if (elements.length === 0) {
13
+ console.log(ansis.yellow(`No elements in ${layer} layer`));
14
+ return;
15
+ }
16
+ console.log(""), console.log(ansis.bold(`Elements in ${ansis.cyan(layer)} layer:`)), console.log(ansis.dim("\u2500".repeat(80)));
17
+ const idWidth = 30, typeWidth = 15, nameWidth = 35;
18
+ console.log(`${ansis.cyan("ID".padEnd(idWidth))} ${ansis.cyan("TYPE".padEnd(typeWidth))} ${ansis.cyan("NAME")}`), console.log(ansis.dim("\u2500".repeat(80)));
19
+ for (const element of elements) {
20
+ const id = element.id.substring(0, idWidth - 1).padEnd(idWidth), type = element.type.substring(0, typeWidth - 1).padEnd(typeWidth), name = element.name.substring(0, nameWidth);
21
+ console.log(`${id} ${type} ${name}`), options.verbose && element.description && console.log(ansis.dim(` \u2514\u2500 ${element.description}`));
22
+ }
23
+ console.log(ansis.dim("\u2500".repeat(80))), console.log(ansis.dim(`Total: ${elements.length} element(s)`)), console.log("");
24
+ } catch (error) {
25
+ const message = error instanceof Error ? error.message : String(error);
26
+ console.error(ansis.red(`Error: ${message}`)), process.exit(1);
27
+ }
28
+ }
29
+ export {
30
+ listCommand
31
+ };
32
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/list.ts"],
4
+ "sourcesContent": ["/**\n * List elements in a layer\n */\n\nimport ansis from 'ansis';\nimport { Model } from '../core/model.js';\n\nexport interface ListOptions {\n type?: string;\n json?: boolean;\n verbose?: boolean;\n debug?: boolean;\n model?: string;\n}\n\nexport async function listCommand(layer: string, options: ListOptions): Promise<void> {\n try {\n // Load model\n const model = await Model.load(options.model);\n\n // Get layer\n const layerObj = await model.getLayer(layer);\n if (!layerObj) {\n console.error(ansis.red(`Error: Layer ${layer} not found`));\n process.exit(1);\n }\n\n // Get elements\n let elements = layerObj.listElements();\n\n // Filter by type if specified\n if (options.type) {\n elements = elements.filter((e) => e.type === options.type);\n }\n\n // Output as JSON if requested\n if (options.json) {\n console.log(JSON.stringify(elements.map((e) => e.toJSON()), null, 2));\n return;\n }\n\n // Display as table\n if (elements.length === 0) {\n console.log(ansis.yellow(`No elements in ${layer} layer`));\n return;\n }\n\n console.log('');\n console.log(ansis.bold(`Elements in ${ansis.cyan(layer)} layer:`));\n console.log(ansis.dim('\u2500'.repeat(80)));\n\n // Print header\n const idWidth = 30;\n const typeWidth = 15;\n const nameWidth = 35;\n\n console.log(\n `${ansis.cyan('ID'.padEnd(idWidth))} ${ansis.cyan('TYPE'.padEnd(typeWidth))} ${ansis.cyan('NAME')}`\n );\n console.log(ansis.dim('\u2500'.repeat(80)));\n\n // Print rows\n for (const element of elements) {\n const id = element.id.substring(0, idWidth - 1).padEnd(idWidth);\n const type = element.type.substring(0, typeWidth - 1).padEnd(typeWidth);\n const name = element.name.substring(0, nameWidth);\n\n console.log(`${id} ${type} ${name}`);\n\n if (options.verbose && element.description) {\n console.log(ansis.dim(` \u2514\u2500 ${element.description}`));\n }\n }\n\n console.log(ansis.dim('\u2500'.repeat(80)));\n console.log(ansis.dim(`Total: ${elements.length} element(s)`));\n console.log('');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n"],
5
+ "mappings": "AAIA,OAAO,WAAW;AAClB,SAAS,aAAa;AAUtB,eAAsB,YAAY,OAAe,SAAoB;AACnE,MAAI;AAKF,UAAM,WAAW,OAHH,MAAM,MAAM,KAAK,QAAQ,KAAK,GAGf,SAAS,KAAK;AAC3C,IAAK,aACH,QAAQ,MAAM,MAAM,IAAI,gBAAgB,KAAK,YAAY,CAAC,GAC1D,QAAQ,KAAK,CAAC;AAIhB,QAAI,WAAW,SAAS,aAAY;AAQpC,QALI,QAAQ,SACV,WAAW,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ,IAAI,IAIvD,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,SAAS,IAAI,CAAC,MAAM,EAAE,OAAM,CAAE,GAAG,MAAM,CAAC,CAAC;AACpE;IACF;AAGA,QAAI,SAAS,WAAW,GAAG;AACzB,cAAQ,IAAI,MAAM,OAAO,kBAAkB,KAAK,QAAQ,CAAC;AACzD;IACF;AAEA,YAAQ,IAAI,EAAE,GACd,QAAQ,IAAI,MAAM,KAAK,eAAe,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC,GACjE,QAAQ,IAAI,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC;AAGrC,UAAM,UAAU,IACV,YAAY,IACZ,YAAY;AAElB,YAAQ,IACN,GAAG,MAAM,KAAK,KAAK,OAAO,OAAO,CAAC,CAAC,IAAI,MAAM,KAAK,OAAO,OAAO,SAAS,CAAC,CAAC,IAAI,MAAM,KAAK,MAAM,CAAC,EAAE,GAErG,QAAQ,IAAI,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC;AAGrC,eAAW,WAAW,UAAU;AAC9B,YAAM,KAAK,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC,EAAE,OAAO,OAAO,GACxD,OAAO,QAAQ,KAAK,UAAU,GAAG,YAAY,CAAC,EAAE,OAAO,SAAS,GAChE,OAAO,QAAQ,KAAK,UAAU,GAAG,SAAS;AAEhD,cAAQ,IAAI,GAAG,EAAE,IAAI,IAAI,IAAI,IAAI,EAAE,GAE/B,QAAQ,WAAW,QAAQ,eAC7B,QAAQ,IAAI,MAAM,IAAI,kBAAQ,QAAQ,WAAW,EAAE,CAAC;IAExD;AAEA,YAAQ,IAAI,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC,GACrC,QAAQ,IAAI,MAAM,IAAI,UAAU,SAAS,MAAM,aAAa,CAAC,GAC7D,QAAQ,IAAI,EAAE;EAChB,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,YAAQ,MAAM,MAAM,IAAI,UAAU,OAAO,EAAE,CAAC,GAC5C,QAAQ,KAAK,CAAC;EAChB;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,36 @@
1
+ import ansis from "ansis";
2
+ import { Model } from "../core/model.js";
3
+ import { MigrationRegistry } from "../core/migration-registry.js";
4
+ async function migrateCommand(options) {
5
+ try {
6
+ const model = await Model.load(process.cwd(), { lazyLoad: !1 }), registry = new MigrationRegistry(), currentVersion = model.manifest.specVersion || "0.5.0", targetVersion = options.to || registry.getLatestVersion();
7
+ if (console.log(ansis.bold(`
8
+ Migrating model from spec v${currentVersion} to v${targetVersion}
9
+ `)), currentVersion === targetVersion) {
10
+ console.log(ansis.yellow(`Model is already at spec version ${targetVersion}`));
11
+ return;
12
+ }
13
+ const summary = registry.getMigrationSummary(currentVersion, targetVersion);
14
+ summary.migrationsNeeded === 0 && (console.log(ansis.yellow(`No migration path found from v${currentVersion} to v${targetVersion}`)), console.log("Available migrations:"), registry.getMigrationSummary("0.5.0").migrations.forEach((m) => {
15
+ console.log(ansis.dim(` - ${m.from} \u2192 ${m.to}: ${m.description}`));
16
+ }), process.exit(1)), console.log(ansis.dim("Migration path:"));
17
+ for (const migration of summary.migrations)
18
+ console.log(ansis.dim(` ${migration.from} \u2192 ${migration.to}: ${migration.description}`));
19
+ console.log(), options.dryRun && (console.log(ansis.yellow("[DRY RUN] The following changes would be applied:")), console.log());
20
+ const result = await registry.applyMigrations(model, {
21
+ fromVersion: currentVersion,
22
+ toVersion: targetVersion,
23
+ dryRun: options.dryRun,
24
+ validate: !options.force
25
+ });
26
+ for (const applied of result.applied)
27
+ applied.dryRun ? console.log(ansis.yellow(`[DRY RUN] ${applied.from} \u2192 ${applied.to}: ${applied.description}`)) : (console.log(ansis.green(`\u2713 ${applied.from} \u2192 ${applied.to}: ${applied.description}`)), applied.changes?.filesModified && console.log(ansis.dim(` Files modified: ${applied.changes.filesModified}`)));
28
+ console.log(), options.dryRun ? console.log(ansis.yellow("\u2713 Dry run complete (no changes saved)")) : (await model.saveManifest(), await model.saveDirtyLayers(), console.log(ansis.green("\u2713 Migration complete")), console.log(ansis.dim(`Spec version updated to v${targetVersion} and saved to model/manifest.yaml`))), console.log();
29
+ } catch (error) {
30
+ console.error(ansis.red(`Error: ${error instanceof Error ? error.message : String(error)}`)), process.exit(1);
31
+ }
32
+ }
33
+ export {
34
+ migrateCommand
35
+ };
36
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/migrate.ts"],
4
+ "sourcesContent": ["/**\n * Migrate Command - Migrates model to a different spec version\n */\n\nimport ansis from 'ansis';\nimport { Model } from '../core/model.js';\nimport { MigrationRegistry } from '../core/migration-registry.js';\n\nexport async function migrateCommand(options: {\n to?: string;\n dryRun?: boolean;\n force?: boolean;\n}): Promise<void> {\n try {\n // Load the model from current directory\n const model = await Model.load(process.cwd(), { lazyLoad: false });\n\n const registry = new MigrationRegistry();\n const currentVersion = model.manifest.specVersion || '0.5.0';\n const targetVersion = options.to || registry.getLatestVersion();\n\n console.log(ansis.bold(`\\nMigrating model from spec v${currentVersion} to v${targetVersion}\\n`));\n\n // Check if migration is needed\n if (currentVersion === targetVersion) {\n console.log(\n ansis.yellow(`Model is already at spec version ${targetVersion}`)\n );\n return;\n }\n\n // Get migration summary\n const summary = registry.getMigrationSummary(currentVersion, targetVersion);\n\n if (summary.migrationsNeeded === 0) {\n console.log(ansis.yellow(`No migration path found from v${currentVersion} to v${targetVersion}`));\n console.log(`Available migrations:`);\n registry.getMigrationSummary('0.5.0').migrations.forEach((m) => {\n console.log(ansis.dim(` - ${m.from} \u2192 ${m.to}: ${m.description}`));\n });\n process.exit(1);\n }\n\n // Display migration plan\n console.log(ansis.dim('Migration path:'));\n for (const migration of summary.migrations) {\n console.log(\n ansis.dim(` ${migration.from} \u2192 ${migration.to}: ${migration.description}`)\n );\n }\n console.log();\n\n if (options.dryRun) {\n console.log(ansis.yellow('[DRY RUN] The following changes would be applied:'));\n console.log();\n }\n\n // Apply migrations\n const result = await registry.applyMigrations(model, {\n fromVersion: currentVersion,\n toVersion: targetVersion,\n dryRun: options.dryRun,\n validate: !options.force,\n });\n\n // Display results\n for (const applied of result.applied) {\n if (applied.dryRun) {\n console.log(\n ansis.yellow(\n `[DRY RUN] ${applied.from} \u2192 ${applied.to}: ${applied.description}`\n )\n );\n } else {\n console.log(\n ansis.green(\n `\u2713 ${applied.from} \u2192 ${applied.to}: ${applied.description}`\n )\n );\n if (applied.changes?.filesModified) {\n console.log(\n ansis.dim(` Files modified: ${applied.changes.filesModified}`)\n );\n }\n }\n }\n\n console.log();\n\n if (!options.dryRun) {\n // Save the updated manifest and all dirty layers\n await model.saveManifest();\n await model.saveDirtyLayers();\n\n console.log(ansis.green(`\u2713 Migration complete`));\n console.log(\n ansis.dim(\n `Spec version updated to v${targetVersion} and saved to model/manifest.yaml`\n )\n );\n } else {\n console.log(ansis.yellow(`\u2713 Dry run complete (no changes saved)`));\n }\n\n console.log();\n } catch (error) {\n console.error(\n ansis.red(\n `Error: ${error instanceof Error ? error.message : String(error)}`\n )\n );\n process.exit(1);\n }\n}\n"],
5
+ "mappings": "AAIA,OAAO,WAAW;AAClB,SAAS,aAAa;AACtB,SAAS,yBAAyB;AAElC,eAAsB,eAAe,SAIpC;AACC,MAAI;AAEF,UAAM,QAAQ,MAAM,MAAM,KAAK,QAAQ,IAAG,GAAI,EAAE,UAAU,GAAK,CAAE,GAE3D,WAAW,IAAI,kBAAiB,GAChC,iBAAiB,MAAM,SAAS,eAAe,SAC/C,gBAAgB,QAAQ,MAAM,SAAS,iBAAgB;AAK7D,QAHA,QAAQ,IAAI,MAAM,KAAK;6BAAgC,cAAc,QAAQ,aAAa;CAAI,CAAC,GAG3F,mBAAmB,eAAe;AACpC,cAAQ,IACN,MAAM,OAAO,oCAAoC,aAAa,EAAE,CAAC;AAEnE;IACF;AAGA,UAAM,UAAU,SAAS,oBAAoB,gBAAgB,aAAa;AAE1E,IAAI,QAAQ,qBAAqB,MAC/B,QAAQ,IAAI,MAAM,OAAO,iCAAiC,cAAc,QAAQ,aAAa,EAAE,CAAC,GAChG,QAAQ,IAAI,uBAAuB,GACnC,SAAS,oBAAoB,OAAO,EAAE,WAAW,QAAQ,CAAC,MAAK;AAC7D,cAAQ,IAAI,MAAM,IAAI,OAAO,EAAE,IAAI,WAAM,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IACpE,CAAC,GACD,QAAQ,KAAK,CAAC,IAIhB,QAAQ,IAAI,MAAM,IAAI,iBAAiB,CAAC;AACxC,eAAW,aAAa,QAAQ;AAC9B,cAAQ,IACN,MAAM,IAAI,KAAK,UAAU,IAAI,WAAM,UAAU,EAAE,KAAK,UAAU,WAAW,EAAE,CAAC;AAGhF,YAAQ,IAAG,GAEP,QAAQ,WACV,QAAQ,IAAI,MAAM,OAAO,mDAAmD,CAAC,GAC7E,QAAQ,IAAG;AAIb,UAAM,SAAS,MAAM,SAAS,gBAAgB,OAAO;MACnD,aAAa;MACb,WAAW;MACX,QAAQ,QAAQ;MAChB,UAAU,CAAC,QAAQ;KACpB;AAGD,eAAW,WAAW,OAAO;AAC3B,MAAI,QAAQ,SACV,QAAQ,IACN,MAAM,OACJ,aAAa,QAAQ,IAAI,WAAM,QAAQ,EAAE,KAAK,QAAQ,WAAW,EAAE,CACpE,KAGH,QAAQ,IACN,MAAM,MACJ,UAAK,QAAQ,IAAI,WAAM,QAAQ,EAAE,KAAK,QAAQ,WAAW,EAAE,CAC5D,GAEC,QAAQ,SAAS,iBACnB,QAAQ,IACN,MAAM,IAAI,qBAAqB,QAAQ,QAAQ,aAAa,EAAE,CAAC;AAMvE,YAAQ,IAAG,GAEN,QAAQ,SAYX,QAAQ,IAAI,MAAM,OAAO,4CAAuC,CAAC,KAVjE,MAAM,MAAM,aAAY,GACxB,MAAM,MAAM,gBAAe,GAE3B,QAAQ,IAAI,MAAM,MAAM,2BAAsB,CAAC,GAC/C,QAAQ,IACN,MAAM,IACJ,4BAA4B,aAAa,mCAAmC,CAC7E,IAML,QAAQ,IAAG;EACb,SAAS,OAAO;AACd,YAAQ,MACN,MAAM,IACJ,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE,CACnE,GAEH,QAAQ,KAAK,CAAC;EAChB;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,74 @@
1
+ import ansis from "ansis";
2
+ import { Model } from "../core/model.js";
3
+ async function projectCommand(elementId, targetLayers, options = {}) {
4
+ try {
5
+ const model = await Model.load(options.model), source = model.getElementById(elementId);
6
+ source || (console.error(ansis.red(`Error: Element '${elementId}' not found`)), process.exit(1));
7
+ const engine = model.getProjectionEngine(), layers = targetLayers.split(",").map((l) => l.trim());
8
+ console.log(""), console.log(ansis.bold(`Projecting element: ${ansis.yellow(elementId)}`)), console.log(ansis.bold(`Target layers: ${ansis.cyan(layers.join(", "))}`)), console.log("");
9
+ const results = [];
10
+ for (const targetLayer of layers)
11
+ try {
12
+ const applicableRules = engine.findApplicableRules(source, targetLayer);
13
+ if (applicableRules.length === 0) {
14
+ console.log(ansis.yellow(`\u26A0 Warning: No projection rule found for ${source.layer} -> ${targetLayer}`));
15
+ continue;
16
+ }
17
+ const projectionRule = options.rule ? applicableRules.find((r) => r.name === options.rule) : applicableRules[0];
18
+ if (!projectionRule) {
19
+ console.log(ansis.yellow(`\u26A0 Warning: Rule '${options.rule}' not found for ${targetLayer}`));
20
+ continue;
21
+ }
22
+ const projected = await engine.projectElement(source, targetLayer, projectionRule, options.dryRun);
23
+ projected && results.push({ layer: targetLayer, element: projected });
24
+ } catch (error) {
25
+ const message = error instanceof Error ? error.message : String(error);
26
+ console.log(ansis.red(`\u2717 Error projecting to ${targetLayer}: ${message}`));
27
+ }
28
+ if (results.length > 0) {
29
+ console.log(ansis.bold.green("\u2713 Projection successful")), console.log("");
30
+ const colLayer = "Target Layer", colId = "Element ID", colName = "Name", maxLayerLen = Math.max(colLayer.length, ...results.map((r) => r.layer.length)), maxIdLen = Math.max(colId.length, ...results.map((r) => r.element.id.length)), maxNameLen = Math.max(colName.length, ...results.map((r) => (r.element.name || "").length));
31
+ console.log(ansis.bold(ansis.cyan(colLayer.padEnd(maxLayerLen)) + " " + ansis.white(colId.padEnd(maxIdLen)) + " " + ansis.green(colName.padEnd(maxNameLen)))), console.log(ansis.dim("\u2500".repeat(maxLayerLen + maxIdLen + maxNameLen + 4)));
32
+ for (const { layer, element } of results)
33
+ console.log(ansis.cyan(layer.padEnd(maxLayerLen)) + " " + ansis.white(element.id.padEnd(maxIdLen)) + " " + ansis.green((element.name || "").padEnd(maxNameLen)));
34
+ console.log(""), options.dryRun ? console.log(ansis.yellow("Dry run - elements not saved")) : (await model.save(), console.log(ansis.green("Model saved successfully")));
35
+ } else
36
+ console.log(ansis.yellow("No elements were projected"));
37
+ console.log("");
38
+ } catch (error) {
39
+ const message = error instanceof Error ? error.message : String(error);
40
+ console.error(ansis.red(`Error: ${message}`)), process.exit(1);
41
+ }
42
+ }
43
+ async function projectAllCommand(options = {}) {
44
+ try {
45
+ const model = await Model.load(options.model), engine = model.getProjectionEngine();
46
+ console.log(""), console.log(ansis.bold("Projecting all applicable elements...")), console.log(""), options.from && console.log(`From layer: ${options.from}`), options.to && console.log(`To layer: ${options.to}`), (options.from || options.to) && console.log("");
47
+ const projected = await engine.projectAll(options.from || void 0, options.to || void 0, options.dryRun);
48
+ if (projected.length > 0) {
49
+ console.log(ansis.bold.green(`\u2713 Projected ${projected.length} element(s)`)), console.log("");
50
+ const byLayer = /* @__PURE__ */ new Map();
51
+ for (const element of projected) {
52
+ const layer = element.layer || "unknown";
53
+ byLayer.has(layer) || byLayer.set(layer, []), byLayer.get(layer).push(element);
54
+ }
55
+ for (const [layer, elements] of Array.from(byLayer.entries()).sort()) {
56
+ console.log(ansis.bold(`${layer}:`));
57
+ for (const element of elements)
58
+ console.log(` ${ansis.dim("\u2022")} ${element.id} ${ansis.gray(`(${element.name || "unnamed"})`)}`);
59
+ console.log("");
60
+ }
61
+ options.dryRun ? console.log(ansis.yellow("Dry run - elements not saved")) : (await model.save(), console.log(ansis.green("Model saved successfully")));
62
+ } else
63
+ console.log(ansis.yellow("No elements were projected"));
64
+ console.log("");
65
+ } catch (error) {
66
+ const message = error instanceof Error ? error.message : String(error);
67
+ console.error(ansis.red(`Error: ${message}`)), process.exit(1);
68
+ }
69
+ }
70
+ export {
71
+ projectAllCommand,
72
+ projectCommand
73
+ };
74
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/project.ts"],
4
+ "sourcesContent": ["/**\n * Project command - project elements across layers using projection rules\n */\n\nimport ansis from 'ansis';\nimport { Model } from '../core/model.js';\n\nexport async function projectCommand(\n elementId: string,\n targetLayers: string,\n options: {\n rule?: string;\n dryRun?: boolean;\n force?: boolean;\n model?: string;\n } = {}\n): Promise<void> {\n try {\n // Load model\n const model = await Model.load(options.model);\n\n // Get source element\n const source = model.getElementById(elementId);\n if (!source) {\n console.error(ansis.red(`Error: Element '${elementId}' not found`));\n process.exit(1);\n }\n\n // Initialize projection engine\n const engine = model.getProjectionEngine();\n\n // Parse target layers\n const layers = targetLayers.split(',').map((l) => l.trim());\n\n console.log('');\n console.log(ansis.bold(`Projecting element: ${ansis.yellow(elementId)}`));\n console.log(ansis.bold(`Target layers: ${ansis.cyan(layers.join(', '))}`));\n console.log('');\n\n // Project to each layer\n const results: Array<{ layer: string; element: any }> = [];\n\n for (const targetLayer of layers) {\n try {\n // Find applicable rules\n const applicableRules = engine.findApplicableRules(source, targetLayer);\n\n if (applicableRules.length === 0) {\n console.log(\n ansis.yellow(\n `\u26A0 Warning: No projection rule found for ${source.layer} -> ${targetLayer}`\n )\n );\n continue;\n }\n\n // Use first applicable rule (or specific rule if provided)\n const projectionRule = options.rule\n ? applicableRules.find((r) => r.name === options.rule)\n : applicableRules[0];\n\n if (!projectionRule) {\n console.log(\n ansis.yellow(\n `\u26A0 Warning: Rule '${options.rule}' not found for ${targetLayer}`\n )\n );\n continue;\n }\n\n // Perform projection\n const projected = await engine.projectElement(\n source,\n targetLayer,\n projectionRule,\n options.dryRun\n );\n\n if (projected) {\n results.push({ layer: targetLayer, element: projected });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.log(ansis.red(`\u2717 Error projecting to ${targetLayer}: ${message}`));\n }\n }\n\n // Display results\n if (results.length > 0) {\n console.log(ansis.bold.green('\u2713 Projection successful'));\n console.log('');\n\n // Table header\n const colLayer = 'Target Layer';\n const colId = 'Element ID';\n const colName = 'Name';\n\n const maxLayerLen = Math.max(\n colLayer.length,\n ...results.map((r) => r.layer.length)\n );\n const maxIdLen = Math.max(colId.length, ...results.map((r) => r.element.id.length));\n const maxNameLen = Math.max(\n colName.length,\n ...results.map((r) => (r.element.name || '').length)\n );\n\n // Print header\n console.log(\n ansis.bold(\n ansis.cyan(colLayer.padEnd(maxLayerLen)) +\n ' ' +\n ansis.white(colId.padEnd(maxIdLen)) +\n ' ' +\n ansis.green(colName.padEnd(maxNameLen))\n )\n );\n console.log(ansis.dim('\u2500'.repeat(maxLayerLen + maxIdLen + maxNameLen + 4)));\n\n // Print rows\n for (const { layer, element } of results) {\n console.log(\n ansis.cyan(layer.padEnd(maxLayerLen)) +\n ' ' +\n ansis.white(element.id.padEnd(maxIdLen)) +\n ' ' +\n ansis.green((element.name || '').padEnd(maxNameLen))\n );\n }\n\n console.log('');\n\n if (options.dryRun) {\n console.log(ansis.yellow('Dry run - elements not saved'));\n } else {\n // Save model\n await model.save();\n console.log(ansis.green('Model saved successfully'));\n }\n } else {\n console.log(ansis.yellow('No elements were projected'));\n }\n\n console.log('');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n\nexport async function projectAllCommand(options: {\n from?: string;\n to?: string;\n dryRun?: boolean;\n model?: string;\n} = {}): Promise<void> {\n try {\n // Load model\n const model = await Model.load(options.model);\n\n // Initialize projection engine\n const engine = model.getProjectionEngine();\n\n console.log('');\n console.log(ansis.bold('Projecting all applicable elements...'));\n console.log('');\n\n if (options.from) {\n console.log(`From layer: ${options.from}`);\n }\n if (options.to) {\n console.log(`To layer: ${options.to}`);\n }\n if (options.from || options.to) {\n console.log('');\n }\n\n // Perform projections\n const projected = await engine.projectAll(\n options.from || undefined,\n options.to || undefined,\n options.dryRun\n );\n\n // Display results\n if (projected.length > 0) {\n console.log(ansis.bold.green(`\u2713 Projected ${projected.length} element(s)`));\n console.log('');\n\n // Group by layer\n const byLayer = new Map<string, any[]>();\n for (const element of projected) {\n const layer = element.layer || 'unknown';\n if (!byLayer.has(layer)) {\n byLayer.set(layer, []);\n }\n byLayer.get(layer)!.push(element);\n }\n\n // Display grouped results\n for (const [layer, elements] of Array.from(byLayer.entries()).sort()) {\n console.log(ansis.bold(`${layer}:`));\n for (const element of elements) {\n console.log(` ${ansis.dim('\u2022')} ${element.id} ${ansis.gray(`(${element.name || 'unnamed'})`)}`);\n }\n console.log('');\n }\n\n if (options.dryRun) {\n console.log(ansis.yellow('Dry run - elements not saved'));\n } else {\n // Save model\n await model.save();\n console.log(ansis.green('Model saved successfully'));\n }\n } else {\n console.log(ansis.yellow('No elements were projected'));\n }\n\n console.log('');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,118 @@
1
+ import ansis from "ansis";
2
+ import { Model } from "../core/model.js";
3
+ import { findElementLayer } from "../utils/element-utils.js";
4
+ function relationshipCommands(program) {
5
+ program.command("add <source> <target>").description("Add a relationship between elements").requiredOption("--predicate <predicate>", "Relationship predicate (e.g., depends-on, implements)").option("--properties <json>", "Relationship properties (JSON)").addHelpText("after", `
6
+ Examples:
7
+ $ dr relationship add business-service-a business-service-b --predicate depends-on
8
+ $ dr relationship add api-endpoint-1 api-endpoint-2 --predicate "service-of"
9
+ $ dr relationship add element-1 element-2 --predicate implements --properties '{"method":"REST"}'`).action(async (source, target, options) => {
10
+ try {
11
+ const model = await Model.load(), sourceLayerName = await findElementLayer(model, source);
12
+ sourceLayerName || (console.error(ansis.red(`Error: Source element ${source} not found`)), process.exit(1));
13
+ const targetLayerName = await findElementLayer(model, target);
14
+ targetLayerName || (console.error(ansis.red(`Error: Target element ${target} not found`)), process.exit(1)), sourceLayerName !== targetLayerName && (console.error(ansis.red("Error: cannot add cross-layer relationship. Relationships must be within the same layer.")), process.exit(1));
15
+ let properties;
16
+ if (options.properties)
17
+ try {
18
+ properties = JSON.parse(options.properties);
19
+ } catch {
20
+ console.error(ansis.red("Error: Invalid JSON in --properties")), process.exit(1);
21
+ }
22
+ model.relationships.add({
23
+ source,
24
+ target,
25
+ predicate: options.predicate,
26
+ layer: sourceLayerName,
27
+ category: "structural",
28
+ // Default category
29
+ properties
30
+ }), await model.saveRelationships(), await model.saveManifest(), console.log(ansis.green(`\u2713 Added relationship: ${ansis.bold(source)} ${options.predicate} ${ansis.bold(target)}`));
31
+ } catch (error) {
32
+ const message = error instanceof Error ? error.message : String(error);
33
+ console.error(ansis.red(`Error: ${message}`)), process.exit(1);
34
+ }
35
+ }), program.command("delete <source> <target>").description("Delete a relationship").option("--predicate <predicate>", "Specific predicate to delete (optional, delete all if not specified)").option("--force", "Skip confirmation prompt").addHelpText("after", `
36
+ Examples:
37
+ $ dr relationship delete element-1 element-2 --predicate depends-on
38
+ $ dr relationship delete element-1 element-2 --force`).action(async (source, target, options) => {
39
+ try {
40
+ const model = await Model.load();
41
+ await findElementLayer(model, source) || (console.error(ansis.red(`Error: Source element ${source} not found`)), process.exit(1));
42
+ const toDelete = model.relationships.find(source, target, options.predicate);
43
+ toDelete.length === 0 && (console.error(ansis.red("Error: No matching relationships found")), process.exit(1));
44
+ const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
45
+ if (!options.force && isInteractive) {
46
+ const { confirm } = await import("@clack/prompts");
47
+ await confirm({
48
+ message: `Delete ${toDelete.length} relationship(s)? This cannot be undone.`,
49
+ initialValue: !1
50
+ }) || (console.log(ansis.dim("Cancelled")), process.exit(0));
51
+ }
52
+ model.relationships.delete(source, target, options.predicate), await model.saveRelationships(), await model.saveManifest(), console.log(ansis.green(`\u2713 Deleted ${toDelete.length} relationship(s) from ${ansis.bold(source)} to ${ansis.bold(target)}`));
53
+ } catch (error) {
54
+ const message = error instanceof Error ? error.message : String(error);
55
+ console.error(ansis.red(`Error: ${message}`)), process.exit(1);
56
+ }
57
+ }), program.command("list <id>").description("List relationships for an element").option("--direction <dir>", "Filter by direction (incoming/outgoing/all)", "all").option("--json", "Output as JSON").addHelpText("after", `
58
+ Examples:
59
+ $ dr relationship list api-endpoint-create-customer
60
+ $ dr relationship list business-service-order --direction outgoing
61
+ $ dr relationship list element-1 --json`).action(async (id, options) => {
62
+ try {
63
+ const model = await Model.load();
64
+ await findElementLayer(model, id) || (console.error(ansis.red(`Error: Element ${id} not found`)), process.exit(1));
65
+ const { outgoing, incoming } = model.relationships.getForElement(id);
66
+ let relationships = [];
67
+ if ((options.direction === "outgoing" || options.direction === "all") && relationships.push(...outgoing), (options.direction === "incoming" || options.direction === "all") && relationships.push(...incoming), options.json) {
68
+ console.log(JSON.stringify(relationships, null, 2));
69
+ return;
70
+ }
71
+ if (relationships.length === 0) {
72
+ console.log(ansis.yellow(`No ${options.direction} relationships for ${id}`));
73
+ return;
74
+ }
75
+ console.log(""), console.log(ansis.bold(`${options.direction === "all" ? "" : options.direction + " "}relationships for ${ansis.cyan(id)}:`)), console.log(ansis.dim("\u2500".repeat(80)));
76
+ for (const rel of relationships) {
77
+ const isOutgoing = rel.source === id, direction = isOutgoing ? "\u2192" : "\u2190", otherElement = isOutgoing ? rel.target : rel.source;
78
+ if (console.log(` ${direction} ${ansis.magenta(rel.predicate)}: ${ansis.yellow(otherElement)}`), rel.properties) {
79
+ const propStr = Object.entries(rel.properties).map(([k, v]) => `${k}=${v}`).join(", ");
80
+ console.log(` ${ansis.dim(propStr)}`);
81
+ }
82
+ }
83
+ console.log(ansis.dim("\u2500".repeat(80))), console.log(ansis.dim(`Total: ${relationships.length} relationship(s)`)), console.log("");
84
+ } catch (error) {
85
+ const message = error instanceof Error ? error.message : String(error);
86
+ console.error(ansis.red(`Error: ${message}`)), process.exit(1);
87
+ }
88
+ }), program.command("show <source> <target>").description("Show relationship details").addHelpText("after", `
89
+ Examples:
90
+ $ dr relationship show api-endpoint-create-customer business-service-customer-mgmt
91
+ $ dr relationship show application-component-api motivation-goal-sales-efficiency`).action(async (source, target) => {
92
+ try {
93
+ const model = await Model.load();
94
+ await findElementLayer(model, source) || (console.error(ansis.red(`Error: Source element ${source} not found`)), process.exit(1));
95
+ const relationships = model.relationships.find(source, target);
96
+ relationships.length === 0 && (console.error(ansis.red(`Error: No relationships from ${source} to ${target}`)), process.exit(1)), console.log(""), console.log(ansis.bold(`Relationship${relationships.length > 1 ? "s" : ""} from ${ansis.cyan(source)} to ${ansis.yellow(target)}:`)), console.log(ansis.dim("\u2500".repeat(60)));
97
+ for (let i = 0; i < relationships.length; i++) {
98
+ const rel = relationships[i];
99
+ if (i > 0 && console.log(""), console.log(`Predicate: ${ansis.magenta(rel.predicate)}`), rel.properties && Object.keys(rel.properties).length > 0) {
100
+ console.log("Properties:");
101
+ for (const [key, value] of Object.entries(rel.properties)) {
102
+ const displayValue = typeof value == "string" ? value : JSON.stringify(value, null, 2);
103
+ console.log(` ${ansis.cyan(key)}: ${displayValue}`);
104
+ }
105
+ } else
106
+ console.log("Properties: none");
107
+ }
108
+ console.log("");
109
+ } catch (error) {
110
+ const message = error instanceof Error ? error.message : String(error);
111
+ console.error(ansis.red(`Error: ${message}`)), process.exit(1);
112
+ }
113
+ });
114
+ }
115
+ export {
116
+ relationshipCommands
117
+ };
118
+ //# sourceMappingURL=relationship.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/relationship.ts"],
4
+ "sourcesContent": ["/**\n * Relationship subcommands for managing intra-layer relationships\n */\n\nimport { Command } from 'commander';\nimport ansis from 'ansis';\nimport { Model } from '../core/model.js';\nimport { findElementLayer } from '../utils/element-utils.js';\n\nexport function relationshipCommands(program: Command): void {\n program\n .command('add <source> <target>')\n .description('Add a relationship between elements')\n .requiredOption('--predicate <predicate>', 'Relationship predicate (e.g., depends-on, implements)')\n .option('--properties <json>', 'Relationship properties (JSON)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ dr relationship add business-service-a business-service-b --predicate depends-on\n $ dr relationship add api-endpoint-1 api-endpoint-2 --predicate \"service-of\"\n $ dr relationship add element-1 element-2 --predicate implements --properties '{\"method\":\"REST\"}'`\n )\n .action(async (source, target, options) => {\n try {\n // Load model\n const model = await Model.load();\n\n // Find source element\n const sourceLayerName = await findElementLayer(model, source);\n if (!sourceLayerName) {\n console.error(ansis.red(`Error: Source element ${source} not found`));\n process.exit(1);\n }\n\n // Find target element\n const targetLayerName = await findElementLayer(model, target);\n if (!targetLayerName) {\n console.error(ansis.red(`Error: Target element ${target} not found`));\n process.exit(1);\n }\n\n // Relationships are intra-layer only\n if (sourceLayerName !== targetLayerName) {\n console.error(\n ansis.red(\n 'Error: cannot add cross-layer relationship. Relationships must be within the same layer.'\n )\n );\n process.exit(1);\n }\n\n // Parse properties if provided\n let properties: Record<string, unknown> | undefined;\n if (options.properties) {\n try {\n properties = JSON.parse(options.properties);\n } catch (e) {\n console.error(ansis.red('Error: Invalid JSON in --properties'));\n process.exit(1);\n }\n }\n\n // Add relationship to centralized relationships.yaml\n model.relationships.add({\n source,\n target,\n predicate: options.predicate,\n layer: sourceLayerName,\n category: 'structural', // Default category\n properties,\n });\n\n // Save relationships\n await model.saveRelationships();\n await model.saveManifest();\n\n console.log(\n ansis.green(\n `\u2713 Added relationship: ${ansis.bold(source)} ${options.predicate} ${ansis.bold(target)}`\n )\n );\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n }\n });\n\n program\n .command('delete <source> <target>')\n .description('Delete a relationship')\n .option('--predicate <predicate>', 'Specific predicate to delete (optional, delete all if not specified)')\n .option('--force', 'Skip confirmation prompt')\n .addHelpText(\n 'after',\n `\nExamples:\n $ dr relationship delete element-1 element-2 --predicate depends-on\n $ dr relationship delete element-1 element-2 --force`\n )\n .action(async (source, target, options) => {\n try {\n // Load model\n const model = await Model.load();\n\n // Find source element\n const sourceLayerName = await findElementLayer(model, source);\n if (!sourceLayerName) {\n console.error(ansis.red(`Error: Source element ${source} not found`));\n process.exit(1);\n }\n\n // Find relationships to delete\n const toDelete = model.relationships.find(source, target, options.predicate);\n\n if (toDelete.length === 0) {\n console.error(ansis.red('Error: No matching relationships found'));\n process.exit(1);\n }\n\n // Confirm deletion unless --force or non-interactive environment\n // In non-interactive environments (CI, tests), skip confirmation\n const isInteractive = process.stdin.isTTY && process.stdout.isTTY;\n if (!options.force && isInteractive) {\n const { confirm } = await import('@clack/prompts');\n const confirmed = await confirm({\n message: `Delete ${toDelete.length} relationship(s)? This cannot be undone.`,\n initialValue: false,\n });\n\n if (!confirmed) {\n console.log(ansis.dim('Cancelled'));\n process.exit(0);\n }\n }\n\n // Delete relationships\n model.relationships.delete(source, target, options.predicate);\n\n // Save\n await model.saveRelationships();\n await model.saveManifest();\n\n console.log(\n ansis.green(\n `\u2713 Deleted ${toDelete.length} relationship(s) from ${ansis.bold(source)} to ${ansis.bold(target)}`\n )\n );\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n }\n });\n\n program\n .command('list <id>')\n .description('List relationships for an element')\n .option('--direction <dir>', 'Filter by direction (incoming/outgoing/all)', 'all')\n .option('--json', 'Output as JSON')\n .addHelpText(\n 'after',\n `\nExamples:\n $ dr relationship list api-endpoint-create-customer\n $ dr relationship list business-service-order --direction outgoing\n $ dr relationship list element-1 --json`\n )\n .action(async (id, options) => {\n try {\n // Load model\n const model = await Model.load();\n const layerName = await findElementLayer(model, id);\n\n if (!layerName) {\n console.error(ansis.red(`Error: Element ${id} not found`));\n process.exit(1);\n }\n\n // Get relationships from centralized store\n const { outgoing, incoming } = model.relationships.getForElement(id);\n\n // Filter by direction\n let relationships: typeof outgoing = [];\n if (options.direction === 'outgoing' || options.direction === 'all') {\n relationships.push(...outgoing);\n }\n if (options.direction === 'incoming' || options.direction === 'all') {\n relationships.push(...incoming);\n }\n\n if (options.json) {\n console.log(JSON.stringify(relationships, null, 2));\n return;\n }\n\n if (relationships.length === 0) {\n console.log(ansis.yellow(`No ${options.direction} relationships for ${id}`));\n return;\n }\n\n console.log('');\n console.log(\n ansis.bold(\n `${options.direction === 'all' ? '' : options.direction + ' '}relationships for ${ansis.cyan(id)}:`\n )\n );\n console.log(ansis.dim('\u2500'.repeat(80)));\n\n for (const rel of relationships) {\n const isOutgoing = rel.source === id;\n const direction = isOutgoing ? '\u2192' : '\u2190';\n const otherElement = isOutgoing ? rel.target : rel.source;\n\n console.log(\n ` ${direction} ${ansis.magenta(rel.predicate)}: ${ansis.yellow(otherElement)}`\n );\n\n if (rel.properties) {\n const propStr = Object.entries(rel.properties)\n .map(([k, v]) => `${k}=${v}`)\n .join(', ');\n console.log(` ${ansis.dim(propStr)}`);\n }\n }\n\n console.log(ansis.dim('\u2500'.repeat(80)));\n console.log(ansis.dim(`Total: ${relationships.length} relationship(s)`));\n console.log('');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n }\n });\n\n program\n .command('show <source> <target>')\n .description('Show relationship details')\n .addHelpText(\n 'after',\n `\nExamples:\n $ dr relationship show api-endpoint-create-customer business-service-customer-mgmt\n $ dr relationship show application-component-api motivation-goal-sales-efficiency`\n )\n .action(async (source, target) => {\n try {\n // Load model\n const model = await Model.load();\n const sourceLayerName = await findElementLayer(model, source);\n\n if (!sourceLayerName) {\n console.error(ansis.red(`Error: Source element ${source} not found`));\n process.exit(1);\n }\n\n // Find relationships from centralized store\n const relationships = model.relationships.find(source, target);\n\n if (relationships.length === 0) {\n console.error(\n ansis.red(`Error: No relationships from ${source} to ${target}`)\n );\n process.exit(1);\n }\n\n console.log('');\n console.log(\n ansis.bold(\n `Relationship${relationships.length > 1 ? 's' : ''} from ${ansis.cyan(source)} to ${ansis.yellow(target)}:`\n )\n );\n console.log(ansis.dim('\u2500'.repeat(60)));\n\n for (let i = 0; i < relationships.length; i++) {\n const rel = relationships[i];\n\n if (i > 0) {\n console.log('');\n }\n\n console.log(`Predicate: ${ansis.magenta(rel.predicate)}`);\n\n if (rel.properties && Object.keys(rel.properties).length > 0) {\n console.log('Properties:');\n for (const [key, value] of Object.entries(rel.properties)) {\n const displayValue =\n typeof value === 'string' ? value : JSON.stringify(value, null, 2);\n console.log(` ${ansis.cyan(key)}: ${displayValue}`);\n }\n } else {\n console.log('Properties: none');\n }\n }\n\n console.log('');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n }\n });\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,48 @@
1
+ import ansis from "ansis";
2
+ import { Model } from "../core/model.js";
3
+ async function searchCommand(query, options) {
4
+ try {
5
+ const model = await Model.load(), results = [], queryLower = query.toLowerCase();
6
+ for (const layerName of model.getLayerNames()) {
7
+ if (options.layer && layerName !== options.layer)
8
+ continue;
9
+ const layerObj = await model.getLayer(layerName);
10
+ if (layerObj)
11
+ for (const element of layerObj.listElements()) {
12
+ if (options.type && element.type !== options.type)
13
+ continue;
14
+ const idMatch = element.id.toLowerCase().includes(queryLower), nameMatch = element.name.toLowerCase().includes(queryLower);
15
+ (idMatch || nameMatch) && results.push({
16
+ layer: layerName,
17
+ id: element.id,
18
+ type: element.type,
19
+ name: element.name,
20
+ description: element.description
21
+ });
22
+ }
23
+ }
24
+ if (options.json) {
25
+ console.log(JSON.stringify(results, null, 2));
26
+ return;
27
+ }
28
+ if (results.length === 0) {
29
+ console.log(ansis.yellow(`No elements matching "${query}"`));
30
+ return;
31
+ }
32
+ console.log(""), console.log(ansis.bold(`Found ${results.length} element(s) matching "${query}":`)), console.log(ansis.dim("\u2500".repeat(80)));
33
+ const layerWidth = 12, idWidth = 28, typeWidth = 12, nameWidth = 28;
34
+ console.log(`${ansis.cyan("LAYER".padEnd(layerWidth))} ${ansis.cyan("ID".padEnd(idWidth))} ${ansis.cyan("TYPE".padEnd(typeWidth))} ${ansis.cyan("NAME")}`), console.log(ansis.dim("\u2500".repeat(80)));
35
+ for (const result of results) {
36
+ const layer = result.layer.substring(0, layerWidth - 1).padEnd(layerWidth), id = result.id.substring(0, idWidth - 1).padEnd(idWidth), type = result.type.substring(0, typeWidth - 1).padEnd(typeWidth), name = result.name.substring(0, nameWidth);
37
+ console.log(`${ansis.blue(layer)} ${id} ${type} ${name}`), options.verbose && result.description && console.log(ansis.dim(` \u2514\u2500 ${result.description}`));
38
+ }
39
+ console.log(ansis.dim("\u2500".repeat(80))), console.log("");
40
+ } catch (error) {
41
+ const message = error instanceof Error ? error.message : String(error);
42
+ console.error(ansis.red(`Error: ${message}`)), process.exit(1);
43
+ }
44
+ }
45
+ export {
46
+ searchCommand
47
+ };
48
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/search.ts"],
4
+ "sourcesContent": ["/**\n * Search for elements across the model\n */\n\nimport ansis from 'ansis';\nimport { Model } from '../core/model.js';\n\nexport interface SearchOptions {\n layer?: string;\n type?: string;\n json?: boolean;\n verbose?: boolean;\n debug?: boolean;\n}\n\nexport async function searchCommand(query: string, options: SearchOptions): Promise<void> {\n try {\n // Load model\n const model = await Model.load();\n\n // Collect all matching elements\n const results: Array<{\n layer: string;\n id: string;\n type: string;\n name: string;\n description?: string;\n }> = [];\n\n const queryLower = query.toLowerCase();\n\n for (const layerName of model.getLayerNames()) {\n // Skip if layer filter specified and doesn't match\n if (options.layer && layerName !== options.layer) {\n continue;\n }\n\n const layerObj = await model.getLayer(layerName);\n if (!layerObj) continue;\n\n for (const element of layerObj.listElements()) {\n // Apply filters\n if (options.type && element.type !== options.type) {\n continue;\n }\n\n // Match query against id and name\n const idMatch = element.id.toLowerCase().includes(queryLower);\n const nameMatch = element.name.toLowerCase().includes(queryLower);\n\n if (idMatch || nameMatch) {\n results.push({\n layer: layerName,\n id: element.id,\n type: element.type,\n name: element.name,\n description: element.description,\n });\n }\n }\n }\n\n // Output as JSON if requested\n if (options.json) {\n console.log(JSON.stringify(results, null, 2));\n return;\n }\n\n // Display results\n if (results.length === 0) {\n console.log(ansis.yellow(`No elements matching \"${query}\"`));\n return;\n }\n\n console.log('');\n console.log(ansis.bold(`Found ${results.length} element(s) matching \"${query}\":`));\n console.log(ansis.dim('\u2500'.repeat(80)));\n\n // Print header\n const layerWidth = 12;\n const idWidth = 28;\n const typeWidth = 12;\n const nameWidth = 28;\n\n console.log(\n `${ansis.cyan('LAYER'.padEnd(layerWidth))} ${ansis.cyan('ID'.padEnd(idWidth))} ${ansis.cyan('TYPE'.padEnd(typeWidth))} ${ansis.cyan('NAME')}`\n );\n console.log(ansis.dim('\u2500'.repeat(80)));\n\n // Print rows\n for (const result of results) {\n const layer = result.layer.substring(0, layerWidth - 1).padEnd(layerWidth);\n const id = result.id.substring(0, idWidth - 1).padEnd(idWidth);\n const type = result.type.substring(0, typeWidth - 1).padEnd(typeWidth);\n const name = result.name.substring(0, nameWidth);\n\n console.log(`${ansis.blue(layer)} ${id} ${type} ${name}`);\n\n if (options.verbose && result.description) {\n console.log(ansis.dim(` \u2514\u2500 ${result.description}`));\n }\n }\n\n console.log(ansis.dim('\u2500'.repeat(80)));\n console.log('');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n"],
5
+ "mappings": "AAIA,OAAO,WAAW;AAClB,SAAS,aAAa;AAUtB,eAAsB,cAAc,OAAe,SAAsB;AACvE,MAAI;AAEF,UAAM,QAAQ,MAAM,MAAM,KAAI,GAGxB,UAMD,CAAA,GAEC,aAAa,MAAM,YAAW;AAEpC,eAAW,aAAa,MAAM,cAAa,GAAI;AAE7C,UAAI,QAAQ,SAAS,cAAc,QAAQ;AACzC;AAGF,YAAM,WAAW,MAAM,MAAM,SAAS,SAAS;AAC/C,UAAK;AAEL,mBAAW,WAAW,SAAS,aAAY,GAAI;AAE7C,cAAI,QAAQ,QAAQ,QAAQ,SAAS,QAAQ;AAC3C;AAIF,gBAAM,UAAU,QAAQ,GAAG,YAAW,EAAG,SAAS,UAAU,GACtD,YAAY,QAAQ,KAAK,YAAW,EAAG,SAAS,UAAU;AAEhE,WAAI,WAAW,cACb,QAAQ,KAAK;YACX,OAAO;YACP,IAAI,QAAQ;YACZ,MAAM,QAAQ;YACd,MAAM,QAAQ;YACd,aAAa,QAAQ;WACtB;QAEL;IACF;AAGA,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAC5C;IACF;AAGA,QAAI,QAAQ,WAAW,GAAG;AACxB,cAAQ,IAAI,MAAM,OAAO,yBAAyB,KAAK,GAAG,CAAC;AAC3D;IACF;AAEA,YAAQ,IAAI,EAAE,GACd,QAAQ,IAAI,MAAM,KAAK,SAAS,QAAQ,MAAM,yBAAyB,KAAK,IAAI,CAAC,GACjF,QAAQ,IAAI,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC;AAGrC,UAAM,aAAa,IACb,UAAU,IACV,YAAY,IACZ,YAAY;AAElB,YAAQ,IACN,GAAG,MAAM,KAAK,QAAQ,OAAO,UAAU,CAAC,CAAC,IAAI,MAAM,KAAK,KAAK,OAAO,OAAO,CAAC,CAAC,IAAI,MAAM,KAAK,OAAO,OAAO,SAAS,CAAC,CAAC,IAAI,MAAM,KAAK,MAAM,CAAC,EAAE,GAE/I,QAAQ,IAAI,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC;AAGrC,eAAW,UAAU,SAAS;AAC5B,YAAM,QAAQ,OAAO,MAAM,UAAU,GAAG,aAAa,CAAC,EAAE,OAAO,UAAU,GACnE,KAAK,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC,EAAE,OAAO,OAAO,GACvD,OAAO,OAAO,KAAK,UAAU,GAAG,YAAY,CAAC,EAAE,OAAO,SAAS,GAC/D,OAAO,OAAO,KAAK,UAAU,GAAG,SAAS;AAE/C,cAAQ,IAAI,GAAG,MAAM,KAAK,KAAK,CAAC,IAAI,EAAE,IAAI,IAAI,IAAI,IAAI,EAAE,GAEpD,QAAQ,WAAW,OAAO,eAC5B,QAAQ,IAAI,MAAM,IAAI,kBAAQ,OAAO,WAAW,EAAE,CAAC;IAEvD;AAEA,YAAQ,IAAI,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC,GACrC,QAAQ,IAAI,EAAE;EAChB,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,YAAQ,MAAM,MAAM,IAAI,UAAU,OAAO,EAAE,CAAC,GAC5C,QAAQ,KAAK,CAAC;EAChB;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,38 @@
1
+ import ansis from "ansis";
2
+ import { Model } from "../core/model.js";
3
+ import { findElementLayer } from "../utils/element-utils.js";
4
+ async function showCommand(id, options = {}) {
5
+ try {
6
+ const model = await Model.load(options.model), layerName = await findElementLayer(model, id);
7
+ layerName || (console.error(ansis.red(`Error: Element ${id} not found`)), process.exit(1));
8
+ const element = (await model.getLayer(layerName)).getElement(id);
9
+ if (console.log(""), console.log(ansis.bold(`${ansis.blue("Element:")} ${id}`)), console.log(ansis.dim("\u2500".repeat(60))), console.log(`${ansis.gray("Layer:")} ${layerName}`), console.log(`${ansis.gray("Type:")} ${element.type}`), console.log(`${ansis.gray("Name:")} ${element.name}`), element.description && console.log(`${ansis.gray("Description:")} ${element.description}`), Object.keys(element.properties).length > 0) {
10
+ console.log(""), console.log(ansis.bold("Properties:"));
11
+ for (const [key, value] of Object.entries(element.properties)) {
12
+ const displayValue = typeof value == "string" ? value : JSON.stringify(value, null, 2);
13
+ console.log(` ${ansis.cyan(key)}: ${displayValue}`);
14
+ }
15
+ }
16
+ if (element.references && element.references.length > 0) {
17
+ console.log(""), console.log(ansis.bold("References:"));
18
+ for (const ref of element.references)
19
+ console.log(` \u2192 ${ansis.yellow(ref.target)} (${ref.type})`), ref.description && console.log(` ${ansis.dim(ref.description)}`);
20
+ }
21
+ if (element.relationships && element.relationships.length > 0) {
22
+ console.log(""), console.log(ansis.bold("Relationships:"));
23
+ for (const rel of element.relationships)
24
+ if (console.log(` ${ansis.magenta(rel.predicate)}: ${rel.target}`), rel.properties) {
25
+ const propStr = Object.entries(rel.properties).map(([k, v]) => `${k}=${v}`).join(", ");
26
+ console.log(` ${ansis.dim(propStr)}`);
27
+ }
28
+ }
29
+ console.log("");
30
+ } catch (error) {
31
+ const message = error instanceof Error ? error.message : String(error);
32
+ console.error(ansis.red(`Error: ${message}`)), process.exit(1);
33
+ }
34
+ }
35
+ export {
36
+ showCommand
37
+ };
38
+ //# sourceMappingURL=show.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/show.ts"],
4
+ "sourcesContent": ["/**\n * Show detailed information about an element\n */\n\nimport ansis from 'ansis';\nimport { Model } from '../core/model.js';\nimport { findElementLayer } from '../utils/element-utils.js';\n\nexport async function showCommand(id: string, options: { model?: string } = {}): Promise<void> {\n try {\n // Load model (optionally from specified path)\n const model = await Model.load(options.model);\n\n // Find element\n const layerName = await findElementLayer(model, id);\n if (!layerName) {\n console.error(ansis.red(`Error: Element ${id} not found`));\n process.exit(1);\n }\n\n const layer = (await model.getLayer(layerName))!;\n const element = layer.getElement(id)!;\n\n // Display element information\n console.log('');\n console.log(ansis.bold(`${ansis.blue('Element:')} ${id}`));\n console.log(ansis.dim('\u2500'.repeat(60)));\n console.log(`${ansis.gray('Layer:')} ${layerName}`);\n console.log(`${ansis.gray('Type:')} ${element.type}`);\n console.log(`${ansis.gray('Name:')} ${element.name}`);\n\n if (element.description) {\n console.log(`${ansis.gray('Description:')} ${element.description}`);\n }\n\n // Display properties\n if (Object.keys(element.properties).length > 0) {\n console.log('');\n console.log(ansis.bold('Properties:'));\n for (const [key, value] of Object.entries(element.properties)) {\n const displayValue =\n typeof value === 'string' ? value : JSON.stringify(value, null, 2);\n console.log(` ${ansis.cyan(key)}: ${displayValue}`);\n }\n }\n\n // Display references\n if (element.references && element.references.length > 0) {\n console.log('');\n console.log(ansis.bold('References:'));\n for (const ref of element.references) {\n console.log(` \u2192 ${ansis.yellow(ref.target)} (${ref.type})`);\n if (ref.description) {\n console.log(` ${ansis.dim(ref.description)}`);\n }\n }\n }\n\n // Display relationships\n if (element.relationships && element.relationships.length > 0) {\n console.log('');\n console.log(ansis.bold('Relationships:'));\n for (const rel of element.relationships) {\n console.log(` ${ansis.magenta(rel.predicate)}: ${rel.target}`);\n if (rel.properties) {\n const propStr = Object.entries(rel.properties)\n .map(([k, v]) => `${k}=${v}`)\n .join(', ');\n console.log(` ${ansis.dim(propStr)}`);\n }\n }\n }\n\n console.log('');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n"],
5
+ "mappings": "AAIA,OAAO,WAAW;AAClB,SAAS,aAAa;AACtB,SAAS,wBAAwB;AAEjC,eAAsB,YAAY,IAAY,UAA8B,CAAA,GAAE;AAC5E,MAAI;AAEF,UAAM,QAAQ,MAAM,MAAM,KAAK,QAAQ,KAAK,GAGtC,YAAY,MAAM,iBAAiB,OAAO,EAAE;AAClD,IAAK,cACH,QAAQ,MAAM,MAAM,IAAI,kBAAkB,EAAE,YAAY,CAAC,GACzD,QAAQ,KAAK,CAAC;AAIhB,UAAM,WADS,MAAM,MAAM,SAAS,SAAS,GACvB,WAAW,EAAE;AAenC,QAZA,QAAQ,IAAI,EAAE,GACd,QAAQ,IAAI,MAAM,KAAK,GAAG,MAAM,KAAK,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,GACzD,QAAQ,IAAI,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC,GACrC,QAAQ,IAAI,GAAG,MAAM,KAAK,QAAQ,CAAC,UAAU,SAAS,EAAE,GACxD,QAAQ,IAAI,GAAG,MAAM,KAAK,OAAO,CAAC,WAAW,QAAQ,IAAI,EAAE,GAC3D,QAAQ,IAAI,GAAG,MAAM,KAAK,OAAO,CAAC,WAAW,QAAQ,IAAI,EAAE,GAEvD,QAAQ,eACV,QAAQ,IAAI,GAAG,MAAM,KAAK,cAAc,CAAC,IAAI,QAAQ,WAAW,EAAE,GAIhE,OAAO,KAAK,QAAQ,UAAU,EAAE,SAAS,GAAG;AAC9C,cAAQ,IAAI,EAAE,GACd,QAAQ,IAAI,MAAM,KAAK,aAAa,CAAC;AACrC,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,UAAU,GAAG;AAC7D,cAAM,eACJ,OAAO,SAAU,WAAW,QAAQ,KAAK,UAAU,OAAO,MAAM,CAAC;AACnE,gBAAQ,IAAI,KAAK,MAAM,KAAK,GAAG,CAAC,KAAK,YAAY,EAAE;MACrD;IACF;AAGA,QAAI,QAAQ,cAAc,QAAQ,WAAW,SAAS,GAAG;AACvD,cAAQ,IAAI,EAAE,GACd,QAAQ,IAAI,MAAM,KAAK,aAAa,CAAC;AACrC,iBAAW,OAAO,QAAQ;AACxB,gBAAQ,IAAI,YAAO,MAAM,OAAO,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,GAAG,GACvD,IAAI,eACN,QAAQ,IAAI,OAAO,MAAM,IAAI,IAAI,WAAW,CAAC,EAAE;IAGrD;AAGA,QAAI,QAAQ,iBAAiB,QAAQ,cAAc,SAAS,GAAG;AAC7D,cAAQ,IAAI,EAAE,GACd,QAAQ,IAAI,MAAM,KAAK,gBAAgB,CAAC;AACxC,iBAAW,OAAO,QAAQ;AAExB,YADA,QAAQ,IAAI,KAAK,MAAM,QAAQ,IAAI,SAAS,CAAC,KAAK,IAAI,MAAM,EAAE,GAC1D,IAAI,YAAY;AAClB,gBAAM,UAAU,OAAO,QAAQ,IAAI,UAAU,EAC1C,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAC3B,KAAK,IAAI;AACZ,kBAAQ,IAAI,OAAO,MAAM,IAAI,OAAO,CAAC,EAAE;QACzC;IAEJ;AAEA,YAAQ,IAAI,EAAE;EAChB,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,YAAQ,MAAM,MAAM,IAAI,UAAU,OAAO,EAAE,CAAC,GAC5C,QAAQ,KAAK,CAAC;EAChB;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,60 @@
1
+ import ansis from "ansis";
2
+ import { Model } from "../core/model.js";
3
+ import { ReferenceRegistry } from "../core/reference-registry.js";
4
+ import { DependencyTracker, TraceDirection } from "../core/dependency-tracker.js";
5
+ import { findElementLayer } from "../utils/element-utils.js";
6
+ async function traceCommand(elementId, options = {}) {
7
+ try {
8
+ const model = await Model.load(options.model);
9
+ await findElementLayer(model, elementId) || (console.error(ansis.red(`Error: Element ${elementId} not found`)), process.exit(1));
10
+ const registry = new ReferenceRegistry();
11
+ for (const layer of model.layers.values())
12
+ for (const element of layer.listElements())
13
+ registry.registerElement(element);
14
+ const tracker = new DependencyTracker(registry), direction = options.direction || "both";
15
+ if (console.log(""), console.log(ansis.bold(`${ansis.blue("Dependency Trace:")} ${ansis.yellow(elementId)}`)), console.log(ansis.dim("\u2500".repeat(80))), direction === "up" || direction === "both") {
16
+ const transitiveDependents = tracker.traceDependencies(elementId, TraceDirection.DOWN, null), directDependents = tracker.traceDependencies(elementId, TraceDirection.DOWN, 1);
17
+ if (console.log(""), console.log(ansis.cyan(`Dependents (${directDependents.length} direct, ${transitiveDependents.length} transitive):`)), directDependents.length === 0)
18
+ console.log(ansis.dim(" (none)"));
19
+ else {
20
+ console.log(ansis.gray(" Direct:"));
21
+ for (const dep of directDependents.slice(0, 10))
22
+ console.log(` ${ansis.yellow("\u2190")} ${ansis.green(dep)}`);
23
+ directDependents.length > 10 && console.log(ansis.dim(` ... and ${directDependents.length - 10} more`));
24
+ }
25
+ if (transitiveDependents.length > 0 && directDependents.length > 0) {
26
+ console.log(ansis.gray(" Transitive:"));
27
+ const transitiveOnly = transitiveDependents.filter((d) => !directDependents.includes(d));
28
+ for (const dep of transitiveOnly.slice(0, 10))
29
+ console.log(` ${ansis.yellow("\u2196")} ${ansis.dim(dep)}`);
30
+ transitiveOnly.length > 10 && console.log(ansis.dim(` ... and ${transitiveOnly.length - 10} more`));
31
+ }
32
+ }
33
+ if (direction === "down" || direction === "both") {
34
+ const transitiveDependencies = tracker.traceDependencies(elementId, TraceDirection.UP, null), directDependencies = tracker.traceDependencies(elementId, TraceDirection.UP, 1);
35
+ if (console.log(""), console.log(ansis.cyan(`Dependencies (${directDependencies.length} direct, ${transitiveDependencies.length} transitive):`)), directDependencies.length === 0)
36
+ console.log(ansis.dim(" (none)"));
37
+ else {
38
+ console.log(ansis.gray(" Direct:"));
39
+ for (const dep of directDependencies.slice(0, 10))
40
+ console.log(` ${ansis.yellow("\u2192")} ${ansis.green(dep)}`);
41
+ directDependencies.length > 10 && console.log(ansis.dim(` ... and ${directDependencies.length - 10} more`));
42
+ }
43
+ if (transitiveDependencies.length > 0 && directDependencies.length > 0) {
44
+ console.log(ansis.gray(" Transitive:"));
45
+ const transitiveOnly = transitiveDependencies.filter((d) => !directDependencies.includes(d));
46
+ for (const dep of transitiveOnly.slice(0, 10))
47
+ console.log(` ${ansis.yellow("\u2198")} ${ansis.dim(dep)}`);
48
+ transitiveOnly.length > 10 && console.log(ansis.dim(` ... and ${transitiveOnly.length - 10} more`));
49
+ }
50
+ }
51
+ console.log("");
52
+ } catch (error) {
53
+ const message = error instanceof Error ? error.message : String(error);
54
+ console.error(ansis.red(`Error: ${message}`)), process.exit(1);
55
+ }
56
+ }
57
+ export {
58
+ traceCommand
59
+ };
60
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/trace.ts"],
4
+ "sourcesContent": ["/**\n * Trace command - display dependency trace for an element\n */\n\nimport ansis from 'ansis';\nimport { Model } from '../core/model.js';\nimport { ReferenceRegistry } from '../core/reference-registry.js';\nimport { DependencyTracker, TraceDirection } from '../core/dependency-tracker.js';\nimport { findElementLayer } from '../utils/element-utils.js';\n\nexport async function traceCommand(\n elementId: string,\n options: {\n direction?: 'up' | 'down' | 'both';\n depth?: number;\n showMetrics?: boolean;\n model?: string;\n } = {}\n): Promise<void> {\n try {\n // Load model\n const model = await Model.load(options.model);\n\n // Find element\n const layerName = await findElementLayer(model, elementId);\n if (!layerName) {\n console.error(ansis.red(`Error: Element ${elementId} not found`));\n process.exit(1);\n }\n\n // Build reference registry\n const registry = new ReferenceRegistry();\n for (const layer of model.layers.values()) {\n for (const element of layer.listElements()) {\n registry.registerElement(element);\n }\n }\n\n // Create dependency tracker with registry\n const tracker = new DependencyTracker(registry);\n\n // Set default direction\n const direction = options.direction || 'both';\n\n // Display header\n console.log('');\n console.log(\n ansis.bold(\n `${ansis.blue('Dependency Trace:')} ${ansis.yellow(elementId)}`\n )\n );\n console.log(ansis.dim('\u2500'.repeat(80)));\n\n // Display dependents (elements that depend on this element - upward)\n if (direction === 'up' || direction === 'both') {\n const transitiveDependents = tracker.traceDependencies(elementId, TraceDirection.DOWN, null);\n const directDependents = tracker.traceDependencies(elementId, TraceDirection.DOWN, 1);\n\n console.log('');\n console.log(\n ansis.cyan(\n `Dependents (${directDependents.length} direct, ${transitiveDependents.length} transitive):`\n )\n );\n\n if (directDependents.length === 0) {\n console.log(ansis.dim(' (none)'));\n } else {\n // Show direct dependents with indentation\n console.log(ansis.gray(' Direct:'));\n for (const dep of directDependents.slice(0, 10)) {\n console.log(\n ` ${ansis.yellow('\u2190')} ${ansis.green(dep)}`\n );\n }\n if (directDependents.length > 10) {\n console.log(\n ansis.dim(` ... and ${directDependents.length - 10} more`)\n );\n }\n }\n\n if (transitiveDependents.length > 0 && directDependents.length > 0) {\n console.log(ansis.gray(' Transitive:'));\n const transitiveOnly = transitiveDependents.filter(\n (d: string) => !directDependents.includes(d)\n );\n for (const dep of transitiveOnly.slice(0, 10)) {\n console.log(\n ` ${ansis.yellow('\u2196')} ${ansis.dim(dep)}`\n );\n }\n if (transitiveOnly.length > 10) {\n console.log(\n ansis.dim(` ... and ${transitiveOnly.length - 10} more`)\n );\n }\n }\n }\n\n // Display dependencies (elements this element depends on - downward)\n if (direction === 'down' || direction === 'both') {\n const transitiveDependencies = tracker.traceDependencies(\n elementId,\n TraceDirection.UP,\n null\n );\n const directDependencies = tracker.traceDependencies(elementId, TraceDirection.UP, 1);\n\n console.log('');\n console.log(\n ansis.cyan(\n `Dependencies (${directDependencies.length} direct, ${transitiveDependencies.length} transitive):`\n )\n );\n\n if (directDependencies.length === 0) {\n console.log(ansis.dim(' (none)'));\n } else {\n // Show direct dependencies with indentation\n console.log(ansis.gray(' Direct:'));\n for (const dep of directDependencies.slice(0, 10)) {\n console.log(\n ` ${ansis.yellow('\u2192')} ${ansis.green(dep)}`\n );\n }\n if (directDependencies.length > 10) {\n console.log(\n ansis.dim(` ... and ${directDependencies.length - 10} more`)\n );\n }\n }\n\n if (transitiveDependencies.length > 0 && directDependencies.length > 0) {\n console.log(ansis.gray(' Transitive:'));\n const transitiveOnly = transitiveDependencies.filter(\n (d: string) => !directDependencies.includes(d)\n );\n for (const dep of transitiveOnly.slice(0, 10)) {\n console.log(\n ` ${ansis.yellow('\u2198')} ${ansis.dim(dep)}`\n );\n }\n if (transitiveOnly.length > 10) {\n console.log(\n ansis.dim(` ... and ${transitiveOnly.length - 10} more`)\n );\n }\n }\n }\n\n // Note: Advanced features like cycle detection and metrics are not yet implemented\n // in the refactored DependencyTracker matching Python CLI API\n\n console.log('');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }