@the-cascade-protocol/cli 0.2.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/.dockerignore +7 -0
- package/.eslintrc.json +23 -0
- package/.prettierrc +7 -0
- package/DOCKER.md +36 -0
- package/Dockerfile +18 -0
- package/README.md +69 -0
- package/dist/commands/capabilities.d.ts +9 -0
- package/dist/commands/capabilities.d.ts.map +1 -0
- package/dist/commands/capabilities.js +194 -0
- package/dist/commands/capabilities.js.map +1 -0
- package/dist/commands/conformance.d.ts +15 -0
- package/dist/commands/conformance.d.ts.map +1 -0
- package/dist/commands/conformance.js +348 -0
- package/dist/commands/conformance.js.map +1 -0
- package/dist/commands/convert.d.ts +21 -0
- package/dist/commands/convert.d.ts.map +1 -0
- package/dist/commands/convert.js +134 -0
- package/dist/commands/convert.js.map +1 -0
- package/dist/commands/pod/export.d.ts +8 -0
- package/dist/commands/pod/export.d.ts.map +1 -0
- package/dist/commands/pod/export.js +72 -0
- package/dist/commands/pod/export.js.map +1 -0
- package/dist/commands/pod/helpers.d.ts +79 -0
- package/dist/commands/pod/helpers.d.ts.map +1 -0
- package/dist/commands/pod/helpers.js +369 -0
- package/dist/commands/pod/helpers.js.map +1 -0
- package/dist/commands/pod/index.d.ts +20 -0
- package/dist/commands/pod/index.d.ts.map +1 -0
- package/dist/commands/pod/index.js +29 -0
- package/dist/commands/pod/index.js.map +1 -0
- package/dist/commands/pod/info.d.ts +9 -0
- package/dist/commands/pod/info.d.ts.map +1 -0
- package/dist/commands/pod/info.js +196 -0
- package/dist/commands/pod/info.js.map +1 -0
- package/dist/commands/pod/init.d.ts +9 -0
- package/dist/commands/pod/init.d.ts.map +1 -0
- package/dist/commands/pod/init.js +251 -0
- package/dist/commands/pod/init.js.map +1 -0
- package/dist/commands/pod/query.d.ts +9 -0
- package/dist/commands/pod/query.d.ts.map +1 -0
- package/dist/commands/pod/query.js +169 -0
- package/dist/commands/pod/query.js.map +1 -0
- package/dist/commands/pod 2.js +1017 -0
- package/dist/commands/pod.d.ts +28 -0
- package/dist/commands/pod.d.ts 2.map +1 -0
- package/dist/commands/pod.d.ts.map +1 -0
- package/dist/commands/pod.js +1031 -0
- package/dist/commands/pod.js 2.map +1 -0
- package/dist/commands/pod.js.map +1 -0
- package/dist/commands/serve.d.ts +33 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +74 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/validate.d.ts +18 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +275 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/fhir-converter/cascade-to-fhir.d.ts +17 -0
- package/dist/lib/fhir-converter/cascade-to-fhir.d.ts.map +1 -0
- package/dist/lib/fhir-converter/cascade-to-fhir.js +358 -0
- package/dist/lib/fhir-converter/cascade-to-fhir.js.map +1 -0
- package/dist/lib/fhir-converter/converters-clinical.d.ts +29 -0
- package/dist/lib/fhir-converter/converters-clinical.d.ts.map +1 -0
- package/dist/lib/fhir-converter/converters-clinical.js +391 -0
- package/dist/lib/fhir-converter/converters-clinical.js.map +1 -0
- package/dist/lib/fhir-converter/converters-demographics.d.ts +20 -0
- package/dist/lib/fhir-converter/converters-demographics.d.ts.map +1 -0
- package/dist/lib/fhir-converter/converters-demographics.js +242 -0
- package/dist/lib/fhir-converter/converters-demographics.js.map +1 -0
- package/dist/lib/fhir-converter/fhir-to-cascade.d.ts +17 -0
- package/dist/lib/fhir-converter/fhir-to-cascade.d.ts.map +1 -0
- package/dist/lib/fhir-converter/fhir-to-cascade.js +63 -0
- package/dist/lib/fhir-converter/fhir-to-cascade.js.map +1 -0
- package/dist/lib/fhir-converter/index.d.ts +36 -0
- package/dist/lib/fhir-converter/index.d.ts.map +1 -0
- package/dist/lib/fhir-converter/index.js +187 -0
- package/dist/lib/fhir-converter/index.js.map +1 -0
- package/dist/lib/fhir-converter/types.d.ts +77 -0
- package/dist/lib/fhir-converter/types.d.ts.map +1 -0
- package/dist/lib/fhir-converter/types.js +236 -0
- package/dist/lib/fhir-converter/types.js.map +1 -0
- package/dist/lib/fhir-converter.d.ts +62 -0
- package/dist/lib/fhir-converter.d.ts.map +1 -0
- package/dist/lib/fhir-converter.js +1474 -0
- package/dist/lib/fhir-converter.js.map +1 -0
- package/dist/lib/mcp/audit.d.ts +24 -0
- package/dist/lib/mcp/audit.d.ts.map +1 -0
- package/dist/lib/mcp/audit.js +85 -0
- package/dist/lib/mcp/audit.js.map +1 -0
- package/dist/lib/mcp/server.d.ts +38 -0
- package/dist/lib/mcp/server.d.ts.map +1 -0
- package/dist/lib/mcp/server.js +172 -0
- package/dist/lib/mcp/server.js.map +1 -0
- package/dist/lib/mcp/tools.d.ts +47 -0
- package/dist/lib/mcp/tools.d.ts.map +1 -0
- package/dist/lib/mcp/tools.js +547 -0
- package/dist/lib/mcp/tools.js.map +1 -0
- package/dist/lib/output.d.ts +26 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +64 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/shacl-validator.d.ts +53 -0
- package/dist/lib/shacl-validator.d.ts.map +1 -0
- package/dist/lib/shacl-validator.js +245 -0
- package/dist/lib/shacl-validator.js.map +1 -0
- package/dist/lib/turtle-parser.d.ts +64 -0
- package/dist/lib/turtle-parser.d.ts.map +1 -0
- package/dist/lib/turtle-parser.js +236 -0
- package/dist/lib/turtle-parser.js.map +1 -0
- package/dist/shapes/checkup.shapes.ttl +1459 -0
- package/dist/shapes/clinical.shapes.ttl +1350 -0
- package/dist/shapes/clinical.ttl +1369 -0
- package/dist/shapes/core.shapes.ttl +450 -0
- package/dist/shapes/core.ttl +603 -0
- package/dist/shapes/coverage.shapes.ttl +214 -0
- package/dist/shapes/coverage.ttl +182 -0
- package/dist/shapes/health.shapes.ttl +697 -0
- package/dist/shapes/health.ttl +859 -0
- package/dist/shapes/pots.shapes.ttl +481 -0
- package/package.json +54 -0
- package/src/commands/capabilities.ts +235 -0
- package/src/commands/conformance.ts +447 -0
- package/src/commands/convert.ts +164 -0
- package/src/commands/pod/export.ts +85 -0
- package/src/commands/pod/helpers.ts +449 -0
- package/src/commands/pod/index.ts +32 -0
- package/src/commands/pod/info.ts +239 -0
- package/src/commands/pod/init.ts +273 -0
- package/src/commands/pod/query.ts +224 -0
- package/src/commands/serve.ts +92 -0
- package/src/commands/validate.ts +303 -0
- package/src/index.ts +58 -0
- package/src/lib/fhir-converter/cascade-to-fhir.ts +369 -0
- package/src/lib/fhir-converter/converters-clinical.ts +446 -0
- package/src/lib/fhir-converter/converters-demographics.ts +270 -0
- package/src/lib/fhir-converter/fhir-to-cascade.ts +82 -0
- package/src/lib/fhir-converter/index.ts +215 -0
- package/src/lib/fhir-converter/types.ts +318 -0
- package/src/lib/mcp/audit.ts +107 -0
- package/src/lib/mcp/server.ts +192 -0
- package/src/lib/mcp/tools.ts +668 -0
- package/src/lib/output.ts +76 -0
- package/src/lib/shacl-validator.ts +314 -0
- package/src/lib/turtle-parser.ts +277 -0
- package/src/shapes/checkup.shapes.ttl +1459 -0
- package/src/shapes/clinical.shapes.ttl +1350 -0
- package/src/shapes/clinical.ttl +1369 -0
- package/src/shapes/core.shapes.ttl +450 -0
- package/src/shapes/core.ttl +603 -0
- package/src/shapes/coverage.shapes.ttl +214 -0
- package/src/shapes/coverage.ttl +182 -0
- package/src/shapes/health.shapes.ttl +697 -0
- package/src/shapes/health.ttl +859 -0
- package/src/shapes/pots.shapes.ttl +481 -0
- package/test-fixtures/fhir-bundle-example.json +216 -0
- package/test-fixtures/fhir-medication-example.json +18 -0
- package/tests/cli.test.ts +126 -0
- package/tests/fhir-converter.test.ts +874 -0
- package/tests/mcp-server.test.ts +396 -0
- package/tests/pod.test.ts +400 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cascade conformance run
|
|
3
|
+
*
|
|
4
|
+
* Run conformance test suite against a CLI command or self-test.
|
|
5
|
+
*
|
|
6
|
+
* Options:
|
|
7
|
+
* --suite <fixtures-dir> Path to test fixtures directory
|
|
8
|
+
* --command "<cmd>" External command to test
|
|
9
|
+
* --self Run self-conformance tests
|
|
10
|
+
* --json Output results as JSON
|
|
11
|
+
* --verbose Show detailed test output
|
|
12
|
+
*/
|
|
13
|
+
import fs from 'node:fs';
|
|
14
|
+
import path from 'node:path';
|
|
15
|
+
import { loadShapes, validateTurtle } from '../lib/shacl-validator.js';
|
|
16
|
+
import { parseTurtle } from '../lib/turtle-parser.js';
|
|
17
|
+
import { printResult, printError, printVerbose } from '../lib/output.js';
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Fixture loading
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
/**
|
|
22
|
+
* Load and parse all `.json` fixture files from the given directory.
|
|
23
|
+
* Files are sorted by id so output order is deterministic.
|
|
24
|
+
*/
|
|
25
|
+
function loadFixtures(suiteDir) {
|
|
26
|
+
if (!fs.existsSync(suiteDir)) {
|
|
27
|
+
throw new Error(`Fixtures directory not found: ${suiteDir}`);
|
|
28
|
+
}
|
|
29
|
+
const files = fs
|
|
30
|
+
.readdirSync(suiteDir)
|
|
31
|
+
.filter((f) => f.endsWith('.json'))
|
|
32
|
+
.sort();
|
|
33
|
+
if (files.length === 0) {
|
|
34
|
+
throw new Error(`No .json fixture files found in ${suiteDir}`);
|
|
35
|
+
}
|
|
36
|
+
const fixtures = [];
|
|
37
|
+
for (const file of files) {
|
|
38
|
+
const filePath = path.join(suiteDir, file);
|
|
39
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
40
|
+
const fixture = JSON.parse(raw);
|
|
41
|
+
fixtures.push(fixture);
|
|
42
|
+
}
|
|
43
|
+
return fixtures;
|
|
44
|
+
}
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Self-conformance runner
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
/**
|
|
49
|
+
* Run a single fixture in self-conformance mode.
|
|
50
|
+
*
|
|
51
|
+
* Positive fixtures (shouldAccept === true):
|
|
52
|
+
* - Parse the expected turtle
|
|
53
|
+
* - Run SHACL validation
|
|
54
|
+
* - PASS if no violations; FAIL otherwise
|
|
55
|
+
*
|
|
56
|
+
* Negative fixtures (shouldAccept === false):
|
|
57
|
+
* - If turtle is empty: PASS (rejection before serialization)
|
|
58
|
+
* - If turtle is non-empty: SHACL validate — PASS if violations found, FAIL if clean
|
|
59
|
+
*/
|
|
60
|
+
function runSelfFixture(fixture, shapesStore, shapeFiles, opts) {
|
|
61
|
+
const base = {
|
|
62
|
+
id: fixture.id,
|
|
63
|
+
description: fixture.description,
|
|
64
|
+
dataType: fixture.dataType,
|
|
65
|
+
negative: !fixture.shouldAccept,
|
|
66
|
+
};
|
|
67
|
+
const turtle = fixture.expectedOutput.turtle;
|
|
68
|
+
const validationMode = fixture.expectedOutput.validationMode;
|
|
69
|
+
try {
|
|
70
|
+
if (fixture.shouldAccept) {
|
|
71
|
+
// ---- Positive fixture ----
|
|
72
|
+
// Step 1: Parse the turtle
|
|
73
|
+
const parseResult = parseTurtle(turtle);
|
|
74
|
+
if (!parseResult.success) {
|
|
75
|
+
return {
|
|
76
|
+
...base,
|
|
77
|
+
status: 'failed',
|
|
78
|
+
details: `Turtle parse error: ${parseResult.errors.join('; ')}`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// Step 2: SHACL validation
|
|
82
|
+
const validation = validateTurtle(turtle, shapesStore, shapeFiles, fixture.id);
|
|
83
|
+
if (validationMode === 'shacl-valid') {
|
|
84
|
+
if (validation.valid) {
|
|
85
|
+
printVerbose(` [${fixture.id}] SHACL valid (${validation.quadCount} quads)`, opts);
|
|
86
|
+
return { ...base, status: 'passed', validationDetails: validation };
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const violations = validation.results
|
|
90
|
+
.filter((r) => r.severity === 'violation')
|
|
91
|
+
.map((r) => `${r.shape}.${r.property}: ${r.message}`)
|
|
92
|
+
.join('; ');
|
|
93
|
+
return {
|
|
94
|
+
...base,
|
|
95
|
+
status: 'failed',
|
|
96
|
+
details: `SHACL violations: ${violations}`,
|
|
97
|
+
validationDetails: validation,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (validationMode === 'exact-match') {
|
|
102
|
+
// Exact-match: for now, verify it parses and is SHACL-valid
|
|
103
|
+
// Full normalized triple-by-triple equivalence is deferred
|
|
104
|
+
if (validation.valid) {
|
|
105
|
+
printVerbose(` [${fixture.id}] exact-match: parsed & SHACL valid (full normalization deferred)`, opts);
|
|
106
|
+
return { ...base, status: 'passed', validationDetails: validation };
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
const violations = validation.results
|
|
110
|
+
.filter((r) => r.severity === 'violation')
|
|
111
|
+
.map((r) => `${r.shape}.${r.property}: ${r.message}`)
|
|
112
|
+
.join('; ');
|
|
113
|
+
return {
|
|
114
|
+
...base,
|
|
115
|
+
status: 'failed',
|
|
116
|
+
details: `SHACL violations (exact-match mode): ${violations}`,
|
|
117
|
+
validationDetails: validation,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
return {
|
|
123
|
+
...base,
|
|
124
|
+
status: 'error',
|
|
125
|
+
details: `Unknown validationMode: ${validationMode}`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
// ---- Negative fixture ----
|
|
131
|
+
if (turtle === '') {
|
|
132
|
+
// Empty turtle means the SDK should reject before serialization — PASS
|
|
133
|
+
printVerbose(` [${fixture.id}] negative: empty turtle (pre-serialization rejection)`, opts);
|
|
134
|
+
return { ...base, status: 'passed' };
|
|
135
|
+
}
|
|
136
|
+
// Non-empty turtle: validate and expect violations
|
|
137
|
+
const parseResult = parseTurtle(turtle);
|
|
138
|
+
if (!parseResult.success) {
|
|
139
|
+
// Parse failure on negative fixture = PASS (malformed is invalid)
|
|
140
|
+
printVerbose(` [${fixture.id}] negative: turtle parse error (expected)`, opts);
|
|
141
|
+
return { ...base, status: 'passed', details: 'Turtle parse error (expected for negative fixture)' };
|
|
142
|
+
}
|
|
143
|
+
const validation = validateTurtle(turtle, shapesStore, shapeFiles, fixture.id);
|
|
144
|
+
if (!validation.valid) {
|
|
145
|
+
// Violations found — PASS for negative fixture
|
|
146
|
+
const violations = validation.results
|
|
147
|
+
.filter((r) => r.severity === 'violation')
|
|
148
|
+
.map((r) => `${r.shape}.${r.property}: ${r.message}`)
|
|
149
|
+
.join('; ');
|
|
150
|
+
printVerbose(` [${fixture.id}] negative: SHACL violations found (expected): ${violations}`, opts);
|
|
151
|
+
return { ...base, status: 'passed', validationDetails: validation };
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
// No violations — FAIL for negative fixture
|
|
155
|
+
return {
|
|
156
|
+
...base,
|
|
157
|
+
status: 'failed',
|
|
158
|
+
details: `Expected SHACL violations but data validated clean. Expected: ${fixture.shaclConstraintViolated ?? 'unspecified'}`,
|
|
159
|
+
validationDetails: validation,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
166
|
+
return {
|
|
167
|
+
...base,
|
|
168
|
+
status: 'error',
|
|
169
|
+
details: `Unexpected error: ${message}`,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
// Report generation
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
/**
|
|
177
|
+
* Build the aggregate suite report from individual fixture results.
|
|
178
|
+
*/
|
|
179
|
+
function buildReport(suitePath, mode, results) {
|
|
180
|
+
const byDataType = {};
|
|
181
|
+
for (const r of results) {
|
|
182
|
+
if (!byDataType[r.dataType]) {
|
|
183
|
+
byDataType[r.dataType] = { total: 0, passed: 0, failed: 0, errors: 0 };
|
|
184
|
+
}
|
|
185
|
+
const group = byDataType[r.dataType];
|
|
186
|
+
group.total++;
|
|
187
|
+
if (r.status === 'passed')
|
|
188
|
+
group.passed++;
|
|
189
|
+
else if (r.status === 'failed')
|
|
190
|
+
group.failed++;
|
|
191
|
+
else
|
|
192
|
+
group.errors++;
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
suite: suitePath,
|
|
196
|
+
mode,
|
|
197
|
+
total: results.length,
|
|
198
|
+
passed: results.filter((r) => r.status === 'passed').length,
|
|
199
|
+
failed: results.filter((r) => r.status === 'failed').length,
|
|
200
|
+
errors: results.filter((r) => r.status === 'error').length,
|
|
201
|
+
results,
|
|
202
|
+
byDataType,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Print a human-readable report to stdout.
|
|
207
|
+
*/
|
|
208
|
+
function printHumanReport(report, opts) {
|
|
209
|
+
console.log('');
|
|
210
|
+
console.log('Cascade Protocol Conformance Test Suite');
|
|
211
|
+
console.log('========================================');
|
|
212
|
+
console.log(`Suite: ${report.suite}`);
|
|
213
|
+
console.log(`Mode: ${report.mode === 'self' ? 'self-conformance' : report.mode}`);
|
|
214
|
+
console.log(`Fixtures: ${report.total}`);
|
|
215
|
+
console.log('');
|
|
216
|
+
console.log('Running tests...');
|
|
217
|
+
console.log('');
|
|
218
|
+
// Group results by dataType, preserving insertion order
|
|
219
|
+
const dataTypes = [];
|
|
220
|
+
const grouped = {};
|
|
221
|
+
for (const r of report.results) {
|
|
222
|
+
if (!grouped[r.dataType]) {
|
|
223
|
+
grouped[r.dataType] = [];
|
|
224
|
+
dataTypes.push(r.dataType);
|
|
225
|
+
}
|
|
226
|
+
grouped[r.dataType].push(r);
|
|
227
|
+
}
|
|
228
|
+
for (const dt of dataTypes) {
|
|
229
|
+
const fixtures = grouped[dt];
|
|
230
|
+
console.log(` ${dt} (${fixtures.length} fixtures)`);
|
|
231
|
+
for (const r of fixtures) {
|
|
232
|
+
const icon = r.status === 'passed' ? '\u2713' : r.status === 'failed' ? '\u2717' : '!';
|
|
233
|
+
const negativeTag = r.negative ? '[negative] ' : '';
|
|
234
|
+
const statusLine = ` ${icon} ${r.id}: ${negativeTag}${r.description}`;
|
|
235
|
+
console.log(statusLine);
|
|
236
|
+
if (r.status !== 'passed' && r.details) {
|
|
237
|
+
console.log(` ${r.details}`);
|
|
238
|
+
}
|
|
239
|
+
// In verbose mode, show validation details even for passing tests
|
|
240
|
+
if (opts.verbose && r.validationDetails) {
|
|
241
|
+
const vd = r.validationDetails;
|
|
242
|
+
console.log(` Quads: ${vd.quadCount}, Shapes: [${vd.shapesUsed.join(', ')}]`);
|
|
243
|
+
if (vd.results.length > 0) {
|
|
244
|
+
for (const issue of vd.results) {
|
|
245
|
+
console.log(` - [${issue.severity}] ${issue.shape}.${issue.property}: ${issue.message}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
console.log('');
|
|
251
|
+
}
|
|
252
|
+
// Summary line
|
|
253
|
+
const parts = [];
|
|
254
|
+
parts.push(`${report.passed} passed`);
|
|
255
|
+
if (report.failed > 0)
|
|
256
|
+
parts.push(`${report.failed} failed`);
|
|
257
|
+
else
|
|
258
|
+
parts.push('0 failed');
|
|
259
|
+
if (report.errors > 0)
|
|
260
|
+
parts.push(`${report.errors} errors`);
|
|
261
|
+
else
|
|
262
|
+
parts.push('0 errors');
|
|
263
|
+
console.log(`Results: ${parts.join(', ')}`);
|
|
264
|
+
const exitCode = report.failed > 0 || report.errors > 0 ? 1 : 0;
|
|
265
|
+
console.log(`Exit code: ${exitCode}`);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Print the JSON report using the output library.
|
|
269
|
+
*/
|
|
270
|
+
function printJsonReport(report, opts) {
|
|
271
|
+
// Strip validationDetails from results for cleaner JSON output
|
|
272
|
+
const cleanResults = report.results.map((r) => {
|
|
273
|
+
const { validationDetails: _vd, ...rest } = r;
|
|
274
|
+
return rest;
|
|
275
|
+
});
|
|
276
|
+
printResult({
|
|
277
|
+
suite: report.suite,
|
|
278
|
+
mode: report.mode,
|
|
279
|
+
total: report.total,
|
|
280
|
+
passed: report.passed,
|
|
281
|
+
failed: report.failed,
|
|
282
|
+
errors: report.errors,
|
|
283
|
+
results: cleanResults,
|
|
284
|
+
byDataType: report.byDataType,
|
|
285
|
+
}, opts);
|
|
286
|
+
}
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
// Command registration
|
|
289
|
+
// ---------------------------------------------------------------------------
|
|
290
|
+
export function registerConformanceCommand(program) {
|
|
291
|
+
const conformance = program
|
|
292
|
+
.command('conformance')
|
|
293
|
+
.description('Run conformance test suite');
|
|
294
|
+
conformance
|
|
295
|
+
.command('run')
|
|
296
|
+
.description('Execute conformance tests')
|
|
297
|
+
.requiredOption('--suite <fixtures-dir>', 'Path to test fixtures directory')
|
|
298
|
+
.option('--command <cmd>', 'External command to test against')
|
|
299
|
+
.option('--self', 'Run self-conformance tests')
|
|
300
|
+
.action(async (options) => {
|
|
301
|
+
const globalOpts = program.opts();
|
|
302
|
+
if (!options.command && !options.self) {
|
|
303
|
+
printError('Either --command or --self must be specified', globalOpts);
|
|
304
|
+
process.exitCode = 1;
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
// External command mode: not yet supported
|
|
308
|
+
if (options.command) {
|
|
309
|
+
printError('External command mode not yet supported', globalOpts);
|
|
310
|
+
process.exitCode = 1;
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
// Resolve suite directory
|
|
314
|
+
const suitePath = path.resolve(options.suite);
|
|
315
|
+
printVerbose(`Conformance suite: ${suitePath}`, globalOpts);
|
|
316
|
+
printVerbose('Running self-conformance tests', globalOpts);
|
|
317
|
+
try {
|
|
318
|
+
// Load fixtures
|
|
319
|
+
const fixtures = loadFixtures(suitePath);
|
|
320
|
+
printVerbose(`Loaded ${fixtures.length} fixture(s)`, globalOpts);
|
|
321
|
+
// Load SHACL shapes once
|
|
322
|
+
const { store: shapesStore, shapeFiles } = loadShapes();
|
|
323
|
+
printVerbose(`Loaded shapes: ${shapeFiles.join(', ')}`, globalOpts);
|
|
324
|
+
// Run each fixture
|
|
325
|
+
const results = [];
|
|
326
|
+
for (const fixture of fixtures) {
|
|
327
|
+
const result = runSelfFixture(fixture, shapesStore, shapeFiles, globalOpts);
|
|
328
|
+
results.push(result);
|
|
329
|
+
}
|
|
330
|
+
// Build and output report
|
|
331
|
+
const report = buildReport(options.suite, 'self', results);
|
|
332
|
+
if (globalOpts.json) {
|
|
333
|
+
printJsonReport(report, globalOpts);
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
printHumanReport(report, globalOpts);
|
|
337
|
+
}
|
|
338
|
+
// Set exit code
|
|
339
|
+
process.exitCode = report.failed > 0 || report.errors > 0 ? 1 : 0;
|
|
340
|
+
}
|
|
341
|
+
catch (err) {
|
|
342
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
343
|
+
printError(`Conformance suite failed: ${message}`, globalOpts);
|
|
344
|
+
process.exitCode = 1;
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conformance.js","sourceRoot":"","sources":["../../src/commands/conformance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cascade convert --from <format> --to <format> [file]
|
|
3
|
+
*
|
|
4
|
+
* Convert between health data formats.
|
|
5
|
+
* Supports FHIR R4, Cascade Protocol Turtle, and JSON-LD.
|
|
6
|
+
*
|
|
7
|
+
* Options:
|
|
8
|
+
* --from <format> Source format (fhir|cascade|c-cda)
|
|
9
|
+
* --to <format> Target format (turtle|jsonld|fhir|cascade)
|
|
10
|
+
* --format <output> Output serialization format (turtle|jsonld) [default: turtle]
|
|
11
|
+
* --json Output results as JSON envelope (machine-readable)
|
|
12
|
+
* --verbose Show detailed conversion information
|
|
13
|
+
*
|
|
14
|
+
* Supports stdin piping:
|
|
15
|
+
* cat patient.json | cascade convert --from fhir --to cascade
|
|
16
|
+
*
|
|
17
|
+
* Zero network calls. All conversion is local.
|
|
18
|
+
*/
|
|
19
|
+
import { Command } from 'commander';
|
|
20
|
+
export declare function registerConvertCommand(program: Command): void;
|
|
21
|
+
//# sourceMappingURL=convert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../src/commands/convert.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8H7D"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cascade convert --from <format> --to <format> [file]
|
|
3
|
+
*
|
|
4
|
+
* Convert between health data formats.
|
|
5
|
+
* Supports FHIR R4, Cascade Protocol Turtle, and JSON-LD.
|
|
6
|
+
*
|
|
7
|
+
* Options:
|
|
8
|
+
* --from <format> Source format (fhir|cascade|c-cda)
|
|
9
|
+
* --to <format> Target format (turtle|jsonld|fhir|cascade)
|
|
10
|
+
* --format <output> Output serialization format (turtle|jsonld) [default: turtle]
|
|
11
|
+
* --json Output results as JSON envelope (machine-readable)
|
|
12
|
+
* --verbose Show detailed conversion information
|
|
13
|
+
*
|
|
14
|
+
* Supports stdin piping:
|
|
15
|
+
* cat patient.json | cascade convert --from fhir --to cascade
|
|
16
|
+
*
|
|
17
|
+
* Zero network calls. All conversion is local.
|
|
18
|
+
*/
|
|
19
|
+
import { readFileSync } from 'node:fs';
|
|
20
|
+
import { printResult, printError, printVerbose } from '../lib/output.js';
|
|
21
|
+
import { convert, detectFormat } from '../lib/fhir-converter/index.js';
|
|
22
|
+
/**
|
|
23
|
+
* Read input from file or stdin.
|
|
24
|
+
* If file is provided, reads from disk.
|
|
25
|
+
* Otherwise reads all of stdin synchronously.
|
|
26
|
+
*/
|
|
27
|
+
function readInput(file) {
|
|
28
|
+
if (file) {
|
|
29
|
+
return readFileSync(file, 'utf-8');
|
|
30
|
+
}
|
|
31
|
+
// Read from stdin
|
|
32
|
+
return readFileSync(0, 'utf-8');
|
|
33
|
+
}
|
|
34
|
+
export function registerConvertCommand(program) {
|
|
35
|
+
program
|
|
36
|
+
.command('convert')
|
|
37
|
+
.description('Convert between health data formats')
|
|
38
|
+
.argument('[file]', 'Input file (reads from stdin if omitted)')
|
|
39
|
+
.requiredOption('--from <format>', 'Source format (fhir|cascade|c-cda)')
|
|
40
|
+
.requiredOption('--to <format>', 'Target format (turtle|jsonld|fhir|cascade)')
|
|
41
|
+
.option('--format <output>', 'Output serialization format (turtle|jsonld)', 'turtle')
|
|
42
|
+
.action(async (file, options) => {
|
|
43
|
+
const globalOpts = program.opts();
|
|
44
|
+
printVerbose(`Converting from ${options.from} to ${options.to}`, globalOpts);
|
|
45
|
+
if (file) {
|
|
46
|
+
printVerbose(`Input file: ${file}`, globalOpts);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
printVerbose('Reading from stdin', globalOpts);
|
|
50
|
+
}
|
|
51
|
+
printVerbose(`Output format: ${options.format}`, globalOpts);
|
|
52
|
+
// 1. Read input
|
|
53
|
+
let input;
|
|
54
|
+
try {
|
|
55
|
+
input = readInput(file);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
printError(`Failed to read input: ${err.message}`, globalOpts);
|
|
59
|
+
process.exitCode = 1;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (!input.trim()) {
|
|
63
|
+
printError('Empty input', globalOpts);
|
|
64
|
+
process.exitCode = 1;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// 2. Validate source/target formats
|
|
68
|
+
const validInputFormats = ['fhir', 'cascade', 'c-cda'];
|
|
69
|
+
const validOutputFormats = ['turtle', 'jsonld', 'fhir', 'cascade'];
|
|
70
|
+
if (!validInputFormats.includes(options.from)) {
|
|
71
|
+
printError(`Invalid source format: ${options.from}. Valid: ${validInputFormats.join(', ')}`, globalOpts);
|
|
72
|
+
process.exitCode = 1;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (!validOutputFormats.includes(options.to)) {
|
|
76
|
+
printError(`Invalid target format: ${options.to}. Valid: ${validOutputFormats.join(', ')}`, globalOpts);
|
|
77
|
+
process.exitCode = 1;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// 3. Auto-detect format if helpful (validate matches declared)
|
|
81
|
+
const detected = detectFormat(input);
|
|
82
|
+
if (detected && detected !== options.from) {
|
|
83
|
+
printVerbose(`Note: Input appears to be ${detected} but --from says ${options.from}. Proceeding with declared format.`, globalOpts);
|
|
84
|
+
}
|
|
85
|
+
// 4. Run conversion
|
|
86
|
+
const outputSerialization = (options.format === 'jsonld' ? 'jsonld' : 'turtle');
|
|
87
|
+
const result = await convert(input, options.from, options.to, outputSerialization);
|
|
88
|
+
// 5. Output
|
|
89
|
+
if (!result.success) {
|
|
90
|
+
for (const err of result.errors) {
|
|
91
|
+
printError(err, globalOpts);
|
|
92
|
+
}
|
|
93
|
+
for (const warn of result.warnings) {
|
|
94
|
+
printVerbose(`Warning: ${warn}`, globalOpts);
|
|
95
|
+
}
|
|
96
|
+
process.exitCode = 1;
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// Print warnings in verbose mode
|
|
100
|
+
for (const warn of result.warnings) {
|
|
101
|
+
printVerbose(`Warning: ${warn}`, globalOpts);
|
|
102
|
+
}
|
|
103
|
+
if (globalOpts.json) {
|
|
104
|
+
// JSON envelope for machine-readable output
|
|
105
|
+
printResult({
|
|
106
|
+
success: true,
|
|
107
|
+
from: options.from,
|
|
108
|
+
to: options.to,
|
|
109
|
+
format: result.format,
|
|
110
|
+
resourceCount: result.resourceCount,
|
|
111
|
+
warnings: result.warnings,
|
|
112
|
+
output: result.output,
|
|
113
|
+
resources: result.results.map(r => ({
|
|
114
|
+
resourceType: r.resourceType,
|
|
115
|
+
cascadeType: r.cascadeType,
|
|
116
|
+
warnings: r.warnings,
|
|
117
|
+
})),
|
|
118
|
+
}, globalOpts);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
// Direct output (Turtle, JSON-LD, or FHIR JSON)
|
|
122
|
+
console.log(result.output);
|
|
123
|
+
// Print summary to stderr so it does not pollute piped output
|
|
124
|
+
if (result.resourceCount > 0) {
|
|
125
|
+
console.error(`Converted ${result.resourceCount} resource${result.resourceCount > 1 ? 's' : ''} ` +
|
|
126
|
+
`(${options.from} -> ${result.format})`);
|
|
127
|
+
}
|
|
128
|
+
if (result.warnings.length > 0) {
|
|
129
|
+
console.error(`${result.warnings.length} warning${result.warnings.length > 1 ? 's' : ''}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../../src/commands/convert.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cascade pod export <pod-dir>
|
|
3
|
+
*
|
|
4
|
+
* Export pod data as a ZIP archive or directory copy.
|
|
5
|
+
*/
|
|
6
|
+
import type { Command } from 'commander';
|
|
7
|
+
export declare function registerExportSubcommand(pod: Command, program: Command): void;
|
|
8
|
+
//# sourceMappingURL=export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/commands/pod/export.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAyE7E"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cascade pod export <pod-dir>
|
|
3
|
+
*
|
|
4
|
+
* Export pod data as a ZIP archive or directory copy.
|
|
5
|
+
*/
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import { printResult, printError, printVerbose } from '../../lib/output.js';
|
|
8
|
+
import { resolvePodDir, isDirectory, copyDirectory, createZipArchive } from './helpers.js';
|
|
9
|
+
export function registerExportSubcommand(pod, program) {
|
|
10
|
+
pod
|
|
11
|
+
.command('export')
|
|
12
|
+
.description('Export pod data')
|
|
13
|
+
.argument('<pod-dir>', 'Path to the Cascade Pod')
|
|
14
|
+
.option('--format <fmt>', 'Export format (zip|directory)', 'zip')
|
|
15
|
+
.option('--output <path>', 'Output path for export')
|
|
16
|
+
.action(async (podDir, options) => {
|
|
17
|
+
const globalOpts = program.opts();
|
|
18
|
+
const absDir = resolvePodDir(podDir);
|
|
19
|
+
printVerbose(`Exporting pod: ${absDir} as ${options.format}`, globalOpts);
|
|
20
|
+
// Validate pod exists
|
|
21
|
+
if (!(await isDirectory(absDir))) {
|
|
22
|
+
printError(`Pod directory not found: ${absDir}`, globalOpts);
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
if (options.format === 'directory') {
|
|
28
|
+
// Copy to new directory
|
|
29
|
+
const outputDir = options.output ?? `${absDir}-export`;
|
|
30
|
+
await copyDirectory(absDir, outputDir);
|
|
31
|
+
if (globalOpts.json) {
|
|
32
|
+
printResult({
|
|
33
|
+
status: 'exported',
|
|
34
|
+
format: 'directory',
|
|
35
|
+
source: absDir,
|
|
36
|
+
output: outputDir,
|
|
37
|
+
}, globalOpts);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.log(`Pod exported to directory: ${outputDir}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else if (options.format === 'zip') {
|
|
44
|
+
// Create ZIP archive
|
|
45
|
+
const outputZip = options.output ?? `${path.basename(absDir)}.zip`;
|
|
46
|
+
const absOutputZip = path.resolve(process.cwd(), outputZip);
|
|
47
|
+
await createZipArchive(absDir, absOutputZip);
|
|
48
|
+
if (globalOpts.json) {
|
|
49
|
+
printResult({
|
|
50
|
+
status: 'exported',
|
|
51
|
+
format: 'zip',
|
|
52
|
+
source: absDir,
|
|
53
|
+
output: absOutputZip,
|
|
54
|
+
}, globalOpts);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
console.log(`Pod exported to ZIP: ${absOutputZip}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
printError(`Unknown export format: ${options.format}. Use 'zip' or 'directory'.`, globalOpts);
|
|
62
|
+
process.exitCode = 1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
67
|
+
printError(`Failed to export pod: ${message}`, globalOpts);
|
|
68
|
+
process.exitCode = 1;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../../src/commands/pod/export.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAsB,MAAM,qBAAqB,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAE3F,MAAM,UAAU,wBAAwB,CAAC,GAAY,EAAE,OAAgB;IACrE,GAAG;SACA,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,iBAAiB,CAAC;SAC9B,QAAQ,CAAC,WAAW,EAAE,yBAAyB,CAAC;SAChD,MAAM,CAAC,gBAAgB,EAAE,+BAA+B,EAAE,KAAK,CAAC;SAChE,MAAM,CAAC,iBAAiB,EAAE,wBAAwB,CAAC;SACnD,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,OAA4C,EAAE,EAAE;QAC7E,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,EAAmB,CAAC;QACnD,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QAErC,YAAY,CAAC,kBAAkB,MAAM,OAAO,OAAO,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC;QAE1E,sBAAsB;QACtB,IAAI,CAAC,CAAC,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACjC,UAAU,CAAC,4BAA4B,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC;YAC7D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBACnC,wBAAwB;gBACxB,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC;gBACvD,MAAM,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;gBAEvC,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;oBACpB,WAAW,CACT;wBACE,MAAM,EAAE,UAAU;wBAClB,MAAM,EAAE,WAAW;wBACnB,MAAM,EAAE,MAAM;wBACd,MAAM,EAAE,SAAS;qBAClB,EACD,UAAU,CACX,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,8BAA8B,SAAS,EAAE,CAAC,CAAC;gBACzD,CAAC;YACH,CAAC;iBAAM,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;gBACpC,qBAAqB;gBACrB,MAAM,SAAS,GACb,OAAO,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;gBACnD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;gBAE5D,MAAM,gBAAgB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;gBAE7C,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;oBACpB,WAAW,CACT;wBACE,MAAM,EAAE,UAAU;wBAClB,MAAM,EAAE,KAAK;wBACb,MAAM,EAAE,MAAM;wBACd,MAAM,EAAE,YAAY;qBACrB,EACD,UAAU,CACX,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,wBAAwB,YAAY,EAAE,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,UAAU,CACR,0BAA0B,OAAO,CAAC,MAAM,6BAA6B,EACrE,UAAU,CACX,CAAC;gBACF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,UAAU,CAAC,yBAAyB,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;YAC3D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|