@transitrix/diagrams 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/yaml-normalize.test.js +9 -9
- package/dist/activities/__tests__/gantt.test.js +39 -0
- package/dist/activities/__tests__/validate.test.js +77 -74
- package/dist/activities/validate.js +5 -12
- package/dist/activity-card/__tests__/example.test.js +2 -2
- package/dist/activity-card/__tests__/validate.test.js +29 -18
- package/dist/activity-card/validate.js +3 -10
- package/dist/actor/__tests__/validate.test.js +6 -0
- package/dist/actor/types.d.ts +1 -1
- package/dist/actor/types.js +2 -0
- package/dist/applications/types.d.ts +7 -0
- package/dist/applications/validate.js +18 -0
- package/dist/blocks/__tests__/layout.test.js +1 -1
- package/dist/blocks/layout.js +1 -1
- package/dist/business-service/__tests__/validate.test.d.ts +1 -0
- package/dist/business-service/__tests__/validate.test.js +135 -0
- package/dist/business-service/index.d.ts +3 -0
- package/dist/business-service/index.js +2 -0
- package/dist/business-service/types.d.ts +20 -0
- package/dist/business-service/types.js +3 -0
- package/dist/business-service/validate.d.ts +2 -0
- package/dist/business-service/validate.js +74 -0
- package/dist/fgca/__tests__/parse-canonical.test.js +10 -10
- package/dist/fgca/__tests__/resolver.test.js +7 -7
- package/dist/fgca/__tests__/validate.test.js +11 -11
- package/dist/fgca/parse-canonical.js +7 -11
- package/dist/fgca/resolver.d.ts +2 -2
- package/dist/fgca/resolver.js +5 -5
- package/dist/fgca/validate.js +4 -13
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/integration/__tests__/validate.test.d.ts +1 -0
- package/dist/integration/__tests__/validate.test.js +169 -0
- package/dist/integration/index.d.ts +2 -0
- package/dist/integration/index.js +1 -0
- package/dist/integration/types.d.ts +27 -0
- package/dist/integration/types.js +5 -0
- package/dist/integration/validate.d.ts +2 -0
- package/dist/integration/validate.js +94 -0
- package/dist/location/__tests__/validate.test.d.ts +1 -0
- package/dist/location/__tests__/validate.test.js +107 -0
- package/dist/location/index.d.ts +3 -0
- package/dist/location/index.js +2 -0
- package/dist/location/types.d.ts +20 -0
- package/dist/location/types.js +3 -0
- package/dist/location/validate.d.ts +2 -0
- package/dist/location/validate.js +63 -0
- package/dist/node/__tests__/validate.test.d.ts +1 -0
- package/dist/node/__tests__/validate.test.js +100 -0
- package/dist/node/index.d.ts +2 -0
- package/dist/node/index.js +1 -0
- package/dist/node/types.d.ts +18 -0
- package/dist/node/types.js +3 -0
- package/dist/node/validate.d.ts +2 -0
- package/dist/node/validate.js +53 -0
- package/dist/repo-validate/__tests__/validate-repo.test.js +444 -0
- package/dist/repo-validate/validate-repo.js +224 -10
- package/dist/technology-service/__tests__/validate.test.d.ts +1 -0
- package/dist/technology-service/__tests__/validate.test.js +121 -0
- package/dist/technology-service/index.d.ts +2 -0
- package/dist/technology-service/index.js +1 -0
- package/dist/technology-service/types.d.ts +18 -0
- package/dist/technology-service/types.js +3 -0
- package/dist/technology-service/validate.d.ts +2 -0
- package/dist/technology-service/validate.js +64 -0
- package/dist/webview/__tests__/entry-notations.test.js +2 -4
- package/dist/webview/__tests__/render-activities.test.d.ts +1 -0
- package/dist/webview/__tests__/render-activities.test.js +91 -0
- package/dist/webview/__tests__/render-blocks.test.d.ts +1 -0
- package/dist/webview/__tests__/render-blocks.test.js +178 -0
- package/dist/webview/entry.d.ts +1 -1
- package/dist/webview/entry.js +8 -15
- package/dist/webview/notation-style.d.ts +11 -0
- package/dist/webview/notation-style.js +11 -0
- package/dist/webview/render-activities.d.ts +12 -0
- package/dist/webview/render-activities.js +9 -3
- package/dist/webview/render-blocks.js +102 -19
- package/dist/webview/render-goals.js +2 -1
- package/package.json +1 -1
- package/src/__tests__/yaml-normalize.test.ts +11 -11
- package/src/activities/__tests__/gantt.test.ts +45 -0
- package/src/activities/__tests__/validate.test.ts +77 -74
- package/src/activities/validate.ts +5 -12
- package/src/activity-card/__tests__/example.test.ts +2 -2
- package/src/activity-card/__tests__/validate.test.ts +30 -18
- package/src/activity-card/validate.ts +3 -9
- package/src/actor/__tests__/validate.test.ts +8 -0
- package/src/actor/types.ts +2 -0
- package/src/applications/types.ts +8 -0
- package/src/applications/validate.ts +20 -0
- package/src/blocks/__tests__/layout.test.ts +1 -1
- package/src/blocks/layout.ts +1 -1
- package/src/business-service/__tests__/validate.test.ts +160 -0
- package/src/business-service/index.ts +3 -0
- package/src/business-service/types.ts +29 -0
- package/src/business-service/validate.ts +82 -0
- package/src/fgca/__tests__/parse-canonical.test.ts +10 -10
- package/src/fgca/__tests__/resolver.test.ts +7 -7
- package/src/fgca/__tests__/validate.test.ts +11 -11
- package/src/fgca/parse-canonical.ts +7 -11
- package/src/fgca/resolver.ts +5 -5
- package/src/fgca/validate.ts +4 -12
- package/src/index.ts +5 -0
- package/src/integration/__tests__/validate.test.ts +203 -0
- package/src/integration/index.ts +2 -0
- package/src/integration/types.ts +38 -0
- package/src/integration/validate.ts +104 -0
- package/src/location/__tests__/validate.test.ts +127 -0
- package/src/location/index.ts +3 -0
- package/src/location/types.ts +29 -0
- package/src/location/validate.ts +70 -0
- package/src/node/__tests__/validate.test.ts +118 -0
- package/src/node/index.ts +2 -0
- package/src/node/types.ts +27 -0
- package/src/node/validate.ts +59 -0
- package/src/repo-validate/__tests__/validate-repo.test.ts +550 -0
- package/src/repo-validate/validate-repo.ts +233 -10
- package/src/technology-service/__tests__/validate.test.ts +143 -0
- package/src/technology-service/index.ts +2 -0
- package/src/technology-service/types.ts +27 -0
- package/src/technology-service/validate.ts +71 -0
- package/src/webview/__tests__/entry-notations.test.ts +2 -4
- package/src/webview/__tests__/render-activities.test.ts +100 -0
- package/src/webview/__tests__/render-blocks.test.ts +209 -0
- package/src/webview/entry.ts +10 -19
- package/src/webview/notation-style.ts +12 -0
- package/src/webview/render-activities.ts +29 -4
- package/src/webview/render-blocks.ts +106 -21
- package/src/webview/render-goals.ts +2 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { validateNode } from '../validate.js';
|
|
3
|
+
|
|
4
|
+
function valid(): Record<string, unknown> {
|
|
5
|
+
return {
|
|
6
|
+
notation: 'node',
|
|
7
|
+
id: 'NODE-KAFKA-HOST-1',
|
|
8
|
+
name: 'Kafka Cluster Host',
|
|
9
|
+
type: 'cloud_instance',
|
|
10
|
+
description: 'AWS EC2 auto-scaling group hosting the Kafka broker cluster.',
|
|
11
|
+
provider: 'AWS',
|
|
12
|
+
region: 'eu-central-1',
|
|
13
|
+
zone: 'canon',
|
|
14
|
+
admitted_at: '2026-06-28',
|
|
15
|
+
admitted_by: 'v.korobeinikov',
|
|
16
|
+
gate_checks: { uniqueness: 'pass', consistency: 'pass', completeness: 'pass' },
|
|
17
|
+
valid_from: '2024-01-01',
|
|
18
|
+
valid_to: null,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const codes = (input: unknown): string[] =>
|
|
23
|
+
validateNode(input).errors.map(e => e.code);
|
|
24
|
+
|
|
25
|
+
describe('validateNode — positive', () => {
|
|
26
|
+
it('accepts a well-formed cloud_instance node with all optional fields', () => {
|
|
27
|
+
const r = validateNode(valid());
|
|
28
|
+
expect(r.valid, JSON.stringify(r.errors)).toBe(true);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('accepts a server node with no optional fields', () => {
|
|
32
|
+
const a = valid();
|
|
33
|
+
a.id = 'NODE-DB-1';
|
|
34
|
+
a.name = 'Primary DB Server';
|
|
35
|
+
a.type = 'server';
|
|
36
|
+
delete a.description;
|
|
37
|
+
delete a.provider;
|
|
38
|
+
delete a.region;
|
|
39
|
+
expect(validateNode(a).valid).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('accepts all five type values', () => {
|
|
43
|
+
for (const t of ['server', 'cloud_instance', 'container_platform', 'database_server', 'network_device']) {
|
|
44
|
+
expect(validateNode({ ...valid(), type: t }).valid).toBe(true);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('accepts valid_to as a date string', () => {
|
|
49
|
+
expect(validateNode({ ...valid(), valid_to: '2026-12-31' }).valid).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('validateNode — NOD-001 (shape / id grammar)', () => {
|
|
54
|
+
it('flags a non-object input', () => {
|
|
55
|
+
expect(codes(null)).toEqual(['NOD-001']);
|
|
56
|
+
expect(codes('string')).toEqual(['NOD-001']);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('flags an id that violates the grammar', () => {
|
|
60
|
+
expect(codes({ ...valid(), id: 'NODE-001' })).toContain('NOD-001');
|
|
61
|
+
expect(codes({ ...valid(), id: 'NOD-1' })).toContain('NOD-001');
|
|
62
|
+
expect(codes({ ...valid(), id: 'node-kafka-1' })).toContain('NOD-001');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('flags a wrong notation tag', () => {
|
|
66
|
+
expect(codes({ ...valid(), notation: 'nodes' })).toContain('NOD-001');
|
|
67
|
+
expect(codes({ ...valid(), notation: 'infrastructure' })).toContain('NOD-001');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('flags a non-canon zone', () => {
|
|
71
|
+
expect(codes({ ...valid(), zone: 'sandbox' })).toContain('NOD-001');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('flags a missing zone', () => {
|
|
75
|
+
const a = valid();
|
|
76
|
+
delete a.zone;
|
|
77
|
+
expect(codes(a)).toContain('NOD-001');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('flags a missing name', () => {
|
|
81
|
+
const a = valid();
|
|
82
|
+
delete a.name;
|
|
83
|
+
expect(codes(a)).toContain('NOD-001');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('flags a missing valid_to key', () => {
|
|
87
|
+
const a = valid();
|
|
88
|
+
delete a.valid_to;
|
|
89
|
+
expect(codes(a)).toContain('NOD-001');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('flags missing gate_checks', () => {
|
|
93
|
+
const a = valid();
|
|
94
|
+
delete a.gate_checks;
|
|
95
|
+
expect(codes(a)).toContain('NOD-001');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('flags a missing type', () => {
|
|
99
|
+
const a = valid();
|
|
100
|
+
delete a.type;
|
|
101
|
+
expect(codes(a)).toContain('NOD-001');
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('validateNode — NOD-002 (type enum)', () => {
|
|
106
|
+
it('flags a type outside the allowed enum', () => {
|
|
107
|
+
expect(codes({ ...valid(), type: 'virtual_machine' })).toContain('NOD-002');
|
|
108
|
+
expect(codes({ ...valid(), type: 'storage' })).toContain('NOD-002');
|
|
109
|
+
expect(codes({ ...valid(), type: 'cluster' })).toContain('NOD-002');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('does not flag a missing type with NOD-002 (NOD-001 fires instead)', () => {
|
|
113
|
+
const a = valid();
|
|
114
|
+
delete a.type;
|
|
115
|
+
expect(codes(a)).not.toContain('NOD-002');
|
|
116
|
+
expect(codes(a)).toContain('NOD-001');
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// NODE — technology-layer infrastructure node primitive (ArchiMate Technology Node).
|
|
2
|
+
// Schema: methodology notations/elements/25-nodes.md
|
|
3
|
+
|
|
4
|
+
import type { GateChecks } from '../requirement/types.js';
|
|
5
|
+
|
|
6
|
+
export const NODE_TYPES = ['server', 'cloud_instance', 'container_platform', 'database_server', 'network_device'] as const;
|
|
7
|
+
export type NodeType = typeof NODE_TYPES[number];
|
|
8
|
+
|
|
9
|
+
export interface Node {
|
|
10
|
+
notation: 'node';
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
type: NodeType;
|
|
14
|
+
description?: string;
|
|
15
|
+
provider?: string;
|
|
16
|
+
region?: string;
|
|
17
|
+
|
|
18
|
+
// Admission record (CONTRACT.md §6).
|
|
19
|
+
zone: 'canon';
|
|
20
|
+
admitted_at: string;
|
|
21
|
+
admitted_by: string;
|
|
22
|
+
gate_checks: GateChecks;
|
|
23
|
+
|
|
24
|
+
// Primitive lifecycle (CONTRACT.md §7).
|
|
25
|
+
valid_from: string;
|
|
26
|
+
valid_to: string | null;
|
|
27
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// NODE validator — methodology notations/elements/25-nodes.md §5.
|
|
2
|
+
//
|
|
3
|
+
// Implements NOD-001, NOD-002. The shared HDR-/LIFECYCLE- rules are
|
|
4
|
+
// cross-cutting concerns (CONTRACT.md §8) and out of scope for the
|
|
5
|
+
// single-artefact validator.
|
|
6
|
+
|
|
7
|
+
import type { ValidationError, ValidationWarning, ValidationResult } from '../validation-types.js';
|
|
8
|
+
import { isCanonicalIdOfType } from '../typed-id.js';
|
|
9
|
+
import { NODE_TYPES } from './types.js';
|
|
10
|
+
|
|
11
|
+
const REQUIRED_STRING_FIELDS = [
|
|
12
|
+
'name', 'admitted_at', 'admitted_by', 'valid_from',
|
|
13
|
+
] as const;
|
|
14
|
+
|
|
15
|
+
const TYPES: readonly string[] = NODE_TYPES;
|
|
16
|
+
|
|
17
|
+
export function validateNode(input: unknown): ValidationResult {
|
|
18
|
+
const errors: ValidationError[] = [];
|
|
19
|
+
const warnings: ValidationWarning[] = [];
|
|
20
|
+
|
|
21
|
+
if (input === null || typeof input !== 'object' || Array.isArray(input)) {
|
|
22
|
+
errors.push({ code: 'NOD-001', message: 'Node must be a YAML mapping.' });
|
|
23
|
+
return { valid: false, errors, warnings };
|
|
24
|
+
}
|
|
25
|
+
const a = input as Record<string, unknown>;
|
|
26
|
+
|
|
27
|
+
// NOD-001 — id grammar + notation tag + envelope.
|
|
28
|
+
if (!isCanonicalIdOfType(a.id, 'NODE')) {
|
|
29
|
+
errors.push({ code: 'NOD-001', message: `id "${String(a.id)}" must match NODE-[<middle>-]<INTEGER>.`, path: 'id' });
|
|
30
|
+
}
|
|
31
|
+
if (a.notation !== 'node') {
|
|
32
|
+
errors.push({ code: 'NOD-001', message: 'notation must be the fixed value "node".', path: 'notation' });
|
|
33
|
+
}
|
|
34
|
+
if (a.zone !== undefined && a.zone !== 'canon') {
|
|
35
|
+
errors.push({ code: 'NOD-001', message: 'zone must be "canon" for a NODE.', path: 'zone' });
|
|
36
|
+
} else if (a.zone === undefined) {
|
|
37
|
+
errors.push({ code: 'NOD-001', message: 'zone is required.', path: 'zone' });
|
|
38
|
+
}
|
|
39
|
+
for (const field of REQUIRED_STRING_FIELDS) {
|
|
40
|
+
const v = a[field];
|
|
41
|
+
if (typeof v !== 'string' || v.trim() === '') {
|
|
42
|
+
errors.push({ code: 'NOD-001', message: `${field} is required.`, path: field });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (a.gate_checks === null || typeof a.gate_checks !== 'object') {
|
|
46
|
+
errors.push({ code: 'NOD-001', message: 'gate_checks is required and must be a mapping.', path: 'gate_checks' });
|
|
47
|
+
}
|
|
48
|
+
if (!('valid_to' in a) || !(typeof a.valid_to === 'string' || a.valid_to === null)) {
|
|
49
|
+
errors.push({ code: 'NOD-001', message: 'valid_to is required (an ISO date string or null).', path: 'valid_to' });
|
|
50
|
+
}
|
|
51
|
+
if (typeof a.type !== 'string' || a.type.trim() === '') {
|
|
52
|
+
errors.push({ code: 'NOD-001', message: 'type is required.', path: 'type' });
|
|
53
|
+
} else if (!TYPES.includes(a.type)) {
|
|
54
|
+
// NOD-002 — type enum.
|
|
55
|
+
errors.push({ code: 'NOD-002', message: `type "${a.type}" must be one of ${TYPES.join(', ')}.`, path: 'type' });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
59
|
+
}
|