@atomic-ehr/codegen 0.0.1-canary.20250830224431.6d211a5 → 0.0.1-canary.20250831211734.bb1536b
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/api/builder.d.ts +1 -9
- package/dist/api/builder.js +1 -41
- package/dist/api/generators/typescript.d.ts +12 -0
- package/dist/api/generators/typescript.js +46 -3
- package/dist/api/index.d.ts +0 -2
- package/dist/api/index.js +0 -1
- package/dist/cli/commands/generate.js +2 -12
- package/dist/cli/index.js +57 -1217
- package/dist/cli/utils/prompts.js +0 -22
- package/dist/config.d.ts +0 -39
- package/dist/config.js +0 -108
- package/package.json +1 -1
- package/dist/api/generators/rest-client.d.ts +0 -117
- package/dist/api/generators/rest-client.js +0 -847
- package/dist/api/generators/search-parameter-enhancer.d.ts +0 -185
- package/dist/api/generators/search-parameter-enhancer.js +0 -801
- package/dist/api/generators/validation-generator.d.ts +0 -126
- package/dist/api/generators/validation-generator.js +0 -632
|
@@ -1,632 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validation Generator
|
|
3
|
-
*
|
|
4
|
-
* Generates client-side validation for FHIR resources including validation types,
|
|
5
|
-
* resource validators, and validation helpers for the REST client.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Validation Generator class
|
|
9
|
-
*
|
|
10
|
-
* Generates client-side validation logic for FHIR resources including
|
|
11
|
-
* validation types, validators, and integration helpers.
|
|
12
|
-
*/
|
|
13
|
-
export class ValidationGenerator {
|
|
14
|
-
resourceTypes = new Set();
|
|
15
|
-
resourceSchemas = new Map();
|
|
16
|
-
/**
|
|
17
|
-
* Collect resource types and schemas for validation generation
|
|
18
|
-
*/
|
|
19
|
-
collectResourceData(schemas) {
|
|
20
|
-
this.resourceTypes.clear();
|
|
21
|
-
this.resourceSchemas.clear();
|
|
22
|
-
for (const schema of schemas) {
|
|
23
|
-
if (schema.identifier.kind === "resource" &&
|
|
24
|
-
schema.identifier.name !== "DomainResource" &&
|
|
25
|
-
schema.identifier.name !== "Resource") {
|
|
26
|
-
this.resourceTypes.add(schema.identifier.name);
|
|
27
|
-
this.resourceSchemas.set(schema.identifier.name, schema);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Generate validation types and interfaces
|
|
33
|
-
*/
|
|
34
|
-
generateValidationTypes() {
|
|
35
|
-
return `/**
|
|
36
|
-
* FHIR Resource Validation Types
|
|
37
|
-
*
|
|
38
|
-
* Client-side validation types and interfaces for FHIR resources.
|
|
39
|
-
* Generated automatically from FHIR schemas.
|
|
40
|
-
*/
|
|
41
|
-
|
|
42
|
-
import type { ResourceTypes } from '../types';
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Validation options for resource validation
|
|
46
|
-
*/
|
|
47
|
-
export interface ValidationOptions {
|
|
48
|
-
/** Validation profile to use (strict, lenient, etc.) */
|
|
49
|
-
profile?: 'strict' | 'lenient' | 'minimal';
|
|
50
|
-
/** Whether to throw on validation errors or return result */
|
|
51
|
-
throwOnError?: boolean;
|
|
52
|
-
/** Whether to validate required fields */
|
|
53
|
-
validateRequired?: boolean;
|
|
54
|
-
/** Whether to validate cardinality constraints */
|
|
55
|
-
validateCardinality?: boolean;
|
|
56
|
-
/** Whether to validate data types */
|
|
57
|
-
validateTypes?: boolean;
|
|
58
|
-
/** Whether to validate value constraints */
|
|
59
|
-
validateConstraints?: boolean;
|
|
60
|
-
/** Whether to collect performance metrics */
|
|
61
|
-
collectMetrics?: boolean;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Validation error details
|
|
66
|
-
*/
|
|
67
|
-
export interface ValidationError {
|
|
68
|
-
/** Error severity */
|
|
69
|
-
severity: 'error' | 'warning' | 'information';
|
|
70
|
-
/** Error code */
|
|
71
|
-
code: string;
|
|
72
|
-
/** Human-readable error message */
|
|
73
|
-
message: string;
|
|
74
|
-
/** Path to the invalid element */
|
|
75
|
-
path: string;
|
|
76
|
-
/** Current value that failed validation */
|
|
77
|
-
value?: unknown;
|
|
78
|
-
/** Expected value or constraint */
|
|
79
|
-
expected?: string;
|
|
80
|
-
/** Suggestion for fixing the error */
|
|
81
|
-
suggestion?: string;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Validation warning details
|
|
86
|
-
*/
|
|
87
|
-
export interface ValidationWarning {
|
|
88
|
-
/** Warning code */
|
|
89
|
-
code: string;
|
|
90
|
-
/** Human-readable warning message */
|
|
91
|
-
message: string;
|
|
92
|
-
/** Path to the element */
|
|
93
|
-
path: string;
|
|
94
|
-
/** Current value */
|
|
95
|
-
value?: unknown;
|
|
96
|
-
/** Suggestion for improvement */
|
|
97
|
-
suggestion?: string;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Validation result
|
|
102
|
-
*/
|
|
103
|
-
export interface ValidationResult {
|
|
104
|
-
/** Whether validation passed */
|
|
105
|
-
valid: boolean;
|
|
106
|
-
/** List of validation errors */
|
|
107
|
-
errors: ValidationError[];
|
|
108
|
-
/** List of validation warnings */
|
|
109
|
-
warnings: ValidationWarning[];
|
|
110
|
-
/** Validation performance metrics */
|
|
111
|
-
metrics?: {
|
|
112
|
-
/** Time taken for validation in milliseconds */
|
|
113
|
-
duration: number;
|
|
114
|
-
/** Number of elements validated */
|
|
115
|
-
elementsValidated: number;
|
|
116
|
-
/** Number of constraints checked */
|
|
117
|
-
constraintsChecked: number;
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Validation exception thrown when validation fails and throwOnError is true
|
|
123
|
-
*/
|
|
124
|
-
export class ValidationException extends Error {
|
|
125
|
-
public errors: ValidationError[];
|
|
126
|
-
public warnings: ValidationWarning[];
|
|
127
|
-
public result: ValidationResult;
|
|
128
|
-
|
|
129
|
-
constructor(result: ValidationResult) {
|
|
130
|
-
const errorCount = result.errors.length;
|
|
131
|
-
const warningCount = result.warnings.length;
|
|
132
|
-
super(\`Validation failed: \${errorCount} error(s), \${warningCount} warning(s)\`);
|
|
133
|
-
|
|
134
|
-
this.name = 'ValidationException';
|
|
135
|
-
this.errors = result.errors;
|
|
136
|
-
this.warnings = result.warnings;
|
|
137
|
-
this.result = result;
|
|
138
|
-
}
|
|
139
|
-
}`;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Generate resource validators for all resource types
|
|
143
|
-
*/
|
|
144
|
-
generateResourceValidators() {
|
|
145
|
-
const resourceTypesArray = Array.from(this.resourceTypes).sort();
|
|
146
|
-
return `/**
|
|
147
|
-
* FHIR Resource Validators
|
|
148
|
-
*
|
|
149
|
-
* Client-side validation logic for FHIR resources.
|
|
150
|
-
* Generated automatically from FHIR schemas.
|
|
151
|
-
*/
|
|
152
|
-
|
|
153
|
-
import type { ResourceTypes, ResourceTypeMap, ${resourceTypesArray.join(", ")} } from './utility.js';
|
|
154
|
-
import type { ValidationOptions, ValidationResult, ValidationError, ValidationWarning, ValidationException } from './validation-types.js';
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Main Resource Validator class
|
|
158
|
-
*
|
|
159
|
-
* Provides validation methods for all FHIR resource types with configurable
|
|
160
|
-
* validation profiles and detailed error reporting.
|
|
161
|
-
*/
|
|
162
|
-
export class ResourceValidator {
|
|
163
|
-
private static defaultOptions: Required<ValidationOptions> = {
|
|
164
|
-
profile: 'strict',
|
|
165
|
-
throwOnError: false,
|
|
166
|
-
validateRequired: true,
|
|
167
|
-
validateCardinality: true,
|
|
168
|
-
validateTypes: true,
|
|
169
|
-
validateConstraints: true,
|
|
170
|
-
collectMetrics: false
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Validate any FHIR resource with type safety
|
|
175
|
-
*/
|
|
176
|
-
static validate<T extends ResourceTypes>(
|
|
177
|
-
resource: ResourceTypeMap[T],
|
|
178
|
-
options: ValidationOptions = {}
|
|
179
|
-
): ValidationResult {
|
|
180
|
-
const opts = { ...this.defaultOptions, ...options };
|
|
181
|
-
const startTime = opts.collectMetrics ? performance.now() : 0;
|
|
182
|
-
|
|
183
|
-
const result: ValidationResult = {
|
|
184
|
-
valid: true,
|
|
185
|
-
errors: [],
|
|
186
|
-
warnings: []
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
try {
|
|
190
|
-
// Basic resource type validation
|
|
191
|
-
if (!resource || typeof resource !== 'object') {
|
|
192
|
-
result.errors.push({
|
|
193
|
-
severity: 'error',
|
|
194
|
-
code: 'INVALID_RESOURCE',
|
|
195
|
-
message: 'Resource must be a valid object',
|
|
196
|
-
path: 'resource',
|
|
197
|
-
value: resource,
|
|
198
|
-
expected: 'object',
|
|
199
|
-
suggestion: 'Provide a valid FHIR resource object'
|
|
200
|
-
});
|
|
201
|
-
result.valid = false;
|
|
202
|
-
} else {
|
|
203
|
-
// Validate resource type
|
|
204
|
-
const resourceType = resource.resourceType as T;
|
|
205
|
-
if (!resourceType) {
|
|
206
|
-
result.errors.push({
|
|
207
|
-
severity: 'error',
|
|
208
|
-
code: 'MISSING_RESOURCE_TYPE',
|
|
209
|
-
message: 'Resource must have a resourceType property',
|
|
210
|
-
path: 'resourceType',
|
|
211
|
-
value: undefined,
|
|
212
|
-
expected: 'string',
|
|
213
|
-
suggestion: 'Add a resourceType property to the resource'
|
|
214
|
-
});
|
|
215
|
-
result.valid = false;
|
|
216
|
-
} else {
|
|
217
|
-
// Call resource-specific validator
|
|
218
|
-
this.validateResourceType(resourceType, resource, result, opts);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Add performance metrics if requested
|
|
223
|
-
if (opts.collectMetrics) {
|
|
224
|
-
const endTime = performance.now();
|
|
225
|
-
result.metrics = {
|
|
226
|
-
duration: endTime - startTime,
|
|
227
|
-
elementsValidated: this.countElements(resource),
|
|
228
|
-
constraintsChecked: result.errors.length + result.warnings.length
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Throw exception if requested and validation failed
|
|
233
|
-
if (opts.throwOnError && !result.valid) {
|
|
234
|
-
const { ValidationException } = require('./validation-types');
|
|
235
|
-
throw new ValidationException(result);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return result;
|
|
239
|
-
|
|
240
|
-
} catch (error) {
|
|
241
|
-
if (error instanceof Error && error.name === 'ValidationException') {
|
|
242
|
-
throw error;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
result.errors.push({
|
|
246
|
-
severity: 'error',
|
|
247
|
-
code: 'VALIDATION_ERROR',
|
|
248
|
-
message: \`Validation failed: \${error instanceof Error ? error.message : String(error)}\`,
|
|
249
|
-
path: 'resource',
|
|
250
|
-
value: resource,
|
|
251
|
-
suggestion: 'Check the resource structure and try again'
|
|
252
|
-
});
|
|
253
|
-
result.valid = false;
|
|
254
|
-
|
|
255
|
-
if (opts.throwOnError) {
|
|
256
|
-
const { ValidationException } = require('./validation-types');
|
|
257
|
-
throw new ValidationException(result);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return result;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
${this.generateResourceSpecificValidators()}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Validate resource type and dispatch to specific validator
|
|
268
|
-
*/
|
|
269
|
-
private static validateResourceType<T extends ResourceTypes>(
|
|
270
|
-
resourceType: T,
|
|
271
|
-
resource: ResourceTypeMap[T],
|
|
272
|
-
result: ValidationResult,
|
|
273
|
-
options: Required<ValidationOptions>
|
|
274
|
-
): void {
|
|
275
|
-
switch (resourceType) {
|
|
276
|
-
${resourceTypesArray
|
|
277
|
-
.map((type) => ` case '${type}':
|
|
278
|
-
this.validate${type}(resource as ${type}, result, options);
|
|
279
|
-
break;`)
|
|
280
|
-
.join("\n")}
|
|
281
|
-
default:
|
|
282
|
-
result.warnings.push({
|
|
283
|
-
code: 'UNKNOWN_RESOURCE_TYPE',
|
|
284
|
-
message: \`Unknown resource type: \${resourceType}\`,
|
|
285
|
-
path: 'resourceType',
|
|
286
|
-
value: resourceType,
|
|
287
|
-
suggestion: 'Check if the resource type is supported'
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Count elements in resource for metrics
|
|
294
|
-
*/
|
|
295
|
-
private static countElements(resource: any, count = 0): number {
|
|
296
|
-
if (!resource || typeof resource !== 'object') return count;
|
|
297
|
-
|
|
298
|
-
for (const value of Object.values(resource)) {
|
|
299
|
-
count++;
|
|
300
|
-
if (Array.isArray(value)) {
|
|
301
|
-
for (const item of value) {
|
|
302
|
-
count = this.countElements(item, count);
|
|
303
|
-
}
|
|
304
|
-
} else if (typeof value === 'object') {
|
|
305
|
-
count = this.countElements(value, count);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return count;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Validate required fields
|
|
314
|
-
*/
|
|
315
|
-
private static validateRequired(
|
|
316
|
-
resource: any,
|
|
317
|
-
requiredFields: string[],
|
|
318
|
-
result: ValidationResult,
|
|
319
|
-
basePath = ''
|
|
320
|
-
): void {
|
|
321
|
-
for (const field of requiredFields) {
|
|
322
|
-
const path = basePath ? \`\${basePath}.\${field}\` : field;
|
|
323
|
-
if (resource[field] === undefined || resource[field] === null) {
|
|
324
|
-
result.errors.push({
|
|
325
|
-
severity: 'error',
|
|
326
|
-
code: 'MISSING_REQUIRED_FIELD',
|
|
327
|
-
message: \`Required field '\${field}' is missing\`,
|
|
328
|
-
path,
|
|
329
|
-
value: resource[field],
|
|
330
|
-
expected: 'non-null value',
|
|
331
|
-
suggestion: \`Add the required '\${field}' field to the resource\`
|
|
332
|
-
});
|
|
333
|
-
result.valid = false;
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Validate field type
|
|
340
|
-
*/
|
|
341
|
-
private static validateFieldType(
|
|
342
|
-
value: any,
|
|
343
|
-
expectedType: string,
|
|
344
|
-
fieldName: string,
|
|
345
|
-
result: ValidationResult,
|
|
346
|
-
basePath = ''
|
|
347
|
-
): void {
|
|
348
|
-
const path = basePath ? \`\${basePath}.\${fieldName}\` : fieldName;
|
|
349
|
-
|
|
350
|
-
if (value === undefined || value === null) return;
|
|
351
|
-
|
|
352
|
-
let isValid = false;
|
|
353
|
-
switch (expectedType) {
|
|
354
|
-
case 'string':
|
|
355
|
-
isValid = typeof value === 'string';
|
|
356
|
-
break;
|
|
357
|
-
case 'number':
|
|
358
|
-
isValid = typeof value === 'number' && !isNaN(value);
|
|
359
|
-
break;
|
|
360
|
-
case 'boolean':
|
|
361
|
-
isValid = typeof value === 'boolean';
|
|
362
|
-
break;
|
|
363
|
-
case 'array':
|
|
364
|
-
isValid = Array.isArray(value);
|
|
365
|
-
break;
|
|
366
|
-
case 'object':
|
|
367
|
-
isValid = typeof value === 'object' && !Array.isArray(value);
|
|
368
|
-
break;
|
|
369
|
-
default:
|
|
370
|
-
isValid = true; // Skip unknown types
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
if (!isValid) {
|
|
374
|
-
result.errors.push({
|
|
375
|
-
severity: 'error',
|
|
376
|
-
code: 'INVALID_FIELD_TYPE',
|
|
377
|
-
message: \`Field '\${fieldName}' has invalid type\`,
|
|
378
|
-
path,
|
|
379
|
-
value,
|
|
380
|
-
expected: expectedType,
|
|
381
|
-
suggestion: \`Ensure '\${fieldName}' is of type \${expectedType}\`
|
|
382
|
-
});
|
|
383
|
-
result.valid = false;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
}`;
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Generate resource-specific validators
|
|
390
|
-
*/
|
|
391
|
-
generateResourceSpecificValidators() {
|
|
392
|
-
const validators = [];
|
|
393
|
-
// Generate validators for key resource types
|
|
394
|
-
const keyResourceTypes = [
|
|
395
|
-
"Patient",
|
|
396
|
-
"Observation",
|
|
397
|
-
"Organization",
|
|
398
|
-
"Practitioner",
|
|
399
|
-
"Bundle",
|
|
400
|
-
];
|
|
401
|
-
for (const resourceType of keyResourceTypes) {
|
|
402
|
-
if (this.resourceTypes.has(resourceType)) {
|
|
403
|
-
validators.push(this.generateResourceValidator(resourceType));
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
// Generate generic validators for remaining resource types
|
|
407
|
-
for (const resourceType of this.resourceTypes) {
|
|
408
|
-
if (!keyResourceTypes.includes(resourceType)) {
|
|
409
|
-
validators.push(this.generateGenericResourceValidator(resourceType));
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
return validators.join("\n\n");
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Generate a specific validator for a key resource type
|
|
416
|
-
*/
|
|
417
|
-
generateResourceValidator(resourceType) {
|
|
418
|
-
const validationRules = this.getValidationRules(resourceType);
|
|
419
|
-
return ` /**
|
|
420
|
-
* Validate ${resourceType} resource
|
|
421
|
-
*/
|
|
422
|
-
private static validate${resourceType}(
|
|
423
|
-
resource: ${resourceType},
|
|
424
|
-
result: ValidationResult,
|
|
425
|
-
options: Required<ValidationOptions>
|
|
426
|
-
): void {
|
|
427
|
-
// Validate required fields
|
|
428
|
-
if (options.validateRequired) {
|
|
429
|
-
this.validateRequired(resource, [${validationRules.required.map((f) => `'${f}'`).join(", ")}], result, '${resourceType.toLowerCase()}');
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// Validate field types
|
|
433
|
-
if (options.validateTypes) {
|
|
434
|
-
${validationRules.fields
|
|
435
|
-
.map((field) => `if (resource.${field.name} !== undefined) {
|
|
436
|
-
this.validateFieldType(resource.${field.name}, '${field.type}', '${field.name}', result, '${resourceType.toLowerCase()}');
|
|
437
|
-
}`)
|
|
438
|
-
.join("\n\t\t\t")}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// Validate specific constraints for ${resourceType}
|
|
442
|
-
if (options.validateConstraints) {
|
|
443
|
-
${this.generateResourceSpecificConstraints(resourceType)}
|
|
444
|
-
}
|
|
445
|
-
}`;
|
|
446
|
-
}
|
|
447
|
-
/**
|
|
448
|
-
* Generate a generic validator for less common resource types
|
|
449
|
-
*/
|
|
450
|
-
generateGenericResourceValidator(resourceType) {
|
|
451
|
-
return ` /**
|
|
452
|
-
* Validate ${resourceType} resource (generic validation)
|
|
453
|
-
*/
|
|
454
|
-
private static validate${resourceType}(
|
|
455
|
-
resource: ${resourceType},
|
|
456
|
-
result: ValidationResult,
|
|
457
|
-
options: Required<ValidationOptions>
|
|
458
|
-
): void {
|
|
459
|
-
// Basic validation for ${resourceType}
|
|
460
|
-
if (options.validateRequired && resource.resourceType !== '${resourceType}') {
|
|
461
|
-
result.errors.push({
|
|
462
|
-
severity: 'error',
|
|
463
|
-
code: 'INVALID_RESOURCE_TYPE',
|
|
464
|
-
message: \`Expected resourceType '${resourceType}', got '\${resource.resourceType}'\`,
|
|
465
|
-
path: 'resourceType',
|
|
466
|
-
value: resource.resourceType,
|
|
467
|
-
expected: '${resourceType}',
|
|
468
|
-
suggestion: 'Ensure the resourceType matches the expected value'
|
|
469
|
-
});
|
|
470
|
-
result.valid = false;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// Generic field validation
|
|
474
|
-
if (options.validateTypes) {
|
|
475
|
-
// Validate common fields
|
|
476
|
-
if (resource.id !== undefined) {
|
|
477
|
-
this.validateFieldType(resource.id, 'string', 'id', result, '${resourceType.toLowerCase()}');
|
|
478
|
-
}
|
|
479
|
-
if ((resource as any).meta !== undefined) {
|
|
480
|
-
this.validateFieldType((resource as any).meta, 'object', 'meta', result, '${resourceType.toLowerCase()}');
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
}`;
|
|
484
|
-
}
|
|
485
|
-
/**
|
|
486
|
-
* Get validation rules for a specific resource type
|
|
487
|
-
*/
|
|
488
|
-
getValidationRules(resourceType) {
|
|
489
|
-
switch (resourceType) {
|
|
490
|
-
case "Patient":
|
|
491
|
-
return {
|
|
492
|
-
required: ["resourceType"],
|
|
493
|
-
fields: [
|
|
494
|
-
{ name: "id", type: "string" },
|
|
495
|
-
{ name: "meta", type: "object" },
|
|
496
|
-
{ name: "identifier", type: "array" },
|
|
497
|
-
{ name: "active", type: "boolean" },
|
|
498
|
-
{ name: "name", type: "array" },
|
|
499
|
-
{ name: "telecom", type: "array" },
|
|
500
|
-
{ name: "gender", type: "string" },
|
|
501
|
-
{ name: "birthDate", type: "string" },
|
|
502
|
-
{ name: "address", type: "array" },
|
|
503
|
-
],
|
|
504
|
-
};
|
|
505
|
-
case "Observation":
|
|
506
|
-
return {
|
|
507
|
-
required: ["resourceType", "status", "code"],
|
|
508
|
-
fields: [
|
|
509
|
-
{ name: "id", type: "string" },
|
|
510
|
-
{ name: "meta", type: "object" },
|
|
511
|
-
{ name: "identifier", type: "array" },
|
|
512
|
-
{ name: "status", type: "string" },
|
|
513
|
-
{ name: "category", type: "array" },
|
|
514
|
-
{ name: "code", type: "object" },
|
|
515
|
-
{ name: "subject", type: "object" },
|
|
516
|
-
{ name: "effectiveDateTime", type: "string" },
|
|
517
|
-
{ name: "valueQuantity", type: "object" },
|
|
518
|
-
{ name: "valueString", type: "string" },
|
|
519
|
-
{ name: "valueBoolean", type: "boolean" },
|
|
520
|
-
],
|
|
521
|
-
};
|
|
522
|
-
case "Organization":
|
|
523
|
-
return {
|
|
524
|
-
required: ["resourceType"],
|
|
525
|
-
fields: [
|
|
526
|
-
{ name: "id", type: "string" },
|
|
527
|
-
{ name: "meta", type: "object" },
|
|
528
|
-
{ name: "identifier", type: "array" },
|
|
529
|
-
{ name: "active", type: "boolean" },
|
|
530
|
-
{ name: "type", type: "array" },
|
|
531
|
-
{ name: "name", type: "string" },
|
|
532
|
-
{ name: "telecom", type: "array" },
|
|
533
|
-
{ name: "address", type: "array" },
|
|
534
|
-
],
|
|
535
|
-
};
|
|
536
|
-
case "Practitioner":
|
|
537
|
-
return {
|
|
538
|
-
required: ["resourceType"],
|
|
539
|
-
fields: [
|
|
540
|
-
{ name: "id", type: "string" },
|
|
541
|
-
{ name: "meta", type: "object" },
|
|
542
|
-
{ name: "identifier", type: "array" },
|
|
543
|
-
{ name: "active", type: "boolean" },
|
|
544
|
-
{ name: "name", type: "array" },
|
|
545
|
-
{ name: "telecom", type: "array" },
|
|
546
|
-
{ name: "address", type: "array" },
|
|
547
|
-
{ name: "gender", type: "string" },
|
|
548
|
-
{ name: "birthDate", type: "string" },
|
|
549
|
-
],
|
|
550
|
-
};
|
|
551
|
-
case "Bundle":
|
|
552
|
-
return {
|
|
553
|
-
required: ["resourceType", "type"],
|
|
554
|
-
fields: [
|
|
555
|
-
{ name: "id", type: "string" },
|
|
556
|
-
{ name: "meta", type: "object" },
|
|
557
|
-
{ name: "identifier", type: "object" },
|
|
558
|
-
{ name: "type", type: "string" },
|
|
559
|
-
{ name: "timestamp", type: "string" },
|
|
560
|
-
{ name: "total", type: "number" },
|
|
561
|
-
{ name: "entry", type: "array" },
|
|
562
|
-
],
|
|
563
|
-
};
|
|
564
|
-
default:
|
|
565
|
-
return {
|
|
566
|
-
required: ["resourceType"],
|
|
567
|
-
fields: [
|
|
568
|
-
{ name: "id", type: "string" },
|
|
569
|
-
{ name: "meta", type: "object" },
|
|
570
|
-
],
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
/**
|
|
575
|
-
* Generate resource-specific constraint validation
|
|
576
|
-
*/
|
|
577
|
-
generateResourceSpecificConstraints(resourceType) {
|
|
578
|
-
switch (resourceType) {
|
|
579
|
-
case "Patient":
|
|
580
|
-
return `// Patient-specific constraints
|
|
581
|
-
if (resource.gender && !['male', 'female', 'other', 'unknown'].includes(resource.gender)) {
|
|
582
|
-
result.errors.push({
|
|
583
|
-
severity: 'error',
|
|
584
|
-
code: 'INVALID_GENDER_VALUE',
|
|
585
|
-
message: 'Invalid gender value',
|
|
586
|
-
path: 'patient.gender',
|
|
587
|
-
value: resource.gender,
|
|
588
|
-
expected: 'male, female, other, or unknown',
|
|
589
|
-
suggestion: 'Use a valid gender code'
|
|
590
|
-
});
|
|
591
|
-
result.valid = false;
|
|
592
|
-
}`;
|
|
593
|
-
case "Observation":
|
|
594
|
-
return `// Observation-specific constraints
|
|
595
|
-
if (resource.status && !['registered', 'preliminary', 'final', 'amended', 'corrected', 'cancelled', 'entered-in-error', 'unknown'].includes(resource.status)) {
|
|
596
|
-
result.errors.push({
|
|
597
|
-
severity: 'error',
|
|
598
|
-
code: 'INVALID_OBSERVATION_STATUS',
|
|
599
|
-
message: 'Invalid observation status',
|
|
600
|
-
path: 'observation.status',
|
|
601
|
-
value: resource.status,
|
|
602
|
-
expected: 'valid observation status code',
|
|
603
|
-
suggestion: 'Use a valid observation status code'
|
|
604
|
-
});
|
|
605
|
-
result.valid = false;
|
|
606
|
-
}`;
|
|
607
|
-
case "Bundle":
|
|
608
|
-
return `// Bundle-specific constraints
|
|
609
|
-
if (resource.type && !['document', 'message', 'transaction', 'transaction-response', 'batch', 'batch-response', 'history', 'searchset', 'collection'].includes(resource.type)) {
|
|
610
|
-
result.errors.push({
|
|
611
|
-
severity: 'error',
|
|
612
|
-
code: 'INVALID_BUNDLE_TYPE',
|
|
613
|
-
message: 'Invalid bundle type',
|
|
614
|
-
path: 'bundle.type',
|
|
615
|
-
value: resource.type,
|
|
616
|
-
expected: 'valid bundle type code',
|
|
617
|
-
suggestion: 'Use a valid bundle type code'
|
|
618
|
-
});
|
|
619
|
-
result.valid = false;
|
|
620
|
-
}`;
|
|
621
|
-
default:
|
|
622
|
-
return `// Generic resource constraints
|
|
623
|
-
// No specific constraints for ${resourceType}`;
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
/**
|
|
627
|
-
* Get collected resource types
|
|
628
|
-
*/
|
|
629
|
-
getResourceTypes() {
|
|
630
|
-
return this.resourceTypes;
|
|
631
|
-
}
|
|
632
|
-
}
|