@living-architecture/riviere-cli 0.2.1 → 0.2.3
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/LICENSE +190 -0
- package/README.md +14 -6
- package/dist/bin.js +24428 -0
- package/dist/index.js +24444 -7
- package/package.json +4 -4
- package/dist/cli.d.ts +0 -8
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -65
- package/dist/command-test-fixtures.d.ts +0 -110
- package/dist/command-test-fixtures.d.ts.map +0 -1
- package/dist/command-test-fixtures.js +0 -184
- package/dist/commands/builder/add-component.d.ts +0 -4
- package/dist/commands/builder/add-component.d.ts.map +0 -1
- package/dist/commands/builder/add-component.js +0 -204
- package/dist/commands/builder/add-domain.d.ts +0 -3
- package/dist/commands/builder/add-domain.d.ts.map +0 -1
- package/dist/commands/builder/add-domain.js +0 -56
- package/dist/commands/builder/add-source.d.ts +0 -3
- package/dist/commands/builder/add-source.d.ts.map +0 -1
- package/dist/commands/builder/add-source.js +0 -28
- package/dist/commands/builder/check-consistency.d.ts +0 -3
- package/dist/commands/builder/check-consistency.d.ts.map +0 -1
- package/dist/commands/builder/check-consistency.js +0 -27
- package/dist/commands/builder/component-checklist.d.ts +0 -3
- package/dist/commands/builder/component-checklist.d.ts.map +0 -1
- package/dist/commands/builder/component-checklist.js +0 -43
- package/dist/commands/builder/component-summary.d.ts +0 -3
- package/dist/commands/builder/component-summary.d.ts.map +0 -1
- package/dist/commands/builder/component-summary.js +0 -23
- package/dist/commands/builder/enrich.d.ts +0 -3
- package/dist/commands/builder/enrich.d.ts.map +0 -1
- package/dist/commands/builder/enrich.js +0 -85
- package/dist/commands/builder/finalize.d.ts +0 -3
- package/dist/commands/builder/finalize.d.ts.map +0 -1
- package/dist/commands/builder/finalize.js +0 -37
- package/dist/commands/builder/init.d.ts +0 -3
- package/dist/commands/builder/init.d.ts.map +0 -1
- package/dist/commands/builder/init.js +0 -100
- package/dist/commands/builder/link-external.d.ts +0 -3
- package/dist/commands/builder/link-external.d.ts.map +0 -1
- package/dist/commands/builder/link-external.js +0 -70
- package/dist/commands/builder/link-http.d.ts +0 -3
- package/dist/commands/builder/link-http.d.ts.map +0 -1
- package/dist/commands/builder/link-http.js +0 -130
- package/dist/commands/builder/link-infrastructure.d.ts +0 -7
- package/dist/commands/builder/link-infrastructure.d.ts.map +0 -1
- package/dist/commands/builder/link-infrastructure.js +0 -41
- package/dist/commands/builder/link.d.ts +0 -3
- package/dist/commands/builder/link.d.ts.map +0 -1
- package/dist/commands/builder/link.js +0 -73
- package/dist/commands/builder/validate.d.ts +0 -3
- package/dist/commands/builder/validate.d.ts.map +0 -1
- package/dist/commands/builder/validate.js +0 -29
- package/dist/commands/query/component-output.d.ts +0 -9
- package/dist/commands/query/component-output.d.ts.map +0 -1
- package/dist/commands/query/component-output.js +0 -8
- package/dist/commands/query/components.d.ts +0 -3
- package/dist/commands/query/components.d.ts.map +0 -1
- package/dist/commands/query/components.js +0 -45
- package/dist/commands/query/domains.d.ts +0 -3
- package/dist/commands/query/domains.d.ts.map +0 -1
- package/dist/commands/query/domains.js +0 -22
- package/dist/commands/query/entry-points.d.ts +0 -3
- package/dist/commands/query/entry-points.d.ts.map +0 -1
- package/dist/commands/query/entry-points.js +0 -22
- package/dist/commands/query/load-graph.d.ts +0 -16
- package/dist/commands/query/load-graph.d.ts.map +0 -1
- package/dist/commands/query/load-graph.js +0 -50
- package/dist/commands/query/orphans.d.ts +0 -3
- package/dist/commands/query/orphans.d.ts.map +0 -1
- package/dist/commands/query/orphans.js +0 -22
- package/dist/commands/query/search.d.ts +0 -3
- package/dist/commands/query/search.d.ts.map +0 -1
- package/dist/commands/query/search.js +0 -25
- package/dist/commands/query/trace.d.ts +0 -3
- package/dist/commands/query/trace.d.ts.map +0 -1
- package/dist/commands/query/trace.js +0 -41
- package/dist/component-types.d.ts +0 -15
- package/dist/component-types.d.ts.map +0 -1
- package/dist/component-types.js +0 -39
- package/dist/error-codes.d.ts +0 -15
- package/dist/error-codes.d.ts.map +0 -1
- package/dist/error-codes.js +0 -15
- package/dist/file-existence.d.ts +0 -2
- package/dist/file-existence.d.ts.map +0 -1
- package/dist/file-existence.js +0 -16
- package/dist/graph-path.d.ts +0 -3
- package/dist/graph-path.d.ts.map +0 -1
- package/dist/graph-path.js +0 -8
- package/dist/index.d.ts +0 -5
- package/dist/index.d.ts.map +0 -1
- package/dist/output.d.ts +0 -17
- package/dist/output.d.ts.map +0 -1
- package/dist/output.js +0 -7
- package/dist/validation.d.ts +0 -12
- package/dist/validation.d.ts.map +0 -1
- package/dist/validation.js +0 -51
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { writeFile } from 'node:fs/promises';
|
|
3
|
-
import { ComponentId } from '@living-architecture/riviere-builder';
|
|
4
|
-
import { RiviereQuery } from '@living-architecture/riviere-query';
|
|
5
|
-
import { getDefaultGraphPathDescription, resolveGraphPath } from '../../graph-path';
|
|
6
|
-
import { fileExists } from '../../file-existence';
|
|
7
|
-
import { formatError, formatSuccess } from '../../output';
|
|
8
|
-
import { CliErrorCode } from '../../error-codes';
|
|
9
|
-
import { isValidLinkType, normalizeComponentType } from '../../component-types';
|
|
10
|
-
import { isValidHttpMethod, validateComponentType, validateHttpMethod, validateLinkType } from '../../validation';
|
|
11
|
-
import { loadGraphBuilder, reportGraphNotFound } from './link-infrastructure';
|
|
12
|
-
function isRestApiWithPath(component) {
|
|
13
|
-
return component.type === 'API' && 'path' in component && 'httpMethod' in component;
|
|
14
|
-
}
|
|
15
|
-
function findApisByPath(graph, path, method) {
|
|
16
|
-
const query = new RiviereQuery(graph);
|
|
17
|
-
const allComponents = query.componentsByType('API');
|
|
18
|
-
const apis = allComponents.filter(isRestApiWithPath);
|
|
19
|
-
const matchingPath = apis.filter((api) => api.path === path);
|
|
20
|
-
if (method) {
|
|
21
|
-
return matchingPath.filter((api) => api.httpMethod === method);
|
|
22
|
-
}
|
|
23
|
-
return matchingPath;
|
|
24
|
-
}
|
|
25
|
-
function getAllApiPaths(graph) {
|
|
26
|
-
const query = new RiviereQuery(graph);
|
|
27
|
-
const allComponents = query.componentsByType('API');
|
|
28
|
-
const apis = allComponents.filter(isRestApiWithPath);
|
|
29
|
-
return [...new Set(apis.map((api) => api.path))];
|
|
30
|
-
}
|
|
31
|
-
function reportNoApiFoundForPath(path, availablePaths) {
|
|
32
|
-
console.log(JSON.stringify(formatError(CliErrorCode.ComponentNotFound, `No API found with path '${path}'`, availablePaths.length > 0 ? [`Available paths: ${availablePaths.join(', ')}`] : [])));
|
|
33
|
-
}
|
|
34
|
-
function reportAmbiguousApiMatch(path, matchingApis) {
|
|
35
|
-
const apiList = matchingApis.map((api) => `${api.id} (${api.httpMethod})`).join(', ');
|
|
36
|
-
console.log(JSON.stringify(formatError(CliErrorCode.AmbiguousApiMatch, `Multiple APIs match path '${path}': ${apiList}`, [
|
|
37
|
-
'Add --method flag to disambiguate',
|
|
38
|
-
])));
|
|
39
|
-
}
|
|
40
|
-
function validateOptions(options) {
|
|
41
|
-
const componentTypeValidation = validateComponentType(options.toType);
|
|
42
|
-
if (!componentTypeValidation.valid) {
|
|
43
|
-
return componentTypeValidation.errorJson;
|
|
44
|
-
}
|
|
45
|
-
const httpMethodValidation = validateHttpMethod(options.method);
|
|
46
|
-
if (!httpMethodValidation.valid) {
|
|
47
|
-
return httpMethodValidation.errorJson;
|
|
48
|
-
}
|
|
49
|
-
const linkTypeValidation = validateLinkType(options.linkType);
|
|
50
|
-
if (!linkTypeValidation.valid) {
|
|
51
|
-
return linkTypeValidation.errorJson;
|
|
52
|
-
}
|
|
53
|
-
return undefined;
|
|
54
|
-
}
|
|
55
|
-
export function createLinkHttpCommand() {
|
|
56
|
-
return new Command('link-http')
|
|
57
|
-
.description('Find an API by HTTP path and link to a target component')
|
|
58
|
-
.addHelpText('after', `
|
|
59
|
-
Examples:
|
|
60
|
-
$ riviere builder link-http \\
|
|
61
|
-
--path "/orders" --method POST \\
|
|
62
|
-
--to-domain orders --to-module checkout --to-type UseCase --to-name "place-order"
|
|
63
|
-
|
|
64
|
-
$ riviere builder link-http \\
|
|
65
|
-
--path "/users/{id}" --method GET \\
|
|
66
|
-
--to-domain users --to-module queries --to-type UseCase --to-name "get-user" \\
|
|
67
|
-
--link-type sync
|
|
68
|
-
`)
|
|
69
|
-
.requiredOption('--path <http-path>', 'HTTP path to match')
|
|
70
|
-
.requiredOption('--to-domain <domain>', 'Target domain')
|
|
71
|
-
.requiredOption('--to-module <module>', 'Target module')
|
|
72
|
-
.requiredOption('--to-type <type>', 'Target component type')
|
|
73
|
-
.requiredOption('--to-name <name>', 'Target component name')
|
|
74
|
-
.option('--method <method>', 'Filter by HTTP method (GET, POST, PUT, PATCH, DELETE)')
|
|
75
|
-
.option('--link-type <type>', 'Link type (sync, async)')
|
|
76
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
77
|
-
.option('--json', 'Output result as JSON')
|
|
78
|
-
.action(async (options) => {
|
|
79
|
-
const validationError = validateOptions(options);
|
|
80
|
-
if (validationError) {
|
|
81
|
-
console.log(validationError);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const graphPath = resolveGraphPath(options.graph);
|
|
85
|
-
const graphExists = await fileExists(graphPath);
|
|
86
|
-
if (!graphExists) {
|
|
87
|
-
reportGraphNotFound(graphPath);
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const builder = await loadGraphBuilder(graphPath);
|
|
91
|
-
const graph = builder.build();
|
|
92
|
-
const normalizedMethod = options.method?.toUpperCase();
|
|
93
|
-
const httpMethod = normalizedMethod && isValidHttpMethod(normalizedMethod) ? normalizedMethod : undefined;
|
|
94
|
-
const matchingApis = findApisByPath(graph, options.path, httpMethod);
|
|
95
|
-
const [matchedApi, ...otherApis] = matchingApis;
|
|
96
|
-
if (!matchedApi) {
|
|
97
|
-
reportNoApiFoundForPath(options.path, getAllApiPaths(graph));
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
if (otherApis.length > 0) {
|
|
101
|
-
reportAmbiguousApiMatch(options.path, matchingApis);
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const targetId = ComponentId.create({
|
|
105
|
-
domain: options.toDomain,
|
|
106
|
-
module: options.toModule,
|
|
107
|
-
type: normalizeComponentType(options.toType),
|
|
108
|
-
name: options.toName,
|
|
109
|
-
}).toString();
|
|
110
|
-
const linkInput = {
|
|
111
|
-
from: matchedApi.id,
|
|
112
|
-
to: targetId,
|
|
113
|
-
};
|
|
114
|
-
if (options.linkType !== undefined && isValidLinkType(options.linkType)) {
|
|
115
|
-
linkInput.type = options.linkType;
|
|
116
|
-
}
|
|
117
|
-
const link = builder.link(linkInput);
|
|
118
|
-
await writeFile(graphPath, builder.serialize(), 'utf-8');
|
|
119
|
-
if (options.json) {
|
|
120
|
-
console.log(JSON.stringify(formatSuccess({
|
|
121
|
-
link,
|
|
122
|
-
matchedApi: {
|
|
123
|
-
id: matchedApi.id,
|
|
124
|
-
path: matchedApi.path,
|
|
125
|
-
method: matchedApi.httpMethod,
|
|
126
|
-
},
|
|
127
|
-
})));
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { RiviereBuilder } from '@living-architecture/riviere-builder';
|
|
2
|
-
export declare function reportGraphNotFound(graphPath: string): void;
|
|
3
|
-
export declare function loadGraphBuilder(graphPath: string): Promise<RiviereBuilder>;
|
|
4
|
-
export declare function withGraphBuilder(graphPathOption: string | undefined, handler: (builder: RiviereBuilder, graphPath: string) => Promise<void>): Promise<void>;
|
|
5
|
-
export declare function handleComponentNotFoundError(error: unknown): void;
|
|
6
|
-
export declare function tryBuilderOperation<T>(operation: () => T): T | undefined;
|
|
7
|
-
//# sourceMappingURL=link-infrastructure.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"link-infrastructure.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/link-infrastructure.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAO9F,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAM3D;AAED,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAKjF;AAED,wBAAsB,gBAAgB,CACpC,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACrE,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAKjE;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAOxE"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { ComponentNotFoundError, RiviereBuilder } from '@living-architecture/riviere-builder';
|
|
3
|
-
import { parseRiviereGraph } from '@living-architecture/riviere-schema';
|
|
4
|
-
import { formatError } from '../../output';
|
|
5
|
-
import { CliErrorCode } from '../../error-codes';
|
|
6
|
-
import { resolveGraphPath } from '../../graph-path';
|
|
7
|
-
import { fileExists } from '../../file-existence';
|
|
8
|
-
export function reportGraphNotFound(graphPath) {
|
|
9
|
-
console.log(JSON.stringify(formatError(CliErrorCode.GraphNotFound, `Graph not found at ${graphPath}`, ['Run riviere builder init first'])));
|
|
10
|
-
}
|
|
11
|
-
export async function loadGraphBuilder(graphPath) {
|
|
12
|
-
const content = await readFile(graphPath, 'utf-8');
|
|
13
|
-
const parsed = JSON.parse(content);
|
|
14
|
-
const graph = parseRiviereGraph(parsed);
|
|
15
|
-
return RiviereBuilder.resume(graph);
|
|
16
|
-
}
|
|
17
|
-
export async function withGraphBuilder(graphPathOption, handler) {
|
|
18
|
-
const graphPath = resolveGraphPath(graphPathOption);
|
|
19
|
-
const graphExists = await fileExists(graphPath);
|
|
20
|
-
if (!graphExists) {
|
|
21
|
-
reportGraphNotFound(graphPath);
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
const builder = await loadGraphBuilder(graphPath);
|
|
25
|
-
await handler(builder, graphPath);
|
|
26
|
-
}
|
|
27
|
-
export function handleComponentNotFoundError(error) {
|
|
28
|
-
if (!(error instanceof ComponentNotFoundError)) {
|
|
29
|
-
throw error;
|
|
30
|
-
}
|
|
31
|
-
console.log(JSON.stringify(formatError(CliErrorCode.ComponentNotFound, error.message, error.suggestions)));
|
|
32
|
-
}
|
|
33
|
-
export function tryBuilderOperation(operation) {
|
|
34
|
-
try {
|
|
35
|
-
return operation();
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
handleComponentNotFoundError(error);
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC,wBAAgB,iBAAiB,IAAI,OAAO,CA4E3C"}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { writeFile } from 'node:fs/promises';
|
|
3
|
-
import { ComponentId } from '@living-architecture/riviere-builder';
|
|
4
|
-
import { getDefaultGraphPathDescription, resolveGraphPath } from '../../graph-path';
|
|
5
|
-
import { fileExists } from '../../file-existence';
|
|
6
|
-
import { formatSuccess } from '../../output';
|
|
7
|
-
import { isValidLinkType, normalizeComponentType } from '../../component-types';
|
|
8
|
-
import { validateComponentType, validateLinkType } from '../../validation';
|
|
9
|
-
import { loadGraphBuilder, reportGraphNotFound, tryBuilderOperation } from './link-infrastructure';
|
|
10
|
-
export function createLinkCommand() {
|
|
11
|
-
return new Command('link')
|
|
12
|
-
.description('Link two components')
|
|
13
|
-
.addHelpText('after', `
|
|
14
|
-
Examples:
|
|
15
|
-
$ riviere builder link \\
|
|
16
|
-
--from "orders:api:api:postorders" \\
|
|
17
|
-
--to-domain orders --to-module checkout --to-type UseCase --to-name "place-order" \\
|
|
18
|
-
--link-type sync
|
|
19
|
-
|
|
20
|
-
$ riviere builder link \\
|
|
21
|
-
--from "orders:checkout:domainop:orderbegin" \\
|
|
22
|
-
--to-domain orders --to-module events --to-type Event --to-name "order-placed" \\
|
|
23
|
-
--link-type async
|
|
24
|
-
`)
|
|
25
|
-
.requiredOption('--from <component-id>', 'Source component ID')
|
|
26
|
-
.requiredOption('--to-domain <domain>', 'Target domain')
|
|
27
|
-
.requiredOption('--to-module <module>', 'Target module')
|
|
28
|
-
.requiredOption('--to-type <type>', 'Target component type (UI, API, UseCase, DomainOp, Event, EventHandler, Custom)')
|
|
29
|
-
.requiredOption('--to-name <name>', 'Target component name')
|
|
30
|
-
.option('--link-type <type>', 'Link type (sync, async)')
|
|
31
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
32
|
-
.option('--json', 'Output result as JSON')
|
|
33
|
-
.action(async (options) => {
|
|
34
|
-
const componentTypeValidation = validateComponentType(options.toType);
|
|
35
|
-
if (!componentTypeValidation.valid) {
|
|
36
|
-
console.log(componentTypeValidation.errorJson);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const linkTypeValidation = validateLinkType(options.linkType);
|
|
40
|
-
if (!linkTypeValidation.valid) {
|
|
41
|
-
console.log(linkTypeValidation.errorJson);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
const graphPath = resolveGraphPath(options.graph);
|
|
45
|
-
const graphExists = await fileExists(graphPath);
|
|
46
|
-
if (!graphExists) {
|
|
47
|
-
reportGraphNotFound(graphPath);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
const builder = await loadGraphBuilder(graphPath);
|
|
51
|
-
const targetId = ComponentId.create({
|
|
52
|
-
domain: options.toDomain,
|
|
53
|
-
module: options.toModule,
|
|
54
|
-
type: normalizeComponentType(options.toType),
|
|
55
|
-
name: options.toName,
|
|
56
|
-
}).toString();
|
|
57
|
-
const linkInput = {
|
|
58
|
-
from: options.from,
|
|
59
|
-
to: targetId,
|
|
60
|
-
};
|
|
61
|
-
if (options.linkType !== undefined && isValidLinkType(options.linkType)) {
|
|
62
|
-
linkInput.type = options.linkType;
|
|
63
|
-
}
|
|
64
|
-
const linkResult = tryBuilderOperation(() => builder.link(linkInput));
|
|
65
|
-
if (linkResult === undefined) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
await writeFile(graphPath, builder.serialize(), 'utf-8');
|
|
69
|
-
if (options.json) {
|
|
70
|
-
console.log(JSON.stringify(formatSuccess({ link: linkResult })));
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,qBAAqB,IAAI,OAAO,CAgC/C"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { formatSuccess } from '../../output';
|
|
3
|
-
import { getDefaultGraphPathDescription } from '../../graph-path';
|
|
4
|
-
import { withGraphBuilder } from './link-infrastructure';
|
|
5
|
-
export function createValidateCommand() {
|
|
6
|
-
return new Command('validate')
|
|
7
|
-
.description('Validate the graph for errors and warnings')
|
|
8
|
-
.addHelpText('after', `
|
|
9
|
-
Examples:
|
|
10
|
-
$ riviere builder validate
|
|
11
|
-
$ riviere builder validate --json
|
|
12
|
-
$ riviere builder validate --graph .riviere/my-graph.json
|
|
13
|
-
`)
|
|
14
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
15
|
-
.option('--json', 'Output result as JSON')
|
|
16
|
-
.action(async (options) => {
|
|
17
|
-
await withGraphBuilder(options.graph, async (builder) => {
|
|
18
|
-
const validationResult = builder.validate();
|
|
19
|
-
const warnings = builder.warnings();
|
|
20
|
-
if (options.json === true) {
|
|
21
|
-
console.log(JSON.stringify(formatSuccess({
|
|
22
|
-
valid: validationResult.valid,
|
|
23
|
-
errors: validationResult.errors,
|
|
24
|
-
warnings,
|
|
25
|
-
})));
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Component } from '@living-architecture/riviere-schema';
|
|
2
|
-
export interface ComponentOutput {
|
|
3
|
-
id: string;
|
|
4
|
-
type: string;
|
|
5
|
-
name: string;
|
|
6
|
-
domain: string;
|
|
7
|
-
}
|
|
8
|
-
export declare function toComponentOutput(component: Component): ComponentOutput;
|
|
9
|
-
//# sourceMappingURL=component-output.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"component-output.d.ts","sourceRoot":"","sources":["../../../src/commands/query/component-output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAErE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,eAAe,CAOvE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../../src/commands/query/components.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,wBAAgB,uBAAuB,IAAI,OAAO,CA+CjD"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { formatSuccess, formatError } from '../../output';
|
|
3
|
-
import { CliErrorCode } from '../../error-codes';
|
|
4
|
-
import { withGraph, getDefaultGraphPathDescription } from './load-graph';
|
|
5
|
-
import { isValidComponentType, normalizeToSchemaComponentType, VALID_COMPONENT_TYPES } from '../../component-types';
|
|
6
|
-
import { toComponentOutput } from './component-output';
|
|
7
|
-
export function createComponentsCommand() {
|
|
8
|
-
return new Command('components')
|
|
9
|
-
.description('List components with optional filtering')
|
|
10
|
-
.addHelpText('after', `
|
|
11
|
-
Examples:
|
|
12
|
-
$ riviere query components
|
|
13
|
-
$ riviere query components --domain orders
|
|
14
|
-
$ riviere query components --type API --json
|
|
15
|
-
$ riviere query components --domain orders --type UseCase
|
|
16
|
-
`)
|
|
17
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
18
|
-
.option('--json', 'Output result as JSON')
|
|
19
|
-
.option('--domain <name>', 'Filter by domain name')
|
|
20
|
-
.option('--type <type>', 'Filter by component type')
|
|
21
|
-
.action(async (options) => {
|
|
22
|
-
if (options.type !== undefined && !isValidComponentType(options.type)) {
|
|
23
|
-
const errorMessage = `Invalid component type: ${options.type}. Valid types: ${VALID_COMPONENT_TYPES.join(', ')}`;
|
|
24
|
-
if (options.json) {
|
|
25
|
-
console.log(JSON.stringify(formatError(CliErrorCode.ValidationError, errorMessage)));
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
console.error(`Error: ${errorMessage}`);
|
|
29
|
-
}
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
await withGraph(options.graph, (query) => {
|
|
33
|
-
const allComponents = query.components();
|
|
34
|
-
const filteredByDomain = options.domain !== undefined
|
|
35
|
-
? allComponents.filter((c) => c.domain === options.domain)
|
|
36
|
-
: allComponents;
|
|
37
|
-
const typeFilter = options.type !== undefined ? normalizeToSchemaComponentType(options.type) : undefined;
|
|
38
|
-
const filteredByType = typeFilter !== undefined ? filteredByDomain.filter((c) => c.type === typeFilter) : filteredByDomain;
|
|
39
|
-
const components = filteredByType.map(toComponentOutput);
|
|
40
|
-
if (options.json) {
|
|
41
|
-
console.log(JSON.stringify(formatSuccess({ components })));
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"domains.d.ts","sourceRoot":"","sources":["../../../src/commands/query/domains.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AASnC,wBAAgB,oBAAoB,IAAI,OAAO,CAsB9C"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { formatSuccess } from '../../output';
|
|
3
|
-
import { withGraph, getDefaultGraphPathDescription } from './load-graph';
|
|
4
|
-
export function createDomainsCommand() {
|
|
5
|
-
return new Command('domains')
|
|
6
|
-
.description('List domains with component counts')
|
|
7
|
-
.addHelpText('after', `
|
|
8
|
-
Examples:
|
|
9
|
-
$ riviere query domains
|
|
10
|
-
$ riviere query domains --json
|
|
11
|
-
`)
|
|
12
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
13
|
-
.option('--json', 'Output result as JSON')
|
|
14
|
-
.action(async (options) => {
|
|
15
|
-
await withGraph(options.graph, (query) => {
|
|
16
|
-
const domains = query.domains();
|
|
17
|
-
if (options.json) {
|
|
18
|
-
console.log(JSON.stringify(formatSuccess({ domains })));
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"entry-points.d.ts","sourceRoot":"","sources":["../../../src/commands/query/entry-points.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AASnC,wBAAgB,wBAAwB,IAAI,OAAO,CAsBlD"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { formatSuccess } from '../../output';
|
|
3
|
-
import { withGraph, getDefaultGraphPathDescription } from './load-graph';
|
|
4
|
-
export function createEntryPointsCommand() {
|
|
5
|
-
return new Command('entry-points')
|
|
6
|
-
.description('List entry points (APIs, UIs, EventHandlers with no incoming links)')
|
|
7
|
-
.addHelpText('after', `
|
|
8
|
-
Examples:
|
|
9
|
-
$ riviere query entry-points
|
|
10
|
-
$ riviere query entry-points --json
|
|
11
|
-
`)
|
|
12
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
13
|
-
.option('--json', 'Output result as JSON')
|
|
14
|
-
.action(async (options) => {
|
|
15
|
-
await withGraph(options.graph, (query) => {
|
|
16
|
-
const entryPoints = query.entryPoints();
|
|
17
|
-
if (options.json) {
|
|
18
|
-
console.log(JSON.stringify(formatSuccess({ entryPoints })));
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { RiviereQuery } from '@living-architecture/riviere-query';
|
|
2
|
-
import { getDefaultGraphPathDescription } from '../../graph-path';
|
|
3
|
-
import { formatError } from '../../output';
|
|
4
|
-
export { getDefaultGraphPathDescription };
|
|
5
|
-
export interface LoadGraphResult {
|
|
6
|
-
query: RiviereQuery;
|
|
7
|
-
graphPath: string;
|
|
8
|
-
}
|
|
9
|
-
export interface LoadGraphError {
|
|
10
|
-
error: ReturnType<typeof formatError>;
|
|
11
|
-
}
|
|
12
|
-
declare function isLoadGraphError(result: LoadGraphResult | LoadGraphError): result is LoadGraphError;
|
|
13
|
-
export declare function loadGraph(graphPathOption?: string): Promise<LoadGraphResult | LoadGraphError>;
|
|
14
|
-
export declare function withGraph(graphPathOption: string | undefined, handler: (query: RiviereQuery) => Promise<void> | void): Promise<void>;
|
|
15
|
-
export { isLoadGraphError };
|
|
16
|
-
//# sourceMappingURL=load-graph.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"load-graph.d.ts","sourceRoot":"","sources":["../../../src/commands/query/load-graph.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AACjE,OAAO,EAAoB,8BAA8B,EAAE,MAAM,kBAAkB,CAAA;AAEnF,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG1C,OAAO,EAAE,8BAA8B,EAAE,CAAA;AAczC,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,YAAY,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;CACtC;AAED,iBAAS,gBAAgB,CAAC,MAAM,EAAE,eAAe,GAAG,cAAc,GAAG,MAAM,IAAI,cAAc,CAE5F;AAED,wBAAsB,SAAS,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,cAAc,CAAC,CA2BnG;AAED,wBAAsB,SAAS,CAC7B,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GACrD,OAAO,CAAC,IAAI,CAAC,CASf;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAA"}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { RiviereQuery } from '@living-architecture/riviere-query';
|
|
3
|
-
import { resolveGraphPath, getDefaultGraphPathDescription } from '../../graph-path';
|
|
4
|
-
import { fileExists } from '../../file-existence';
|
|
5
|
-
import { formatError } from '../../output';
|
|
6
|
-
import { CliErrorCode } from '../../error-codes';
|
|
7
|
-
export { getDefaultGraphPathDescription };
|
|
8
|
-
function parseJsonSafely(content) {
|
|
9
|
-
try {
|
|
10
|
-
return { success: true, data: JSON.parse(content) };
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
return { success: false };
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function isLoadGraphError(result) {
|
|
17
|
-
return 'error' in result;
|
|
18
|
-
}
|
|
19
|
-
export async function loadGraph(graphPathOption) {
|
|
20
|
-
const graphPath = resolveGraphPath(graphPathOption);
|
|
21
|
-
const graphExists = await fileExists(graphPath);
|
|
22
|
-
if (!graphExists) {
|
|
23
|
-
return {
|
|
24
|
-
error: formatError(CliErrorCode.GraphNotFound, `Graph not found at ${graphPath}`, [
|
|
25
|
-
'Run riviere builder init first',
|
|
26
|
-
]),
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
const content = await readFile(graphPath, 'utf-8');
|
|
30
|
-
const parseResult = parseJsonSafely(content);
|
|
31
|
-
if (!parseResult.success) {
|
|
32
|
-
return {
|
|
33
|
-
error: formatError(CliErrorCode.GraphCorrupted, `Graph file at ${graphPath} is not valid JSON`, [
|
|
34
|
-
'Check that the graph file contains valid JSON',
|
|
35
|
-
'Try running riviere builder init to create a new graph',
|
|
36
|
-
]),
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
const query = RiviereQuery.fromJSON(parseResult.data);
|
|
40
|
-
return { query, graphPath };
|
|
41
|
-
}
|
|
42
|
-
export async function withGraph(graphPathOption, handler) {
|
|
43
|
-
const result = await loadGraph(graphPathOption);
|
|
44
|
-
if (isLoadGraphError(result)) {
|
|
45
|
-
console.log(JSON.stringify(result.error));
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
await handler(result.query);
|
|
49
|
-
}
|
|
50
|
-
export { isLoadGraphError };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"orphans.d.ts","sourceRoot":"","sources":["../../../src/commands/query/orphans.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AASnC,wBAAgB,oBAAoB,IAAI,OAAO,CAsB9C"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { formatSuccess } from '../../output';
|
|
3
|
-
import { withGraph, getDefaultGraphPathDescription } from './load-graph';
|
|
4
|
-
export function createOrphansCommand() {
|
|
5
|
-
return new Command('orphans')
|
|
6
|
-
.description('Find orphan components with no links')
|
|
7
|
-
.addHelpText('after', `
|
|
8
|
-
Examples:
|
|
9
|
-
$ riviere query orphans
|
|
10
|
-
$ riviere query orphans --json
|
|
11
|
-
`)
|
|
12
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
13
|
-
.option('--json', 'Output result as JSON')
|
|
14
|
-
.action(async (options) => {
|
|
15
|
-
await withGraph(options.graph, (query) => {
|
|
16
|
-
const orphans = query.detectOrphans();
|
|
17
|
-
if (options.json) {
|
|
18
|
-
console.log(JSON.stringify(formatSuccess({ orphans })));
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/commands/query/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,mBAAmB,IAAI,OAAO,CAwB7C"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { formatSuccess } from '../../output';
|
|
3
|
-
import { withGraph, getDefaultGraphPathDescription } from './load-graph';
|
|
4
|
-
import { toComponentOutput } from './component-output';
|
|
5
|
-
export function createSearchCommand() {
|
|
6
|
-
return new Command('search')
|
|
7
|
-
.description('Search components by name')
|
|
8
|
-
.addHelpText('after', `
|
|
9
|
-
Examples:
|
|
10
|
-
$ riviere query search order
|
|
11
|
-
$ riviere query search "place-order" --json
|
|
12
|
-
`)
|
|
13
|
-
.argument('<term>', 'Search term')
|
|
14
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
15
|
-
.option('--json', 'Output result as JSON')
|
|
16
|
-
.action(async (term, options) => {
|
|
17
|
-
await withGraph(options.graph, (query) => {
|
|
18
|
-
const result = query.search(term);
|
|
19
|
-
const components = result.map(toComponentOutput);
|
|
20
|
-
if (options.json) {
|
|
21
|
-
console.log(JSON.stringify(formatSuccess({ components })));
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../../src/commands/query/trace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAYnC,wBAAgB,kBAAkB,IAAI,OAAO,CA0C5C"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { ComponentNotFoundError, parseComponentId } from '@living-architecture/riviere-query';
|
|
3
|
-
import { findNearMatches, ComponentId } from '@living-architecture/riviere-builder';
|
|
4
|
-
import { formatError, formatSuccess } from '../../output';
|
|
5
|
-
import { CliErrorCode } from '../../error-codes';
|
|
6
|
-
import { withGraph, getDefaultGraphPathDescription } from './load-graph';
|
|
7
|
-
export function createTraceCommand() {
|
|
8
|
-
return new Command('trace')
|
|
9
|
-
.description('Trace flow from a component (bidirectional)')
|
|
10
|
-
.addHelpText('after', `
|
|
11
|
-
Examples:
|
|
12
|
-
$ riviere query trace "orders:api:api:postorders"
|
|
13
|
-
$ riviere query trace "orders:checkout:usecase:placeorder" --json
|
|
14
|
-
`)
|
|
15
|
-
.argument('<componentId>', 'Component ID to trace from')
|
|
16
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
17
|
-
.option('--json', 'Output result as JSON')
|
|
18
|
-
.action(async (componentIdArg, options) => {
|
|
19
|
-
await withGraph(options.graph, (query) => {
|
|
20
|
-
try {
|
|
21
|
-
const componentId = parseComponentId(componentIdArg);
|
|
22
|
-
const flow = query.traceFlow(componentId);
|
|
23
|
-
if (options.json) {
|
|
24
|
-
console.log(JSON.stringify(formatSuccess(flow)));
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
if (error instanceof ComponentNotFoundError) {
|
|
29
|
-
const parsedId = ComponentId.parse(componentIdArg);
|
|
30
|
-
const matches = findNearMatches(query.components(), { name: parsedId.name() }, { limit: 3 });
|
|
31
|
-
/* v8 ignore next -- @preserve v8 fails to track inline arrow function coverage despite test execution */
|
|
32
|
-
const suggestions = matches.map((m) => m.component.id);
|
|
33
|
-
console.log(JSON.stringify(formatError(CliErrorCode.ComponentNotFound, error.message, suggestions)));
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
/* v8 ignore next -- @preserve v8 fails to track throw statement coverage despite test execution */
|
|
37
|
-
throw error;
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
}
|