@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,56 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { writeFile } from 'node:fs/promises';
|
|
3
|
-
import { DuplicateDomainError } from '@living-architecture/riviere-builder';
|
|
4
|
-
import { formatError, formatSuccess } from '../../output';
|
|
5
|
-
import { CliErrorCode } from '../../error-codes';
|
|
6
|
-
import { getDefaultGraphPathDescription } from '../../graph-path';
|
|
7
|
-
import { isValidSystemType, VALID_SYSTEM_TYPES } from '../../component-types';
|
|
8
|
-
import { withGraphBuilder } from './link-infrastructure';
|
|
9
|
-
export function createAddDomainCommand() {
|
|
10
|
-
return new Command('add-domain')
|
|
11
|
-
.description('Add a domain to the graph')
|
|
12
|
-
.addHelpText('after', `
|
|
13
|
-
Examples:
|
|
14
|
-
$ riviere builder add-domain --name orders --system-type domain \\
|
|
15
|
-
--description "Order management"
|
|
16
|
-
|
|
17
|
-
$ riviere builder add-domain --name checkout-bff --system-type bff \\
|
|
18
|
-
--description "Checkout backend-for-frontend"
|
|
19
|
-
`)
|
|
20
|
-
.requiredOption('--name <name>', 'Domain name')
|
|
21
|
-
.requiredOption('--description <description>', 'Domain description')
|
|
22
|
-
.requiredOption('--system-type <type>', 'System type (domain, bff, ui, other)')
|
|
23
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
24
|
-
.option('--json', 'Output result as JSON')
|
|
25
|
-
.action(async (options) => {
|
|
26
|
-
if (!isValidSystemType(options.systemType)) {
|
|
27
|
-
console.log(JSON.stringify(formatError(CliErrorCode.ValidationError, `Invalid system type: ${options.systemType}`, [`Valid types: ${VALID_SYSTEM_TYPES.join(', ')}`])));
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const systemType = options.systemType;
|
|
31
|
-
await withGraphBuilder(options.graph, async (builder, graphPath) => {
|
|
32
|
-
try {
|
|
33
|
-
builder.addDomain({
|
|
34
|
-
name: options.name,
|
|
35
|
-
description: options.description,
|
|
36
|
-
systemType,
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
if (error instanceof DuplicateDomainError) {
|
|
41
|
-
console.log(JSON.stringify(formatError(CliErrorCode.DuplicateDomain, error.message, ['Use a different domain name'])));
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
throw error;
|
|
45
|
-
}
|
|
46
|
-
await writeFile(graphPath, builder.serialize(), 'utf-8');
|
|
47
|
-
if (options.json === true) {
|
|
48
|
-
console.log(JSON.stringify(formatSuccess({
|
|
49
|
-
name: options.name,
|
|
50
|
-
description: options.description,
|
|
51
|
-
systemType: options.systemType,
|
|
52
|
-
})));
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"add-source.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/add-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,sBAAsB,IAAI,OAAO,CA+BhD"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { writeFile } from 'node:fs/promises';
|
|
3
|
-
import { formatSuccess } from '../../output';
|
|
4
|
-
import { getDefaultGraphPathDescription } from '../../graph-path';
|
|
5
|
-
import { withGraphBuilder } from './link-infrastructure';
|
|
6
|
-
export function createAddSourceCommand() {
|
|
7
|
-
return new Command('add-source')
|
|
8
|
-
.description('Add a source repository to the graph')
|
|
9
|
-
.addHelpText('after', `
|
|
10
|
-
Examples:
|
|
11
|
-
$ riviere builder add-source --repository https://github.com/org/orders-service
|
|
12
|
-
$ riviere builder add-source --repository https://github.com/org/payments-api --json
|
|
13
|
-
`)
|
|
14
|
-
.requiredOption('--repository <url>', 'Source repository URL')
|
|
15
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
16
|
-
.option('--json', 'Output result as JSON')
|
|
17
|
-
.action(async (options) => {
|
|
18
|
-
await withGraphBuilder(options.graph, async (builder, graphPath) => {
|
|
19
|
-
builder.addSource({ repository: options.repository });
|
|
20
|
-
await writeFile(graphPath, builder.serialize(), 'utf-8');
|
|
21
|
-
if (options.json === true) {
|
|
22
|
-
console.log(JSON.stringify(formatSuccess({
|
|
23
|
-
repository: options.repository,
|
|
24
|
-
})));
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"check-consistency.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/check-consistency.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,6BAA6B,IAAI,OAAO,CA8BvD"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { getDefaultGraphPathDescription } from '../../graph-path';
|
|
3
|
-
import { formatSuccess } from '../../output';
|
|
4
|
-
import { withGraphBuilder } from './link-infrastructure';
|
|
5
|
-
export function createCheckConsistencyCommand() {
|
|
6
|
-
return new Command('check-consistency')
|
|
7
|
-
.description('Check for structural issues in the graph')
|
|
8
|
-
.addHelpText('after', `
|
|
9
|
-
Examples:
|
|
10
|
-
$ riviere builder check-consistency
|
|
11
|
-
$ riviere builder check-consistency --json
|
|
12
|
-
`)
|
|
13
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
14
|
-
.option('--json', 'Output result as JSON')
|
|
15
|
-
.action(async (options) => {
|
|
16
|
-
await withGraphBuilder(options.graph, async (builder) => {
|
|
17
|
-
const warnings = builder.warnings();
|
|
18
|
-
const consistent = warnings.length === 0;
|
|
19
|
-
if (options.json === true) {
|
|
20
|
-
console.log(JSON.stringify(formatSuccess({
|
|
21
|
-
consistent,
|
|
22
|
-
warnings,
|
|
23
|
-
})));
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"component-checklist.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/component-checklist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,+BAA+B,IAAI,OAAO,CAmDzD"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { getDefaultGraphPathDescription } from '../../graph-path';
|
|
3
|
-
import { formatError, formatSuccess } from '../../output';
|
|
4
|
-
import { CliErrorCode } from '../../error-codes';
|
|
5
|
-
import { isValidComponentType } from '../../component-types';
|
|
6
|
-
import { withGraphBuilder } from './link-infrastructure';
|
|
7
|
-
export function createComponentChecklistCommand() {
|
|
8
|
-
return new Command('component-checklist')
|
|
9
|
-
.description('List components as a checklist for linking/enrichment')
|
|
10
|
-
.addHelpText('after', `
|
|
11
|
-
Examples:
|
|
12
|
-
$ riviere builder component-checklist
|
|
13
|
-
$ riviere builder component-checklist --type DomainOp
|
|
14
|
-
$ riviere builder component-checklist --type API --json
|
|
15
|
-
`)
|
|
16
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
17
|
-
.option('--json', 'Output result as JSON')
|
|
18
|
-
.option('--type <type>', 'Filter by component type')
|
|
19
|
-
.action(async (options) => {
|
|
20
|
-
if (options.type !== undefined && !isValidComponentType(options.type)) {
|
|
21
|
-
console.log(JSON.stringify(formatError(CliErrorCode.InvalidComponentType, `Invalid component type: ${options.type}`, [
|
|
22
|
-
'Valid types: UI, API, UseCase, DomainOp, Event, EventHandler, Custom',
|
|
23
|
-
])));
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
await withGraphBuilder(options.graph, async (builder) => {
|
|
27
|
-
const allComponents = builder.query().components();
|
|
28
|
-
const filteredComponents = options.type !== undefined ? allComponents.filter((c) => c.type === options.type) : allComponents;
|
|
29
|
-
const checklistItems = filteredComponents.map((c) => ({
|
|
30
|
-
id: c.id,
|
|
31
|
-
type: c.type,
|
|
32
|
-
name: c.name,
|
|
33
|
-
domain: c.domain,
|
|
34
|
-
}));
|
|
35
|
-
if (options.json === true) {
|
|
36
|
-
console.log(JSON.stringify(formatSuccess({
|
|
37
|
-
total: checklistItems.length,
|
|
38
|
-
components: checklistItems,
|
|
39
|
-
})));
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"component-summary.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/component-summary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,6BAA6B,IAAI,OAAO,CAsBvD"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { getDefaultGraphPathDescription } from '../../graph-path';
|
|
3
|
-
import { formatSuccess } from '../../output';
|
|
4
|
-
import { withGraphBuilder } from './link-infrastructure';
|
|
5
|
-
export function createComponentSummaryCommand() {
|
|
6
|
-
return new Command('component-summary')
|
|
7
|
-
.description('Show component counts by type and domain')
|
|
8
|
-
.addHelpText('after', `
|
|
9
|
-
Examples:
|
|
10
|
-
$ riviere builder component-summary
|
|
11
|
-
$ riviere builder component-summary --json
|
|
12
|
-
`)
|
|
13
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
14
|
-
.option('--json', 'Output result as JSON')
|
|
15
|
-
.action(async (options) => {
|
|
16
|
-
await withGraphBuilder(options.graph, async (builder) => {
|
|
17
|
-
const stats = builder.stats();
|
|
18
|
-
if (options.json === true) {
|
|
19
|
-
console.log(JSON.stringify(formatSuccess(stats)));
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"enrich.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/enrich.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoDpC,wBAAgB,mBAAmB,IAAI,OAAO,CAsD7C"}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { writeFile } from 'node:fs/promises';
|
|
3
|
-
import { InvalidEnrichmentTargetError } from '@living-architecture/riviere-builder';
|
|
4
|
-
import { withGraphBuilder, handleComponentNotFoundError } from './link-infrastructure';
|
|
5
|
-
import { formatError, formatSuccess } from '../../output';
|
|
6
|
-
import { CliErrorCode } from '../../error-codes';
|
|
7
|
-
import { getDefaultGraphPathDescription } from '../../graph-path';
|
|
8
|
-
function collectOption(value, previous) {
|
|
9
|
-
return [...previous, value];
|
|
10
|
-
}
|
|
11
|
-
function parseStateChange(input) {
|
|
12
|
-
const [from, to, ...rest] = input.split(':');
|
|
13
|
-
if (from === undefined || to === undefined || rest.length > 0) {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
return { from, to };
|
|
17
|
-
}
|
|
18
|
-
function parseStateChanges(inputs) {
|
|
19
|
-
const stateChanges = [];
|
|
20
|
-
for (const sc of inputs) {
|
|
21
|
-
const parsed = parseStateChange(sc);
|
|
22
|
-
if (parsed === undefined) {
|
|
23
|
-
return { success: false, invalidInput: sc };
|
|
24
|
-
}
|
|
25
|
-
stateChanges.push(parsed);
|
|
26
|
-
}
|
|
27
|
-
return { success: true, stateChanges };
|
|
28
|
-
}
|
|
29
|
-
function handleEnrichmentError(error) {
|
|
30
|
-
if (error instanceof InvalidEnrichmentTargetError) {
|
|
31
|
-
console.log(JSON.stringify(formatError(CliErrorCode.InvalidComponentType, error.message, [])));
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
handleComponentNotFoundError(error);
|
|
35
|
-
}
|
|
36
|
-
export function createEnrichCommand() {
|
|
37
|
-
return new Command('enrich')
|
|
38
|
-
.description('Enrich a DomainOp component with entity, state changes, and business rules')
|
|
39
|
-
.addHelpText('after', `
|
|
40
|
-
Examples:
|
|
41
|
-
$ riviere builder enrich \\
|
|
42
|
-
--id "orders:checkout:domainop:orderbegin" \\
|
|
43
|
-
--entity Order \\
|
|
44
|
-
--state-change "Draft:Placed" \\
|
|
45
|
-
--business-rule "Order must have at least one item"
|
|
46
|
-
|
|
47
|
-
$ riviere builder enrich \\
|
|
48
|
-
--id "payments:gateway:domainop:paymentprocess" \\
|
|
49
|
-
--state-change "Pending:Processing" \\
|
|
50
|
-
--state-change "Processing:Completed" \\
|
|
51
|
-
--business-rule "Amount must be positive" \\
|
|
52
|
-
--business-rule "Currency must be valid"
|
|
53
|
-
`)
|
|
54
|
-
.requiredOption('--id <component-id>', 'Component ID to enrich')
|
|
55
|
-
.option('--entity <name>', 'Entity name')
|
|
56
|
-
.option('--state-change <from:to>', 'State transition (repeatable)', collectOption, [])
|
|
57
|
-
.option('--business-rule <rule>', 'Business rule (repeatable)', collectOption, [])
|
|
58
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
59
|
-
.option('--json', 'Output result as JSON')
|
|
60
|
-
.action(async (options) => {
|
|
61
|
-
const parseResult = parseStateChanges(options.stateChange);
|
|
62
|
-
if (!parseResult.success) {
|
|
63
|
-
const msg = `Invalid state-change format: '${parseResult.invalidInput}'. Expected 'from:to'.`;
|
|
64
|
-
console.log(JSON.stringify(formatError(CliErrorCode.ValidationError, msg, [])));
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
await withGraphBuilder(options.graph, async (builder, graphPath) => {
|
|
68
|
-
try {
|
|
69
|
-
builder.enrichComponent(options.id, {
|
|
70
|
-
...(options.entity !== undefined && { entity: options.entity }),
|
|
71
|
-
...(parseResult.stateChanges.length > 0 && { stateChanges: parseResult.stateChanges }),
|
|
72
|
-
...(options.businessRule.length > 0 && { businessRules: options.businessRule }),
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
handleEnrichmentError(error);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
await writeFile(graphPath, builder.serialize(), 'utf-8');
|
|
80
|
-
if (options.json === true) {
|
|
81
|
-
console.log(JSON.stringify(formatSuccess({ componentId: options.id })));
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"finalize.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/finalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,qBAAqB,IAAI,OAAO,CAwC/C"}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { writeFile } from 'node:fs/promises';
|
|
3
|
-
import { formatError, formatSuccess } from '../../output';
|
|
4
|
-
import { CliErrorCode } from '../../error-codes';
|
|
5
|
-
import { getDefaultGraphPathDescription } from '../../graph-path';
|
|
6
|
-
import { withGraphBuilder } from './link-infrastructure';
|
|
7
|
-
export function createFinalizeCommand() {
|
|
8
|
-
return new Command('finalize')
|
|
9
|
-
.description('Validate and export the final graph')
|
|
10
|
-
.addHelpText('after', `
|
|
11
|
-
Examples:
|
|
12
|
-
$ riviere builder finalize
|
|
13
|
-
$ riviere builder finalize --output ./dist/architecture.json
|
|
14
|
-
$ riviere builder finalize --json
|
|
15
|
-
`)
|
|
16
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
17
|
-
.option('--output <path>', 'Output path for finalized graph (defaults to input path)')
|
|
18
|
-
.option('--json', 'Output result as JSON')
|
|
19
|
-
.action(async (options) => {
|
|
20
|
-
await withGraphBuilder(options.graph, async (builder, graphPath) => {
|
|
21
|
-
const validationResult = builder.validate();
|
|
22
|
-
if (!validationResult.valid) {
|
|
23
|
-
const messages = validationResult.errors.map((e) => e.message).join('; ');
|
|
24
|
-
console.log(JSON.stringify(formatError(CliErrorCode.ValidationError, `Validation failed: ${messages}`, [
|
|
25
|
-
'Fix the validation errors and try again',
|
|
26
|
-
])));
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
const outputPath = options.output ?? graphPath;
|
|
30
|
-
const finalGraph = builder.build();
|
|
31
|
-
await writeFile(outputPath, JSON.stringify(finalGraph, null, 2), 'utf-8');
|
|
32
|
-
if (options.json === true) {
|
|
33
|
-
console.log(JSON.stringify(formatSuccess({ path: outputPath })));
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqDpC,wBAAgB,iBAAiB,IAAI,OAAO,CAiG3C"}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { mkdir, writeFile } from 'node:fs/promises';
|
|
3
|
-
import { dirname } from 'node:path';
|
|
4
|
-
import { RiviereBuilder } from '@living-architecture/riviere-builder';
|
|
5
|
-
import { formatError, formatSuccess } from '../../output';
|
|
6
|
-
import { CliErrorCode } from '../../error-codes';
|
|
7
|
-
import { fileExists } from '../../file-existence';
|
|
8
|
-
import { resolveGraphPath, getDefaultGraphPathDescription } from '../../graph-path';
|
|
9
|
-
import { isValidSystemType } from '../../component-types';
|
|
10
|
-
function isDomainInputParsed(value) {
|
|
11
|
-
if (typeof value !== 'object' || value === null) {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
return ('name' in value &&
|
|
15
|
-
typeof value.name === 'string' &&
|
|
16
|
-
'description' in value &&
|
|
17
|
-
typeof value.description === 'string' &&
|
|
18
|
-
'systemType' in value &&
|
|
19
|
-
typeof value.systemType === 'string' &&
|
|
20
|
-
isValidSystemType(value.systemType));
|
|
21
|
-
}
|
|
22
|
-
function parseDomainJson(value, previous) {
|
|
23
|
-
const parsed = JSON.parse(value);
|
|
24
|
-
if (!isDomainInputParsed(parsed)) {
|
|
25
|
-
throw new Error(`Invalid domain JSON: ${value}`);
|
|
26
|
-
}
|
|
27
|
-
return [...previous, parsed];
|
|
28
|
-
}
|
|
29
|
-
function collectSource(value, previous) {
|
|
30
|
-
return [...previous, value];
|
|
31
|
-
}
|
|
32
|
-
export function createInitCommand() {
|
|
33
|
-
return new Command('init')
|
|
34
|
-
.description('Initialize a new graph')
|
|
35
|
-
.addHelpText('after', `
|
|
36
|
-
Examples:
|
|
37
|
-
$ riviere builder init --source https://github.com/org/repo \\
|
|
38
|
-
--domain '{"name":"orders","description":"Order management","systemType":"domain"}'
|
|
39
|
-
|
|
40
|
-
$ riviere builder init --name "ecommerce" \\
|
|
41
|
-
--source https://github.com/org/orders \\
|
|
42
|
-
--source https://github.com/org/payments \\
|
|
43
|
-
--domain '{"name":"orders","description":"Order management","systemType":"domain"}' \\
|
|
44
|
-
--domain '{"name":"payments","description":"Payment processing","systemType":"domain"}'
|
|
45
|
-
`)
|
|
46
|
-
.option('--name <name>', 'System name')
|
|
47
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
48
|
-
.option('--json', 'Output result as JSON')
|
|
49
|
-
.option('--source <url>', 'Source repository URL (repeatable)', collectSource, [])
|
|
50
|
-
.option('--domain <json>', 'Domain as JSON (repeatable)', parseDomainJson, [])
|
|
51
|
-
.action(async (options) => {
|
|
52
|
-
// Validate required flags
|
|
53
|
-
if (options.source.length === 0) {
|
|
54
|
-
console.log(JSON.stringify(formatError(CliErrorCode.ValidationError, 'At least one source required', [
|
|
55
|
-
'Add --source <url> flag',
|
|
56
|
-
])));
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
if (options.domain.length === 0) {
|
|
60
|
-
console.log(JSON.stringify(formatError(CliErrorCode.ValidationError, 'At least one domain required', [
|
|
61
|
-
'Add --domain <json> flag',
|
|
62
|
-
])));
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
const graphPath = resolveGraphPath(options.graph);
|
|
66
|
-
const graphDir = dirname(graphPath);
|
|
67
|
-
const graphExists = await fileExists(graphPath);
|
|
68
|
-
if (graphExists) {
|
|
69
|
-
console.log(JSON.stringify(formatError(CliErrorCode.GraphExists, `Graph already exists at ${graphPath}`, [
|
|
70
|
-
'Delete the file to reinitialize',
|
|
71
|
-
])));
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const domains = {};
|
|
75
|
-
for (const d of options.domain) {
|
|
76
|
-
domains[d.name] = {
|
|
77
|
-
description: d.description,
|
|
78
|
-
systemType: d.systemType,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
const builderOptions = {
|
|
82
|
-
sources: options.source.map((url) => ({ repository: url })),
|
|
83
|
-
domains,
|
|
84
|
-
};
|
|
85
|
-
if (options.name !== undefined) {
|
|
86
|
-
builderOptions.name = options.name;
|
|
87
|
-
}
|
|
88
|
-
const builder = RiviereBuilder.new(builderOptions);
|
|
89
|
-
await mkdir(graphDir, { recursive: true });
|
|
90
|
-
await writeFile(graphPath, builder.serialize(), 'utf-8');
|
|
91
|
-
if (options.json === true) {
|
|
92
|
-
const domainNames = options.domain.map((d) => d.name);
|
|
93
|
-
console.log(JSON.stringify(formatSuccess({
|
|
94
|
-
path: graphPath,
|
|
95
|
-
sources: options.source.length,
|
|
96
|
-
domains: domainNames,
|
|
97
|
-
})));
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"link-external.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/link-external.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkCpC,wBAAgB,yBAAyB,IAAI,OAAO,CAiEnD"}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { writeFile } from 'node:fs/promises';
|
|
3
|
-
import { getDefaultGraphPathDescription, resolveGraphPath } from '../../graph-path';
|
|
4
|
-
import { fileExists } from '../../file-existence';
|
|
5
|
-
import { formatSuccess } from '../../output';
|
|
6
|
-
import { isValidLinkType } from '../../component-types';
|
|
7
|
-
import { validateLinkType } from '../../validation';
|
|
8
|
-
import { loadGraphBuilder, reportGraphNotFound, tryBuilderOperation } from './link-infrastructure';
|
|
9
|
-
function buildExternalTarget(options) {
|
|
10
|
-
return {
|
|
11
|
-
name: options.targetName,
|
|
12
|
-
...(options.targetDomain && { domain: options.targetDomain }),
|
|
13
|
-
...(options.targetUrl && { url: options.targetUrl }),
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
export function createLinkExternalCommand() {
|
|
17
|
-
return new Command('link-external')
|
|
18
|
-
.description('Link a component to an external system')
|
|
19
|
-
.addHelpText('after', `
|
|
20
|
-
Examples:
|
|
21
|
-
$ riviere builder link-external \\
|
|
22
|
-
--from "payments:gateway:usecase:processpayment" \\
|
|
23
|
-
--target-name "Stripe" \\
|
|
24
|
-
--target-url "https://api.stripe.com" \\
|
|
25
|
-
--link-type sync
|
|
26
|
-
|
|
27
|
-
$ riviere builder link-external \\
|
|
28
|
-
--from "shipping:tracking:usecase:updatetracking" \\
|
|
29
|
-
--target-name "FedEx API" \\
|
|
30
|
-
--target-domain "shipping" \\
|
|
31
|
-
--link-type async
|
|
32
|
-
`)
|
|
33
|
-
.requiredOption('--from <component-id>', 'Source component ID')
|
|
34
|
-
.requiredOption('--target-name <name>', 'External target name')
|
|
35
|
-
.option('--target-domain <domain>', 'External target domain')
|
|
36
|
-
.option('--target-url <url>', 'External target URL')
|
|
37
|
-
.option('--link-type <type>', 'Link type (sync, async)')
|
|
38
|
-
.option('--graph <path>', getDefaultGraphPathDescription())
|
|
39
|
-
.option('--json', 'Output result as JSON')
|
|
40
|
-
.action(async (options) => {
|
|
41
|
-
const linkTypeValidation = validateLinkType(options.linkType);
|
|
42
|
-
if (!linkTypeValidation.valid) {
|
|
43
|
-
console.log(linkTypeValidation.errorJson);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
const graphPath = resolveGraphPath(options.graph);
|
|
47
|
-
const graphExists = await fileExists(graphPath);
|
|
48
|
-
if (!graphExists) {
|
|
49
|
-
reportGraphNotFound(graphPath);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
const builder = await loadGraphBuilder(graphPath);
|
|
53
|
-
const target = buildExternalTarget(options);
|
|
54
|
-
const externalLinkInput = {
|
|
55
|
-
from: options.from,
|
|
56
|
-
target,
|
|
57
|
-
};
|
|
58
|
-
if (options.linkType !== undefined && isValidLinkType(options.linkType)) {
|
|
59
|
-
externalLinkInput.type = options.linkType;
|
|
60
|
-
}
|
|
61
|
-
const externalLink = tryBuilderOperation(() => builder.linkExternal(externalLinkInput));
|
|
62
|
-
if (externalLink === undefined) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
await writeFile(graphPath, builder.serialize(), 'utf-8');
|
|
66
|
-
if (options.json) {
|
|
67
|
-
console.log(JSON.stringify(formatSuccess({ externalLink })));
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"link-http.d.ts","sourceRoot":"","sources":["../../../src/commands/builder/link-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoGpC,wBAAgB,qBAAqB,IAAI,OAAO,CA+F/C"}
|