@documentation-robotics/cli 0.1.10 → 0.1.12
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/dist/cli.js +18 -2
- package/dist/cli.js.map +2 -2
- package/dist/commands/repair.js +62 -0
- package/dist/commands/repair.js.map +7 -0
- package/dist/commands/version.js +1 -1
- package/dist/core/attribute-collision-repair.js +73 -0
- package/dist/core/attribute-collision-repair.js.map +7 -0
- package/dist/core/graph-model.js +14 -1
- package/dist/core/graph-model.js.map +2 -2
- package/dist/core/model.js +10 -7
- package/dist/core/model.js.map +2 -2
- package/dist/core/reference-registry.js +11 -5
- package/dist/core/reference-registry.js.map +2 -2
- package/dist/export/plantuml-exporter.js +3 -1
- package/dist/export/plantuml-exporter.js.map +2 -2
- package/dist/telemetry/index.js +1 -1
- package/dist/utils/element-reference-shape.js +12 -0
- package/dist/utils/element-reference-shape.js.map +7 -0
- package/dist/utils/spec-version.js +1 -1
- package/dist/utils/spec-version.js.map +1 -1
- package/package.json +9 -9
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ALL_LAYERS, LAYER_COLORS } from "./types.js";
|
|
2
2
|
import { isTelemetryEnabled, startSpan, endSpan } from "../telemetry/index.js";
|
|
3
3
|
import { getErrorMessage } from "../utils/errors.js";
|
|
4
|
+
import { getNodeType } from "../generated/node-types.js";
|
|
4
5
|
class PlantUMLExporter {
|
|
5
6
|
name = "PlantUML";
|
|
6
7
|
supportedLayers = ALL_LAYERS;
|
|
@@ -96,7 +97,8 @@ class PlantUMLExporter {
|
|
|
96
97
|
if (!node)
|
|
97
98
|
return null;
|
|
98
99
|
let sourceRef = node.source_reference;
|
|
99
|
-
|
|
100
|
+
const nodeType = node.spec_node_id ? getNodeType(node.spec_node_id) : void 0, declaresAttribute = (key) => !!nodeType && (nodeType.requiredAttributes.includes(key) || nodeType.optionalAttributes.includes(key));
|
|
101
|
+
if (!sourceRef && !declaresAttribute("x-source-reference") && (sourceRef = node.properties?.["x-source-reference"]), !sourceRef && !declaresAttribute("source") && node.properties?.source?.reference && (sourceRef = node.properties.source.reference), !sourceRef)
|
|
100
102
|
return null;
|
|
101
103
|
const parts = [];
|
|
102
104
|
if (Array.isArray(sourceRef.locations) && sourceRef.locations.length > 0) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/export/plantuml-exporter.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Model } from \"../core/model.js\";\nimport type { Exporter, ExportOptions } from \"./types.js\";\nimport { ALL_LAYERS, LAYER_COLORS } from \"./types.js\";\nimport { isTelemetryEnabled, startSpan, endSpan } from \"../telemetry/index.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\n\n/**\n * PlantUML element entry for diagram generation\n * Contains element metadata for rendering from graph nodes\n */\ninterface PlantUMLElementEntry {\n id: string;\n name: string;\n type: string;\n description?: string;\n}\n\n/**\n * PlantUML Exporter - generates PlantUML syntax for diagram visualization\n * Supports all 13 layers\n *\n * Exports the model as PlantUML component diagram syntax with layers,\n * elements, relationships, and optional source references.\n */\nexport class PlantUMLExporter implements Exporter {\n name = \"PlantUML\";\n supportedLayers = ALL_LAYERS;\n\n async export(model: Model, options: ExportOptions = {}): Promise<string> {\n const span = isTelemetryEnabled\n ? startSpan(\"export.format.plantuml\", {\n \"export.layerCount\": options.layers?.length || this.supportedLayers.length,\n \"export.includeSources\": options.includeSources === true,\n })\n : null;\n\n try {\n const lines: string[] = [];\n\n lines.push(\"@startuml\");\n lines.push(`title \"${this.escapeQuotes(model.manifest.name)}\"`);\n lines.push(\"\");\n\n if (model.manifest.description) {\n lines.push(`note top : \"${this.escapeQuotes(model.manifest.description)}\"`);\n lines.push(\"\");\n }\n\n const layersToExport = options.layers || this.supportedLayers;\n const elementsByLayer = new Map<string, PlantUMLElementEntry[]>();\n const nodesByLayer = new Map<string, any[]>();\n // Map from raw graph node ID \u2192 sanitized PlantUML ID for edge rendering\n const rawToPlantUMLId = new Map<string, string>();\n\n // Collect nodes by layer from graph model\n for (const layerName of layersToExport) {\n const nodes = model.graph.getNodesByLayer(layerName);\n if (nodes.length === 0) continue;\n\n const layerElements: PlantUMLElementEntry[] = [];\n nodesByLayer.set(layerName, nodes);\n\n for (const node of nodes) {\n const pumlId = this.toPlantUMLId(node.id);\n rawToPlantUMLId.set(node.id, pumlId);\n layerElements.push({\n id: pumlId,\n name: node.name,\n type: node.type,\n description: node.description,\n });\n }\n elementsByLayer.set(layerName, layerElements);\n }\n\n // Create packages for each layer\n for (const layerName of layersToExport) {\n const elements = elementsByLayer.get(layerName);\n if (!elements || elements.length === 0) continue;\n\n const color = LAYER_COLORS[layerName] || \"FFFFFF\";\n lines.push(`package \"${layerName}\" #${color} {`);\n\n const nodes = nodesByLayer.get(layerName) || [];\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n lines.push(` component \"${this.escapeQuotes(element.name)}\" as ${element.id}`);\n\n // Add source reference as note if includeSources option is enabled\n if (options.includeSources) {\n const node = nodes[i];\n const sourceRef = this.extractSourceReference(node);\n if (sourceRef) {\n lines.push(` note right of ${element.id}`);\n lines.push(` ${this.escapeQuotes(sourceRef)}`);\n lines.push(` end note`);\n }\n }\n }\n\n lines.push(\"}\");\n lines.push(\"\");\n }\n\n // Add relationships from graph edges\n const edges = model.graph.getAllEdges();\n\n for (const edge of edges) {\n // Only include edges between exported nodes (check raw IDs)\n const srcPuml = rawToPlantUMLId.get(edge.source);\n const dstPuml = rawToPlantUMLId.get(edge.destination);\n if (srcPuml && dstPuml) {\n const arrow = this.getArrowType(edge.predicate);\n lines.push(\n `${srcPuml} ${arrow} ${dstPuml} : ${this.escapeQuotes(edge.predicate)}`\n );\n }\n }\n\n lines.push(\"\");\n lines.push(\"@enduml\");\n\n const result = lines.join(\"\\n\") + \"\\n\";\n\n if (isTelemetryEnabled && span) {\n // Count total elements and relationships\n let totalElements = 0;\n let totalEdges = 0;\n\n for (const elements of elementsByLayer.values()) {\n totalElements += elements.length;\n }\n\n for (const edge of edges) {\n if (rawToPlantUMLId.has(edge.source) && rawToPlantUMLId.has(edge.destination)) {\n totalEdges++;\n }\n }\n\n (span as any).setAttribute(\"export.elementCount\", totalElements);\n (span as any).setAttribute(\"export.relationshipCount\", totalEdges);\n (span as any).setAttribute(\"export.size\", result.length);\n (span as any).setStatus({ code: 0 });\n }\n\n return result;\n } catch (error) {\n if (isTelemetryEnabled && span) {\n (span as any).recordException(error as Error);\n (span as any).setStatus({\n code: 2,\n message: getErrorMessage(error),\n });\n }\n throw error;\n } finally {\n endSpan(span);\n }\n }\n\n /**\n * Get PlantUML arrow type based on predicate\n */\n private getArrowType(predicate: string): string {\n const arrowMap: Record<string, string> = {\n composes: \"*--\",\n aggregates: \"o--\",\n supports: \"-->\",\n realizes: \"..|>\",\n \"flows-to\": \"-->\",\n \"refers-to\": \"..>\",\n };\n return arrowMap[predicate] || \"-->\";\n }\n\n /**\n * Extract and format source reference from node properties\n */\n private extractSourceReference(node: any): string | null {\n if (!node) return null;\n\n // Try node.source_reference first (primary field on GraphNode)\n let sourceRef = node.source_reference;\n\n //
|
|
5
|
-
"mappings": "AAEA,SAAS,YAAY,oBAAoB;AACzC,SAAS,oBAAoB,WAAW,eAAe;AACvD,SAAS,uBAAuB;
|
|
4
|
+
"sourcesContent": ["import type { Model } from \"../core/model.js\";\nimport type { Exporter, ExportOptions } from \"./types.js\";\nimport { ALL_LAYERS, LAYER_COLORS } from \"./types.js\";\nimport { isTelemetryEnabled, startSpan, endSpan } from \"../telemetry/index.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { getNodeType, type SpecNodeId } from \"../generated/node-types.js\";\n\n/**\n * PlantUML element entry for diagram generation\n * Contains element metadata for rendering from graph nodes\n */\ninterface PlantUMLElementEntry {\n id: string;\n name: string;\n type: string;\n description?: string;\n}\n\n/**\n * PlantUML Exporter - generates PlantUML syntax for diagram visualization\n * Supports all 13 layers\n *\n * Exports the model as PlantUML component diagram syntax with layers,\n * elements, relationships, and optional source references.\n */\nexport class PlantUMLExporter implements Exporter {\n name = \"PlantUML\";\n supportedLayers = ALL_LAYERS;\n\n async export(model: Model, options: ExportOptions = {}): Promise<string> {\n const span = isTelemetryEnabled\n ? startSpan(\"export.format.plantuml\", {\n \"export.layerCount\": options.layers?.length || this.supportedLayers.length,\n \"export.includeSources\": options.includeSources === true,\n })\n : null;\n\n try {\n const lines: string[] = [];\n\n lines.push(\"@startuml\");\n lines.push(`title \"${this.escapeQuotes(model.manifest.name)}\"`);\n lines.push(\"\");\n\n if (model.manifest.description) {\n lines.push(`note top : \"${this.escapeQuotes(model.manifest.description)}\"`);\n lines.push(\"\");\n }\n\n const layersToExport = options.layers || this.supportedLayers;\n const elementsByLayer = new Map<string, PlantUMLElementEntry[]>();\n const nodesByLayer = new Map<string, any[]>();\n // Map from raw graph node ID \u2192 sanitized PlantUML ID for edge rendering\n const rawToPlantUMLId = new Map<string, string>();\n\n // Collect nodes by layer from graph model\n for (const layerName of layersToExport) {\n const nodes = model.graph.getNodesByLayer(layerName);\n if (nodes.length === 0) continue;\n\n const layerElements: PlantUMLElementEntry[] = [];\n nodesByLayer.set(layerName, nodes);\n\n for (const node of nodes) {\n const pumlId = this.toPlantUMLId(node.id);\n rawToPlantUMLId.set(node.id, pumlId);\n layerElements.push({\n id: pumlId,\n name: node.name,\n type: node.type,\n description: node.description,\n });\n }\n elementsByLayer.set(layerName, layerElements);\n }\n\n // Create packages for each layer\n for (const layerName of layersToExport) {\n const elements = elementsByLayer.get(layerName);\n if (!elements || elements.length === 0) continue;\n\n const color = LAYER_COLORS[layerName] || \"FFFFFF\";\n lines.push(`package \"${layerName}\" #${color} {`);\n\n const nodes = nodesByLayer.get(layerName) || [];\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n lines.push(` component \"${this.escapeQuotes(element.name)}\" as ${element.id}`);\n\n // Add source reference as note if includeSources option is enabled\n if (options.includeSources) {\n const node = nodes[i];\n const sourceRef = this.extractSourceReference(node);\n if (sourceRef) {\n lines.push(` note right of ${element.id}`);\n lines.push(` ${this.escapeQuotes(sourceRef)}`);\n lines.push(` end note`);\n }\n }\n }\n\n lines.push(\"}\");\n lines.push(\"\");\n }\n\n // Add relationships from graph edges\n const edges = model.graph.getAllEdges();\n\n for (const edge of edges) {\n // Only include edges between exported nodes (check raw IDs)\n const srcPuml = rawToPlantUMLId.get(edge.source);\n const dstPuml = rawToPlantUMLId.get(edge.destination);\n if (srcPuml && dstPuml) {\n const arrow = this.getArrowType(edge.predicate);\n lines.push(\n `${srcPuml} ${arrow} ${dstPuml} : ${this.escapeQuotes(edge.predicate)}`\n );\n }\n }\n\n lines.push(\"\");\n lines.push(\"@enduml\");\n\n const result = lines.join(\"\\n\") + \"\\n\";\n\n if (isTelemetryEnabled && span) {\n // Count total elements and relationships\n let totalElements = 0;\n let totalEdges = 0;\n\n for (const elements of elementsByLayer.values()) {\n totalElements += elements.length;\n }\n\n for (const edge of edges) {\n if (rawToPlantUMLId.has(edge.source) && rawToPlantUMLId.has(edge.destination)) {\n totalEdges++;\n }\n }\n\n (span as any).setAttribute(\"export.elementCount\", totalElements);\n (span as any).setAttribute(\"export.relationshipCount\", totalEdges);\n (span as any).setAttribute(\"export.size\", result.length);\n (span as any).setStatus({ code: 0 });\n }\n\n return result;\n } catch (error) {\n if (isTelemetryEnabled && span) {\n (span as any).recordException(error as Error);\n (span as any).setStatus({\n code: 2,\n message: getErrorMessage(error),\n });\n }\n throw error;\n } finally {\n endSpan(span);\n }\n }\n\n /**\n * Get PlantUML arrow type based on predicate\n */\n private getArrowType(predicate: string): string {\n const arrowMap: Record<string, string> = {\n composes: \"*--\",\n aggregates: \"o--\",\n supports: \"-->\",\n realizes: \"..|>\",\n \"flows-to\": \"-->\",\n \"refers-to\": \"..>\",\n };\n return arrowMap[predicate] || \"-->\";\n }\n\n /**\n * Extract and format source reference from node properties\n */\n private extractSourceReference(node: any): string | null {\n if (!node) return null;\n\n // Try node.source_reference first (primary, structurally-typed field on GraphNode)\n let sourceRef = node.source_reference;\n\n // Legacy fallback for pre-migration data that stored provenance directly under\n // properties[\"x-source-reference\"] / properties.source.reference instead of the\n // first-class source_reference field. Only trust these fallbacks when the node's OWN\n // schema does NOT declare \"x-source-reference\"/\"source\" as a real attribute \u2014 4 node\n // types (data-store.accesspattern/collection/field/storedlogic) declare\n // \"x-source-reference\", and 37 more declare \"source\", as genuine domain string\n // attributes (e.g. security.accesscondition.source); for those, node.properties[...]\n // holds real domain data, not source-code provenance, and reading it here would\n // silently mislabel it as \"Source:\"/\"Repo:\" in the generated diagram.\n const nodeType = node.spec_node_id ? getNodeType(node.spec_node_id as SpecNodeId) : undefined;\n const declaresAttribute = (key: string): boolean =>\n !!nodeType && (nodeType.requiredAttributes.includes(key) || nodeType.optionalAttributes.includes(key));\n\n if (!sourceRef && !declaresAttribute(\"x-source-reference\")) {\n sourceRef = node.properties?.[\"x-source-reference\"];\n }\n\n if (!sourceRef && !declaresAttribute(\"source\") && node.properties?.source?.reference) {\n sourceRef = node.properties.source.reference;\n }\n\n if (!sourceRef) return null;\n\n // Format source reference for display\n const parts: string[] = [];\n\n if (Array.isArray(sourceRef.locations) && sourceRef.locations.length > 0) {\n const location = sourceRef.locations[0];\n if (location.file) {\n parts.push(`Source: ${location.file}`);\n }\n if (location.symbol) {\n parts.push(`Symbol: ${location.symbol}`);\n }\n }\n\n if (sourceRef.repository?.url) {\n parts.push(`Repo: ${sourceRef.repository.url}`);\n if (sourceRef.repository.commit) {\n parts.push(`Commit: ${sourceRef.repository.commit.substring(0, 8)}`);\n }\n }\n\n return parts.length > 0 ? parts.join(\"\\\\n\") : null;\n }\n\n /**\n * Escape quotes for PlantUML syntax\n */\n private escapeQuotes(str: string): string {\n // Escape double quotes within strings for PlantUML\n return str.replace(/\"/g, '\\\\\"');\n }\n\n /**\n * Convert a raw element ID (path or UUID) to a valid PlantUML identifier.\n * PlantUML identifiers cannot contain dots or hyphens, so replace with underscores.\n */\n private toPlantUMLId(id: string): string {\n return id.replace(/[.\\-]/g, \"_\");\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/telemetry/index.js
CHANGED
|
@@ -21,7 +21,7 @@ async function initTelemetry() {
|
|
|
21
21
|
`), process.stderr.write(` - Logs endpoint: ${otlpConfig.logsEndpoint}
|
|
22
22
|
`), process.stderr.write(` - Service name: ${otlpConfig.serviceName}
|
|
23
23
|
`));
|
|
24
|
-
const cliVersion = "0.1.
|
|
24
|
+
const cliVersion = "0.1.12";
|
|
25
25
|
let projectName = "unknown";
|
|
26
26
|
try {
|
|
27
27
|
const [{ readFileSync, existsSync }, { parse }] = await Promise.all([
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getAllLayerIds } from "../generated/layer-registry.js";
|
|
2
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, KNOWN_LAYERS = new Set(getAllLayerIds());
|
|
3
|
+
function looksLikeElementReference(value) {
|
|
4
|
+
if (UUID_PATTERN.test(value))
|
|
5
|
+
return !0;
|
|
6
|
+
const dotIndex = value.indexOf(".");
|
|
7
|
+
return dotIndex <= 0 ? !1 : KNOWN_LAYERS.has(value.slice(0, dotIndex));
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
looksLikeElementReference
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=element-reference-shape.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/element-reference-shape.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Shape check for \"does this string plausibly identify a DR model element\" \u2014 a UUIDv4\n * (element.id) or a dot-separated `{layer}.{type}.{slug}` id whose first segment is a real,\n * known DR layer (matching the id scheme `NamingValidator` enforces on every element).\n *\n * Used by `ReferenceRegistry` to gate its `*Ref`/`*Reference` attribute-name heuristic: an\n * attribute NAME matching that convention is not, by itself, reliable evidence that its VALUE\n * is an element reference \u2014 `api.link.operationRef` is a schema-declared OpenAPI URL fragment\n * (e.g. \"#/paths/~1users/get\"), not an element id, and matches the naming convention purely by\n * coincidence. Checking the value's shape catches that case (and any future one like it)\n * without needing per-attribute schema annotations that don't exist today.\n *\n * Deliberately a shape check, not an existence check: a value that looks like an element id but\n * doesn't resolve to one is exactly what `ReferenceRegistry.findBrokenReferences()` is supposed\n * to catch, so this must not filter those out too.\n */\nimport { getAllLayerIds } from \"../generated/layer-registry.js\";\n\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst KNOWN_LAYERS = new Set(getAllLayerIds());\n\nexport function looksLikeElementReference(value: string): boolean {\n if (UUID_PATTERN.test(value)) return true;\n\n const dotIndex = value.indexOf(\".\");\n if (dotIndex <= 0) return false;\n\n return KNOWN_LAYERS.has(value.slice(0, dotIndex));\n}\n"],
|
|
5
|
+
"mappings": "AAgBA,SAAS,sBAAsB;AAE/B,MAAM,eAAe,mEACf,eAAe,IAAI,IAAI,eAAc,CAAE;AAEvC,SAAU,0BAA0B,OAAa;AACrD,MAAI,aAAa,KAAK,KAAK;AAAG,WAAO;AAErC,QAAM,WAAW,MAAM,QAAQ,GAAG;AAClC,SAAI,YAAY,IAAU,KAEnB,aAAa,IAAI,MAAM,MAAM,GAAG,QAAQ,CAAC;AAClD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/spec-version.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Spec Version Utilities\n *\n * Manages spec version information for the CLI\n */\n\nimport { readJSON, fileExists } from \"./file-io.js\";\nimport { join } from \"path\";\n\n/**\n * CLI version\n * This should match the version in ../package.json\n * Updated during release process\n */\nconst CLI_VERSION = \"0.1.
|
|
4
|
+
"sourcesContent": ["/**\n * Spec Version Utilities\n *\n * Manages spec version information for the CLI\n */\n\nimport { readJSON, fileExists } from \"./file-io.js\";\nimport { join } from \"path\";\n\n/**\n * CLI version\n * This should match the version in ../package.json\n * Updated during release process\n */\nconst CLI_VERSION = \"0.1.12\";\n\n/**\n * Bundled spec version\n * This should match the version in ../../../spec/VERSION\n * Updated during build process\n */\nconst BUNDLED_SPEC_VERSION = \"0.9.0\";\n\n/**\n * Get the CLI version\n *\n * @returns CLI version string\n */\nexport function getCliVersion(): string {\n return CLI_VERSION;\n}\n\n/**\n * Get the CLI's bundled spec version\n *\n * This is the version of the DR specification that is bundled with this CLI.\n * It represents what version of the spec this CLI supports.\n *\n * @returns Bundled spec version string\n */\nexport function getCliBundledSpecVersion(): string {\n return BUNDLED_SPEC_VERSION;\n}\n\n/**\n * Read spec version from .dr/manifest.json (installed spec reference)\n *\n * @param drPath - Path to .dr/ directory\n * @returns Spec version from .dr/manifest.json, or null if not found\n */\nexport async function getInstalledSpecVersion(drPath: string): Promise<string | null> {\n const manifestPath = join(drPath, \"manifest.json\");\n\n if (!(await fileExists(manifestPath))) {\n return null;\n }\n\n try {\n const manifest = await readJSON<{ specVersion?: string }>(manifestPath);\n return manifest.specVersion || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Read spec version from documentation_robotics/model/manifest.yaml\n *\n * @param modelPath - Path to model directory\n * @returns Spec version from model manifest, or null if not found\n */\nexport async function getModelSpecVersion(modelPath: string): Promise<string | null> {\n const manifestPath = join(modelPath, \"manifest.yaml\");\n\n if (!(await fileExists(manifestPath))) {\n return null;\n }\n\n try {\n // Use YAML parser\n const yaml = await import(\"yaml\");\n const fs = await import(\"fs/promises\");\n const content = await fs.readFile(manifestPath, \"utf-8\");\n const manifest = yaml.parse(content) as { spec_version?: string; specVersion?: string };\n // Check snake_case first (Python CLI format), then camelCase (legacy)\n return manifest.spec_version || manifest.specVersion || null;\n } catch {\n return null;\n }\n}\n"],
|
|
5
5
|
"mappings": "AAMA,SAAS,UAAU,kBAAkB;AACrC,SAAS,YAAY;AAOrB,MAAM,cAAc,UAOd,uBAAuB;AAOvB,SAAU,gBAAa;AAC3B,SAAO;AACT;AAUM,SAAU,2BAAwB;AACtC,SAAO;AACT;AAQA,eAAsB,wBAAwB,QAAc;AAC1D,QAAM,eAAe,KAAK,QAAQ,eAAe;AAEjD,MAAI,CAAE,MAAM,WAAW,YAAY;AACjC,WAAO;AAGT,MAAI;AAEF,YADiB,MAAM,SAAmC,YAAY,GACtD,eAAe;EACjC,QAAQ;AACN,WAAO;EACT;AACF;AAQA,eAAsB,oBAAoB,WAAiB;AACzD,QAAM,eAAe,KAAK,WAAW,eAAe;AAEpD,MAAI,CAAE,MAAM,WAAW,YAAY;AACjC,WAAO;AAGT,MAAI;AAEF,UAAM,OAAO,MAAM,OAAO,MAAM,GAE1B,UAAU,OADL,MAAM,OAAO,aAAa,GACZ,SAAS,cAAc,OAAO,GACjD,WAAW,KAAK,MAAM,OAAO;AAEnC,WAAO,SAAS,gBAAgB,SAAS,eAAe;EAC1D,QAAQ;AACN,WAAO;EACT;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@documentation-robotics/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "CLI for Documentation Robotics",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cli.js",
|
|
@@ -24,17 +24,17 @@
|
|
|
24
24
|
"dev": "node dist/cli.js",
|
|
25
25
|
"lint": "tsc --noEmit",
|
|
26
26
|
"type-check": "tsc --noEmit",
|
|
27
|
-
"test": "bun test --timeout=30000 --concurrent ./tests/unit/core/ ./tests/unit/validators/ ./tests/unit/telemetry/ ./tests/unit/utils/ ./tests/unit/coding-agents/ ./tests/unit/integrations/ ./tests/unit/server/ ./tests/unit/audit/ ./tests/unit/export/ ./tests/compatibility/ --test-name-pattern '^(?!BaseIntegrationManager)' ; bun test --timeout=30000 ./tests/unit/analyzers/ ; bun test --timeout=30000 tests/unit/chat/*.test.ts tests/integration
|
|
28
|
-
"test:unit": "bun test --timeout=30000 --concurrent ./tests/unit/core/ ./tests/unit/validators/ ./tests/unit/telemetry/ ./tests/unit/utils/ ./tests/unit/coding-agents/ ./tests/unit/integrations/ ./tests/unit/server/ ./tests/unit/scripts/ ./tests/unit/audit/ ./tests/unit/export/ --test-name-pattern '^(?!BaseIntegrationManager)' ; bun test --timeout=30000 ./tests/unit/analyzers/ ; bun test --timeout=30000 tests/unit/chat/*.test.ts tests/unit/integrations/base-manager.test.ts",
|
|
27
|
+
"test": "bun test --timeout=30000 --concurrent ./tests/unit/core/ ./tests/unit/validators/ ./tests/unit/telemetry/ ./tests/unit/utils/ ./tests/unit/coding-agents/ ./tests/unit/integrations/ ./tests/unit/server/ ./tests/unit/audit/ ./tests/unit/export/ ./tests/compatibility/ --test-name-pattern '^(?!BaseIntegrationManager)(?!.*trace with three-element dependency chain)(?!.*trace with branching dependencies)' ; bun test --timeout=30000 ./tests/unit/analyzers/ ; bun test --timeout=30000 tests/unit/chat/*.test.ts ./tests/integration/ tests/unit/integrations/base-manager.test.ts --test-name-pattern '^(?!.*trace with three-element dependency chain)(?!.*trace with branching dependencies)'",
|
|
28
|
+
"test:unit": "bun test --timeout=30000 --concurrent ./tests/unit/core/ ./tests/unit/validators/ ./tests/unit/telemetry/ ./tests/unit/utils/ ./tests/unit/coding-agents/ ./tests/unit/integrations/ ./tests/unit/server/ ./tests/unit/scripts/ ./tests/unit/audit/ ./tests/unit/export/ --test-name-pattern '^(?!BaseIntegrationManager)(?!.*trace with three-element dependency chain)(?!.*trace with branching dependencies)' ; bun test --timeout=30000 ./tests/unit/analyzers/ ; bun test --timeout=30000 tests/unit/chat/*.test.ts tests/unit/integrations/base-manager.test.ts",
|
|
29
29
|
"test:generated": "bun test --timeout=30000 tests/unit/generators/*.test.ts",
|
|
30
|
-
"test:integration": "[ -f dist/cli.js ] || npm run build && bun test --timeout=30000 tests/integration
|
|
30
|
+
"test:integration": "[ -f dist/cli.js ] || npm run build && bun test --timeout=30000 ./tests/integration/ --test-name-pattern '^(?!.*trace with three-element dependency chain)(?!.*trace with branching dependencies)'",
|
|
31
31
|
"test:validators": "bun test --timeout=30000 --concurrent ./tests/unit/validators/",
|
|
32
32
|
"test:compatibility": "bun test --timeout=30000 --concurrent tests/compatibility",
|
|
33
|
-
"test:all": "[ -f dist/cli.js ] || npm run build && bun test --timeout=30000 --concurrent ./tests/ --test-name-pattern '^(?!BaseIntegrationManager)' ; bun test --timeout=30000 tests/unit/integrations/base-manager.test.ts",
|
|
34
|
-
"test:coverage": "[ -f dist/cli.js ] || npm run build && bun test --timeout=30000 --concurrent --coverage ./tests/ --test-name-pattern '^(?!BaseIntegrationManager)' ; bun test --timeout=30000 --coverage tests/unit/integrations/base-manager.test.ts",
|
|
35
|
-
"test:coverage:html": "[ -f dist/cli.js ] || npm run build && bun test --timeout=30000 --concurrent --coverage --coverage-reporter=html ./tests/ --test-name-pattern '^(?!BaseIntegrationManager)' ; bun test --timeout=30000 --coverage --coverage-reporter=html tests/unit/integrations/base-manager.test.ts",
|
|
36
|
-
"test:coverage:ci": "[ -f dist/cli.js ] || npm run build && bun test --timeout=30000 --concurrent --coverage --coverage-reporter=lcov ./tests/ --test-name-pattern '^(?!BaseIntegrationManager)' ; bun test --timeout=30000 --coverage --coverage-reporter=lcov tests/unit/integrations/base-manager.test.ts && node scripts/validate-coverage-threshold.js",
|
|
37
|
-
"test:perf": "bun test --timeout=30000 tests/performance
|
|
33
|
+
"test:all": "[ -f dist/cli.js ] || npm run build && bun test --timeout=30000 --concurrent ./tests/ --test-name-pattern '^(?!BaseIntegrationManager)(?!.*trace with three-element dependency chain)(?!.*trace with branching dependencies)' ; bun test --timeout=30000 tests/unit/integrations/base-manager.test.ts",
|
|
34
|
+
"test:coverage": "[ -f dist/cli.js ] || npm run build && bun test --timeout=30000 --concurrent --coverage ./tests/ --test-name-pattern '^(?!BaseIntegrationManager)(?!.*trace with three-element dependency chain)(?!.*trace with branching dependencies)' ; bun test --timeout=30000 --coverage tests/unit/integrations/base-manager.test.ts",
|
|
35
|
+
"test:coverage:html": "[ -f dist/cli.js ] || npm run build && bun test --timeout=30000 --concurrent --coverage --coverage-reporter=html ./tests/ --test-name-pattern '^(?!BaseIntegrationManager)(?!.*trace with three-element dependency chain)(?!.*trace with branching dependencies)' ; bun test --timeout=30000 --coverage --coverage-reporter=html tests/unit/integrations/base-manager.test.ts",
|
|
36
|
+
"test:coverage:ci": "[ -f dist/cli.js ] || npm run build && bun test --timeout=30000 --concurrent --coverage --coverage-reporter=lcov ./tests/ --test-name-pattern '^(?!BaseIntegrationManager)(?!.*trace with three-element dependency chain)(?!.*trace with branching dependencies)' ; bun test --timeout=30000 --coverage --coverage-reporter=lcov tests/unit/integrations/base-manager.test.ts && node scripts/validate-coverage-threshold.js",
|
|
37
|
+
"test:perf": "bun test --timeout=30000 ./tests/performance/",
|
|
38
38
|
"test:smoke": "[ -f dist/cli.js ] || npm run build && bash scripts/run-smoke-tests.sh"
|
|
39
39
|
},
|
|
40
40
|
"keywords": [
|