@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,111 @@
|
|
|
1
|
+
import ansis from "ansis";
|
|
2
|
+
import { text, intro, outro } from "@clack/prompts";
|
|
3
|
+
import { Model } from "../core/model.js";
|
|
4
|
+
async function checkClaudeAvailable() {
|
|
5
|
+
try {
|
|
6
|
+
return Bun.spawnSync({
|
|
7
|
+
cmd: ["which", "claude"],
|
|
8
|
+
stdout: "pipe",
|
|
9
|
+
stderr: "pipe"
|
|
10
|
+
}).exitCode === 0;
|
|
11
|
+
} catch {
|
|
12
|
+
return !1;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
async function sendMessage(message, modelPath) {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const proc = Bun.spawn({
|
|
18
|
+
cmd: [
|
|
19
|
+
"claude",
|
|
20
|
+
"--agent",
|
|
21
|
+
"dr-architect",
|
|
22
|
+
"--print",
|
|
23
|
+
"--dangerously-skip-permissions",
|
|
24
|
+
"--verbose",
|
|
25
|
+
"--output-format",
|
|
26
|
+
"stream-json"
|
|
27
|
+
],
|
|
28
|
+
cwd: modelPath,
|
|
29
|
+
stdin: "pipe",
|
|
30
|
+
stdout: "pipe",
|
|
31
|
+
stderr: "pipe"
|
|
32
|
+
});
|
|
33
|
+
proc.stdin?.write(new TextEncoder().encode(message)), proc.stdin?.end();
|
|
34
|
+
let buffer = "";
|
|
35
|
+
const stdoutReader = proc.stdout.getReader(), decoder = new TextDecoder(), readLoop = async () => {
|
|
36
|
+
try {
|
|
37
|
+
for (; ; ) {
|
|
38
|
+
const { done, value } = await stdoutReader.read();
|
|
39
|
+
if (done)
|
|
40
|
+
break;
|
|
41
|
+
const chunk = decoder.decode(value, { stream: !0 });
|
|
42
|
+
buffer += chunk;
|
|
43
|
+
const lines = buffer.split(`
|
|
44
|
+
`);
|
|
45
|
+
buffer = lines.pop() || "";
|
|
46
|
+
for (const line of lines)
|
|
47
|
+
if (line.trim())
|
|
48
|
+
try {
|
|
49
|
+
const event = JSON.parse(line);
|
|
50
|
+
if (event.type === "assistant") {
|
|
51
|
+
const content = event.message?.content || [];
|
|
52
|
+
for (const block of content)
|
|
53
|
+
block.type === "text" ? process.stdout.write(block.text) : block.type === "tool_use" && process.stdout.write(ansis.dim(`
|
|
54
|
+
[Using tool: ${block.name}]
|
|
55
|
+
`));
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
process.stdout.write(line + `
|
|
59
|
+
`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
buffer.trim() && process.stdout.write(buffer);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
reject(error);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
proc.exited.then((exitCode) => {
|
|
68
|
+
readLoop().then(() => {
|
|
69
|
+
exitCode === 0 ? resolve() : reject(new Error(`Claude process exited with code ${exitCode}`));
|
|
70
|
+
}).catch(reject);
|
|
71
|
+
}).catch(reject);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async function chatCommand() {
|
|
75
|
+
try {
|
|
76
|
+
await checkClaudeAvailable() || (console.error(ansis.red("Error: Claude Code CLI not found.")), console.error(ansis.dim("Install Claude Code to enable chat functionality.")), console.error(ansis.dim("Visit: https://claude.ai")), process.exit(1));
|
|
77
|
+
const model = await Model.load(process.cwd());
|
|
78
|
+
for (model || (console.error(ansis.red("Error: Could not load architecture model")), process.exit(1)), intro(ansis.bold(ansis.cyan("Documentation Robotics Chat"))), console.log(ansis.dim(`Powered by Claude Code dr-architect agent
|
|
79
|
+
`)); ; ) {
|
|
80
|
+
let userInput;
|
|
81
|
+
try {
|
|
82
|
+
userInput = await text({
|
|
83
|
+
message: ansis.cyan("You:"),
|
|
84
|
+
placeholder: 'Ask about the architecture (or "exit" to quit)'
|
|
85
|
+
});
|
|
86
|
+
} catch {
|
|
87
|
+
console.log(""), outro(ansis.green("Goodbye!"));
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
if (userInput.toLowerCase() === "exit" || userInput.toLowerCase() === "quit" || userInput.toLowerCase() === "q") {
|
|
91
|
+
console.log(""), outro(ansis.green("Goodbye!"));
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
if (userInput.trim())
|
|
95
|
+
try {
|
|
96
|
+
process.stdout.write(ansis.cyan("Claude: ")), await sendMessage(userInput, model.rootPath), console.log(`
|
|
97
|
+
`);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
100
|
+
console.error(ansis.red(`Error: ${message}`));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
} catch (error) {
|
|
104
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
105
|
+
console.error(ansis.red(`Error: ${message}`)), process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
chatCommand
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=chat.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/commands/chat.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Chat Command - Interactive chat with Claude about the architecture model\n * Uses Claude Code CLI subprocess with dr-architect agent\n */\n\nimport ansis from 'ansis';\nimport { text, intro, outro } from '@clack/prompts';\nimport { Model } from '../core/model.js';\n\n/**\n * Check if Claude Code CLI is available\n */\nasync function checkClaudeAvailable(): Promise<boolean> {\n try {\n const result = Bun.spawnSync({\n cmd: ['which', 'claude'],\n stdout: 'pipe',\n stderr: 'pipe',\n });\n return result.exitCode === 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Send a message to Claude Code CLI and stream response using dr-architect agent\n */\nasync function sendMessage(\n message: string,\n modelPath: string\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const proc = Bun.spawn({\n cmd: [\n 'claude',\n '--agent', 'dr-architect',\n '--print',\n '--dangerously-skip-permissions',\n '--verbose',\n '--output-format', 'stream-json',\n ],\n cwd: modelPath,\n stdin: 'pipe',\n stdout: 'pipe',\n stderr: 'pipe',\n });\n\n // Send message via stdin\n proc.stdin?.write(new TextEncoder().encode(message));\n proc.stdin?.end();\n\n // Stream stdout\n let buffer = '';\n const stdoutReader = proc.stdout.getReader();\n const decoder = new TextDecoder();\n\n const readLoop = async () => {\n try {\n while (true) {\n const { done, value } = await stdoutReader.read();\n if (done) break;\n\n const chunk = decoder.decode(value, { stream: true });\n buffer += chunk;\n\n // Process complete lines\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (!line.trim()) continue;\n\n try {\n const event = JSON.parse(line);\n\n if (event.type === 'assistant') {\n const content = event.message?.content || [];\n for (const block of content) {\n if (block.type === 'text') {\n process.stdout.write(block.text);\n } else if (block.type === 'tool_use') {\n process.stdout.write(ansis.dim(`\\n[Using tool: ${block.name}]\\n`));\n }\n }\n }\n } catch {\n // Non-JSON line, print as-is\n process.stdout.write(line + '\\n');\n }\n }\n }\n\n // Print any remaining buffer\n if (buffer.trim()) {\n process.stdout.write(buffer);\n }\n } catch (error) {\n reject(error);\n }\n };\n\n // Handle process completion\n proc.exited.then((exitCode) => {\n readLoop().then(() => {\n if (exitCode === 0) {\n resolve();\n } else {\n reject(new Error(`Claude process exited with code ${exitCode}`));\n }\n }).catch(reject);\n }).catch(reject);\n });\n}\n\n/**\n * Chat command implementation\n * Launches an interactive conversation with Claude Code CLI\n */\nexport async function chatCommand(): Promise<void> {\n try {\n // Check if Claude Code CLI is available\n const claudeAvailable = await checkClaudeAvailable();\n if (!claudeAvailable) {\n console.error(ansis.red('Error: Claude Code CLI not found.'));\n console.error(ansis.dim('Install Claude Code to enable chat functionality.'));\n console.error(ansis.dim('Visit: https://claude.ai'));\n process.exit(1);\n }\n\n // Load the model to verify it exists\n const model = await Model.load(process.cwd());\n if (!model) {\n console.error(ansis.red('Error: Could not load architecture model'));\n process.exit(1);\n }\n\n // Show intro\n intro(ansis.bold(ansis.cyan('Documentation Robotics Chat')));\n console.log(ansis.dim('Powered by Claude Code dr-architect agent\\n'));\n\n // Start conversation loop\n while (true) {\n // Get user input\n let userInput: string;\n try {\n userInput = (await text({\n message: ansis.cyan('You:'),\n placeholder: 'Ask about the architecture (or \"exit\" to quit)',\n })) as string;\n } catch (e) {\n // Handle Ctrl+C or other input errors gracefully\n console.log('');\n outro(ansis.green('Goodbye!'));\n break;\n }\n\n // Check for exit\n if (\n userInput.toLowerCase() === 'exit' ||\n userInput.toLowerCase() === 'quit' ||\n userInput.toLowerCase() === 'q'\n ) {\n console.log('');\n outro(ansis.green('Goodbye!'));\n break;\n }\n\n if (!userInput.trim()) {\n continue;\n }\n\n try {\n // Stream the response\n process.stdout.write(ansis.cyan('Claude: '));\n await sendMessage(userInput, model.rootPath);\n console.log('\\n');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\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"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import ansis from "ansis";
|
|
2
|
+
import { Model } from "../core/model.js";
|
|
3
|
+
const LAYER_ELEMENT_TYPES = {
|
|
4
|
+
motivation: ["stakeholder", "goal", "requirement", "principle"],
|
|
5
|
+
business: ["business-service", "business-process", "business-actor"],
|
|
6
|
+
security: ["authentication-mechanism", "authorization-policy", "threat", "security-control"],
|
|
7
|
+
application: ["application-service", "application-component", "application-interface"],
|
|
8
|
+
technology: ["technology-service", "technology-component", "infrastructure-service"],
|
|
9
|
+
api: ["rest-resource", "rest-operation", "api-specification"],
|
|
10
|
+
"data-model": ["entity", "value-object", "relationship", "attribute"],
|
|
11
|
+
"data-store": ["database", "table", "storage-service"],
|
|
12
|
+
ux: ["ux-application", "ux-library", "ux-spec", "screen", "component"],
|
|
13
|
+
navigation: ["navigation-path", "navigation-transition", "route"],
|
|
14
|
+
apm: ["metric", "trace", "log-source", "alert-rule"],
|
|
15
|
+
testing: ["test-strategy", "test-case", "test-data", "test-result"]
|
|
16
|
+
}, LAYER_RELATIONSHIPS = {
|
|
17
|
+
business: [
|
|
18
|
+
{ target: "motivation", relationship: "realizes" }
|
|
19
|
+
],
|
|
20
|
+
application: [
|
|
21
|
+
{ target: "business", relationship: "realizes" },
|
|
22
|
+
{ target: "security", relationship: "uses" }
|
|
23
|
+
],
|
|
24
|
+
technology: [
|
|
25
|
+
{ target: "application", relationship: "hosts" },
|
|
26
|
+
{ target: "security", relationship: "implements" }
|
|
27
|
+
],
|
|
28
|
+
api: [
|
|
29
|
+
{ target: "application", relationship: "exposes" }
|
|
30
|
+
],
|
|
31
|
+
"data-model": [
|
|
32
|
+
{ target: "application", relationship: "used-by" }
|
|
33
|
+
],
|
|
34
|
+
"data-store": [
|
|
35
|
+
{ target: "technology", relationship: "runs-on" },
|
|
36
|
+
{ target: "data-model", relationship: "implements" }
|
|
37
|
+
],
|
|
38
|
+
ux: [
|
|
39
|
+
{ target: "application", relationship: "implements" },
|
|
40
|
+
{ target: "navigation", relationship: "uses" }
|
|
41
|
+
],
|
|
42
|
+
navigation: [
|
|
43
|
+
{ target: "ux", relationship: "defines" }
|
|
44
|
+
],
|
|
45
|
+
apm: [
|
|
46
|
+
{ target: "technology", relationship: "monitors" },
|
|
47
|
+
{ target: "application", relationship: "monitors" }
|
|
48
|
+
],
|
|
49
|
+
testing: [
|
|
50
|
+
{ target: "application", relationship: "tests" },
|
|
51
|
+
{ target: "api", relationship: "tests" }
|
|
52
|
+
]
|
|
53
|
+
};
|
|
54
|
+
async function conformanceCommand(options) {
|
|
55
|
+
try {
|
|
56
|
+
const model = await Model.load(process.cwd(), { lazyLoad: !1 });
|
|
57
|
+
options.json || console.log(ansis.bold(`
|
|
58
|
+
Checking conformance to layer specifications...
|
|
59
|
+
`));
|
|
60
|
+
const results = {};
|
|
61
|
+
let totalIssues = 0, compliantLayers = 0;
|
|
62
|
+
for (const [layerName, layer] of model.layers) {
|
|
63
|
+
if (options.layers && !options.layers.includes(layerName))
|
|
64
|
+
continue;
|
|
65
|
+
const issues = [], elements = layer.listElements(), expectedTypes = LAYER_ELEMENT_TYPES[layerName] || [], presentTypes = new Set(elements.map((e) => e.type)), missingTypes = [];
|
|
66
|
+
for (const expectedType of expectedTypes)
|
|
67
|
+
presentTypes.has(expectedType) || missingTypes.push(expectedType);
|
|
68
|
+
missingTypes.length > 0 && issues.push({
|
|
69
|
+
severity: "warning",
|
|
70
|
+
message: `Missing element types: ${missingTypes.join(", ")}`
|
|
71
|
+
});
|
|
72
|
+
for (const element of elements)
|
|
73
|
+
element.id || issues.push({
|
|
74
|
+
severity: "error",
|
|
75
|
+
message: "Element missing required property: id"
|
|
76
|
+
}), element.type || issues.push({
|
|
77
|
+
severity: "error",
|
|
78
|
+
message: "Element missing required property: type"
|
|
79
|
+
}), !element.properties.name && !element.properties.description && issues.push({
|
|
80
|
+
severity: "warning",
|
|
81
|
+
message: `Element ${element.id} should have a name or description`
|
|
82
|
+
});
|
|
83
|
+
const expectedRelationships = LAYER_RELATIONSHIPS[layerName] || [];
|
|
84
|
+
for (const expectedRel of expectedRelationships)
|
|
85
|
+
issues.push({
|
|
86
|
+
severity: "warning",
|
|
87
|
+
message: `Expected relationship to ${expectedRel.target}: ${expectedRel.relationship}`
|
|
88
|
+
});
|
|
89
|
+
results[layerName] = {
|
|
90
|
+
compliant: issues.filter((i) => i.severity === "error").length === 0,
|
|
91
|
+
issues,
|
|
92
|
+
stats: {
|
|
93
|
+
elementCount: elements.length,
|
|
94
|
+
elementTypes: presentTypes.size,
|
|
95
|
+
relationshipCount: 0
|
|
96
|
+
// Would be populated from relationship registry
|
|
97
|
+
}
|
|
98
|
+
}, results[layerName].compliant && compliantLayers++, totalIssues += issues.length;
|
|
99
|
+
}
|
|
100
|
+
if (options.json) {
|
|
101
|
+
const jsonOutput = {
|
|
102
|
+
conformance: {
|
|
103
|
+
compliant: compliantLayers === Object.keys(results).length,
|
|
104
|
+
compliantLayers,
|
|
105
|
+
totalLayers: Object.keys(results).length,
|
|
106
|
+
totalIssues,
|
|
107
|
+
layers: results
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
console.log(JSON.stringify(jsonOutput, null, 2));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
console.log(ansis.dim("Layer conformance:")), console.log();
|
|
114
|
+
for (const [layerName, result] of Object.entries(results)) {
|
|
115
|
+
if (result.compliant)
|
|
116
|
+
console.log(ansis.green(`\u2713 ${layerName}`));
|
|
117
|
+
else if (console.log(ansis.red(`\u2717 ${layerName} - ${result.issues.length} issue(s)`)), options.verbose)
|
|
118
|
+
for (const issue of result.issues) {
|
|
119
|
+
const prefix = issue.severity === "error" ? ansis.red("[ERROR]") : ansis.yellow("[WARNING]");
|
|
120
|
+
console.log(ansis.dim(` ${prefix} ${issue.message}`));
|
|
121
|
+
}
|
|
122
|
+
console.log(ansis.dim(` Elements: ${result.stats.elementCount}, Types: ${result.stats.elementTypes}`)), console.log();
|
|
123
|
+
}
|
|
124
|
+
console.log(ansis.dim("Summary:")), console.log(ansis.dim(` Compliant layers: ${compliantLayers}/${Object.keys(results).length}`)), console.log(ansis.dim(` Total issues: ${totalIssues}`)), console.log(), console.log(totalIssues === 0 ? ansis.green("\u2713 Model is fully conformant") : ansis.yellow("\u26A0 Model has conformance issues. Run 'dr validate' for more details.")), console.log();
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error(ansis.red(`Error: ${error instanceof Error ? error.message : String(error)}`)), process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
export {
|
|
130
|
+
conformanceCommand
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=conformance.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/commands/conformance.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Conformance Command - Validates model against layer specifications\n */\n\nimport ansis from 'ansis';\nimport { Model } from '../core/model.js';\n\n/**\n * Expected element types per layer\n */\nconst LAYER_ELEMENT_TYPES: Record<string, string[]> = {\n 'motivation': ['stakeholder', 'goal', 'requirement', 'principle'],\n 'business': ['business-service', 'business-process', 'business-actor'],\n 'security': ['authentication-mechanism', 'authorization-policy', 'threat', 'security-control'],\n 'application': ['application-service', 'application-component', 'application-interface'],\n 'technology': ['technology-service', 'technology-component', 'infrastructure-service'],\n 'api': ['rest-resource', 'rest-operation', 'api-specification'],\n 'data-model': ['entity', 'value-object', 'relationship', 'attribute'],\n 'data-store': ['database', 'table', 'storage-service'],\n 'ux': ['ux-application', 'ux-library', 'ux-spec', 'screen', 'component'],\n 'navigation': ['navigation-path', 'navigation-transition', 'route'],\n 'apm': ['metric', 'trace', 'log-source', 'alert-rule'],\n 'testing': ['test-strategy', 'test-case', 'test-data', 'test-result'],\n};\n\n/**\n * Expected cross-layer relationships per layer\n */\nconst LAYER_RELATIONSHIPS: Record<string, Array<{\n target: string;\n relationship: string;\n}>> = {\n 'business': [\n { target: 'motivation', relationship: 'realizes' },\n ],\n 'application': [\n { target: 'business', relationship: 'realizes' },\n { target: 'security', relationship: 'uses' },\n ],\n 'technology': [\n { target: 'application', relationship: 'hosts' },\n { target: 'security', relationship: 'implements' },\n ],\n 'api': [\n { target: 'application', relationship: 'exposes' },\n ],\n 'data-model': [\n { target: 'application', relationship: 'used-by' },\n ],\n 'data-store': [\n { target: 'technology', relationship: 'runs-on' },\n { target: 'data-model', relationship: 'implements' },\n ],\n 'ux': [\n { target: 'application', relationship: 'implements' },\n { target: 'navigation', relationship: 'uses' },\n ],\n 'navigation': [\n { target: 'ux', relationship: 'defines' },\n ],\n 'apm': [\n { target: 'technology', relationship: 'monitors' },\n { target: 'application', relationship: 'monitors' },\n ],\n 'testing': [\n { target: 'application', relationship: 'tests' },\n { target: 'api', relationship: 'tests' },\n ],\n};\n\ninterface ConformanceIssue {\n severity: 'error' | 'warning';\n message: string;\n}\n\ninterface ConformanceResult {\n compliant: boolean;\n issues: ConformanceIssue[];\n stats: {\n elementCount: number;\n elementTypes: number;\n relationshipCount: number;\n };\n}\n\nexport async function conformanceCommand(options: {\n layers?: string[];\n json?: boolean;\n verbose?: boolean;\n}): Promise<void> {\n try {\n const model = await Model.load(process.cwd(), { lazyLoad: false });\n\n if (!options.json) {\n console.log(ansis.bold('\\nChecking conformance to layer specifications...\\n'));\n }\n\n const results: Record<string, ConformanceResult> = {};\n\n let totalIssues = 0;\n let compliantLayers = 0;\n\n for (const [layerName, layer] of model.layers) {\n // Skip if specific layers requested\n if (options.layers && !options.layers.includes(layerName)) {\n continue;\n }\n\n const issues: ConformanceIssue[] = [];\n const elements = layer.listElements();\n\n // Check 1: Required element types\n const expectedTypes = LAYER_ELEMENT_TYPES[layerName] || [];\n const presentTypes = new Set(elements.map((e) => e.type));\n const missingTypes: string[] = [];\n\n for (const expectedType of expectedTypes) {\n if (!presentTypes.has(expectedType)) {\n missingTypes.push(expectedType);\n }\n }\n\n if (missingTypes.length > 0) {\n issues.push({\n severity: 'warning',\n message: `Missing element types: ${missingTypes.join(', ')}`,\n });\n }\n\n // Check 2: Elements have required properties\n for (const element of elements) {\n // Require id and type\n if (!element.id) {\n issues.push({\n severity: 'error',\n message: `Element missing required property: id`,\n });\n }\n\n if (!element.type) {\n issues.push({\n severity: 'error',\n message: `Element missing required property: type`,\n });\n }\n\n // Check for name field (recommended in v0.4.0+)\n if (!element.properties.name && !element.properties.description) {\n issues.push({\n severity: 'warning',\n message: `Element ${element.id} should have a name or description`,\n });\n }\n }\n\n // Check 3: Cross-layer relationships are documented\n const expectedRelationships = LAYER_RELATIONSHIPS[layerName] || [];\n\n // Validate expected cross-layer relationships exist\n // Note: The relationship registry would be accessed in production\n // This check documents which relationships are expected per layer specification\n for (const expectedRel of expectedRelationships) {\n // In a full implementation, check model.relationshipRegistry for actual relationships\n // For now, just document that the layer has expected cross-layer relationships defined\n issues.push({\n severity: 'warning',\n message: `Expected relationship to ${expectedRel.target}: ${expectedRel.relationship}`,\n });\n }\n\n // Populate results\n results[layerName] = {\n compliant: issues.filter((i) => i.severity === 'error').length === 0,\n issues,\n stats: {\n elementCount: elements.length,\n elementTypes: presentTypes.size,\n relationshipCount: 0, // Would be populated from relationship registry\n },\n };\n\n if (results[layerName].compliant) {\n compliantLayers++;\n }\n\n totalIssues += issues.length;\n }\n\n // Output as JSON if requested\n if (options.json) {\n const jsonOutput = {\n conformance: {\n compliant: compliantLayers === Object.keys(results).length,\n compliantLayers,\n totalLayers: Object.keys(results).length,\n totalIssues,\n layers: results,\n },\n };\n console.log(JSON.stringify(jsonOutput, null, 2));\n return;\n }\n\n // Display results\n console.log(ansis.dim('Layer conformance:'));\n console.log();\n\n for (const [layerName, result] of Object.entries(results)) {\n if (result.compliant) {\n console.log(ansis.green(`\u2713 ${layerName}`));\n } else {\n console.log(ansis.red(`\u2717 ${layerName} - ${result.issues.length} issue(s)`));\n\n if (options.verbose) {\n for (const issue of result.issues) {\n const prefix =\n issue.severity === 'error'\n ? ansis.red('[ERROR]')\n : ansis.yellow('[WARNING]');\n console.log(ansis.dim(` ${prefix} ${issue.message}`));\n }\n }\n }\n\n console.log(\n ansis.dim(\n ` Elements: ${result.stats.elementCount}, Types: ${result.stats.elementTypes}`\n )\n );\n console.log();\n }\n\n // Summary\n console.log(ansis.dim('Summary:'));\n console.log(\n ansis.dim(` Compliant layers: ${compliantLayers}/${Object.keys(results).length}`)\n );\n console.log(ansis.dim(` Total issues: ${totalIssues}`));\n console.log();\n\n if (totalIssues === 0) {\n console.log(ansis.green(`\u2713 Model is fully conformant`));\n } else {\n console.log(\n ansis.yellow(\n `\u26A0 Model has conformance issues. Run 'dr validate' for more details.`\n )\n );\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": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { confirm } from "@clack/prompts";
|
|
2
|
+
import ansis from "ansis";
|
|
3
|
+
import { Model } from "../core/model.js";
|
|
4
|
+
import { findElementLayer } from "../utils/element-utils.js";
|
|
5
|
+
import { startSpan, endSpan } from "../telemetry/index.js";
|
|
6
|
+
const isTelemetryEnabled = !1;
|
|
7
|
+
async function deleteCommand(id, options) {
|
|
8
|
+
const span = isTelemetryEnabled ? startSpan("element.delete", {
|
|
9
|
+
"element.id": id,
|
|
10
|
+
"element.force": !!options.force
|
|
11
|
+
}) : null;
|
|
12
|
+
try {
|
|
13
|
+
const model = await Model.load(), layerName = await findElementLayer(model, id);
|
|
14
|
+
layerName || (console.error(ansis.red(`Error: Element ${id} not found`)), process.exit(1)), options.force || await confirm({
|
|
15
|
+
message: `Delete element ${ansis.bold(id)}? This cannot be undone.`,
|
|
16
|
+
initialValue: !1
|
|
17
|
+
}) || (console.log(ansis.dim("Cancelled")), process.exit(0));
|
|
18
|
+
const layer = await model.getLayer(layerName), beforeState = layer.getElement(id).toJSON();
|
|
19
|
+
layer.deleteElement(id) || (console.error(ansis.red(`Error: Failed to delete element ${id}`)), process.exit(1)), model.relationships.deleteForElement(id), await model.getActiveChangesetContext().trackChange("delete", id, layerName, beforeState, void 0), await model.saveLayer(layerName), model.relationships.isDirty() && await model.saveRelationships(), await model.saveManifest(), isTelemetryEnabled && span && span.setAttribute("layer.name", layerName), console.log(ansis.green(`\u2713 Deleted element ${ansis.bold(id)}`)), options.verbose && console.log(ansis.dim(` Layer: ${layerName}`));
|
|
20
|
+
} catch (error) {
|
|
21
|
+
isTelemetryEnabled && span && (span.recordException(error), span.setStatus({ code: 2, message: error.message }));
|
|
22
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
23
|
+
console.error(ansis.red(`Error: ${message}`)), process.exit(1);
|
|
24
|
+
} finally {
|
|
25
|
+
isTelemetryEnabled && endSpan(span);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
deleteCommand
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/commands/delete.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Delete an element\n */\n\nimport { confirm } from '@clack/prompts';\nimport ansis from 'ansis';\nimport { Model } from '../core/model.js';\nimport { findElementLayer } from '../utils/element-utils.js';\nimport { startSpan, endSpan } from '../telemetry/index.js';\n\ndeclare const TELEMETRY_ENABLED: boolean | undefined;\nconst isTelemetryEnabled = typeof TELEMETRY_ENABLED !== 'undefined' ? TELEMETRY_ENABLED : false;\n\nexport interface DeleteOptions {\n force?: boolean;\n verbose?: boolean;\n debug?: boolean;\n}\n\nexport async function deleteCommand(id: string, options: DeleteOptions): Promise<void> {\n const span = isTelemetryEnabled ? startSpan('element.delete', {\n 'element.id': id,\n 'element.force': !!options.force,\n }) : null;\n\n try {\n // Load model\n const model = await Model.load();\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 // Confirm deletion unless --force\n if (!options.force) {\n const confirmed = await confirm({\n message: `Delete element ${ansis.bold(id)}? 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 const layer = (await model.getLayer(layerName))!;\n\n // Capture element state for changeset tracking before deletion\n const element = layer.getElement(id)!;\n const beforeState = element.toJSON();\n\n // Delete element\n const deleted = layer.deleteElement(id);\n if (!deleted) {\n console.error(ansis.red(`Error: Failed to delete element ${id}`));\n process.exit(1);\n }\n\n // Delete all relationships involving this element\n model.relationships.deleteForElement(id);\n\n // Track change in active changeset if present\n const activeChangeset = model.getActiveChangesetContext();\n await activeChangeset.trackChange(\n 'delete',\n id,\n layerName,\n beforeState as unknown as Record<string, unknown>,\n undefined\n );\n\n // Save layer and manifest\n await model.saveLayer(layerName);\n\n // Only save relationships if they were modified\n if (model.relationships.isDirty()) {\n await model.saveRelationships();\n }\n\n await model.saveManifest();\n\n if (isTelemetryEnabled && span) {\n (span as any).setAttribute('layer.name', layerName);\n }\n\n console.log(ansis.green(`\u2713 Deleted element ${ansis.bold(id)}`));\n if (options.verbose) {\n console.log(ansis.dim(` Layer: ${layerName}`));\n }\n } catch (error) {\n if (isTelemetryEnabled && span) {\n (span as any).recordException(error as Error);\n (span as any).setStatus({ code: 2, message: (error as Error).message });\n }\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n } finally {\n if (isTelemetryEnabled) {\n endSpan(span);\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "AAIA,SAAS,eAAe;AACxB,OAAO,WAAW;AAClB,SAAS,aAAa;AACtB,SAAS,wBAAwB;AACjC,SAAS,WAAW,eAAe;AAGnC,MAAM,qBAAgE;AAQtE,eAAsB,cAAc,IAAY,SAAsB;AACpE,QAAM,OAAO,qBAAqB,UAAU,kBAAkB;IAC5D,cAAc;IACd,iBAAiB,CAAC,CAAC,QAAQ;GAC5B,IAAI;AAEL,MAAI;AAEF,UAAM,QAAQ,MAAM,MAAM,KAAI,GAGxB,YAAY,MAAM,iBAAiB,OAAO,EAAE;AAClD,IAAK,cACH,QAAQ,MAAM,MAAM,IAAI,kBAAkB,EAAE,YAAY,CAAC,GACzD,QAAQ,KAAK,CAAC,IAIX,QAAQ,SACO,MAAM,QAAQ;MAC9B,SAAS,kBAAkB,MAAM,KAAK,EAAE,CAAC;MACzC,cAAc;KACf,MAGC,QAAQ,IAAI,MAAM,IAAI,WAAW,CAAC,GAClC,QAAQ,KAAK,CAAC;AAIlB,UAAM,QAAS,MAAM,MAAM,SAAS,SAAS,GAIvC,cADU,MAAM,WAAW,EAAE,EACP,OAAM;AAIlC,IADgB,MAAM,cAAc,EAAE,MAEpC,QAAQ,MAAM,MAAM,IAAI,mCAAmC,EAAE,EAAE,CAAC,GAChE,QAAQ,KAAK,CAAC,IAIhB,MAAM,cAAc,iBAAiB,EAAE,GAIvC,MADwB,MAAM,0BAAyB,EACjC,YACpB,UACA,IACA,WACA,aACA,MAAS,GAIX,MAAM,MAAM,UAAU,SAAS,GAG3B,MAAM,cAAc,QAAO,KAC7B,MAAM,MAAM,kBAAiB,GAG/B,MAAM,MAAM,aAAY,GAEpB,sBAAsB,QACvB,KAAa,aAAa,cAAc,SAAS,GAGpD,QAAQ,IAAI,MAAM,MAAM,0BAAqB,MAAM,KAAK,EAAE,CAAC,EAAE,CAAC,GAC1D,QAAQ,WACV,QAAQ,IAAI,MAAM,IAAI,YAAY,SAAS,EAAE,CAAC;EAElD,SAAS,OAAO;AACd,IAAI,sBAAsB,SACvB,KAAa,gBAAgB,KAAc,GAC3C,KAAa,UAAU,EAAE,MAAM,GAAG,SAAU,MAAgB,QAAO,CAAE;AAExE,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,YAAQ,MAAM,MAAM,IAAI,UAAU,OAAO,EAAE,CAAC,GAC5C,QAAQ,KAAK,CAAC;EAChB;AACE,IAAI,sBACF,QAAQ,IAAI;EAEhB;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { addCommand } from "./add.js";
|
|
2
|
+
import { updateCommand } from "./update.js";
|
|
3
|
+
import { deleteCommand } from "./delete.js";
|
|
4
|
+
import { showCommand } from "./show.js";
|
|
5
|
+
import { listCommand } from "./list.js";
|
|
6
|
+
function elementCommands(program) {
|
|
7
|
+
program.command("add <layer> <type> <id>").description("Add an element to a layer").option("--name <name>", "Element name (defaults to ID)").option("--description <desc>", "Element description").option("--properties <json>", "Element properties as JSON object").addHelpText("after", `
|
|
8
|
+
Examples:
|
|
9
|
+
$ dr element add business business-service customer-mgmt --name "Customer Management"
|
|
10
|
+
$ dr element add api endpoint create-customer --properties '{"method":"POST","path":"/customers"}'`).action(addCommand), program.command("update <id>").description("Update an element").option("--name <name>", "New element name").option("--description <desc>", "New description").option("--properties <json>", "Updated properties (JSON)").addHelpText("after", `
|
|
11
|
+
Examples:
|
|
12
|
+
$ dr element update api-endpoint-create-customer --name "Create Customer (v2)"
|
|
13
|
+
$ dr element update business-service-order --description "Updated description"`).action(updateCommand), program.command("delete <id>").description("Delete an element").option("--force", "Skip confirmation prompt").addHelpText("after", `
|
|
14
|
+
Examples:
|
|
15
|
+
$ dr element delete api-endpoint-old-endpoint
|
|
16
|
+
$ dr element delete api-endpoint-old-endpoint --force`).action(deleteCommand), program.command("show <id>").description("Display element details").addHelpText("after", `
|
|
17
|
+
Examples:
|
|
18
|
+
$ dr element show api-endpoint-create-customer
|
|
19
|
+
$ dr element show business-service-order-mgmt`).action(showCommand), program.command("list <layer>").description("List elements in a layer").option("--type <type>", "Filter by element type").option("--json", "Output as JSON").addHelpText("after", `
|
|
20
|
+
Examples:
|
|
21
|
+
$ dr element list api
|
|
22
|
+
$ dr element list business --type business-service
|
|
23
|
+
$ dr element list api --json`).action(listCommand);
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
elementCommands
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=element.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/commands/element.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Element subcommands\n * Re-exports standalone commands as subcommands for consistency\n */\n\nimport { Command } from 'commander';\nimport { addCommand } from './add.js';\nimport { updateCommand } from './update.js';\nimport { deleteCommand } from './delete.js';\nimport { showCommand } from './show.js';\nimport { listCommand } from './list.js';\n\nexport function elementCommands(program: Command): void {\n program\n .command('add <layer> <type> <id>')\n .description('Add an element to a layer')\n .option('--name <name>', 'Element name (defaults to ID)')\n .option('--description <desc>', 'Element description')\n .option('--properties <json>', 'Element properties as JSON object')\n .addHelpText(\n 'after',\n `\nExamples:\n $ dr element add business business-service customer-mgmt --name \"Customer Management\"\n $ dr element add api endpoint create-customer --properties '{\"method\":\"POST\",\"path\":\"/customers\"}'`\n )\n .action(addCommand);\n\n program\n .command('update <id>')\n .description('Update an element')\n .option('--name <name>', 'New element name')\n .option('--description <desc>', 'New description')\n .option('--properties <json>', 'Updated properties (JSON)')\n .addHelpText(\n 'after',\n `\nExamples:\n $ dr element update api-endpoint-create-customer --name \"Create Customer (v2)\"\n $ dr element update business-service-order --description \"Updated description\"`\n )\n .action(updateCommand);\n\n program\n .command('delete <id>')\n .description('Delete an element')\n .option('--force', 'Skip confirmation prompt')\n .addHelpText(\n 'after',\n `\nExamples:\n $ dr element delete api-endpoint-old-endpoint\n $ dr element delete api-endpoint-old-endpoint --force`\n )\n .action(deleteCommand);\n\n program\n .command('show <id>')\n .description('Display element details')\n .addHelpText(\n 'after',\n `\nExamples:\n $ dr element show api-endpoint-create-customer\n $ dr element show business-service-order-mgmt`\n )\n .action(showCommand);\n\n program\n .command('list <layer>')\n .description('List elements in a layer')\n .option('--type <type>', 'Filter by element type')\n .option('--json', 'Output as JSON')\n .addHelpText(\n 'after',\n `\nExamples:\n $ dr element list api\n $ dr element list business --type business-service\n $ dr element list api --json`\n )\n .action(listCommand);\n}\n"],
|
|
5
|
+
"mappings": "AAMA,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAEtB,SAAU,gBAAgB,SAAgB;AAC9C,UACG,QAAQ,yBAAyB,EACjC,YAAY,2BAA2B,EACvC,OAAO,iBAAiB,+BAA+B,EACvD,OAAO,wBAAwB,qBAAqB,EACpD,OAAO,uBAAuB,mCAAmC,EACjE,YACC,SACA;;;qGAG+F,EAEhG,OAAO,UAAU,GAEpB,QACG,QAAQ,aAAa,EACrB,YAAY,mBAAmB,EAC/B,OAAO,iBAAiB,kBAAkB,EAC1C,OAAO,wBAAwB,iBAAiB,EAChD,OAAO,uBAAuB,2BAA2B,EACzD,YACC,SACA;;;iFAG2E,EAE5E,OAAO,aAAa,GAEvB,QACG,QAAQ,aAAa,EACrB,YAAY,mBAAmB,EAC/B,OAAO,WAAW,0BAA0B,EAC5C,YACC,SACA;;;wDAGkD,EAEnD,OAAO,aAAa,GAEvB,QACG,QAAQ,WAAW,EACnB,YAAY,yBAAyB,EACrC,YACC,SACA;;;gDAG0C,EAE3C,OAAO,WAAW,GAErB,QACG,QAAQ,cAAc,EACtB,YAAY,0BAA0B,EACtC,OAAO,iBAAiB,wBAAwB,EAChD,OAAO,UAAU,gBAAgB,EACjC,YACC,SACA;;;;+BAIyB,EAE1B,OAAO,WAAW;AACvB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import ansis from "ansis";
|
|
2
|
+
import { Model } from "../core/model.js";
|
|
3
|
+
import { ExportManager, ArchiMateExporter, OpenAPIExporter, JsonSchemaExporter, PlantUMLExporter, GraphMLExporter, MarkdownExporter } from "../export/index.js";
|
|
4
|
+
import { writeFile } from "../utils/file-io.js";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import { startSpan, endSpan } from "../telemetry/index.js";
|
|
7
|
+
const isTelemetryEnabled = !1;
|
|
8
|
+
async function exportCommand(options) {
|
|
9
|
+
const span = isTelemetryEnabled ? startSpan("export.execute", {
|
|
10
|
+
"export.format": options.format,
|
|
11
|
+
"export.layer_count": options.layers?.length || 0,
|
|
12
|
+
"export.has_output": !!options.output
|
|
13
|
+
}) : null;
|
|
14
|
+
try {
|
|
15
|
+
const model = await Model.load(options.model), manager = new ExportManager();
|
|
16
|
+
manager.register("archimate", new ArchiMateExporter(), {
|
|
17
|
+
description: "ArchiMate 3.2 XML format",
|
|
18
|
+
mimeType: "application/xml"
|
|
19
|
+
}), manager.register("openapi", new OpenAPIExporter(), {
|
|
20
|
+
description: "OpenAPI 3.0 specification",
|
|
21
|
+
mimeType: "application/json"
|
|
22
|
+
}), manager.register("json-schema", new JsonSchemaExporter(), {
|
|
23
|
+
description: "JSON Schema Draft 7",
|
|
24
|
+
mimeType: "application/json"
|
|
25
|
+
}), manager.register("jsonschema", new JsonSchemaExporter(), {
|
|
26
|
+
description: "JSON Schema Draft 7",
|
|
27
|
+
mimeType: "application/json"
|
|
28
|
+
}), manager.register("plantuml", new PlantUMLExporter(), {
|
|
29
|
+
description: "PlantUML diagram format",
|
|
30
|
+
mimeType: "text/plain"
|
|
31
|
+
}), manager.register("graphml", new GraphMLExporter(), {
|
|
32
|
+
description: "GraphML graph format",
|
|
33
|
+
mimeType: "application/xml"
|
|
34
|
+
}), manager.register("markdown", new MarkdownExporter(), {
|
|
35
|
+
description: "Markdown documentation",
|
|
36
|
+
mimeType: "text/markdown"
|
|
37
|
+
});
|
|
38
|
+
const format = options.format.toLowerCase();
|
|
39
|
+
if (!manager.hasFormat(format)) {
|
|
40
|
+
console.error(ansis.red(`Error: Unknown export format: ${format}`)), console.error(""), console.error("Available formats:");
|
|
41
|
+
for (const info of manager.getAllFormats())
|
|
42
|
+
console.error(` - ${ansis.cyan(info.format)}: ${info.description}`), console.error(` Supported layers: ${info.supportedLayers.join(", ")}`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
const result = await manager.export(model, format, {
|
|
46
|
+
layers: options.layers,
|
|
47
|
+
outputPath: options.output
|
|
48
|
+
});
|
|
49
|
+
if (isTelemetryEnabled && span && span.setAttribute("export.result_size", result.length), options.output) {
|
|
50
|
+
const outputPath = path.isAbsolute(options.output) ? options.output : path.join(process.cwd(), options.output);
|
|
51
|
+
await writeFile(outputPath, result), console.log(ansis.green(`\u2713 Exported to ${ansis.cyan(outputPath)}`));
|
|
52
|
+
} else
|
|
53
|
+
console.log(result);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
isTelemetryEnabled && span && (span.recordException(error), span.setStatus({ code: 2, message: error.message }));
|
|
56
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
57
|
+
console.error(ansis.red(`Error: ${message}`)), process.exit(1);
|
|
58
|
+
} finally {
|
|
59
|
+
isTelemetryEnabled && endSpan(span);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
exportCommand
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/commands/export.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Export the architecture model to various formats\n */\n\nimport ansis from \"ansis\";\nimport { Model } from \"../core/model.js\";\nimport {\n ExportManager,\n ArchiMateExporter,\n OpenAPIExporter,\n JsonSchemaExporter,\n PlantUMLExporter,\n GraphMLExporter,\n MarkdownExporter,\n} from \"../export/index.js\";\nimport { writeFile } from \"../utils/file-io.js\";\nimport * as path from \"path\";\nimport { startSpan, endSpan } from \"../telemetry/index.js\";\n\ndeclare const TELEMETRY_ENABLED: boolean | undefined;\nconst isTelemetryEnabled = typeof TELEMETRY_ENABLED !== 'undefined' ? TELEMETRY_ENABLED : false;\n\nexport interface ExportOptions {\n format: string;\n output?: string;\n layers?: string[];\n model?: string;\n}\n\nexport async function exportCommand(options: ExportOptions): Promise<void> {\n const span = isTelemetryEnabled ? startSpan('export.execute', {\n 'export.format': options.format,\n 'export.layer_count': options.layers?.length || 0,\n 'export.has_output': !!options.output,\n }) : null;\n\n try {\n // Load model\n const model = await Model.load(options.model);\n\n // Initialize ExportManager and register all exporters\n const manager = new ExportManager();\n\n manager.register(\"archimate\", new ArchiMateExporter(), {\n description: \"ArchiMate 3.2 XML format\",\n mimeType: \"application/xml\",\n });\n\n manager.register(\"openapi\", new OpenAPIExporter(), {\n description: \"OpenAPI 3.0 specification\",\n mimeType: \"application/json\",\n });\n\n manager.register(\"json-schema\", new JsonSchemaExporter(), {\n description: \"JSON Schema Draft 7\",\n mimeType: \"application/json\",\n });\n\n // Register alias for jsonschema (without hyphen)\n manager.register(\"jsonschema\", new JsonSchemaExporter(), {\n description: \"JSON Schema Draft 7\",\n mimeType: \"application/json\",\n });\n\n manager.register(\"plantuml\", new PlantUMLExporter(), {\n description: \"PlantUML diagram format\",\n mimeType: \"text/plain\",\n });\n\n manager.register(\"graphml\", new GraphMLExporter(), {\n description: \"GraphML graph format\",\n mimeType: \"application/xml\",\n });\n\n manager.register(\"markdown\", new MarkdownExporter(), {\n description: \"Markdown documentation\",\n mimeType: \"text/markdown\",\n });\n\n // Validate format\n const format = options.format.toLowerCase();\n if (!manager.hasFormat(format)) {\n console.error(\n ansis.red(`Error: Unknown export format: ${format}`)\n );\n console.error(\"\");\n console.error(\"Available formats:\");\n for (const info of manager.getAllFormats()) {\n console.error(\n ` - ${ansis.cyan(info.format)}: ${info.description}`\n );\n console.error(\n ` Supported layers: ${info.supportedLayers.join(\", \")}`\n );\n }\n process.exit(1);\n }\n\n\n // Perform export\n const result = await manager.export(model, format, {\n layers: options.layers,\n outputPath: options.output,\n });\n\n if (isTelemetryEnabled && span) {\n (span as any).setAttribute('export.result_size', result.length);\n }\n\n if (options.output) {\n // Write to file\n // For relative paths, use current working directory instead of rootPath\n // This allows tests to detect file creation in their working directory\n const outputPath = path.isAbsolute(options.output)\n ? options.output\n : path.join(process.cwd(), options.output);\n\n await writeFile(outputPath, result);\n\n console.log(\n ansis.green(`\u2713 Exported to ${ansis.cyan(outputPath)}`)\n );\n } else {\n // Output to stdout\n console.log(result);\n }\n } catch (error) {\n if (isTelemetryEnabled && span) {\n (span as any).recordException(error as Error);\n (span as any).setStatus({ code: 2, message: (error as Error).message });\n }\n const message = error instanceof Error ? error.message : String(error);\n console.error(ansis.red(`Error: ${message}`));\n process.exit(1);\n } finally {\n if (isTelemetryEnabled) {\n endSpan(span);\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "AAIA,OAAO,WAAW;AAClB,SAAS,aAAa;AACtB,SACE,eACA,mBACA,iBACA,oBACA,kBACA,iBACA,wBACK;AACP,SAAS,iBAAiB;AAC1B,YAAY,UAAU;AACtB,SAAS,WAAW,eAAe;AAGnC,MAAM,qBAAgE;AAStE,eAAsB,cAAc,SAAsB;AACxD,QAAM,OAAO,qBAAqB,UAAU,kBAAkB;IAC5D,iBAAiB,QAAQ;IACzB,sBAAsB,QAAQ,QAAQ,UAAU;IAChD,qBAAqB,CAAC,CAAC,QAAQ;GAChC,IAAI;AAEL,MAAI;AAEF,UAAM,QAAQ,MAAM,MAAM,KAAK,QAAQ,KAAK,GAGtC,UAAU,IAAI,cAAa;AAEjC,YAAQ,SAAS,aAAa,IAAI,kBAAiB,GAAI;MACrD,aAAa;MACb,UAAU;KACX,GAED,QAAQ,SAAS,WAAW,IAAI,gBAAe,GAAI;MACjD,aAAa;MACb,UAAU;KACX,GAED,QAAQ,SAAS,eAAe,IAAI,mBAAkB,GAAI;MACxD,aAAa;MACb,UAAU;KACX,GAGD,QAAQ,SAAS,cAAc,IAAI,mBAAkB,GAAI;MACvD,aAAa;MACb,UAAU;KACX,GAED,QAAQ,SAAS,YAAY,IAAI,iBAAgB,GAAI;MACnD,aAAa;MACb,UAAU;KACX,GAED,QAAQ,SAAS,WAAW,IAAI,gBAAe,GAAI;MACjD,aAAa;MACb,UAAU;KACX,GAED,QAAQ,SAAS,YAAY,IAAI,iBAAgB,GAAI;MACnD,aAAa;MACb,UAAU;KACX;AAGD,UAAM,SAAS,QAAQ,OAAO,YAAW;AACzC,QAAI,CAAC,QAAQ,UAAU,MAAM,GAAG;AAC9B,cAAQ,MACN,MAAM,IAAI,iCAAiC,MAAM,EAAE,CAAC,GAEtD,QAAQ,MAAM,EAAE,GAChB,QAAQ,MAAM,oBAAoB;AAClC,iBAAW,QAAQ,QAAQ,cAAa;AACtC,gBAAQ,MACN,OAAO,MAAM,KAAK,KAAK,MAAM,CAAC,KAAK,KAAK,WAAW,EAAE,GAEvD,QAAQ,MACN,yBAAyB,KAAK,gBAAgB,KAAK,IAAI,CAAC,EAAE;AAG9D,cAAQ,KAAK,CAAC;IAChB;AAIA,UAAM,SAAS,MAAM,QAAQ,OAAO,OAAO,QAAQ;MACjD,QAAQ,QAAQ;MAChB,YAAY,QAAQ;KACrB;AAMD,QAJI,sBAAsB,QACvB,KAAa,aAAa,sBAAsB,OAAO,MAAM,GAG5D,QAAQ,QAAQ;AAIlB,YAAM,aAAa,KAAK,WAAW,QAAQ,MAAM,IAC7C,QAAQ,SACR,KAAK,KAAK,QAAQ,IAAG,GAAI,QAAQ,MAAM;AAE3C,YAAM,UAAU,YAAY,MAAM,GAElC,QAAQ,IACN,MAAM,MAAM,sBAAiB,MAAM,KAAK,UAAU,CAAC,EAAE,CAAC;IAE1D;AAEE,cAAQ,IAAI,MAAM;EAEtB,SAAS,OAAO;AACd,IAAI,sBAAsB,SACvB,KAAa,gBAAgB,KAAc,GAC3C,KAAa,UAAU,EAAE,MAAM,GAAG,SAAU,MAAgB,QAAO,CAAE;AAExE,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,YAAQ,MAAM,MAAM,IAAI,UAAU,OAAO,EAAE,CAAC,GAC5C,QAAQ,KAAK,CAAC;EAChB;AACE,IAAI,sBACF,QAAQ,IAAI;EAEhB;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import ansis from "ansis";
|
|
2
|
+
import { Model } from "../core/model.js";
|
|
3
|
+
async function infoCommand(options) {
|
|
4
|
+
try {
|
|
5
|
+
const model = await Model.load(), manifest = model.manifest;
|
|
6
|
+
console.log(""), console.log(ansis.bold(`${ansis.blue("Model:")} ${manifest.name}`)), console.log(ansis.dim("\u2500".repeat(80))), console.log(`${ansis.gray("Name:")} ${manifest.name}`), console.log(`${ansis.gray("Version:")} ${manifest.version}`), console.log(`${ansis.gray("Spec Version:")} ${manifest.specVersion}`), manifest.description && console.log(`${ansis.gray("Description:")} ${manifest.description}`), manifest.author && console.log(`${ansis.gray("Author:")} ${manifest.author}`), console.log(`${ansis.gray("Created:")} ${manifest.created}`), console.log(`${ansis.gray("Modified:")} ${manifest.modified}`);
|
|
7
|
+
const layerNames = model.getLayerNames();
|
|
8
|
+
if (layerNames.length > 0)
|
|
9
|
+
if (console.log(""), console.log(ansis.bold("Layers:")), console.log(ansis.dim("\u2500".repeat(80))), options.layer) {
|
|
10
|
+
const layer = await model.getLayer(options.layer);
|
|
11
|
+
layer || (console.error(ansis.red(`Error: Layer ${options.layer} not found`)), process.exit(1));
|
|
12
|
+
const elements = layer.listElements();
|
|
13
|
+
if (console.log(`${ansis.cyan(options.layer)}`), console.log(` ${ansis.gray("Elements:")} ${elements.length}`), options.verbose && elements.length > 0) {
|
|
14
|
+
console.log(` ${ansis.gray("Details:")}`);
|
|
15
|
+
const types = new Set(elements.map((e) => e.type));
|
|
16
|
+
for (const type of types) {
|
|
17
|
+
const count = elements.filter((e) => e.type === type).length;
|
|
18
|
+
console.log(` - ${type}: ${count}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
} else
|
|
22
|
+
for (const layerName of layerNames) {
|
|
23
|
+
const layer = await model.getLayer(layerName);
|
|
24
|
+
if (!layer)
|
|
25
|
+
continue;
|
|
26
|
+
const count = layer.listElements().length, paddedName = layerName.padEnd(20), paddedCount = String(count).padEnd(10);
|
|
27
|
+
console.log(`${ansis.cyan(paddedName)} ${paddedCount} elements`);
|
|
28
|
+
}
|
|
29
|
+
else
|
|
30
|
+
console.log(""), console.log(ansis.yellow("No layers found"));
|
|
31
|
+
console.log("");
|
|
32
|
+
} catch (error) {
|
|
33
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
34
|
+
console.error(ansis.red(`Error: ${message}`)), process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
infoCommand
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=info.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/commands/info.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Show information about a model or layer\n */\n\nimport ansis from 'ansis';\nimport { Model } from '../core/model.js';\n\nexport interface InfoOptions {\n layer?: string;\n verbose?: boolean;\n debug?: boolean;\n}\n\nexport async function infoCommand(options: InfoOptions): Promise<void> {\n try {\n // Load model\n const model = await Model.load();\n const manifest = model.manifest;\n\n console.log('');\n console.log(ansis.bold(`${ansis.blue('Model:')} ${manifest.name}`));\n console.log(ansis.dim('\u2500'.repeat(80)));\n\n console.log(`${ansis.gray('Name:')} ${manifest.name}`);\n console.log(`${ansis.gray('Version:')} ${manifest.version}`);\n console.log(`${ansis.gray('Spec Version:')} ${manifest.specVersion}`);\n\n if (manifest.description) {\n console.log(`${ansis.gray('Description:')} ${manifest.description}`);\n }\n\n if (manifest.author) {\n console.log(`${ansis.gray('Author:')} ${manifest.author}`);\n }\n\n console.log(`${ansis.gray('Created:')} ${manifest.created}`);\n console.log(`${ansis.gray('Modified:')} ${manifest.modified}`);\n\n // Show layer information\n const layerNames = model.getLayerNames();\n if (layerNames.length > 0) {\n console.log('');\n console.log(ansis.bold('Layers:'));\n console.log(ansis.dim('\u2500'.repeat(80)));\n\n if (options.layer) {\n // Show specific layer info\n const layer = await model.getLayer(options.layer);\n if (!layer) {\n console.error(ansis.red(`Error: Layer ${options.layer} not found`));\n process.exit(1);\n }\n\n const elements = layer.listElements();\n console.log(`${ansis.cyan(options.layer)}`);\n console.log(` ${ansis.gray('Elements:')} ${elements.length}`);\n\n if (options.verbose && elements.length > 0) {\n console.log(` ${ansis.gray('Details:')}`);\n const types = new Set(elements.map((e) => e.type));\n for (const type of types) {\n const count = elements.filter((e) => e.type === type).length;\n console.log(` - ${type}: ${count}`);\n }\n }\n } else {\n // Show all layers summary\n const idWidth = 20;\n const countWidth = 10;\n\n for (const layerName of layerNames) {\n const layer = await model.getLayer(layerName);\n if (!layer) continue;\n\n const count = layer.listElements().length;\n const paddedName = layerName.padEnd(idWidth);\n const paddedCount = String(count).padEnd(countWidth);\n\n console.log(`${ansis.cyan(paddedName)} ${paddedCount} elements`);\n }\n }\n } else {\n console.log('');\n console.log(ansis.yellow('No layers found'));\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;AAQtB,eAAsB,YAAY,SAAoB;AACpD,MAAI;AAEF,UAAM,QAAQ,MAAM,MAAM,KAAI,GACxB,WAAW,MAAM;AAEvB,YAAQ,IAAI,EAAE,GACd,QAAQ,IAAI,MAAM,KAAK,GAAG,MAAM,KAAK,QAAQ,CAAC,IAAI,SAAS,IAAI,EAAE,CAAC,GAClE,QAAQ,IAAI,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC,GAErC,QAAQ,IAAI,GAAG,MAAM,KAAK,OAAO,CAAC,aAAa,SAAS,IAAI,EAAE,GAC9D,QAAQ,IAAI,GAAG,MAAM,KAAK,UAAU,CAAC,UAAU,SAAS,OAAO,EAAE,GACjE,QAAQ,IAAI,GAAG,MAAM,KAAK,eAAe,CAAC,KAAK,SAAS,WAAW,EAAE,GAEjE,SAAS,eACX,QAAQ,IAAI,GAAG,MAAM,KAAK,cAAc,CAAC,MAAM,SAAS,WAAW,EAAE,GAGnE,SAAS,UACX,QAAQ,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,WAAW,SAAS,MAAM,EAAE,GAGlE,QAAQ,IAAI,GAAG,MAAM,KAAK,UAAU,CAAC,UAAU,SAAS,OAAO,EAAE,GACjE,QAAQ,IAAI,GAAG,MAAM,KAAK,WAAW,CAAC,SAAS,SAAS,QAAQ,EAAE;AAGlE,UAAM,aAAa,MAAM,cAAa;AACtC,QAAI,WAAW,SAAS;AAKtB,UAJA,QAAQ,IAAI,EAAE,GACd,QAAQ,IAAI,MAAM,KAAK,SAAS,CAAC,GACjC,QAAQ,IAAI,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC,GAEjC,QAAQ,OAAO;AAEjB,cAAM,QAAQ,MAAM,MAAM,SAAS,QAAQ,KAAK;AAChD,QAAK,UACH,QAAQ,MAAM,MAAM,IAAI,gBAAgB,QAAQ,KAAK,YAAY,CAAC,GAClE,QAAQ,KAAK,CAAC;AAGhB,cAAM,WAAW,MAAM,aAAY;AAInC,YAHA,QAAQ,IAAI,GAAG,MAAM,KAAK,QAAQ,KAAK,CAAC,EAAE,GAC1C,QAAQ,IAAI,KAAK,MAAM,KAAK,WAAW,CAAC,IAAI,SAAS,MAAM,EAAE,GAEzD,QAAQ,WAAW,SAAS,SAAS,GAAG;AAC1C,kBAAQ,IAAI,KAAK,MAAM,KAAK,UAAU,CAAC,EAAE;AACzC,gBAAM,QAAQ,IAAI,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AACjD,qBAAW,QAAQ,OAAO;AACxB,kBAAM,QAAQ,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,EAAE;AACtD,oBAAQ,IAAI,SAAS,IAAI,KAAK,KAAK,EAAE;UACvC;QACF;MACF;AAKE,mBAAW,aAAa,YAAY;AAClC,gBAAM,QAAQ,MAAM,MAAM,SAAS,SAAS;AAC5C,cAAI,CAAC;AAAO;AAEZ,gBAAM,QAAQ,MAAM,aAAY,EAAG,QAC7B,aAAa,UAAU,OAAO,EAAO,GACrC,cAAc,OAAO,KAAK,EAAE,OAAO,EAAU;AAEnD,kBAAQ,IAAI,GAAG,MAAM,KAAK,UAAU,CAAC,IAAI,WAAW,WAAW;QACjE;;AAGF,cAAQ,IAAI,EAAE,GACd,QAAQ,IAAI,MAAM,OAAO,iBAAiB,CAAC;AAG7C,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,45 @@
|
|
|
1
|
+
import { intro, text, outro } from "@clack/prompts";
|
|
2
|
+
import ansis from "ansis";
|
|
3
|
+
import { Model } from "../core/model.js";
|
|
4
|
+
import { fileExists } from "../utils/file-io.js";
|
|
5
|
+
import { logVerbose, logDebug } from "../utils/globals.js";
|
|
6
|
+
import { installSpecReference } from "../utils/spec-installer.js";
|
|
7
|
+
async function initCommand(options) {
|
|
8
|
+
intro(ansis.bold(ansis.blue("\u2699\uFE0F Initialize Documentation Robotics Model")));
|
|
9
|
+
try {
|
|
10
|
+
const rootPath = process.cwd(), manifestPath = `${`${rootPath}/documentation-robotics/model`}/manifest.yaml`;
|
|
11
|
+
await fileExists(manifestPath) && (console.error(ansis.red("Error: Model already initialized in this directory")), process.exit(1));
|
|
12
|
+
const isInteractive = process.stdin.isTTY, name = options.name || (isInteractive ? await text({
|
|
13
|
+
message: "Model name:",
|
|
14
|
+
validate: (value) => value.length === 0 ? "Name is required" : void 0
|
|
15
|
+
}) : (() => {
|
|
16
|
+
console.error(ansis.red("Error: Model name is required (use --name option)")), process.exit(1);
|
|
17
|
+
})()), description = options.description || (isInteractive ? await text({
|
|
18
|
+
message: "Description (optional):",
|
|
19
|
+
defaultValue: ""
|
|
20
|
+
}) : ""), author = options.author || (isInteractive ? await text({
|
|
21
|
+
message: "Author (optional):",
|
|
22
|
+
defaultValue: ""
|
|
23
|
+
}) : "");
|
|
24
|
+
logDebug(`Creating model directory at ${rootPath}/documentation-robotics/model`);
|
|
25
|
+
const model = await Model.init(rootPath, {
|
|
26
|
+
name,
|
|
27
|
+
version: "0.1.0",
|
|
28
|
+
description: description || void 0,
|
|
29
|
+
author: author || void 0,
|
|
30
|
+
specVersion: "0.6.0",
|
|
31
|
+
created: (/* @__PURE__ */ new Date()).toISOString()
|
|
32
|
+
}, { lazyLoad: !1 });
|
|
33
|
+
logVerbose(`Model saved with:
|
|
34
|
+
- Version: 0.1.0
|
|
35
|
+
- Spec Version: 0.6.0
|
|
36
|
+
- Location: ${rootPath}/documentation-robotics/model`), logDebug("Installing spec reference (.dr/ folder)..."), await installSpecReference(rootPath, !1), logVerbose("Spec reference installed"), outro(ansis.green(`\u2713 Model initialized: ${ansis.bold(model.manifest.name)}`));
|
|
37
|
+
} catch (error) {
|
|
38
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
39
|
+
console.error(ansis.red(`Error: ${message}`)), process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
initCommand
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/commands/init.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Initialize a new Documentation Robotics model\n */\n\nimport { intro, text, outro } from '@clack/prompts';\nimport ansis from 'ansis';\nimport { Model } from '../core/model.js';\nimport { fileExists } from '../utils/file-io.js';\nimport { logVerbose, logDebug } from '../utils/globals.js';\nimport { installSpecReference } from '../utils/spec-installer.js';\n\nexport interface InitOptions {\n name?: string;\n author?: string;\n description?: string;\n verbose?: boolean;\n debug?: boolean;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n intro(ansis.bold(ansis.blue('\u2699\uFE0F Initialize Documentation Robotics Model')));\n\n try {\n const rootPath = process.cwd();\n // Use Python CLI structure: documentation-robotics/model/\n const modelPath = `${rootPath}/documentation-robotics/model`;\n const manifestPath = `${modelPath}/manifest.yaml`;\n\n // Check if model already exists\n if (await fileExists(manifestPath)) {\n console.error(ansis.red('Error: Model already initialized in this directory'));\n process.exit(1);\n }\n\n // Gather model metadata\n // Check if stdin is a TTY to determine if we should prompt\n const isInteractive = process.stdin.isTTY;\n\n const name =\n options.name ||\n (isInteractive\n ? await text({\n message: 'Model name:',\n validate: (value) => (value.length === 0 ? 'Name is required' : undefined),\n })\n : (() => {\n console.error(ansis.red('Error: Model name is required (use --name option)'));\n process.exit(1);\n })());\n\n const description =\n options.description ||\n (isInteractive\n ? await text({\n message: 'Description (optional):',\n defaultValue: '',\n })\n : '');\n\n const author =\n options.author ||\n (isInteractive\n ? await text({\n message: 'Author (optional):',\n defaultValue: '',\n })\n : '');\n\n // Initialize model\n logDebug(`Creating model directory at ${rootPath}/documentation-robotics/model`);\n const model = await Model.init(\n rootPath,\n {\n name: name as string,\n version: '0.1.0',\n description: (description as string) || undefined,\n author: (author as string) || undefined,\n specVersion: '0.6.0',\n created: new Date().toISOString(),\n },\n { lazyLoad: false }\n );\n\n logVerbose(`Model saved with:\n - Version: 0.1.0\n - Spec Version: 0.6.0\n - Location: ${rootPath}/documentation-robotics/model`);\n\n // Install spec reference (.dr/ folder)\n logDebug('Installing spec reference (.dr/ folder)...');\n await installSpecReference(rootPath, false);\n logVerbose('Spec reference installed');\n\n outro(ansis.green(`\u2713 Model initialized: ${ansis.bold(model.manifest.name)}`));\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,SAAS,OAAO,MAAM,aAAa;AACnC,OAAO,WAAW;AAClB,SAAS,aAAa;AACtB,SAAS,kBAAkB;AAC3B,SAAS,YAAY,gBAAgB;AACrC,SAAS,4BAA4B;AAUrC,eAAsB,YAAY,SAAoB;AACpD,QAAM,MAAM,KAAK,MAAM,KAAK,uDAA6C,CAAC,CAAC;AAE3E,MAAI;AACF,UAAM,WAAW,QAAQ,IAAG,GAGtB,eAAe,GADH,GAAG,QAAQ,+BACI;AAGjC,IAAI,MAAM,WAAW,YAAY,MAC/B,QAAQ,MAAM,MAAM,IAAI,oDAAoD,CAAC,GAC7E,QAAQ,KAAK,CAAC;AAKhB,UAAM,gBAAgB,QAAQ,MAAM,OAE9B,OACJ,QAAQ,SACP,gBACG,MAAM,KAAK;MACT,SAAS;MACT,UAAU,CAAC,UAAW,MAAM,WAAW,IAAI,qBAAqB;KACjE,KACA,MAAK;AACJ,cAAQ,MAAM,MAAM,IAAI,mDAAmD,CAAC,GAC5E,QAAQ,KAAK,CAAC;IAChB,GAAE,IAEF,cACJ,QAAQ,gBACP,gBACG,MAAM,KAAK;MACT,SAAS;MACT,cAAc;KACf,IACD,KAEA,SACJ,QAAQ,WACP,gBACG,MAAM,KAAK;MACT,SAAS;MACT,cAAc;KACf,IACD;AAGN,aAAS,+BAA+B,QAAQ,+BAA+B;AAC/E,UAAM,QAAQ,MAAM,MAAM,KACxB,UACA;MACE;MACA,SAAS;MACT,aAAc,eAA0B;MACxC,QAAS,UAAqB;MAC9B,aAAa;MACb,UAAS,oBAAI,KAAI,GAAG,YAAW;OAEjC,EAAE,UAAU,GAAK,CAAE;AAGrB,eAAW;;;gBAGC,QAAQ,+BAA+B,GAGnD,SAAS,4CAA4C,GACrD,MAAM,qBAAqB,UAAU,EAAK,GAC1C,WAAW,0BAA0B,GAErC,MAAM,MAAM,MAAM,6BAAwB,MAAM,KAAK,MAAM,SAAS,IAAI,CAAC,EAAE,CAAC;EAC9E,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
|
+
}
|