fhirsmith 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/package.json +1 -1
- package/translations/Messages.properties +3 -1
- package/tx/cs/cs-api.js +2 -1
- package/tx/cs/cs-areacode.js +1 -1
- package/tx/cs/cs-country.js +1 -1
- package/tx/cs/cs-cpt.js +1 -1
- package/tx/cs/cs-cs.js +1 -1
- package/tx/cs/cs-currency.js +1 -1
- package/tx/cs/cs-hgvs.js +1 -1
- package/tx/cs/cs-lang.js +1 -1
- package/tx/cs/cs-loinc.js +1 -1
- package/tx/cs/cs-ndc.js +1 -1
- package/tx/cs/cs-omop.js +1 -1
- package/tx/cs/cs-rxnorm.js +1 -1
- package/tx/cs/cs-snomed.js +603 -22
- package/tx/cs/cs-ucum.js +1 -1
- package/tx/importers/import-sct.module.js +167 -79
- package/tx/library.js +3 -0
- package/tx/sct/ecl.js +98 -49
- package/tx/tx.js +6 -2
- package/tx/vs/vs-database.js +213 -92
- package/tx/vs/vs-vsac.js +151 -55
- package/tx/workers/expand.js +42 -24
- package/tx/workers/related.js +1 -1
- package/tx/workers/validate.js +21 -24
- package/tx/workers/worker.js +16 -1
package/tx/cs/cs-ucum.js
CHANGED
|
@@ -256,7 +256,7 @@ class UcumCodeSystemProvider extends BaseCSServices {
|
|
|
256
256
|
// filterContext.filters.push(ucumFilter);
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
async filter(filterContext, prop, op, value) {
|
|
259
|
+
async filter(filterContext, forIteration, prop, op, value) {
|
|
260
260
|
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
261
261
|
assert(prop != null && typeof prop === 'string', 'prop must be a non-null string');
|
|
262
262
|
assert(op != null && typeof op === 'string', 'op must be a non-null string');
|
|
@@ -48,37 +48,37 @@ class SnomedModule extends BaseTerminologyModule {
|
|
|
48
48
|
registerCommands(terminologyCommand, globalOptions) {
|
|
49
49
|
// Import command
|
|
50
50
|
terminologyCommand
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
51
|
+
.command('import')
|
|
52
|
+
.description('Import SNOMED CT data from RF2 source directory')
|
|
53
|
+
.option('-s, --source <directory>', 'Source directory containing RF2 files')
|
|
54
|
+
.option('-b, --base <directory>', 'Base edition directory (for extensions)')
|
|
55
|
+
.option('-d, --dest <file>', 'Destination cache file')
|
|
56
|
+
.option('-e, --edition <code>', 'Edition code (e.g., 900000000000207008 for International)')
|
|
57
|
+
.option('-v, --version <version>', 'Version in YYYYMMDD format (e.g., 20250801)')
|
|
58
|
+
.option('-u, --uri <uri>', 'Version URI (overrides edition/version if provided)')
|
|
59
|
+
.option('-l, --language <code>', 'Default language code (overrides edition default if provided)')
|
|
60
|
+
.option('-y, --yes', 'Skip confirmations')
|
|
61
|
+
.action(async (options) => {
|
|
62
|
+
await this.handleImportCommand({...globalOptions, ...options});
|
|
63
|
+
});
|
|
64
64
|
|
|
65
65
|
// Validate command
|
|
66
66
|
terminologyCommand
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
.command('validate')
|
|
68
|
+
.description('Validate SNOMED CT RF2 directory structure')
|
|
69
|
+
.option('-s, --source <directory>', 'Source directory to validate')
|
|
70
|
+
.action(async (options) => {
|
|
71
|
+
await this.handleValidateCommand({...globalOptions, ...options});
|
|
72
|
+
});
|
|
73
73
|
|
|
74
74
|
// Status command
|
|
75
75
|
terminologyCommand
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
.command('status')
|
|
77
|
+
.description('Show status of SNOMED CT cache')
|
|
78
|
+
.option('-d, --dest <file>', 'Cache file to check')
|
|
79
|
+
.action(async (options) => {
|
|
80
|
+
await this.handleStatusCommand({...globalOptions, ...options});
|
|
81
|
+
});
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
async handleImportCommand(options) {
|
|
@@ -633,7 +633,7 @@ class SnomedModule extends BaseTerminologyModule {
|
|
|
633
633
|
}
|
|
634
634
|
|
|
635
635
|
const additionalAnswers = additionalQuestions.length > 0 ?
|
|
636
|
-
|
|
636
|
+
await inquirer.prompt(additionalQuestions) : {};
|
|
637
637
|
|
|
638
638
|
// Build the final configuration
|
|
639
639
|
const config = {
|
|
@@ -774,7 +774,7 @@ class SnomedModule extends BaseTerminologyModule {
|
|
|
774
774
|
} else if (firstLine.startsWith('id\teffectiveTime\tactive\tmoduleId\tconceptId\tlanguageCode\ttypeId\tterm\tcaseSignificanceId')) {
|
|
775
775
|
files.descriptions.push(filePath);
|
|
776
776
|
} else if (firstLine.startsWith('id\teffectiveTime\tactive\tmoduleId\tsourceId\tdestinationId\trelationshipGroup\ttypeId\tcharacteristicTypeId\tmodifierId') &&
|
|
777
|
-
|
|
777
|
+
!filePath.includes('StatedRelationship')) {
|
|
778
778
|
files.relationships.push(filePath);
|
|
779
779
|
}
|
|
780
780
|
} catch (error) {
|
|
@@ -1165,6 +1165,19 @@ class SnomedImporter {
|
|
|
1165
1165
|
refsetDirectories: []
|
|
1166
1166
|
};
|
|
1167
1167
|
|
|
1168
|
+
// For extensions: load base edition files first so that all International
|
|
1169
|
+
// Edition concepts, descriptions, and relationships are present before the
|
|
1170
|
+
// extension content is layered on top.
|
|
1171
|
+
if (this.config.base) {
|
|
1172
|
+
if (this.config.verbose) {
|
|
1173
|
+
console.log(`Loading base edition from: ${this.config.base}`);
|
|
1174
|
+
}
|
|
1175
|
+
this._scanDirectory(this.config.base, files);
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
// Then load the extension (or standalone edition) source files.
|
|
1179
|
+
// For extensions these come second so that extension rows can override
|
|
1180
|
+
// base rows where the same component has been updated.
|
|
1168
1181
|
this._scanDirectory(this.config.source, files);
|
|
1169
1182
|
return files;
|
|
1170
1183
|
}
|
|
@@ -1200,7 +1213,7 @@ class SnomedImporter {
|
|
|
1200
1213
|
} else if (firstLine.startsWith('id\teffectiveTime\tactive\tmoduleId\tconceptId\tlanguageCode\ttypeId\tterm\tcaseSignificanceId')) {
|
|
1201
1214
|
files.descriptions.push(filePath);
|
|
1202
1215
|
} else if (firstLine.startsWith('id\teffectiveTime\tactive\tmoduleId\tsourceId\tdestinationId\trelationshipGroup\ttypeId\tcharacteristicTypeId\tmodifierId') &&
|
|
1203
|
-
|
|
1216
|
+
!filePath.includes('StatedRelationship')) {
|
|
1204
1217
|
files.relationships.push(filePath);
|
|
1205
1218
|
}
|
|
1206
1219
|
} catch (error) {
|
|
@@ -1250,6 +1263,9 @@ class SnomedImporter {
|
|
|
1250
1263
|
this.conceptList = [];
|
|
1251
1264
|
let processedLines = 0;
|
|
1252
1265
|
|
|
1266
|
+
// When loading base + extension, track list indices for fast replacement
|
|
1267
|
+
const conceptIdToListIndex = this.config.base ? new Map() : null;
|
|
1268
|
+
|
|
1253
1269
|
for (let i = 0; i < this.files.concepts.length; i++) {
|
|
1254
1270
|
const file = this.files.concepts[i];
|
|
1255
1271
|
const rl = readline.createInterface({
|
|
@@ -1275,8 +1291,23 @@ class SnomedImporter {
|
|
|
1275
1291
|
};
|
|
1276
1292
|
|
|
1277
1293
|
if (this.conceptMap.has(concept.id)) {
|
|
1278
|
-
|
|
1294
|
+
// When loading base + extension, the same concept may appear in both.
|
|
1295
|
+
// The extension snapshot row takes precedence (it is loaded second).
|
|
1296
|
+
// If there is no base directory this is a genuine duplicate in a single
|
|
1297
|
+
// snapshot and we should still raise an error.
|
|
1298
|
+
if (!this.config.base) {
|
|
1299
|
+
throw new Error(`Duplicate Concept Id at line ${lineCount}: ${concept.id} - check you are processing the snapshot not the full edition`);
|
|
1300
|
+
}
|
|
1301
|
+
// Replace the base edition row with the extension row
|
|
1302
|
+
const idx = conceptIdToListIndex.get(concept.id);
|
|
1303
|
+
if (idx !== undefined) {
|
|
1304
|
+
this.conceptList[idx] = concept;
|
|
1305
|
+
}
|
|
1306
|
+
this.conceptMap.set(concept.id, concept);
|
|
1279
1307
|
} else {
|
|
1308
|
+
if (conceptIdToListIndex) {
|
|
1309
|
+
conceptIdToListIndex.set(concept.id, this.conceptList.length);
|
|
1310
|
+
}
|
|
1280
1311
|
this.conceptList.push(concept);
|
|
1281
1312
|
this.conceptMap.set(concept.id, concept);
|
|
1282
1313
|
}
|
|
@@ -1347,6 +1378,12 @@ class SnomedImporter {
|
|
|
1347
1378
|
const descriptionList = [];
|
|
1348
1379
|
let processedLines = 0;
|
|
1349
1380
|
|
|
1381
|
+
// Build a lookup from description id -> index in descriptionList so that
|
|
1382
|
+
// extension rows can replace base rows for the same description.
|
|
1383
|
+
if (this.config.base) {
|
|
1384
|
+
this._descriptionIdSet = new Map();
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1350
1387
|
for (const file of this.files.descriptions) {
|
|
1351
1388
|
const rl = readline.createInterface({
|
|
1352
1389
|
input: fs.createReadStream(file),
|
|
@@ -1372,7 +1409,19 @@ class SnomedImporter {
|
|
|
1372
1409
|
caseSignificanceId: BigInt(parts[8])
|
|
1373
1410
|
};
|
|
1374
1411
|
|
|
1375
|
-
|
|
1412
|
+
// When loading base + extension, the same description may appear in
|
|
1413
|
+
// both. The extension row (loaded second) takes precedence.
|
|
1414
|
+
if (this.config.base && this._descriptionIdSet) {
|
|
1415
|
+
const existingIdx = this._descriptionIdSet.get(desc.id);
|
|
1416
|
+
if (existingIdx !== undefined) {
|
|
1417
|
+
descriptionList[existingIdx] = desc;
|
|
1418
|
+
} else {
|
|
1419
|
+
this._descriptionIdSet.set(desc.id, descriptionList.length);
|
|
1420
|
+
descriptionList.push(desc);
|
|
1421
|
+
}
|
|
1422
|
+
} else {
|
|
1423
|
+
descriptionList.push(desc);
|
|
1424
|
+
}
|
|
1376
1425
|
}
|
|
1377
1426
|
|
|
1378
1427
|
processedLines++;
|
|
@@ -1417,8 +1466,8 @@ class SnomedImporter {
|
|
|
1417
1466
|
const caps = this.conceptMap.get(desc.caseSignificanceId);
|
|
1418
1467
|
|
|
1419
1468
|
const descOffset = this.descriptions.addDescription(
|
|
1420
|
-
|
|
1421
|
-
|
|
1469
|
+
termOffset, desc.id, effectiveTime, concept.index,
|
|
1470
|
+
module.index, kind.index, caps.index, desc.active, lang
|
|
1422
1471
|
);
|
|
1423
1472
|
|
|
1424
1473
|
// Track description on concept
|
|
@@ -1692,6 +1741,11 @@ class SnomedImporter {
|
|
|
1692
1741
|
}
|
|
1693
1742
|
this.isAIndex = isAConcept.index;
|
|
1694
1743
|
|
|
1744
|
+
// Pass 1: collect all relationship rows, deduplicating so that extension
|
|
1745
|
+
// rows (loaded second) override base rows with the same relationship id.
|
|
1746
|
+
const relationshipRows = [];
|
|
1747
|
+
const relationshipIdMap = this.config.base ? new Map() : null; // id -> index in relationshipRows
|
|
1748
|
+
|
|
1695
1749
|
for (const file of this.files.relationships) {
|
|
1696
1750
|
const rl = readline.createInterface({
|
|
1697
1751
|
input: fs.createReadStream(file),
|
|
@@ -1718,40 +1772,16 @@ class SnomedImporter {
|
|
|
1718
1772
|
modifierId: BigInt(parts[9])
|
|
1719
1773
|
};
|
|
1720
1774
|
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
// Check if this is a defining relationship
|
|
1729
|
-
const defining = rel.characteristicTypeId === RF2_MAGIC_RELN_DEFINING ||
|
|
1730
|
-
rel.characteristicTypeId === RF2_MAGIC_RELN_STATED ||
|
|
1731
|
-
rel.characteristicTypeId === RF2_MAGIC_RELN_INFERRED;
|
|
1732
|
-
|
|
1733
|
-
const relationshipIndex = this.relationships.addRelationship(
|
|
1734
|
-
rel.id, source.index, destination.index, type.index,
|
|
1735
|
-
0, 0, 0, effectiveTime, rel.active, defining, rel.relationshipGroup
|
|
1736
|
-
);
|
|
1737
|
-
|
|
1738
|
-
// Track parent/child relationships for is-a relationships
|
|
1739
|
-
if (type.index === this.isAIndex && defining) {
|
|
1740
|
-
const sourceTracker = this.getOrCreateConceptTracker(source.index);
|
|
1741
|
-
if (rel.active) {
|
|
1742
|
-
sourceTracker.addActiveParent(destination.index);
|
|
1743
|
-
} else {
|
|
1744
|
-
sourceTracker.addInactiveParent(destination.index);
|
|
1745
|
-
}
|
|
1775
|
+
if (relationshipIdMap) {
|
|
1776
|
+
const existingIdx = relationshipIdMap.get(rel.id);
|
|
1777
|
+
if (existingIdx !== undefined) {
|
|
1778
|
+
relationshipRows[existingIdx] = rel;
|
|
1779
|
+
} else {
|
|
1780
|
+
relationshipIdMap.set(rel.id, relationshipRows.length);
|
|
1781
|
+
relationshipRows.push(rel);
|
|
1746
1782
|
}
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
const sourceTracker = this.getOrCreateConceptTracker(source.index);
|
|
1750
|
-
const destTracker = this.getOrCreateConceptTracker(destination.index);
|
|
1751
|
-
|
|
1752
|
-
sourceTracker.addOutbound(relationshipIndex);
|
|
1753
|
-
destTracker.addInbound(relationshipIndex);
|
|
1754
|
-
|
|
1783
|
+
} else {
|
|
1784
|
+
relationshipRows.push(rel);
|
|
1755
1785
|
}
|
|
1756
1786
|
}
|
|
1757
1787
|
|
|
@@ -1762,10 +1792,62 @@ class SnomedImporter {
|
|
|
1762
1792
|
}
|
|
1763
1793
|
}
|
|
1764
1794
|
|
|
1795
|
+
if (this.progressReporter) {
|
|
1796
|
+
this.progressReporter.completeTask('Reading Relationships', processedLines, totalLines);
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
// Pass 2: process the deduplicated relationship rows into the binary
|
|
1800
|
+
// structures and concept trackers.
|
|
1801
|
+
const buildProgressBar = this.progressReporter?.createTaskProgressBar('Building Relationships');
|
|
1802
|
+
buildProgressBar?.start(relationshipRows.length, 0);
|
|
1803
|
+
|
|
1804
|
+
for (let i = 0; i < relationshipRows.length; i++) {
|
|
1805
|
+
const rel = relationshipRows[i];
|
|
1806
|
+
|
|
1807
|
+
const source = this.conceptMap.get(rel.sourceId);
|
|
1808
|
+
const destination = this.conceptMap.get(rel.destinationId);
|
|
1809
|
+
const type = this.conceptMap.get(rel.typeId);
|
|
1810
|
+
|
|
1811
|
+
if (source && destination && type) {
|
|
1812
|
+
const effectiveTime = this.convertDateToSnomedDate(rel.effectiveTime);
|
|
1813
|
+
|
|
1814
|
+
// Check if this is a defining relationship
|
|
1815
|
+
const defining = rel.characteristicTypeId === RF2_MAGIC_RELN_DEFINING ||
|
|
1816
|
+
rel.characteristicTypeId === RF2_MAGIC_RELN_STATED ||
|
|
1817
|
+
rel.characteristicTypeId === RF2_MAGIC_RELN_INFERRED;
|
|
1818
|
+
|
|
1819
|
+
const relationshipIndex = this.relationships.addRelationship(
|
|
1820
|
+
rel.id, source.index, destination.index, type.index,
|
|
1821
|
+
0, 0, 0, effectiveTime, rel.active, defining, rel.relationshipGroup
|
|
1822
|
+
);
|
|
1823
|
+
|
|
1824
|
+
// Track parent/child relationships for is-a relationships
|
|
1825
|
+
if (type.index === this.isAIndex && defining) {
|
|
1826
|
+
const sourceTracker = this.getOrCreateConceptTracker(source.index);
|
|
1827
|
+
if (rel.active) {
|
|
1828
|
+
sourceTracker.addActiveParent(destination.index);
|
|
1829
|
+
} else {
|
|
1830
|
+
sourceTracker.addInactiveParent(destination.index);
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
// Track inbound/outbound relationships
|
|
1835
|
+
const sourceTracker = this.getOrCreateConceptTracker(source.index);
|
|
1836
|
+
const destTracker = this.getOrCreateConceptTracker(destination.index);
|
|
1837
|
+
|
|
1838
|
+
sourceTracker.addOutbound(relationshipIndex);
|
|
1839
|
+
destTracker.addInbound(relationshipIndex);
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
if (i % 1000 === 0) {
|
|
1843
|
+
buildProgressBar?.update(i);
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1765
1847
|
this.relationships.doneBuild();
|
|
1766
1848
|
|
|
1767
1849
|
if (this.progressReporter) {
|
|
1768
|
-
this.progressReporter.completeTask('
|
|
1850
|
+
this.progressReporter.completeTask('Building Relationships', relationshipRows.length, relationshipRows.length);
|
|
1769
1851
|
}
|
|
1770
1852
|
}
|
|
1771
1853
|
|
|
@@ -1800,9 +1882,9 @@ class SnomedImporter {
|
|
|
1800
1882
|
// Set parents if concept has any
|
|
1801
1883
|
if (tracker.activeParents.length > 0 || tracker.inactiveParents.length > 0) {
|
|
1802
1884
|
const activeParentsRef = tracker.activeParents.length > 0 ?
|
|
1803
|
-
|
|
1885
|
+
this.refs.addReferences(tracker.activeParents) : 0;
|
|
1804
1886
|
const inactiveParentsRef = tracker.inactiveParents.length > 0 ?
|
|
1805
|
-
|
|
1887
|
+
this.refs.addReferences(tracker.inactiveParents) : 0;
|
|
1806
1888
|
|
|
1807
1889
|
this.concepts.setParents(concept.index, activeParentsRef, inactiveParentsRef);
|
|
1808
1890
|
} else {
|
|
@@ -2104,14 +2186,14 @@ class SnomedImporter {
|
|
|
2104
2186
|
// NOTE: This calls addString() so it must happen AFTER strings.reopen()
|
|
2105
2187
|
for (const refSet of refSetsArray) {
|
|
2106
2188
|
this.refsetIndex.addReferenceSet(
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2189
|
+
this.addString(refSet.title), // This needs strings builder to be active
|
|
2190
|
+
refSet.filename,
|
|
2191
|
+
refSet.index,
|
|
2192
|
+
refSet.membersByRef,
|
|
2193
|
+
refSet.membersByName,
|
|
2194
|
+
refSet.fieldTypes,
|
|
2195
|
+
refSet.fieldNames,
|
|
2196
|
+
refSet.langs
|
|
2115
2197
|
);
|
|
2116
2198
|
}
|
|
2117
2199
|
}
|
|
@@ -2216,7 +2298,13 @@ class SnomedImporter {
|
|
|
2216
2298
|
if (!refSet || currentRefSetId !== refSetId) {
|
|
2217
2299
|
currentRefSetId = refSetId;
|
|
2218
2300
|
refSet = this.getOrCreateRefSet(refSetId, displayName, isLangRefset);
|
|
2219
|
-
|
|
2301
|
+
// Compute relative path — the file may live under the base directory
|
|
2302
|
+
// rather than the extension source directory.
|
|
2303
|
+
let relPath = path.relative(this.config.source, filePath);
|
|
2304
|
+
if (this.config.base && relPath.startsWith('..')) {
|
|
2305
|
+
relPath = path.relative(this.config.base, filePath);
|
|
2306
|
+
}
|
|
2307
|
+
refSet.filename = this.addString(relPath);
|
|
2220
2308
|
refSet.fieldTypes = this.getOrCreateFieldTypes(fieldTypes);
|
|
2221
2309
|
refSet.fieldNames = this.getOrCreateFieldNames(headers.slice(6), fieldTypes); // Additional fields beyond standard 6
|
|
2222
2310
|
}
|
|
@@ -2577,8 +2665,8 @@ class SnomedImporter {
|
|
|
2577
2665
|
};
|
|
2578
2666
|
|
|
2579
2667
|
const services = new SnomedExpressionServices(
|
|
2580
|
-
|
|
2581
|
-
|
|
2668
|
+
snomedStructures,
|
|
2669
|
+
this.isAIndex
|
|
2582
2670
|
);
|
|
2583
2671
|
|
|
2584
2672
|
// Set building flag to true so services will generate normal forms dynamically
|
package/tx/library.js
CHANGED
|
@@ -35,6 +35,7 @@ const { OCLCodeSystemProvider, OCLSourceCodeSystemFactory } = require('./ocl/cs-
|
|
|
35
35
|
const { OCLValueSetProvider } = require('./ocl/vs-ocl');
|
|
36
36
|
const { OCLConceptMapProvider } = require('./ocl/cm-ocl');
|
|
37
37
|
const {UriServicesFactory} = require("./cs/cs-uri");
|
|
38
|
+
const {debugLog} = require("./operation-context");
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
41
|
* This class holds all the loaded content ready for processing
|
|
@@ -185,6 +186,7 @@ class Library {
|
|
|
185
186
|
try {
|
|
186
187
|
await this.processSource(source, this.packageManager, "cs");
|
|
187
188
|
} catch (error) {
|
|
189
|
+
debugLog(error);
|
|
188
190
|
console.error(`Failed to load code systems from '${source}': ${error.message}`);
|
|
189
191
|
throw error;
|
|
190
192
|
}
|
|
@@ -196,6 +198,7 @@ class Library {
|
|
|
196
198
|
try {
|
|
197
199
|
await this.processSource(source, this.packageManager, "npm");
|
|
198
200
|
} catch (error) {
|
|
201
|
+
debugLog(error);
|
|
199
202
|
console.error(`Failed to load package '${source}': ${error.message}`);
|
|
200
203
|
throw error;
|
|
201
204
|
}
|