@aurabx/jmix-js 0.1.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.
Files changed (73) hide show
  1. package/.ai/security.md +184 -0
  2. package/.eslintrc.cjs +23 -0
  3. package/.idea/jmix-ts.iml +13 -0
  4. package/.idea/modules.xml +8 -0
  5. package/.idea/vcs.xml +6 -0
  6. package/.prettierrc +9 -0
  7. package/README.md +335 -0
  8. package/WARP.md +143 -0
  9. package/dist/JmixBuilder.d.ts +82 -0
  10. package/dist/JmixBuilder.d.ts.map +1 -0
  11. package/dist/JmixBuilder.js +353 -0
  12. package/dist/JmixBuilder.js.map +1 -0
  13. package/dist/crypto/PayloadDecryptor.d.ts +12 -0
  14. package/dist/crypto/PayloadDecryptor.d.ts.map +1 -0
  15. package/dist/crypto/PayloadDecryptor.js +39 -0
  16. package/dist/crypto/PayloadDecryptor.js.map +1 -0
  17. package/dist/crypto/PayloadEncryptor.d.ts +21 -0
  18. package/dist/crypto/PayloadEncryptor.d.ts.map +1 -0
  19. package/dist/crypto/PayloadEncryptor.js +79 -0
  20. package/dist/crypto/PayloadEncryptor.js.map +1 -0
  21. package/dist/demo-decrypt-existing.js +27 -0
  22. package/dist/demo-decrypt.js +39 -0
  23. package/dist/demo-no-validation.js +95 -0
  24. package/dist/demo-package-encrypted.js +34 -0
  25. package/dist/demo-package.js +28 -0
  26. package/dist/demo-verify-hash.js +30 -0
  27. package/dist/demo.js +73 -0
  28. package/dist/dicom/DicomProcessor.d.ts +40 -0
  29. package/dist/dicom/DicomProcessor.d.ts.map +1 -0
  30. package/dist/dicom/DicomProcessor.js +231 -0
  31. package/dist/dicom/DicomProcessor.js.map +1 -0
  32. package/dist/index.d.ts +6 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +8 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/types/index.d.ts +165 -0
  37. package/dist/types/index.d.ts.map +1 -0
  38. package/dist/types/index.js +31 -0
  39. package/dist/types/index.js.map +1 -0
  40. package/dist/validation/SchemaValidator.d.ts +25 -0
  41. package/dist/validation/SchemaValidator.d.ts.map +1 -0
  42. package/dist/validation/SchemaValidator.js +125 -0
  43. package/dist/validation/SchemaValidator.js.map +1 -0
  44. package/jest.config.json +20 -0
  45. package/package.json +74 -0
  46. package/samples/sample_config.json +52 -0
  47. package/samples/study_1/series_1/CT.1.1.dcm +0 -0
  48. package/samples/study_1/series_1/CT.1.2.dcm +0 -0
  49. package/samples/study_1/series_1/CT.1.3.dcm +0 -0
  50. package/samples/study_1/series_1/CT.1.4.dcm +0 -0
  51. package/samples/study_1/series_1/CT.1.5.dcm +0 -0
  52. package/samples/study_1/series_2/CT.2.1.dcm +0 -0
  53. package/samples/study_1/series_2/CT.2.2.dcm +0 -0
  54. package/samples/study_1/series_2/CT.2.3.dcm +0 -0
  55. package/samples/study_1/series_2/CT.2.4.dcm +0 -0
  56. package/samples/study_1/series_2/CT.2.5.dcm +0 -0
  57. package/samples/study_1/series_3/CT.3.1.dcm +0 -0
  58. package/samples/study_1/series_3/CT.3.2.dcm +0 -0
  59. package/samples/study_1/series_3/CT.3.3.dcm +0 -0
  60. package/samples/study_1/series_3/CT.3.4.dcm +0 -0
  61. package/samples/study_1/series_3/CT.3.5.dcm +0 -0
  62. package/src/JmixBuilder.ts +572 -0
  63. package/src/crypto/PayloadDecryptor.ts +45 -0
  64. package/src/crypto/PayloadEncryptor.ts +97 -0
  65. package/src/dicom/DicomProcessor.ts +262 -0
  66. package/src/index.ts +30 -0
  67. package/src/types/daikon.d.ts +1 -0
  68. package/src/types/index.ts +201 -0
  69. package/src/validation/SchemaValidator.ts +156 -0
  70. package/test-encrypt.js +10 -0
  71. package/tests/JmixBuilder.test.ts +170 -0
  72. package/tests/SchemaValidator.test.ts +196 -0
  73. package/tsconfig.json +21 -0
@@ -0,0 +1,231 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import { DicomError } from '../types/index.js';
4
+ import daikon from 'daikon';
5
+ const DICOM_MAGIC_OFFSET = 128;
6
+ const DICOM_MAGIC_SIGNATURE = 'DICM';
7
+ function toArrayBuffer(buf) {
8
+ const ab = new ArrayBuffer(buf.byteLength);
9
+ const view = new Uint8Array(ab);
10
+ view.set(buf);
11
+ return ab;
12
+ }
13
+ export class DicomProcessor {
14
+ /**
15
+ * Process a DICOM directory and extract metadata
16
+ */
17
+ async processDicomFolder(dicomPath, config) {
18
+ try {
19
+ const dicomFiles = await this.findDicomFiles(dicomPath);
20
+ if (dicomFiles.length === 0) {
21
+ // Fallback to config data if no DICOM files found
22
+ return this.createMetadataFromConfig(config);
23
+ }
24
+ // Parse files with Daikon and group by series
25
+ const images = [];
26
+ const seriesMap = new Map();
27
+ const modalitiesSet = new Set();
28
+ for (const f of dicomFiles) {
29
+ try {
30
+ const buf = await fs.readFile(f);
31
+ const view = new DataView(toArrayBuffer(buf));
32
+ const image = daikon.Series.parseImage(view);
33
+ if (!image)
34
+ continue;
35
+ images.push(image);
36
+ const seriesId = image.getSeriesId ? image.getSeriesId() : path.dirname(f);
37
+ const arr = seriesMap.get(seriesId) || [];
38
+ arr.push(image);
39
+ seriesMap.set(seriesId, arr);
40
+ // Try to read modality if available
41
+ try {
42
+ const modality = (image.getModality && image.getModality()) || this.readTag(image, 0x0008, 0x0060) || 'UNKNOWN';
43
+ if (modality)
44
+ modalitiesSet.add(String(modality));
45
+ }
46
+ catch {
47
+ // ignore modality errors
48
+ }
49
+ }
50
+ catch {
51
+ // skip unreadable file
52
+ }
53
+ }
54
+ const series = [];
55
+ for (const [sid, imgs] of seriesMap.entries()) {
56
+ series.push({
57
+ series_uid: String(sid),
58
+ modality: 'UNKNOWN',
59
+ instance_count: imgs.length,
60
+ });
61
+ }
62
+ // Attempt to extract some study-level tags from the first image
63
+ let study_description = undefined;
64
+ let study_uid = undefined;
65
+ let study_date = undefined;
66
+ let patient_name = config?.patient.name;
67
+ let patient_id = config?.patient.id;
68
+ let patient_dob = config?.patient.dob;
69
+ let patient_sex = config?.patient.sex;
70
+ const first = images[0];
71
+ if (first) {
72
+ study_description = this.readTag(first, 0x0008, 0x1030) || 'Study';
73
+ study_uid = this.readTag(first, 0x0020, 0x000D) || this.generateStudyUID();
74
+ const sd = this.readTag(first, 0x0008, 0x0020);
75
+ study_date = sd && String(sd).length === 8 ? DicomProcessor.formatDicomDate(String(sd)) : new Date().toISOString().split('T')[0];
76
+ patient_name = this.readTag(first, 0x0010, 0x0010) || patient_name;
77
+ patient_id = this.readTag(first, 0x0010, 0x0020) || patient_id;
78
+ const dob = this.readTag(first, 0x0010, 0x0030);
79
+ patient_dob = dob && String(dob).length === 8 ? DicomProcessor.formatDicomDate(String(dob)) : patient_dob;
80
+ patient_sex = this.readTag(first, 0x0010, 0x0040) || patient_sex;
81
+ }
82
+ const metadata = {
83
+ patient_name,
84
+ patient_id,
85
+ patient_dob,
86
+ patient_sex,
87
+ study_description,
88
+ study_uid,
89
+ study_date,
90
+ modalities: Array.from(modalitiesSet.size ? modalitiesSet : new Set(['UNKNOWN'])),
91
+ series_count: seriesMap.size || 1,
92
+ instance_count: images.length,
93
+ series,
94
+ };
95
+ return metadata;
96
+ }
97
+ catch (error) {
98
+ throw new DicomError(`Failed to process DICOM folder: ${dicomPath}`, error instanceof Error ? error : new Error(String(error)));
99
+ }
100
+ }
101
+ /**
102
+ * Recursively find DICOM files in a directory
103
+ */
104
+ async findDicomFiles(dirPath) {
105
+ const dicomFiles = [];
106
+ try {
107
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
108
+ for (const entry of entries) {
109
+ const fullPath = path.join(dirPath, entry.name);
110
+ if (entry.isDirectory()) {
111
+ // Recursively search subdirectories
112
+ const subDirFiles = await this.findDicomFiles(fullPath);
113
+ dicomFiles.push(...subDirFiles);
114
+ }
115
+ else if (entry.isFile()) {
116
+ if (await this.isDicomFile(fullPath)) {
117
+ dicomFiles.push(fullPath);
118
+ }
119
+ }
120
+ }
121
+ }
122
+ catch (error) {
123
+ throw new DicomError(`Failed to read directory: ${dirPath}`, error instanceof Error ? error : new Error(String(error)));
124
+ }
125
+ return dicomFiles;
126
+ }
127
+ /**
128
+ * Check if a file is a DICOM file by checking the magic signature
129
+ */
130
+ async isDicomFile(filePath) {
131
+ try {
132
+ // Check file extension first (quick check)
133
+ const ext = path.extname(filePath).toLowerCase();
134
+ if (['.dcm', '.dicom'].includes(ext)) {
135
+ return true;
136
+ }
137
+ // Check for DICM magic number at offset 128
138
+ const fileHandle = await fs.open(filePath, 'r');
139
+ const buffer = Buffer.alloc(4);
140
+ await fileHandle.read(buffer, 0, 4, DICOM_MAGIC_OFFSET);
141
+ await fileHandle.close();
142
+ return buffer.toString('ascii') === DICOM_MAGIC_SIGNATURE;
143
+ }
144
+ catch {
145
+ // If we can't read the file, assume it's not a DICOM file
146
+ return false;
147
+ }
148
+ }
149
+ /**
150
+ * Create metadata from config when DICOM parsing fails or no files found
151
+ */
152
+ createMetadataFromConfig(config) {
153
+ return {
154
+ patient_name: config?.patient.name,
155
+ patient_id: config?.patient.id,
156
+ patient_dob: config?.patient.dob,
157
+ patient_sex: config?.patient.sex,
158
+ study_description: 'Study from configuration',
159
+ study_uid: this.generateStudyUID(),
160
+ study_date: new Date().toISOString().split('T')[0],
161
+ modalities: ['UNKNOWN'],
162
+ series_count: 1,
163
+ instance_count: 0,
164
+ series: [],
165
+ };
166
+ }
167
+ /**
168
+ * Generate a study UID (placeholder implementation)
169
+ */
170
+ generateStudyUID() {
171
+ // Simple UID generation - in production would use proper DICOM UID format
172
+ const timestamp = Date.now();
173
+ const random = Math.floor(Math.random() * 10000);
174
+ return `1.2.3.${timestamp}.${random}`;
175
+ }
176
+ /**
177
+ * Estimate series count based on file naming patterns or directory structure
178
+ */
179
+ estimateSeriesCount(files) {
180
+ // Simple estimation based on directory structure
181
+ const directories = new Set();
182
+ for (const file of files) {
183
+ directories.add(path.dirname(file));
184
+ }
185
+ return Math.max(1, directories.size);
186
+ }
187
+ /**
188
+ * Attempt to read a DICOM tag value using Daikon's API (best-effort)
189
+ */
190
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
191
+ readTag(image, group, element) {
192
+ try {
193
+ if (image && image.getTag && typeof image.getTag === 'function') {
194
+ const tag = image.getTag(group, element);
195
+ if (tag && tag.value && tag.value.length) {
196
+ return String(tag.value[0]);
197
+ }
198
+ }
199
+ }
200
+ catch {
201
+ // ignore
202
+ }
203
+ return undefined;
204
+ }
205
+ /**
206
+ * Format DICOM date to ISO format
207
+ */
208
+ static formatDicomDate(dicomDate) {
209
+ if (!dicomDate || dicomDate.length !== 8) {
210
+ return new Date().toISOString().split('T')[0];
211
+ }
212
+ const year = dicomDate.substring(0, 4);
213
+ const month = dicomDate.substring(4, 6);
214
+ const day = dicomDate.substring(6, 8);
215
+ return `${year}-${month}-${day}`;
216
+ }
217
+ /**
218
+ * Format DICOM person name to readable format
219
+ */
220
+ static formatDicomPersonName(dicomName) {
221
+ if (!dicomName)
222
+ return '';
223
+ // DICOM names are in format: "Last^First^Middle^Prefix^Suffix"
224
+ const parts = dicomName.split('^');
225
+ const last = parts[0] || '';
226
+ const first = parts[1] || '';
227
+ const middle = parts[2] || '';
228
+ return [first, middle, last].filter(Boolean).join(' ').trim();
229
+ }
230
+ }
231
+ //# sourceMappingURL=DicomProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DicomProcessor.js","sourceRoot":"","sources":["../../src/dicom/DicomProcessor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { JmixBuilder, type JmixBuilderOptions } from './JmixBuilder.js';
2
+ export { SchemaValidator, type SchemaValidatorOptions, } from './validation/SchemaValidator.js';
3
+ export { DicomProcessor } from './dicom/DicomProcessor.js';
4
+ export * from './types/index.js';
5
+ export type { JmixEnvelope, Config, Manifest, Metadata, Audit, Files, DicomMetadata, Patient, ContactVariant, Contact, Security, Consent, Encryption, SenderAssertion, } from './types/index.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,GAC5B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,cAAc,kBAAkB,CAAC;AAGjC,YAAY,EACV,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,KAAK,EACL,aAAa,EACb,OAAO,EACP,cAAc,EACd,OAAO,EACP,QAAQ,EACR,OAAO,EACP,UAAU,EACV,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ // JMIX TypeScript Library - Main Entry Point
2
+ // JSON Medical Interchange format for secure medical data exchange
3
+ export { JmixBuilder } from './JmixBuilder.js';
4
+ export { SchemaValidator, } from './validation/SchemaValidator.js';
5
+ export { DicomProcessor } from './dicom/DicomProcessor.js';
6
+ // Export all types
7
+ export * from './types/index.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,mEAAmE;AAEnE,OAAO,EAAE,WAAW,EAA2B,MAAM,kBAAkB,CAAC;AACxE,OAAO,EACL,eAAe,GAEhB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,mBAAmB;AACnB,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,165 @@
1
+ export interface Contact {
2
+ system?: string;
3
+ value: string;
4
+ use_field?: string;
5
+ }
6
+ export interface ContactVariant {
7
+ name: string;
8
+ id: string;
9
+ contact: string | Contact;
10
+ }
11
+ export interface PatientIdentifier {
12
+ system: string;
13
+ value: string;
14
+ use_field?: string;
15
+ }
16
+ export interface Patient {
17
+ name: string;
18
+ id: string;
19
+ dob?: string;
20
+ sex?: 'M' | 'F' | 'O' | 'U';
21
+ identifiers?: PatientIdentifier[];
22
+ }
23
+ export interface Consent {
24
+ status: 'granted' | 'denied' | 'pending';
25
+ scope?: string[];
26
+ method?: string;
27
+ }
28
+ export interface Security {
29
+ classification: 'public' | 'internal' | 'confidential' | 'restricted';
30
+ payload_hash?: string;
31
+ }
32
+ export interface Encryption {
33
+ algorithm: 'AES-256-GCM';
34
+ ephemeral_public_key: string;
35
+ iv: string;
36
+ auth_tag: string;
37
+ }
38
+ export interface SenderAssertion {
39
+ signing_key: {
40
+ alg: string;
41
+ public_key: string;
42
+ fingerprint: string;
43
+ };
44
+ key_reference?: string;
45
+ signed_fields: string[];
46
+ signature: string;
47
+ expires_at?: string;
48
+ directory_attestation?: {
49
+ provider: string;
50
+ attestation_signature: string;
51
+ attestation_timestamp: string;
52
+ attestation_public_key: string;
53
+ };
54
+ }
55
+ export interface Manifest {
56
+ jmix_version: string;
57
+ envelope_id: string;
58
+ created_at: string;
59
+ sender: ContactVariant & {
60
+ assertion?: SenderAssertion;
61
+ };
62
+ requester?: ContactVariant & {
63
+ assertion?: SenderAssertion;
64
+ };
65
+ receivers: ContactVariant[];
66
+ patient: Patient;
67
+ security: Security;
68
+ consent?: Consent;
69
+ custom_tags?: string[];
70
+ report?: {
71
+ file: string;
72
+ };
73
+ deid_keys?: string[];
74
+ encryption?: Encryption;
75
+ }
76
+ export interface DicomMetadata {
77
+ patient_name?: string;
78
+ patient_id?: string;
79
+ patient_dob?: string;
80
+ patient_sex?: string;
81
+ study_description?: string;
82
+ study_uid?: string;
83
+ study_date?: string;
84
+ modalities: string[];
85
+ series_count: number;
86
+ instance_count: number;
87
+ series?: Array<{
88
+ series_uid: string;
89
+ series_description?: string;
90
+ modality: string;
91
+ instance_count: number;
92
+ }>;
93
+ }
94
+ export interface Metadata {
95
+ patient: Patient;
96
+ study: {
97
+ description?: string;
98
+ uid?: string;
99
+ date?: string;
100
+ };
101
+ dicom: DicomMetadata;
102
+ custom_metadata?: Record<string, unknown>;
103
+ }
104
+ export interface AuditEntityRef {
105
+ id: string;
106
+ name?: string;
107
+ }
108
+ export interface AuditEntry {
109
+ event: string;
110
+ by: AuditEntityRef;
111
+ to?: AuditEntityRef;
112
+ timestamp: string;
113
+ assertion?: SenderAssertion;
114
+ }
115
+ export interface Audit {
116
+ audit: AuditEntry[];
117
+ }
118
+ export interface FileEntry {
119
+ path: string;
120
+ size: number;
121
+ hash: string;
122
+ mime_type?: string;
123
+ description?: string;
124
+ }
125
+ export interface Files {
126
+ payload_directory: string;
127
+ files: FileEntry[];
128
+ total_size: number;
129
+ file_count: number;
130
+ }
131
+ export interface JmixEnvelope {
132
+ manifest: Manifest;
133
+ metadata: Metadata;
134
+ audit: Audit;
135
+ files?: Files;
136
+ }
137
+ export interface Config {
138
+ version: string;
139
+ sender: ContactVariant;
140
+ requester?: ContactVariant;
141
+ receivers: ContactVariant[];
142
+ patient: Patient;
143
+ security: Security;
144
+ consent?: Consent;
145
+ custom_tags?: string[];
146
+ report?: {
147
+ file: string;
148
+ };
149
+ deid_keys?: string[];
150
+ }
151
+ export declare class JmixError extends Error {
152
+ readonly cause?: Error | undefined;
153
+ constructor(message: string, cause?: Error | undefined);
154
+ }
155
+ export declare class ValidationError extends JmixError {
156
+ readonly errors: string[];
157
+ constructor(message: string, errors?: string[]);
158
+ }
159
+ export declare class CryptographyError extends JmixError {
160
+ constructor(message: string, cause?: Error);
161
+ }
162
+ export declare class DicomError extends JmixError {
163
+ constructor(message: string, cause?: Error);
164
+ }
165
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ // JMIX Core Types - TypeScript interfaces for JMIX envelope components
2
+ // Error types
3
+ export class JmixError extends Error {
4
+ cause;
5
+ constructor(message, cause) {
6
+ super(message);
7
+ this.cause = cause;
8
+ this.name = 'JmixError';
9
+ }
10
+ }
11
+ export class ValidationError extends JmixError {
12
+ errors;
13
+ constructor(message, errors = []) {
14
+ super(message);
15
+ this.errors = errors;
16
+ this.name = 'ValidationError';
17
+ }
18
+ }
19
+ export class CryptographyError extends JmixError {
20
+ constructor(message, cause) {
21
+ super(message, cause);
22
+ this.name = 'CryptographyError';
23
+ }
24
+ }
25
+ export class DicomError extends JmixError {
26
+ constructor(message, cause) {
27
+ super(message, cause);
28
+ this.name = 'DicomError';
29
+ }
30
+ }
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAuKvE,cAAc;AACd,MAAM,OAAO,SAAU,SAAQ,KAAK;IAGhB;IAFlB,YACE,OAAe,EACC,KAAa;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,UAAK,GAAL,KAAK,CAAQ;QAG7B,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAG1B;IAFlB,YACE,OAAe,EACC,SAAmB,EAAE;QAErC,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,WAAM,GAAN,MAAM,CAAe;QAGrC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,SAAS;IAC9C,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,MAAM,OAAO,UAAW,SAAQ,SAAS;IACvC,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,25 @@
1
+ export interface SchemaValidatorOptions {
2
+ schemaPath?: string;
3
+ strictMode?: boolean;
4
+ }
5
+ export declare class SchemaValidator {
6
+ private ajv;
7
+ private schemaPath;
8
+ private schemaCache;
9
+ constructor(options?: SchemaValidatorOptions);
10
+ private loadSchema;
11
+ private getSchemaPath;
12
+ validateManifest(data: unknown): Promise<void>;
13
+ validateMetadata(data: unknown): Promise<void>;
14
+ validateAudit(data: unknown): Promise<void>;
15
+ validateFiles(data: unknown): Promise<void>;
16
+ private validate;
17
+ validateEnvelope(envelope: {
18
+ manifest: unknown;
19
+ metadata: unknown;
20
+ audit: unknown;
21
+ files?: unknown;
22
+ }): Promise<void>;
23
+ isSchemaAvailable(schemaName?: string): Promise<boolean>;
24
+ }
25
+ //# sourceMappingURL=SchemaValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaValidator.d.ts","sourceRoot":"","sources":["../../src/validation/SchemaValidator.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAkC;gBAEzC,OAAO,GAAE,sBAA2B;YAelC,UAAU;IAiBxB,OAAO,CAAC,aAAa;IAIf,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;YAInC,QAAQ;IA0ChB,gBAAgB,CAAC,QAAQ,EAAE;QAC/B,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,OAAO,CAAC;QAClB,KAAK,EAAE,OAAO,CAAC;QACf,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBX,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAgB/D"}
@@ -0,0 +1,125 @@
1
+ import Ajv from 'ajv';
2
+ import addFormats from 'ajv-formats';
3
+ import * as fs from 'fs/promises';
4
+ import * as path from 'path';
5
+ import { ValidationError } from '../types/index.js';
6
+ export class SchemaValidator {
7
+ ajv;
8
+ schemaPath;
9
+ schemaCache = new Map();
10
+ constructor(options = {}) {
11
+ this.schemaPath =
12
+ options.schemaPath ||
13
+ process.env.JMIX_SCHEMA_PATH ||
14
+ path.resolve(process.cwd(), '../jmix/schemas');
15
+ this.ajv = new Ajv({
16
+ allErrors: true,
17
+ strict: options.strictMode ?? true,
18
+ loadSchema: this.loadSchema.bind(this),
19
+ });
20
+ addFormats(this.ajv);
21
+ }
22
+ async loadSchema(uri) {
23
+ if (this.schemaCache.has(uri)) {
24
+ return this.schemaCache.get(uri);
25
+ }
26
+ try {
27
+ const schemaContent = await fs.readFile(uri, 'utf-8');
28
+ const schema = JSON.parse(schemaContent);
29
+ this.schemaCache.set(uri, schema);
30
+ return schema;
31
+ }
32
+ catch (error) {
33
+ throw new ValidationError(`Failed to load schema from ${uri}`, [
34
+ error instanceof Error ? error.message : String(error),
35
+ ]);
36
+ }
37
+ }
38
+ getSchemaPath(schemaName) {
39
+ return path.join(this.schemaPath, `${schemaName}.schema.json`);
40
+ }
41
+ async validateManifest(data) {
42
+ await this.validate('manifest', data);
43
+ }
44
+ async validateMetadata(data) {
45
+ await this.validate('metadata', data);
46
+ }
47
+ async validateAudit(data) {
48
+ await this.validate('audit', data);
49
+ }
50
+ async validateFiles(data) {
51
+ await this.validate('files', data);
52
+ }
53
+ async validate(schemaName, data) {
54
+ const schemaPath = this.getSchemaPath(schemaName);
55
+ try {
56
+ // Check if schema file exists
57
+ await fs.access(schemaPath);
58
+ }
59
+ catch {
60
+ // Schema file doesn't exist, skip validation gracefully
61
+ console.warn(`Schema validation skipped: ${schemaPath} not found`);
62
+ return;
63
+ }
64
+ try {
65
+ const schema = await this.loadSchema(schemaPath);
66
+ const validate = this.ajv.compile(schema);
67
+ const valid = validate(data);
68
+ if (!valid) {
69
+ const errors = validate.errors?.map((error) => {
70
+ const instancePath = error.instancePath || 'root';
71
+ return `${instancePath}: ${error.message}`;
72
+ }) || [];
73
+ throw new ValidationError(`${schemaName} validation failed`, errors);
74
+ }
75
+ }
76
+ catch (error) {
77
+ if (error instanceof ValidationError &&
78
+ error.message.includes('validation failed')) {
79
+ throw error;
80
+ }
81
+ // For schema loading errors, just skip validation gracefully
82
+ console.warn(`Schema validation error for ${schemaName}, skipping: ${error instanceof Error ? error.message : String(error)}`);
83
+ return;
84
+ }
85
+ }
86
+ async validateEnvelope(envelope) {
87
+ const validationPromises = [
88
+ this.validateManifest(envelope.manifest),
89
+ this.validateMetadata(envelope.metadata),
90
+ this.validateAudit(envelope.audit),
91
+ ];
92
+ if (envelope.files) {
93
+ validationPromises.push(this.validateFiles(envelope.files));
94
+ }
95
+ try {
96
+ await Promise.all(validationPromises);
97
+ }
98
+ catch (error) {
99
+ if (error instanceof ValidationError) {
100
+ throw error;
101
+ }
102
+ throw new ValidationError('Envelope validation failed', [
103
+ error instanceof Error ? error.message : String(error),
104
+ ]);
105
+ }
106
+ }
107
+ // Check if schema files are available
108
+ async isSchemaAvailable(schemaName) {
109
+ if (schemaName) {
110
+ try {
111
+ await fs.access(this.getSchemaPath(schemaName));
112
+ return true;
113
+ }
114
+ catch {
115
+ return false;
116
+ }
117
+ }
118
+ // Check if any schema files are available
119
+ const schemaNames = ['manifest', 'metadata', 'audit', 'files'];
120
+ const checks = schemaNames.map((name) => this.isSchemaAvailable(name));
121
+ const results = await Promise.all(checks);
122
+ return results.some((available) => available);
123
+ }
124
+ }
125
+ //# sourceMappingURL=SchemaValidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaValidator.js","sourceRoot":"","sources":["../../src/validation/SchemaValidator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ {
2
+ "preset": "ts-jest/presets/default-esm",
3
+ "extensionsToTreatAsEsm": [".ts"],
4
+ "moduleNameMapper": {
5
+ "^(\\.{1,2}/.*)\\.js$": "$1"
6
+ },
7
+ "testEnvironment": "node",
8
+ "testMatch": ["**/tests/**/*.test.ts", "**/__tests__/**/*.test.ts"],
9
+ "collectCoverageFrom": ["src/**/*.ts", "!src/**/*.d.ts", "!src/**/*.test.ts"],
10
+ "coverageDirectory": "coverage",
11
+ "coverageReporters": ["text", "lcov", "html"],
12
+ "transform": {
13
+ "^.+\\.ts$": [
14
+ "ts-jest",
15
+ {
16
+ "useESM": true
17
+ }
18
+ ]
19
+ }
20
+ }