@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.
- package/PYTHON_CLI_PARITY.md +265 -0
- package/PYTHON_CLI_STRUCTURE_UPDATE.md +246 -0
- package/README.md +926 -0
- package/biome.json +42 -0
- package/bunfig.toml +3 -0
- package/dist/ai/claude-client.js +71 -0
- package/dist/ai/claude-client.js.map +7 -0
- package/dist/ai/context-provider.js +129 -0
- package/dist/ai/context-provider.js.map +7 -0
- package/dist/ai/tools.js +231 -0
- package/dist/ai/tools.js.map +7 -0
- package/dist/cli.js +224 -0
- package/dist/cli.js.map +7 -0
- package/dist/commands/add.js +51 -0
- package/dist/commands/add.js.map +7 -0
- package/dist/commands/changeset.js +174 -0
- package/dist/commands/changeset.js.map +7 -0
- package/dist/commands/chat.js +111 -0
- package/dist/commands/chat.js.map +7 -0
- package/dist/commands/conformance.js +132 -0
- package/dist/commands/conformance.js.map +7 -0
- package/dist/commands/delete.js +31 -0
- package/dist/commands/delete.js.map +7 -0
- package/dist/commands/element.js +28 -0
- package/dist/commands/element.js.map +7 -0
- package/dist/commands/export.js +65 -0
- package/dist/commands/export.js.map +7 -0
- package/dist/commands/info.js +40 -0
- package/dist/commands/info.js.map +7 -0
- package/dist/commands/init.js +45 -0
- package/dist/commands/init.js.map +7 -0
- package/dist/commands/list.js +32 -0
- package/dist/commands/list.js.map +7 -0
- package/dist/commands/migrate.js +36 -0
- package/dist/commands/migrate.js.map +7 -0
- package/dist/commands/project.js +74 -0
- package/dist/commands/project.js.map +7 -0
- package/dist/commands/relationship.js +118 -0
- package/dist/commands/relationship.js.map +7 -0
- package/dist/commands/search.js +48 -0
- package/dist/commands/search.js.map +7 -0
- package/dist/commands/show.js +38 -0
- package/dist/commands/show.js.map +7 -0
- package/dist/commands/trace.js +60 -0
- package/dist/commands/trace.js.map +7 -0
- package/dist/commands/update.js +37 -0
- package/dist/commands/update.js.map +7 -0
- package/dist/commands/upgrade.js +152 -0
- package/dist/commands/upgrade.js.map +7 -0
- package/dist/commands/validate.js +71 -0
- package/dist/commands/validate.js.map +7 -0
- package/dist/commands/version.js +20 -0
- package/dist/commands/version.js.map +7 -0
- package/dist/commands/visualize.js +51 -0
- package/dist/commands/visualize.js.map +7 -0
- package/dist/core/active-changeset.js +52 -0
- package/dist/core/active-changeset.js.map +7 -0
- package/dist/core/changeset.js +244 -0
- package/dist/core/changeset.js.map +7 -0
- package/dist/core/dependency-tracker.js +322 -0
- package/dist/core/dependency-tracker.js.map +7 -0
- package/dist/core/element.js +65 -0
- package/dist/core/element.js.map +7 -0
- package/dist/core/layer.js +75 -0
- package/dist/core/layer.js.map +7 -0
- package/dist/core/manifest.js +57 -0
- package/dist/core/manifest.js.map +7 -0
- package/dist/core/migration-registry.js +131 -0
- package/dist/core/migration-registry.js.map +7 -0
- package/dist/core/model.js +455 -0
- package/dist/core/model.js.map +7 -0
- package/dist/core/projection-engine.js +288 -0
- package/dist/core/projection-engine.js.map +7 -0
- package/dist/core/reference-registry.js +188 -0
- package/dist/core/reference-registry.js.map +7 -0
- package/dist/core/relationship-registry.js +114 -0
- package/dist/core/relationship-registry.js.map +7 -0
- package/dist/core/relationships.js +78 -0
- package/dist/core/relationships.js.map +7 -0
- package/dist/export/archimate-exporter.js +111 -0
- package/dist/export/archimate-exporter.js.map +7 -0
- package/dist/export/export-manager.js +63 -0
- package/dist/export/export-manager.js.map +7 -0
- package/dist/export/graphml-exporter.js +39 -0
- package/dist/export/graphml-exporter.js.map +7 -0
- package/dist/export/index.js +17 -0
- package/dist/export/index.js.map +7 -0
- package/dist/export/json-schema-exporter.js +60 -0
- package/dist/export/json-schema-exporter.js.map +7 -0
- package/dist/export/markdown-exporter.js +99 -0
- package/dist/export/markdown-exporter.js.map +7 -0
- package/dist/export/openapi-exporter.js +85 -0
- package/dist/export/openapi-exporter.js.map +7 -0
- package/dist/export/plantuml-exporter.js +60 -0
- package/dist/export/plantuml-exporter.js.map +7 -0
- package/dist/export/types.js +36 -0
- package/dist/export/types.js.map +7 -0
- package/dist/schemas/bundled/01-motivation-layer.schema.json +942 -0
- package/dist/schemas/bundled/02-business-layer.schema.json +1293 -0
- package/dist/schemas/bundled/03-security-layer.schema.json +2177 -0
- package/dist/schemas/bundled/04-application-layer.schema.json +1328 -0
- package/dist/schemas/bundled/05-technology-layer.schema.json +1465 -0
- package/dist/schemas/bundled/06-api-layer.schema.json +1743 -0
- package/dist/schemas/bundled/07-data-model-layer.schema.json +1253 -0
- package/dist/schemas/bundled/08-datastore-layer.schema.json +892 -0
- package/dist/schemas/bundled/09-ux-layer.schema.json +1506 -0
- package/dist/schemas/bundled/10-navigation-layer.schema.json +843 -0
- package/dist/schemas/bundled/11-apm-observability-layer.schema.json +1430 -0
- package/dist/schemas/bundled/12-testing-layer.schema.json +1091 -0
- package/dist/schemas/bundled/common/layer-extensions.schema.json +266 -0
- package/dist/schemas/bundled/common/predicates.schema.json +493 -0
- package/dist/schemas/bundled/common/relationships.schema.json +791 -0
- package/dist/schemas/bundled/common/source-references.schema.json +71 -0
- package/dist/schemas/bundled/link-registry.json +1839 -0
- package/dist/schemas/bundled/link-registry.schema.json +339 -0
- package/dist/schemas/bundled/relationship-catalog.json +1302 -0
- package/dist/schemas/bundled/relationship-type.schema.json +221 -0
- package/dist/server/server.js +1207 -0
- package/dist/server/server.js.map +7 -0
- package/dist/server/telemetry-middleware.js +24 -0
- package/dist/server/telemetry-middleware.js.map +7 -0
- package/dist/telemetry/console-interceptor.js +34 -0
- package/dist/telemetry/console-interceptor.js.map +7 -0
- package/dist/telemetry/index.js +54 -0
- package/dist/telemetry/index.js.map +7 -0
- package/dist/telemetry/resilient-exporter.js +41 -0
- package/dist/telemetry/resilient-exporter.js.map +7 -0
- package/dist/telemetry/resilient-log-exporter.js +41 -0
- package/dist/telemetry/resilient-log-exporter.js.map +7 -0
- package/dist/telemetry/test-instrumentation.js +32 -0
- package/dist/telemetry/test-instrumentation.js.map +7 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +7 -0
- package/dist/utils/element-utils.js +11 -0
- package/dist/utils/element-utils.js.map +7 -0
- package/dist/utils/errors.js +105 -0
- package/dist/utils/errors.js.map +7 -0
- package/dist/utils/file-io.js +69 -0
- package/dist/utils/file-io.js.map +7 -0
- package/dist/utils/globals.js +28 -0
- package/dist/utils/globals.js.map +7 -0
- package/dist/utils/model-path.js +22 -0
- package/dist/utils/model-path.js.map +7 -0
- package/dist/utils/project-paths.js +45 -0
- package/dist/utils/project-paths.js.map +7 -0
- package/dist/utils/spec-installer.js +85 -0
- package/dist/utils/spec-installer.js.map +7 -0
- package/dist/utils/spec-version.js +33 -0
- package/dist/utils/spec-version.js.map +7 -0
- package/dist/validators/index.js +15 -0
- package/dist/validators/index.js.map +7 -0
- package/dist/validators/naming-validator.js +82 -0
- package/dist/validators/naming-validator.js.map +7 -0
- package/dist/validators/reference-validator.js +106 -0
- package/dist/validators/reference-validator.js.map +7 -0
- package/dist/validators/schema-validator.js +148 -0
- package/dist/validators/schema-validator.js.map +7 -0
- package/dist/validators/semantic-validator.js +80 -0
- package/dist/validators/semantic-validator.js.map +7 -0
- package/dist/validators/types.js +48 -0
- package/dist/validators/types.js.map +7 -0
- package/dist/validators/validator.js +67 -0
- package/dist/validators/validator.js.map +7 -0
- package/docs/TEST-INSTRUMENTATION.md +405 -0
- package/docs/telemetry.md +427 -0
- package/package.json +70 -0
- package/test-debug.js +33 -0
- package/test-special.mjs +46 -0
- package/test_runner.ts +7 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import { Layer } from "./layer.js";
|
|
2
|
+
import { Manifest } from "./manifest.js";
|
|
3
|
+
import { Element } from "./element.js";
|
|
4
|
+
import { ProjectionEngine } from "./projection-engine.js";
|
|
5
|
+
import { Relationships } from "./relationships.js";
|
|
6
|
+
import { ActiveChangesetContext } from "./active-changeset.js";
|
|
7
|
+
import { ensureDir, writeFile } from "../utils/file-io.js";
|
|
8
|
+
import { startSpan, endSpan } from "../telemetry/index.js";
|
|
9
|
+
import { findProjectRoot } from "../utils/project-paths.js";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import fs from "node:fs/promises";
|
|
12
|
+
const isTelemetryEnabled = !1;
|
|
13
|
+
class Model {
|
|
14
|
+
rootPath;
|
|
15
|
+
manifest;
|
|
16
|
+
layers;
|
|
17
|
+
relationships;
|
|
18
|
+
lazyLoad;
|
|
19
|
+
loadedLayers;
|
|
20
|
+
projectionEngine;
|
|
21
|
+
activeChangesetContext;
|
|
22
|
+
constructor(rootPath, manifest, options = {}) {
|
|
23
|
+
this.rootPath = rootPath, this.manifest = manifest, this.layers = /* @__PURE__ */ new Map(), this.relationships = new Relationships(), this.lazyLoad = options.lazyLoad ?? !1, this.loadedLayers = /* @__PURE__ */ new Set();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get a layer, loading it if lazy loading is enabled
|
|
27
|
+
*/
|
|
28
|
+
async getLayer(name) {
|
|
29
|
+
return this.lazyLoad && !this.loadedLayers.has(name) && await this.loadLayer(name), this.layers.get(name);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get an element by ID across all layers
|
|
33
|
+
*/
|
|
34
|
+
getElementById(id) {
|
|
35
|
+
for (const layer of this.layers.values()) {
|
|
36
|
+
const element = layer.elements.get(id);
|
|
37
|
+
if (element)
|
|
38
|
+
return element;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get projection engine (lazily initialized)
|
|
43
|
+
*/
|
|
44
|
+
getProjectionEngine() {
|
|
45
|
+
return this.projectionEngine || (this.projectionEngine = new ProjectionEngine(this)), this.projectionEngine;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get active changeset context (lazily initialized)
|
|
49
|
+
*/
|
|
50
|
+
getActiveChangesetContext() {
|
|
51
|
+
return this.activeChangesetContext || (this.activeChangesetContext = new ActiveChangesetContext(this.rootPath)), this.activeChangesetContext;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Load a layer from disk (legacy format: model/XX_layername/*.yaml files)
|
|
55
|
+
* Supports reading layer paths from manifest for Python CLI compatibility
|
|
56
|
+
*/
|
|
57
|
+
async loadLayer(name) {
|
|
58
|
+
const layerSpan = isTelemetryEnabled ? startSpan("layer.load", {
|
|
59
|
+
"layer.name": name
|
|
60
|
+
}) : null;
|
|
61
|
+
try {
|
|
62
|
+
const fs2 = await import("fs/promises"), yaml = await import("yaml");
|
|
63
|
+
let layerPath = null;
|
|
64
|
+
if (this.manifest.layers && this.manifest.layers[name]) {
|
|
65
|
+
const layerConfig = this.manifest.layers[name];
|
|
66
|
+
if (layerConfig.path) {
|
|
67
|
+
const fullPath = `${this.rootPath}/${layerConfig.path.replace(/\/$/, "")}`;
|
|
68
|
+
try {
|
|
69
|
+
await fs2.access(fullPath), layerPath = fullPath;
|
|
70
|
+
} catch {
|
|
71
|
+
process.env.DEBUG && console.debug(`Manifest specifies path ${layerConfig.path} but it doesn't exist`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (!layerPath) {
|
|
76
|
+
const modelDir = `${this.rootPath}/documentation-robotics/model`;
|
|
77
|
+
try {
|
|
78
|
+
const layerDir = (await fs2.readdir(modelDir, { withFileTypes: !0 })).find((e) => e.isDirectory() && e.name.match(/^\d{2}_/) && e.name.replace(/^\d{2}_/, "") === name);
|
|
79
|
+
layerDir && (layerPath = `${modelDir}/${layerDir.name}`);
|
|
80
|
+
} catch {
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!layerPath)
|
|
84
|
+
return;
|
|
85
|
+
const layer = new Layer(name), files = await fs2.readdir(layerPath);
|
|
86
|
+
for (const file of files)
|
|
87
|
+
if (file.endsWith(".yaml") || file.endsWith(".yml")) {
|
|
88
|
+
const filePath = `${layerPath}/${file}`, yamlContent = await fs2.readFile(filePath, "utf-8"), elements = yaml.parse(yamlContent);
|
|
89
|
+
if (elements && typeof elements == "object") {
|
|
90
|
+
for (const [key, element] of Object.entries(elements))
|
|
91
|
+
if (element && typeof element == "object") {
|
|
92
|
+
const el = element, elementId = el.id || `${name}.${key}`;
|
|
93
|
+
let elementType = el.type;
|
|
94
|
+
if (!elementType) {
|
|
95
|
+
const stem = file.replace(/\.ya?ml$/, "");
|
|
96
|
+
elementType = stem.endsWith("s") ? stem.slice(0, -1) : stem;
|
|
97
|
+
}
|
|
98
|
+
const newElement = new Element({
|
|
99
|
+
id: elementId,
|
|
100
|
+
name: el.name || key,
|
|
101
|
+
type: elementType,
|
|
102
|
+
description: el.description || el.documentation || "",
|
|
103
|
+
properties: el.properties || {},
|
|
104
|
+
relationships: el.relationships || [],
|
|
105
|
+
references: el.references || [],
|
|
106
|
+
layer: name,
|
|
107
|
+
// Track layer (Python CLI compatibility)
|
|
108
|
+
filePath,
|
|
109
|
+
// Track source file (Python CLI compatibility)
|
|
110
|
+
rawData: el
|
|
111
|
+
// Preserve raw YAML data (Python CLI compatibility)
|
|
112
|
+
});
|
|
113
|
+
layer.addElement(newElement);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
this.layers.set(name, layer), this.loadedLayers.add(name), isTelemetryEnabled && layerSpan && layerSpan.setAttribute("layer.element_count", layer.elements.size);
|
|
118
|
+
} finally {
|
|
119
|
+
isTelemetryEnabled && endSpan(layerSpan);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Add a layer to the model
|
|
124
|
+
*/
|
|
125
|
+
addLayer(layer) {
|
|
126
|
+
this.layers.set(layer.name, layer), this.loadedLayers.add(layer.name);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get all loaded layer names
|
|
130
|
+
*/
|
|
131
|
+
getLayerNames() {
|
|
132
|
+
return Array.from(this.layers.keys());
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Save a layer to disk (legacy format: model/XX_layername/*.yaml)
|
|
136
|
+
*/
|
|
137
|
+
async saveLayer(name) {
|
|
138
|
+
const layer = this.layers.get(name);
|
|
139
|
+
if (!layer)
|
|
140
|
+
throw new Error(`Layer ${name} not found`);
|
|
141
|
+
const fs2 = await import("fs/promises"), yaml = await import("yaml");
|
|
142
|
+
let layerPath = null;
|
|
143
|
+
if (this.manifest.layers && this.manifest.layers[name]) {
|
|
144
|
+
const layerConfig = this.manifest.layers[name];
|
|
145
|
+
if (layerConfig.path) {
|
|
146
|
+
const fullPath = `${this.rootPath}/${layerConfig.path.replace(/\/$/, "")}`;
|
|
147
|
+
try {
|
|
148
|
+
await fs2.access(fullPath), layerPath = fullPath;
|
|
149
|
+
} catch {
|
|
150
|
+
await ensureDir(fullPath), layerPath = fullPath;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (!layerPath) {
|
|
155
|
+
const modelDir = `${this.rootPath}/documentation-robotics/model`;
|
|
156
|
+
try {
|
|
157
|
+
const layerDir = (await fs2.readdir(modelDir, { withFileTypes: !0 })).find((e) => e.isDirectory() && e.name.match(/^\d{2}_/) && e.name.replace(/^\d{2}_/, "") === name);
|
|
158
|
+
layerDir && (layerPath = `${modelDir}/${layerDir.name}`);
|
|
159
|
+
} catch {
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (!layerPath) {
|
|
163
|
+
const layerNameWithoutPrefix = name.replace(/^\d{2}-/, ""), index = [
|
|
164
|
+
"motivation",
|
|
165
|
+
"business",
|
|
166
|
+
"security",
|
|
167
|
+
"application",
|
|
168
|
+
"technology",
|
|
169
|
+
"api",
|
|
170
|
+
"data-model",
|
|
171
|
+
"datastore",
|
|
172
|
+
"ux",
|
|
173
|
+
"navigation",
|
|
174
|
+
"apm",
|
|
175
|
+
"testing"
|
|
176
|
+
].indexOf(layerNameWithoutPrefix);
|
|
177
|
+
if (index >= 0) {
|
|
178
|
+
const orderNum = String(index + 1).padStart(2, "0");
|
|
179
|
+
layerPath = `${this.rootPath}/documentation-robotics/model/${orderNum}_${layerNameWithoutPrefix}`, await ensureDir(layerPath);
|
|
180
|
+
} else
|
|
181
|
+
throw new Error(`Unknown layer ${name} and no path configured in manifest`);
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
const existingFiles = await fs2.readdir(layerPath);
|
|
185
|
+
for (const file of existingFiles)
|
|
186
|
+
(file.endsWith(".yaml") || file.endsWith(".yml")) && await fs2.unlink(`${layerPath}/${file}`);
|
|
187
|
+
} catch {
|
|
188
|
+
}
|
|
189
|
+
const elementsByType = /* @__PURE__ */ new Map();
|
|
190
|
+
for (const element of layer.elements.values()) {
|
|
191
|
+
const type = element.type + "s";
|
|
192
|
+
elementsByType.has(type) || elementsByType.set(type, []), elementsByType.get(type).push(element);
|
|
193
|
+
}
|
|
194
|
+
for (const [type, elements] of elementsByType) {
|
|
195
|
+
const filename = `${type}.yaml`, filePath = `${layerPath}/${filename}`, yamlData = {};
|
|
196
|
+
for (const element of elements) {
|
|
197
|
+
const key = element.id.split(".").pop() || element.id;
|
|
198
|
+
yamlData[key] = {
|
|
199
|
+
id: element.id,
|
|
200
|
+
name: element.name,
|
|
201
|
+
type: element.type,
|
|
202
|
+
...element.description && { documentation: element.description },
|
|
203
|
+
...Object.keys(element.properties || {}).length > 0 && { properties: element.properties },
|
|
204
|
+
...element.references && element.references.length > 0 && { references: element.references }
|
|
205
|
+
// Relationships are now stored in centralized relationships.yaml, not inline
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
await writeFile(filePath, yaml.stringify(yamlData));
|
|
209
|
+
}
|
|
210
|
+
layer.markClean();
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Save model (saves all dirty layers and manifest)
|
|
214
|
+
*/
|
|
215
|
+
async save() {
|
|
216
|
+
await this.saveDirtyLayers(), await this.saveManifest();
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Save all dirty layers to disk
|
|
220
|
+
*/
|
|
221
|
+
async saveDirtyLayers() {
|
|
222
|
+
let dirtyLayerCount = 0;
|
|
223
|
+
for (const layer of this.layers.values())
|
|
224
|
+
layer.isDirty() && dirtyLayerCount++;
|
|
225
|
+
const span = isTelemetryEnabled ? startSpan("model.save", {
|
|
226
|
+
"model.path": this.rootPath,
|
|
227
|
+
"model.dirty_layer_count": dirtyLayerCount
|
|
228
|
+
}) : null;
|
|
229
|
+
try {
|
|
230
|
+
for (const layer of this.layers.values())
|
|
231
|
+
layer.isDirty() && await this.saveLayer(layer.name);
|
|
232
|
+
} finally {
|
|
233
|
+
isTelemetryEnabled && endSpan(span);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Save the manifest to disk (Python CLI format: documentation-robotics/model/manifest.yaml)
|
|
238
|
+
* Preserves Python CLI metadata fields for compatibility
|
|
239
|
+
*/
|
|
240
|
+
async saveManifest() {
|
|
241
|
+
this.manifest.updateModified();
|
|
242
|
+
const yaml = await import("yaml"), manifestPath = `${this.rootPath}/documentation-robotics/model/manifest.yaml`, yamlData = {
|
|
243
|
+
version: this.manifest.version,
|
|
244
|
+
schema: "documentation-robotics-v1",
|
|
245
|
+
cli_version: this.manifest.version || "0.1.0",
|
|
246
|
+
spec_version: this.manifest.specVersion,
|
|
247
|
+
created: this.manifest.created,
|
|
248
|
+
updated: this.manifest.modified,
|
|
249
|
+
project: {
|
|
250
|
+
name: this.manifest.name,
|
|
251
|
+
description: this.manifest.description,
|
|
252
|
+
version: this.manifest.version
|
|
253
|
+
},
|
|
254
|
+
documentation: ".dr/README.md",
|
|
255
|
+
layers: this.manifest.layers || {}
|
|
256
|
+
};
|
|
257
|
+
if (!this.manifest.layers || Object.keys(this.manifest.layers).length === 0) {
|
|
258
|
+
const layerOrder = [
|
|
259
|
+
"motivation",
|
|
260
|
+
"business",
|
|
261
|
+
"security",
|
|
262
|
+
"application",
|
|
263
|
+
"technology",
|
|
264
|
+
"api",
|
|
265
|
+
"data-model",
|
|
266
|
+
"datastore",
|
|
267
|
+
"ux",
|
|
268
|
+
"navigation",
|
|
269
|
+
"apm",
|
|
270
|
+
"testing"
|
|
271
|
+
];
|
|
272
|
+
for (let i = 0; i < layerOrder.length; i++) {
|
|
273
|
+
const layerName = layerOrder[i], layer = this.layers.get(layerName), orderNum = String(i + 1).padStart(2, "0");
|
|
274
|
+
yamlData.layers[layerName] = {
|
|
275
|
+
order: i + 1,
|
|
276
|
+
name: layerName.charAt(0).toUpperCase() + layerName.slice(1).replace("-", " "),
|
|
277
|
+
path: `documentation-robotics/model/${orderNum}_${layerName}/`,
|
|
278
|
+
schema: `.dr/schemas/${orderNum}-${layerName}-layer.schema.json`,
|
|
279
|
+
enabled: !0,
|
|
280
|
+
...layer && { elements: this.getLayerElementCounts(layer) }
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
} else
|
|
284
|
+
for (const [layerName, layerConfig] of Object.entries(yamlData.layers)) {
|
|
285
|
+
const layer = this.layers.get(layerName);
|
|
286
|
+
layer && (layerConfig.elements = this.getLayerElementCounts(layer));
|
|
287
|
+
}
|
|
288
|
+
if (this.manifest.statistics) {
|
|
289
|
+
const stats = { ...this.manifest.statistics };
|
|
290
|
+
stats.total_elements = Array.from(this.layers.values()).reduce((sum, layer) => sum + layer.elements.size, 0), yamlData.statistics = stats;
|
|
291
|
+
}
|
|
292
|
+
this.manifest.cross_references && (yamlData.cross_references = this.manifest.cross_references), this.manifest.conventions && (yamlData.conventions = this.manifest.conventions), this.manifest.upgrade_history && (yamlData.upgrade_history = this.manifest.upgrade_history), this.manifest.changeset_history && this.manifest.changeset_history.length > 0 && (yamlData.changeset_history = this.manifest.changeset_history), await ensureDir(`${this.rootPath}/documentation-robotics/model`), await writeFile(manifestPath, yaml.stringify(yamlData));
|
|
293
|
+
}
|
|
294
|
+
getLayerElementCounts(layer) {
|
|
295
|
+
const counts = {};
|
|
296
|
+
for (const element of layer.elements.values())
|
|
297
|
+
counts[element.type] = (counts[element.type] || 0) + 1;
|
|
298
|
+
return counts;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Load relationships from relationships.yaml
|
|
302
|
+
*/
|
|
303
|
+
async loadRelationships() {
|
|
304
|
+
const fs2 = await import("fs/promises"), yaml = await import("yaml"), relationshipsPath = `${this.rootPath}/documentation-robotics/model/relationships.yaml`;
|
|
305
|
+
try {
|
|
306
|
+
const yamlContent = await fs2.readFile(relationshipsPath, "utf-8"), data = yaml.parse(yamlContent);
|
|
307
|
+
Array.isArray(data) && (this.relationships = Relationships.fromArray(data));
|
|
308
|
+
} catch (err) {
|
|
309
|
+
err.code !== "ENOENT" && process.env.DEBUG && console.debug(`Warning: Failed to load relationships.yaml: ${err}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Save relationships to relationships.yaml
|
|
314
|
+
*/
|
|
315
|
+
async saveRelationships() {
|
|
316
|
+
const fs2 = await import("fs/promises"), yaml = await import("yaml"), relationshipsPath = `${this.rootPath}/documentation-robotics/model/relationships.yaml`;
|
|
317
|
+
await ensureDir(`${this.rootPath}/documentation-robotics/model`);
|
|
318
|
+
const data = this.relationships.toArray(), yamlContent = `# Intra-layer relationships
|
|
319
|
+
# Format: source_id -> predicate -> target_id
|
|
320
|
+
# Last updated: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
321
|
+
|
|
322
|
+
` + yaml.stringify(data);
|
|
323
|
+
await fs2.writeFile(relationshipsPath, yamlContent, "utf-8"), this.relationships.markClean();
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Resolve model paths (private helper)
|
|
327
|
+
*
|
|
328
|
+
* @param startPath - Starting path for search
|
|
329
|
+
* @returns Project root and manifest path
|
|
330
|
+
*/
|
|
331
|
+
static async resolveModelPaths(startPath) {
|
|
332
|
+
const searchPath = startPath || process.cwd();
|
|
333
|
+
if (process.env.DR_MODEL_PATH) {
|
|
334
|
+
const envPath = path.resolve(process.env.DR_MODEL_PATH);
|
|
335
|
+
let manifestPath2;
|
|
336
|
+
envPath.endsWith("manifest.yaml") ? manifestPath2 = envPath : envPath.endsWith("model") ? manifestPath2 = path.join(envPath, "manifest.yaml") : manifestPath2 = path.join(envPath, "documentation-robotics", "model", "manifest.yaml");
|
|
337
|
+
try {
|
|
338
|
+
return await fs.access(manifestPath2), { projectRoot: path.dirname(path.dirname(path.dirname(manifestPath2))), manifestPath: path.normalize(manifestPath2) };
|
|
339
|
+
} catch {
|
|
340
|
+
throw new Error(`Model not found at DR_MODEL_PATH: ${process.env.DR_MODEL_PATH}`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
const projectRoot = await findProjectRoot(searchPath);
|
|
344
|
+
if (!projectRoot)
|
|
345
|
+
throw new Error(`No DR project found. Could not find documentation_robotics/ folder.
|
|
346
|
+
Run "dr init" to create a new project, or navigate to a directory containing a DR project.`);
|
|
347
|
+
const manifestPath = path.join(projectRoot, "documentation-robotics", "model", "manifest.yaml");
|
|
348
|
+
try {
|
|
349
|
+
return await fs.access(manifestPath), { projectRoot, manifestPath };
|
|
350
|
+
} catch {
|
|
351
|
+
throw new Error(`Found documentation_robotics/ at ${projectRoot} but no model found. Expected: ${manifestPath}
|
|
352
|
+
Run "dr init" to create a model.`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Load a model from disk
|
|
357
|
+
*
|
|
358
|
+
* Expected structure:
|
|
359
|
+
* <project-root>/
|
|
360
|
+
* └── documentation_robotics/
|
|
361
|
+
* └── model/
|
|
362
|
+
* └── manifest.yaml
|
|
363
|
+
*
|
|
364
|
+
* @param startPath - Starting path for project search (defaults to process.cwd())
|
|
365
|
+
* @param options - Model loading options
|
|
366
|
+
* @returns Loaded Model instance
|
|
367
|
+
*/
|
|
368
|
+
static async load(startPath, options = {}) {
|
|
369
|
+
const span = isTelemetryEnabled ? startSpan("model.load", {
|
|
370
|
+
"model.path": startPath || process.cwd(),
|
|
371
|
+
"model.type": "dr-legacy"
|
|
372
|
+
}) : null;
|
|
373
|
+
try {
|
|
374
|
+
const { projectRoot, manifestPath } = await Model.resolveModelPaths(startPath), yaml = await import("yaml"), yamlContent = await fs.readFile(manifestPath, "utf-8"), legacyData = yaml.parse(yamlContent), manifestData = {
|
|
375
|
+
name: legacyData.project?.name || "Unnamed Model",
|
|
376
|
+
description: legacyData.project?.description || "",
|
|
377
|
+
version: legacyData.project?.version || legacyData.version || "0.1.0",
|
|
378
|
+
specVersion: legacyData.spec_version || "0.6.0",
|
|
379
|
+
created: legacyData.created || (/* @__PURE__ */ new Date()).toISOString(),
|
|
380
|
+
modified: legacyData.updated || (/* @__PURE__ */ new Date()).toISOString(),
|
|
381
|
+
// Preserve Python CLI metadata fields
|
|
382
|
+
layers: legacyData.layers,
|
|
383
|
+
statistics: legacyData.statistics || {
|
|
384
|
+
total_elements: 0,
|
|
385
|
+
total_relationships: 0,
|
|
386
|
+
completeness: 0,
|
|
387
|
+
last_validation: null,
|
|
388
|
+
validation_status: "not_validated"
|
|
389
|
+
},
|
|
390
|
+
cross_references: legacyData.cross_references || {
|
|
391
|
+
total: 0,
|
|
392
|
+
by_type: {}
|
|
393
|
+
},
|
|
394
|
+
conventions: legacyData.conventions,
|
|
395
|
+
upgrade_history: legacyData.upgrade_history || []
|
|
396
|
+
}, manifest = new Manifest(manifestData), model = new Model(projectRoot, manifest, options);
|
|
397
|
+
if (!options.lazyLoad)
|
|
398
|
+
try {
|
|
399
|
+
if (legacyData.layers)
|
|
400
|
+
for (const layerName of Object.keys(legacyData.layers))
|
|
401
|
+
legacyData.layers[layerName].enabled !== !1 && await model.loadLayer(layerName);
|
|
402
|
+
else {
|
|
403
|
+
const modelDir = manifestPath.replace("/manifest.yaml", ""), entries = await fs.readdir(modelDir, { withFileTypes: !0 });
|
|
404
|
+
for (const entry of entries)
|
|
405
|
+
if (entry.isDirectory() && entry.name.match(/^\d{2}_/)) {
|
|
406
|
+
const layerName = entry.name.replace(/^\d{2}_/, "");
|
|
407
|
+
await model.loadLayer(layerName);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
} catch (e) {
|
|
411
|
+
if (process.env.DEBUG) {
|
|
412
|
+
const error = e instanceof Error ? e.message : String(e);
|
|
413
|
+
error.includes("ENOENT") || console.debug(`Warning: Failed to load layers directory: ${error}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
await model.loadRelationships();
|
|
417
|
+
let entityCount = 0;
|
|
418
|
+
for (const layer of model.layers.values())
|
|
419
|
+
entityCount += layer.elements.size;
|
|
420
|
+
return isTelemetryEnabled && span && (span.setAttribute("model.entity_count", entityCount), span.setAttribute("model.layer_count", model.layers.size)), model;
|
|
421
|
+
} finally {
|
|
422
|
+
isTelemetryEnabled && endSpan(span);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Initialize a new model in a directory (legacy format)
|
|
427
|
+
*/
|
|
428
|
+
static async init(rootPath, manifestData, options = {}) {
|
|
429
|
+
await ensureDir(`${rootPath}/documentation-robotics/model`);
|
|
430
|
+
const layerOrder = [
|
|
431
|
+
"motivation",
|
|
432
|
+
"business",
|
|
433
|
+
"security",
|
|
434
|
+
"application",
|
|
435
|
+
"technology",
|
|
436
|
+
"api",
|
|
437
|
+
"data-model",
|
|
438
|
+
"datastore",
|
|
439
|
+
"ux",
|
|
440
|
+
"navigation",
|
|
441
|
+
"apm",
|
|
442
|
+
"testing"
|
|
443
|
+
];
|
|
444
|
+
for (let i = 0; i < layerOrder.length; i++) {
|
|
445
|
+
const orderNum = String(i + 1).padStart(2, "0"), layerName = layerOrder[i];
|
|
446
|
+
await ensureDir(`${rootPath}/documentation-robotics/model/${orderNum}_${layerName}`);
|
|
447
|
+
}
|
|
448
|
+
const manifest = new Manifest(manifestData), model = new Model(rootPath, manifest, options);
|
|
449
|
+
return await model.saveManifest(), model;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
export {
|
|
453
|
+
Model
|
|
454
|
+
};
|
|
455
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/core/model.ts"],
|
|
4
|
+
"sourcesContent": ["import { Layer } from \"./layer.js\"\nimport { Manifest } from \"./manifest.js\"\nimport { Element } from \"./element.js\";\nimport { ProjectionEngine } from \"./projection-engine.js\";\nimport { Relationships } from \"./relationships.js\";\nimport { ActiveChangesetContext } from \"./active-changeset.js\";\nimport { ensureDir, writeFile } from \"../utils/file-io.js\";\nimport { startSpan, endSpan } from \"../telemetry/index.js\";\nimport { findProjectRoot } from \"../utils/project-paths.js\";\nimport type { ManifestData, ModelOptions } from \"../types/index.js\";\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\n\n// Fallback for runtime environments where TELEMETRY_ENABLED is not defined by esbuild\ndeclare const TELEMETRY_ENABLED: boolean | undefined\nconst isTelemetryEnabled = typeof TELEMETRY_ENABLED !== 'undefined' ? TELEMETRY_ENABLED : false\n\n/**\n * Model class representing the complete architecture model\n */\nexport class Model {\n rootPath: string\n manifest: Manifest\n layers: Map<string, Layer>\n relationships: Relationships\n lazyLoad: boolean\n private loadedLayers: Set<string>\n private projectionEngine?: ProjectionEngine\n private activeChangesetContext?: ActiveChangesetContext\n\n constructor(rootPath: string, manifest: Manifest, options: ModelOptions = {}) {\n this.rootPath = rootPath\n this.manifest = manifest\n this.layers = new Map()\n this.relationships = new Relationships()\n this.lazyLoad = options.lazyLoad ?? false\n this.loadedLayers = new Set()\n }\n\n /**\n * Get a layer, loading it if lazy loading is enabled\n */\n async getLayer(name: string): Promise<Layer | undefined> {\n if (this.lazyLoad && !this.loadedLayers.has(name)) {\n await this.loadLayer(name)\n }\n return this.layers.get(name)\n }\n\n /**\n * Get an element by ID across all layers\n */\n getElementById(id: string): Element | undefined {\n for (const layer of this.layers.values()) {\n const element = layer.elements.get(id);\n if (element) {\n return element;\n }\n }\n return undefined;\n }\n\n /**\n * Get projection engine (lazily initialized)\n */\n getProjectionEngine(): ProjectionEngine {\n if (!this.projectionEngine) {\n this.projectionEngine = new ProjectionEngine(this);\n }\n return this.projectionEngine;\n }\n\n /**\n * Get active changeset context (lazily initialized)\n */\n getActiveChangesetContext(): ActiveChangesetContext {\n if (!this.activeChangesetContext) {\n this.activeChangesetContext = new ActiveChangesetContext(this.rootPath);\n }\n return this.activeChangesetContext;\n }\n\n /**\n * Load a layer from disk (legacy format: model/XX_layername/*.yaml files)\n * Supports reading layer paths from manifest for Python CLI compatibility\n */\n async loadLayer(name: string): Promise<void> {\n const layerSpan = isTelemetryEnabled ? startSpan('layer.load', {\n 'layer.name': name,\n }) : null\n\n try {\n const fs = await import('fs/promises')\n const yaml = await import('yaml')\n\n let layerPath: string | null = null\n\n // PRIORITY 1: Read layer path from manifest (Python CLI compatibility)\n if (this.manifest.layers && this.manifest.layers[name]) {\n const layerConfig = this.manifest.layers[name]\n if (layerConfig.path) {\n // Path in manifest is relative to root\n const fullPath = `${this.rootPath}/${layerConfig.path.replace(/\\/$/, '')}`\n try {\n await fs.access(fullPath)\n layerPath = fullPath\n } catch (err) {\n // Path in manifest doesn't exist - this is an error\n if (process.env.DEBUG) {\n console.debug(`Manifest specifies path ${layerConfig.path} but it doesn't exist`)\n }\n }\n }\n }\n\n // FALLBACK: Auto-discover by scanning directory with naming convention\n if (!layerPath) {\n const modelDir = `${this.rootPath}/documentation-robotics/model`\n\n try {\n const entries = await fs.readdir(modelDir, { withFileTypes: true })\n const layerDir = entries.find(e =>\n e.isDirectory() && e.name.match(/^\\d{2}_/) && e.name.replace(/^\\d{2}_/, '') === name\n )\n\n if (layerDir) {\n layerPath = `${modelDir}/${layerDir.name}`\n }\n } catch {\n // Model directory doesn't exist or can't be read\n }\n }\n\n if (!layerPath) {\n return // Layer directory not found\n }\n\n const layer = new Layer(name)\n\n // Load all YAML files in the layer directory\n const files = await fs.readdir(layerPath)\n for (const file of files) {\n if (file.endsWith('.yaml') || file.endsWith('.yml')) {\n const filePath = `${layerPath}/${file}`\n const yamlContent = await fs.readFile(filePath, 'utf-8')\n const elements = yaml.parse(yamlContent)\n\n // Add each element from the YAML file\n if (elements && typeof elements === 'object') {\n for (const [key, element] of Object.entries(elements)) {\n if (element && typeof element === 'object') {\n const el: any = element\n\n // Auto-generate layer-prefixed ID if missing (Python CLI compatibility)\n // Python: element_id = f\"{self.name}.{key}\" when no id field\n const elementId = el.id || `${name}.${key}`\n\n // Infer type from filename if not specified (Python CLI compatibility)\n // Python: _infer_type_from_file removes trailing 's' from stem\n let elementType = el.type\n if (!elementType) {\n const stem = file.replace(/\\.ya?ml$/, '')\n elementType = stem.endsWith('s') ? stem.slice(0, -1) : stem\n }\n\n const newElement = new Element({\n id: elementId,\n name: el.name || key,\n type: elementType,\n description: el.description || el.documentation || '',\n properties: el.properties || {},\n relationships: el.relationships || [],\n references: el.references || [],\n layer: name, // Track layer (Python CLI compatibility)\n filePath: filePath, // Track source file (Python CLI compatibility)\n rawData: el // Preserve raw YAML data (Python CLI compatibility)\n });\n layer.addElement(newElement);\n }\n }\n }\n }\n }\n\n this.layers.set(name, layer)\n this.loadedLayers.add(name)\n\n if (isTelemetryEnabled && layerSpan) {\n layerSpan.setAttribute('layer.element_count', layer.elements.size)\n }\n } finally {\n if (isTelemetryEnabled) {\n endSpan(layerSpan)\n }\n }\n }\n\n /**\n * Add a layer to the model\n */\n addLayer(layer: Layer): void {\n this.layers.set(layer.name, layer)\n this.loadedLayers.add(layer.name)\n }\n\n /**\n * Get all loaded layer names\n */\n getLayerNames(): string[] {\n return Array.from(this.layers.keys())\n }\n\n /**\n * Save a layer to disk (legacy format: model/XX_layername/*.yaml)\n */\n async saveLayer(name: string): Promise<void> {\n const layer = this.layers.get(name)\n if (!layer) {\n throw new Error(`Layer ${name} not found`)\n }\n\n const fs = await import('fs/promises')\n const yaml = await import('yaml')\n\n let layerPath: string | null = null\n\n // Try to get layer path from manifest first (Python CLI compatibility)\n if (this.manifest.layers && this.manifest.layers[name]) {\n const layerConfig = this.manifest.layers[name]\n if (layerConfig.path) {\n const fullPath = `${this.rootPath}/${layerConfig.path.replace(/\\/$/, '')}`\n try {\n await fs.access(fullPath)\n layerPath = fullPath\n } catch {\n // Path doesn't exist, create it\n await ensureDir(fullPath)\n layerPath = fullPath\n }\n }\n }\n\n // If manifest path not found, try discovery by scanning directory\n if (!layerPath) {\n const modelDir = `${this.rootPath}/documentation-robotics/model`\n\n try {\n const entries = await fs.readdir(modelDir, { withFileTypes: true })\n const layerDir = entries.find(e =>\n e.isDirectory() && e.name.match(/^\\d{2}_/) &&\n e.name.replace(/^\\d{2}_/, '') === name\n )\n\n if (layerDir) {\n layerPath = `${modelDir}/${layerDir.name}`\n }\n } catch {\n // Model directory doesn't exist or can't be read\n }\n }\n\n // If still not found, create using default format\n if (!layerPath) {\n // Find the order number for this layer\n // Handle layer names with or without numeric prefix (e.g., \"motivation\" or \"01-motivation\")\n const layerNameWithoutPrefix = name.replace(/^\\d{2}-/, '')\n const layerOrder = [\n 'motivation', 'business', 'security', 'application', 'technology',\n 'api', 'data-model', 'datastore', 'ux', 'navigation', 'apm', 'testing'\n ]\n const index = layerOrder.indexOf(layerNameWithoutPrefix)\n if (index >= 0) {\n const orderNum = String(index + 1).padStart(2, '0')\n // Use Python CLI structure\n layerPath = `${this.rootPath}/documentation-robotics/model/${orderNum}_${layerNameWithoutPrefix}`\n await ensureDir(layerPath)\n } else {\n throw new Error(`Unknown layer ${name} and no path configured in manifest`)\n }\n }\n\n // Delete all existing YAML files in the layer directory to ensure\n // we don't keep stale files after element deletion\n try {\n const existingFiles = await fs.readdir(layerPath)\n for (const file of existingFiles) {\n if (file.endsWith('.yaml') || file.endsWith('.yml')) {\n await fs.unlink(`${layerPath}/${file}`)\n }\n }\n } catch (err) {\n // Directory might not exist yet, that's okay\n }\n\n // Group elements by type\n const elementsByType = new Map<string, any[]>()\n for (const element of layer.elements.values()) {\n const type = element.type + 's' // pluralize (e.g., goal -> goals)\n if (!elementsByType.has(type)) {\n elementsByType.set(type, [])\n }\n elementsByType.get(type)!.push(element)\n }\n\n // Write each type to its own YAML file\n for (const [type, elements] of elementsByType) {\n const filename = `${type}.yaml`\n const filePath = `${layerPath}/${filename}`\n\n // Convert elements to YAML format\n const yamlData: any = {}\n for (const element of elements) {\n const key = element.id.split('.').pop() || element.id\n yamlData[key] = {\n id: element.id,\n name: element.name,\n type: element.type,\n ...(element.description && { documentation: element.description }),\n ...(Object.keys(element.properties || {}).length > 0 && { properties: element.properties }),\n ...(element.references && element.references.length > 0 && { references: element.references }),\n // Relationships are now stored in centralized relationships.yaml, not inline\n }\n }\n\n await writeFile(filePath, yaml.stringify(yamlData))\n }\n\n layer.markClean()\n }\n\n /**\n * Save model (saves all dirty layers and manifest)\n */\n async save(): Promise<void> {\n await this.saveDirtyLayers();\n await this.saveManifest();\n }\n\n /**\n * Save all dirty layers to disk\n */\n async saveDirtyLayers(): Promise<void> {\n // Count dirty layers before operation\n let dirtyLayerCount = 0\n for (const layer of this.layers.values()) {\n if (layer.isDirty()) {\n dirtyLayerCount++\n }\n }\n\n const span = isTelemetryEnabled ? startSpan('model.save', {\n 'model.path': this.rootPath,\n 'model.dirty_layer_count': dirtyLayerCount,\n }) : null\n\n try {\n for (const layer of this.layers.values()) {\n if (layer.isDirty()) {\n await this.saveLayer(layer.name)\n }\n }\n } finally {\n if (isTelemetryEnabled) {\n endSpan(span)\n }\n }\n }\n\n /**\n * Save the manifest to disk (Python CLI format: documentation-robotics/model/manifest.yaml)\n * Preserves Python CLI metadata fields for compatibility\n */\n async saveManifest(): Promise<void> {\n this.manifest.updateModified()\n const yaml = await import('yaml')\n const manifestPath = `${this.rootPath}/documentation-robotics/model/manifest.yaml`\n\n // Convert to legacy YAML format, preserving Python CLI fields\n const yamlData: any = {\n version: this.manifest.version,\n schema: 'documentation-robotics-v1',\n cli_version: this.manifest.version || '0.1.0',\n spec_version: this.manifest.specVersion,\n created: this.manifest.created,\n updated: this.manifest.modified,\n project: {\n name: this.manifest.name,\n description: this.manifest.description,\n version: this.manifest.version,\n },\n documentation: '.dr/README.md',\n layers: this.manifest.layers || {} as any,\n }\n\n // If layers not preserved from load, generate default structure\n if (!this.manifest.layers || Object.keys(this.manifest.layers).length === 0) {\n const layerOrder = [\n 'motivation', 'business', 'security', 'application', 'technology',\n 'api', 'data-model', 'datastore', 'ux', 'navigation', 'apm', 'testing'\n ]\n\n for (let i = 0; i < layerOrder.length; i++) {\n const layerName = layerOrder[i]\n const layer = this.layers.get(layerName)\n const orderNum = String(i + 1).padStart(2, '0')\n\n yamlData.layers[layerName] = {\n order: i + 1,\n name: layerName.charAt(0).toUpperCase() + layerName.slice(1).replace('-', ' '),\n path: `documentation-robotics/model/${orderNum}_${layerName}/`,\n schema: `.dr/schemas/${orderNum}-${layerName}-layer.schema.json`,\n enabled: true,\n ...(layer && { elements: this.getLayerElementCounts(layer) }),\n }\n }\n } else {\n // Update element counts in existing layer configs\n for (const [layerName, layerConfig] of Object.entries(yamlData.layers)) {\n const layer = this.layers.get(layerName)\n if (layer) {\n (layerConfig as any).elements = this.getLayerElementCounts(layer)\n }\n }\n }\n\n // Preserve Python CLI metadata fields\n if (this.manifest.statistics) {\n // Update statistics with current counts\n const stats = { ...this.manifest.statistics }\n stats.total_elements = Array.from(this.layers.values())\n .reduce((sum, layer) => sum + layer.elements.size, 0)\n yamlData.statistics = stats\n }\n\n if (this.manifest.cross_references) {\n yamlData.cross_references = this.manifest.cross_references\n }\n\n if (this.manifest.conventions) {\n yamlData.conventions = this.manifest.conventions\n }\n\n if (this.manifest.upgrade_history) {\n yamlData.upgrade_history = this.manifest.upgrade_history\n }\n\n if (this.manifest.changeset_history && this.manifest.changeset_history.length > 0) {\n yamlData.changeset_history = this.manifest.changeset_history\n }\n\n await ensureDir(`${this.rootPath}/documentation-robotics/model`)\n await writeFile(manifestPath, yaml.stringify(yamlData))\n }\n\n private getLayerElementCounts(layer: Layer): Record<string, number> {\n const counts: Record<string, number> = {}\n for (const element of layer.elements.values()) {\n counts[element.type] = (counts[element.type] || 0) + 1\n }\n return counts\n }\n\n /**\n * Load relationships from relationships.yaml\n */\n async loadRelationships(): Promise<void> {\n const fs = await import('fs/promises')\n const yaml = await import('yaml')\n const relationshipsPath = `${this.rootPath}/documentation-robotics/model/relationships.yaml`\n\n try {\n const yamlContent = await fs.readFile(relationshipsPath, 'utf-8')\n const data = yaml.parse(yamlContent)\n\n if (Array.isArray(data)) {\n this.relationships = Relationships.fromArray(data)\n }\n } catch (err) {\n // If file doesn't exist, that's okay - start with empty relationships\n if ((err as any).code !== 'ENOENT') {\n // But if it's a different error, we should know about it\n if (process.env.DEBUG) {\n console.debug(`Warning: Failed to load relationships.yaml: ${err}`)\n }\n }\n }\n }\n\n /**\n * Save relationships to relationships.yaml\n */\n async saveRelationships(): Promise<void> {\n const fs = await import('fs/promises')\n const yaml = await import('yaml')\n const relationshipsPath = `${this.rootPath}/documentation-robotics/model/relationships.yaml`\n\n await ensureDir(`${this.rootPath}/documentation-robotics/model`)\n\n const data = this.relationships.toArray()\n\n // Add header comment with timestamp to ensure file always changes\n // This matches Python CLI behavior\n const timestamp = new Date().toISOString()\n const header = `# Intra-layer relationships\n# Format: source_id -> predicate -> target_id\n# Last updated: ${timestamp}\n\n`\n const yamlContent = header + yaml.stringify(data)\n\n await fs.writeFile(relationshipsPath, yamlContent, 'utf-8')\n this.relationships.markClean()\n }\n\n /**\n * Resolve model paths (private helper)\n *\n * @param startPath - Starting path for search\n * @returns Project root and manifest path\n */\n private static async resolveModelPaths(startPath?: string): Promise<{\n projectRoot: string;\n manifestPath: string;\n }> {\n const searchPath = startPath || process.cwd();\n\n // Optional override via env var (highest priority)\n if (process.env.DR_MODEL_PATH) {\n const envPath = path.resolve(process.env.DR_MODEL_PATH);\n let manifestPath: string;\n\n if (envPath.endsWith('manifest.yaml')) {\n manifestPath = envPath;\n } else if (envPath.endsWith('model')) {\n manifestPath = path.join(envPath, 'manifest.yaml');\n } else {\n manifestPath = path.join(envPath, 'documentation-robotics', 'model', 'manifest.yaml');\n }\n\n try {\n await fs.access(manifestPath);\n const projectRoot = path.dirname(path.dirname(path.dirname(manifestPath)));\n return { projectRoot, manifestPath: path.normalize(manifestPath) };\n } catch {\n throw new Error(`Model not found at DR_MODEL_PATH: ${process.env.DR_MODEL_PATH}`);\n }\n }\n\n // Use findProjectRoot to locate documentation_robotics/ folder\n const projectRoot = await findProjectRoot(searchPath);\n\n if (!projectRoot) {\n throw new Error(\n 'No DR project found. Could not find documentation_robotics/ folder.\\n' +\n 'Run \"dr init\" to create a new project, or navigate to a directory containing a DR project.'\n );\n }\n\n const manifestPath = path.join(projectRoot, 'documentation-robotics', 'model', 'manifest.yaml');\n\n try {\n await fs.access(manifestPath);\n return { projectRoot, manifestPath };\n } catch {\n throw new Error(\n `Found documentation_robotics/ at ${projectRoot} but no model found. ` +\n `Expected: ${manifestPath}\\n` +\n `Run \"dr init\" to create a model.`\n );\n }\n }\n\n /**\n * Load a model from disk\n *\n * Expected structure:\n * <project-root>/\n * \u2514\u2500\u2500 documentation_robotics/\n * \u2514\u2500\u2500 model/\n * \u2514\u2500\u2500 manifest.yaml\n *\n * @param startPath - Starting path for project search (defaults to process.cwd())\n * @param options - Model loading options\n * @returns Loaded Model instance\n */\n static async load(startPath?: string, options: ModelOptions = {}): Promise<Model> {\n const span = isTelemetryEnabled ? startSpan('model.load', {\n 'model.path': startPath || process.cwd(),\n 'model.type': 'dr-legacy',\n }) : null\n\n try {\n // Resolve project root and manifest path\n const { projectRoot, manifestPath } = await Model.resolveModelPaths(startPath);\n\n const yaml = await import('yaml')\n\n // Load manifest from resolved path\n const yamlContent = await fs.readFile(manifestPath, 'utf-8')\n const legacyData = yaml.parse(yamlContent)\n\n // Convert legacy format to internal format\n const manifestData: any = {\n name: legacyData.project?.name || 'Unnamed Model',\n description: legacyData.project?.description || '',\n version: legacyData.project?.version || legacyData.version || '0.1.0',\n specVersion: legacyData.spec_version || '0.6.0',\n created: legacyData.created || new Date().toISOString(),\n modified: legacyData.updated || new Date().toISOString(),\n // Preserve Python CLI metadata fields\n layers: legacyData.layers,\n statistics: legacyData.statistics || {\n total_elements: 0,\n total_relationships: 0,\n completeness: 0.0,\n last_validation: null,\n validation_status: 'not_validated'\n },\n cross_references: legacyData.cross_references || {\n total: 0,\n by_type: {}\n },\n conventions: legacyData.conventions,\n upgrade_history: legacyData.upgrade_history || []\n }\n const manifest = new Manifest(manifestData)\n const model = new Model(projectRoot, manifest, options)\n\n // Load all available layers if lazyLoad is false\n if (!options.lazyLoad) {\n try {\n // If manifest has layer definitions, use those\n if (legacyData.layers) {\n for (const layerName of Object.keys(legacyData.layers)) {\n const layerConfig = legacyData.layers[layerName]\n if (layerConfig.enabled !== false) {\n await model.loadLayer(layerName)\n }\n }\n } else {\n // Otherwise scan for layer directories\n const modelDir = manifestPath.replace('/manifest.yaml', '')\n const entries = await fs.readdir(modelDir, { withFileTypes: true })\n\n for (const entry of entries) {\n if (entry.isDirectory() && entry.name.match(/^\\d{2}_/)) {\n const layerName = entry.name.replace(/^\\d{2}_/, '')\n await model.loadLayer(layerName)\n }\n }\n }\n } catch (e) {\n // If layers directory doesn't exist or can't be read, just continue\n if (process.env.DEBUG) {\n const error = e instanceof Error ? e.message : String(e)\n if (!error.includes('ENOENT')) {\n console.debug(`Warning: Failed to load layers directory: ${error}`)\n }\n }\n }\n }\n\n // Load relationships from relationships.yaml\n await model.loadRelationships()\n\n // Count total entities across all layers\n let entityCount = 0\n for (const layer of model.layers.values()) {\n entityCount += layer.elements.size\n }\n\n if (isTelemetryEnabled && span) {\n span.setAttribute('model.entity_count', entityCount)\n span.setAttribute('model.layer_count', model.layers.size)\n }\n\n return model\n } finally {\n if (isTelemetryEnabled) {\n endSpan(span)\n }\n }\n }\n\n /**\n * Initialize a new model in a directory (legacy format)\n */\n static async init(\n rootPath: string,\n manifestData: ManifestData,\n options: ModelOptions = {}\n ): Promise<Model> {\n // Create model directory using Python CLI structure: documentation-robotics/model/\n await ensureDir(`${rootPath}/documentation-robotics/model`);\n\n const layerOrder = [\n 'motivation', 'business', 'security', 'application', 'technology',\n 'api', 'data-model', 'datastore', 'ux', 'navigation', 'apm', 'testing'\n ];\n\n for (let i = 0; i < layerOrder.length; i++) {\n const orderNum = String(i + 1).padStart(2, '0');\n const layerName = layerOrder[i];\n await ensureDir(`${rootPath}/documentation-robotics/model/${orderNum}_${layerName}`);\n }\n\n const manifest = new Manifest(manifestData);\n const model = new Model(rootPath, manifest, options);\n\n await model.saveManifest();\n\n return model;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["fs", "manifestPath"]
|
|
7
|
+
}
|