fhirsmith 0.7.6 → 0.8.2
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 +48 -0
- package/README.md +5 -1
- package/library/languages.js +10 -0
- package/package.json +1 -1
- package/packages/package-crawler.js +2 -2
- package/publisher/publisher.js +1 -1
- package/registry/registry.js +2 -2
- package/root-bare-template.html +1 -2
- package/security.md +3 -0
- package/server.js +100 -70
- package/stats.js +37 -6
- package/tx/cs/cs-api.js +8 -4
- package/tx/cs/cs-loinc.js +14 -2
- package/tx/cs/cs-omop.js +5 -3
- package/tx/cs/cs-rxnorm.js +18 -16
- package/tx/cs/cs-snomed.js +279 -6
- package/tx/data/cpt-fragment.db +0 -0
- package/tx/data/cs-de.json +186 -0
- package/tx/data/cs-extensions.json +92 -0
- package/tx/data/cs-simple.json +130 -0
- package/tx/data/cs-supplement.json +78 -0
- package/tx/data/lang.dat +49180 -0
- package/tx/data/languages.csv +191 -0
- package/tx/data/loinc-subset.txt +75 -0
- package/tx/data/omop-fragment.db +0 -0
- package/tx/data/readme.md +43 -0
- package/tx/data/regions.csv +273 -0
- package/tx/data/rxnorm-subset.txt +22 -0
- package/tx/data/snomed-subset.txt +47 -0
- package/tx/data/ucum-essence.xml +2059 -0
- package/tx/html/dash-metrics.liquid +147 -0
- package/tx/importers/import-rxnorm.module.js +4 -30
- package/tx/library/canonical-resource.js +8 -0
- package/tx/library/conceptmap.js +29 -1
- package/tx/library/designations.js +4 -8
- package/tx/library/extensions.js +4 -3
- package/tx/library/renderer.js +9 -9
- package/tx/ocl/cm-ocl.cjs +185 -65
- package/tx/ocl/cs-ocl.cjs +69 -50
- package/tx/ocl/jobs/background-queue.cjs +0 -8
- package/tx/ocl/mappers/concept-mapper.cjs +13 -3
- package/tx/ocl/shared/patches.cjs +1 -0
- package/tx/ocl/vs-ocl.cjs +137 -157
- package/tx/operation-context.js +3 -3
- package/tx/params.js +2 -2
- package/tx/provider.js +6 -3
- package/tx/sct/structures.js +6 -1
- package/tx/tx.fhir.org.yml +1 -1
- package/tx/vs/vs-database.js +107 -23
- package/tx/vs/vs-vsac.js +66 -19
- package/tx/workers/expand.js +10 -10
- package/tx/workers/related.js +2 -2
- package/tx/workers/search.js +2 -1
- package/tx/workers/translate.js +222 -33
- package/tx/workers/validate.js +13 -13
- package/tx/xversion/xv-parameters.js +54 -1
- package/xig/xig.js +171 -9
package/tx/vs/vs-database.js
CHANGED
|
@@ -33,12 +33,31 @@ class ValueSetDatabase {
|
|
|
33
33
|
db.all("PRAGMA table_info(valuesets)", [], (err, cols) => {
|
|
34
34
|
if (err) { reject(err); return; }
|
|
35
35
|
const hasCol = cols.some(c => c.name === 'date_first_seen');
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
const migrations = [];
|
|
37
|
+
if (!hasCol) {
|
|
38
|
+
migrations.push(new Promise((res, rej) => {
|
|
39
|
+
db.run(
|
|
40
|
+
"ALTER TABLE valuesets ADD COLUMN date_first_seen INTEGER DEFAULT 0",
|
|
41
|
+
[],
|
|
42
|
+
(err) => err ? rej(err) : res()
|
|
43
|
+
);
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
// Ensure vsac_runs table exists
|
|
47
|
+
migrations.push(new Promise((res, rej) => {
|
|
48
|
+
db.run(`
|
|
49
|
+
CREATE TABLE IF NOT EXISTS vsac_runs (
|
|
50
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
51
|
+
started_at INTEGER NOT NULL,
|
|
52
|
+
finished_at INTEGER,
|
|
53
|
+
status TEXT NOT NULL DEFAULT 'running',
|
|
54
|
+
error_message TEXT,
|
|
55
|
+
total_fetched INTEGER,
|
|
56
|
+
total_new INTEGER
|
|
57
|
+
)
|
|
58
|
+
`, [], (err) => err ? rej(err) : res());
|
|
59
|
+
}));
|
|
60
|
+
Promise.all(migrations).then(() => resolve()).catch(reject);
|
|
42
61
|
});
|
|
43
62
|
});
|
|
44
63
|
}
|
|
@@ -204,6 +223,19 @@ class ValueSetDatabase {
|
|
|
204
223
|
)
|
|
205
224
|
`);
|
|
206
225
|
|
|
226
|
+
// Run tracking table
|
|
227
|
+
db.run(`
|
|
228
|
+
CREATE TABLE vsac_runs (
|
|
229
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
230
|
+
started_at INTEGER NOT NULL,
|
|
231
|
+
finished_at INTEGER,
|
|
232
|
+
status TEXT NOT NULL DEFAULT 'running',
|
|
233
|
+
error_message TEXT,
|
|
234
|
+
total_fetched INTEGER,
|
|
235
|
+
total_new INTEGER
|
|
236
|
+
)
|
|
237
|
+
`);
|
|
238
|
+
|
|
207
239
|
// Create indexes for better search performance
|
|
208
240
|
db.run('CREATE INDEX idx_valuesets_url ON valuesets(url, version)');
|
|
209
241
|
db.run('CREATE INDEX idx_valuesets_version ON valuesets(version)');
|
|
@@ -231,6 +263,58 @@ class ValueSetDatabase {
|
|
|
231
263
|
});
|
|
232
264
|
}
|
|
233
265
|
|
|
266
|
+
/**
|
|
267
|
+
* Record the start of a VSAC sync run
|
|
268
|
+
* @returns {Promise<number>} The run ID
|
|
269
|
+
*/
|
|
270
|
+
async startRun() {
|
|
271
|
+
const db = await this._getWriteConnection();
|
|
272
|
+
return new Promise((resolve, reject) => {
|
|
273
|
+
db.run(
|
|
274
|
+
`INSERT INTO vsac_runs (started_at, status) VALUES (strftime('%s','now'), 'running')`,
|
|
275
|
+
[],
|
|
276
|
+
function(err) { err ? reject(err) : resolve(this.lastID); }
|
|
277
|
+
);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Record the successful completion of a VSAC sync run
|
|
283
|
+
* @param {number} id - The run ID from startRun()
|
|
284
|
+
* @param {number} totalFetched - Total value sets fetched
|
|
285
|
+
* @param {number} totalNew - Number of new value sets found
|
|
286
|
+
* @returns {Promise<void>}
|
|
287
|
+
*/
|
|
288
|
+
async finishRun(id, totalFetched, totalNew) {
|
|
289
|
+
const db = await this._getWriteConnection();
|
|
290
|
+
return new Promise((resolve, reject) => {
|
|
291
|
+
db.run(
|
|
292
|
+
`UPDATE vsac_runs SET finished_at = strftime('%s','now'), status = 'ok',
|
|
293
|
+
total_fetched = ?, total_new = ? WHERE id = ?`,
|
|
294
|
+
[totalFetched, totalNew, id],
|
|
295
|
+
err => err ? reject(err) : resolve()
|
|
296
|
+
);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Record a failed VSAC sync run
|
|
302
|
+
* @param {number} id - The run ID from startRun()
|
|
303
|
+
* @param {string} errorMessage - The error message
|
|
304
|
+
* @returns {Promise<void>}
|
|
305
|
+
*/
|
|
306
|
+
async failRun(id, errorMessage) {
|
|
307
|
+
const db = await this._getWriteConnection();
|
|
308
|
+
return new Promise((resolve, reject) => {
|
|
309
|
+
db.run(
|
|
310
|
+
`UPDATE vsac_runs SET finished_at = strftime('%s','now'), status = 'error',
|
|
311
|
+
error_message = ? WHERE id = ?`,
|
|
312
|
+
[errorMessage, id],
|
|
313
|
+
err => err ? reject(err) : resolve()
|
|
314
|
+
);
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
234
318
|
/**
|
|
235
319
|
* Insert or update a single ValueSet in the database
|
|
236
320
|
* @param {Object} valueSet - The ValueSet resource
|
|
@@ -270,23 +354,23 @@ class ValueSetDatabase {
|
|
|
270
354
|
|
|
271
355
|
db.run(`
|
|
272
356
|
INSERT INTO valuesets (
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
357
|
+
id, url, version, date, description, effectivePeriod_start, effectivePeriod_end,
|
|
358
|
+
expansion_identifier, name, publisher, status, title, content, last_seen, date_first_seen
|
|
359
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, strftime('%s', 'now'), strftime('%s', 'now'))
|
|
360
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
361
|
+
url=excluded.url,
|
|
362
|
+
version=excluded.version,
|
|
363
|
+
date=excluded.date,
|
|
364
|
+
description=excluded.description,
|
|
365
|
+
effectivePeriod_start=excluded.effectivePeriod_start,
|
|
366
|
+
effectivePeriod_end=excluded.effectivePeriod_end,
|
|
367
|
+
expansion_identifier=excluded.expansion_identifier,
|
|
368
|
+
name=excluded.name,
|
|
369
|
+
publisher=excluded.publisher,
|
|
370
|
+
status=excluded.status,
|
|
371
|
+
title=excluded.title,
|
|
372
|
+
content=excluded.content,
|
|
373
|
+
last_seen=strftime('%s', 'now')
|
|
290
374
|
`, [
|
|
291
375
|
valueSet.id,
|
|
292
376
|
valueSet.url,
|
package/tx/vs/vs-vsac.js
CHANGED
|
@@ -98,6 +98,7 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
98
98
|
try {
|
|
99
99
|
await this.refreshValueSets();
|
|
100
100
|
} catch (error) {
|
|
101
|
+
debugLog(error);
|
|
101
102
|
this.log.error(error, 'Error during scheduled refresh:');
|
|
102
103
|
}
|
|
103
104
|
}, intervalMs);
|
|
@@ -126,6 +127,7 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
126
127
|
this.queue = [];
|
|
127
128
|
|
|
128
129
|
this.isRefreshing = true;
|
|
130
|
+
const runId = await this.database.startRun();
|
|
129
131
|
|
|
130
132
|
try {
|
|
131
133
|
// phase 1: list all value sets
|
|
@@ -202,10 +204,15 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
202
204
|
|
|
203
205
|
// Reload map with fresh data
|
|
204
206
|
await this._reloadMap();
|
|
205
|
-
|
|
207
|
+
let msg = `VSAC refresh completed. Total: ${tracking.totalFetched} ValueSets, Deleted: ${tracking.deletedCount}`;
|
|
208
|
+
this.stats.taskDone('VSAC Sync', msg);
|
|
209
|
+
console.log(msg);
|
|
210
|
+
|
|
211
|
+
await this.database.finishRun(runId, tracking.totalFetched, tracking.totalNew);
|
|
206
212
|
} catch (error) {
|
|
207
213
|
debugLog(error, 'Error during VSAC refresh:');
|
|
208
|
-
this.stats.
|
|
214
|
+
this.stats.taskError('VSAC Sync', `Error (${error.message})`);
|
|
215
|
+
await this.database.failRun(runId, error.message);
|
|
209
216
|
throw error;
|
|
210
217
|
} finally {
|
|
211
218
|
this.isRefreshing = false;
|
|
@@ -265,7 +272,6 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
265
272
|
}
|
|
266
273
|
}
|
|
267
274
|
|
|
268
|
-
|
|
269
275
|
/**
|
|
270
276
|
* Fetch a FHIR Bundle from the server
|
|
271
277
|
* @param {string} url - Relative URL to fetch
|
|
@@ -511,7 +517,6 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
511
517
|
let logMsg = `VSAC (${tracking.count} of ${length}) ${q}: ${vcount} versions`;
|
|
512
518
|
console.log(logMsg);
|
|
513
519
|
this.stats.task('VSAC Sync', logMsg);
|
|
514
|
-
|
|
515
520
|
}
|
|
516
521
|
|
|
517
522
|
name() {
|
|
@@ -523,35 +528,77 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
523
528
|
}
|
|
524
529
|
|
|
525
530
|
async info() {
|
|
531
|
+
const escape = require('escape-html');
|
|
526
532
|
const db = await this.database._getReadConnection();
|
|
533
|
+
|
|
527
534
|
const rows = await new Promise((resolve, reject) => {
|
|
528
535
|
db.all(
|
|
529
|
-
`SELECT
|
|
536
|
+
`SELECT 'vs' AS kind,
|
|
537
|
+
url,
|
|
538
|
+
version,
|
|
539
|
+
date_first_seen AS ts,
|
|
540
|
+
NULL AS status,
|
|
541
|
+
NULL AS error_message,
|
|
542
|
+
NULL AS finished_at,
|
|
543
|
+
NULL AS total_fetched,
|
|
544
|
+
NULL AS total_new
|
|
530
545
|
FROM valuesets
|
|
531
546
|
WHERE date_first_seen > 0
|
|
532
|
-
|
|
533
|
-
|
|
547
|
+
UNION ALL
|
|
548
|
+
SELECT 'run' AS kind,
|
|
549
|
+
NULL,
|
|
550
|
+
NULL,
|
|
551
|
+
started_at AS ts,
|
|
552
|
+
status,
|
|
553
|
+
error_message,
|
|
554
|
+
finished_at,
|
|
555
|
+
total_fetched,
|
|
556
|
+
total_new
|
|
557
|
+
FROM vsac_runs
|
|
558
|
+
ORDER BY ts DESC
|
|
559
|
+
LIMIT 200`,
|
|
534
560
|
[],
|
|
535
561
|
(err, rows) => err ? reject(err) : resolve(rows)
|
|
536
562
|
);
|
|
537
563
|
});
|
|
538
564
|
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
|
|
565
|
+
const fmt = ts => ts
|
|
566
|
+
? new Date(ts * 1000).toISOString().replace('T', ' ').substring(0, 19) + ' UTC'
|
|
567
|
+
: '—';
|
|
568
|
+
|
|
569
|
+
let html = '<h3>VSAC Sync History</h3>';
|
|
542
570
|
html += '<table class="grid">';
|
|
543
|
-
html += '<thead><tr><th>
|
|
571
|
+
html += '<thead><tr><th>Time</th><th>Event</th><th>Detail</th></tr></thead>';
|
|
544
572
|
html += '<tbody>';
|
|
573
|
+
|
|
545
574
|
for (const row of rows) {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
575
|
+
if (row.kind === 'run') {
|
|
576
|
+
const duration = row.finished_at ? `${row.finished_at - row.ts}s` : 'in progress';
|
|
577
|
+
let detail, colour;
|
|
578
|
+
if (row.status === 'ok') {
|
|
579
|
+
detail = `${row.total_fetched} fetched, ${row.total_new} new, ${duration}`;
|
|
580
|
+
colour = 'green';
|
|
581
|
+
} else if (row.status === 'error') {
|
|
582
|
+
detail = `Failed: ${escape(row.error_message || '')} (${duration})`;
|
|
583
|
+
colour = 'red';
|
|
584
|
+
} else {
|
|
585
|
+
detail = `Running... (started ${fmt(row.ts)})`;
|
|
586
|
+
colour = 'orange';
|
|
587
|
+
}
|
|
588
|
+
html += `<tr style="background:#f0f0f0">`;
|
|
589
|
+
html += `<td>${escape(fmt(row.ts))}</td>`;
|
|
590
|
+
html += `<td><strong style="color:${colour}">Sync run</strong></td>`;
|
|
591
|
+
html += `<td>${detail}</td>`;
|
|
592
|
+
html += `</tr>`;
|
|
593
|
+
} else {
|
|
594
|
+
html += `<tr>`;
|
|
595
|
+
html += `<td>${escape(fmt(row.ts))}</td>`;
|
|
596
|
+
html += `<td>New value set</td>`;
|
|
597
|
+
html += `<td>${escape(row.url || '')}#${escape(row.version || '')}</td>`;
|
|
598
|
+
html += `</tr>`;
|
|
599
|
+
}
|
|
554
600
|
}
|
|
601
|
+
|
|
555
602
|
html += '</tbody></table>';
|
|
556
603
|
return html;
|
|
557
604
|
}
|
package/tx/workers/expand.js
CHANGED
|
@@ -604,7 +604,7 @@ class ValueSetExpander {
|
|
|
604
604
|
|
|
605
605
|
async checkSource(cset, exp, filter, srcURL, ts, vsInfo) {
|
|
606
606
|
this.worker.deadCheck('checkSource');
|
|
607
|
-
Extensions.checkNoModifiers(cset, 'ValueSetExpander.checkSource', 'set');
|
|
607
|
+
Extensions.checkNoModifiers(cset, 'ValueSetExpander.checkSource', 'set', srcURL);
|
|
608
608
|
let imp = false;
|
|
609
609
|
for (const u of cset.valueSet || []) {
|
|
610
610
|
this.worker.deadCheck('checkSource');
|
|
@@ -682,7 +682,7 @@ class ValueSetExpander {
|
|
|
682
682
|
this.worker.deadCheck('processCodes#1');
|
|
683
683
|
const valueSets = [];
|
|
684
684
|
|
|
685
|
-
Extensions.checkNoModifiers(cset, 'ValueSetExpander.processCodes', 'set');
|
|
685
|
+
Extensions.checkNoModifiers(cset, 'ValueSetExpander.processCodes', 'set', vsSrc.vurl);
|
|
686
686
|
|
|
687
687
|
if (cset.valueSet || cset.concept || (cset.filter || []).length > 1) {
|
|
688
688
|
this.canBeHierarchy = false;
|
|
@@ -792,7 +792,7 @@ class ValueSetExpander {
|
|
|
792
792
|
for (const cc of cset.concept) {
|
|
793
793
|
this.worker.deadCheck('processCodes#3');
|
|
794
794
|
cds.clear();
|
|
795
|
-
Extensions.checkNoModifiers(cc, 'ValueSetExpander.processCodes', 'set concept reference');
|
|
795
|
+
Extensions.checkNoModifiers(cc, 'ValueSetExpander.processCodes', 'set concept reference', vsSrc.vurl);
|
|
796
796
|
const cctxt = await cs.locate(cc.code, this.allAltCodes);
|
|
797
797
|
if (cctxt && cctxt.context && (!this.params.activeOnly || !await cs.isInactive(cctxt.context)) && await this.passesFilters(cs, cctxt.context, prep, filters, 0)) {
|
|
798
798
|
await this.listDisplaysFromProvider(cds, cs, cctxt.context);
|
|
@@ -834,7 +834,7 @@ class ValueSetExpander {
|
|
|
834
834
|
if (!fc.value) {
|
|
835
835
|
throw new Issue('error', 'invalid', path + ".filter[" + i + "]", 'UNABLE_TO_HANDLE_SYSTEM_FILTER_WITH_NO_VALUE', this.worker.i18n.translate('UNABLE_TO_HANDLE_SYSTEM_FILTER_WITH_NO_VALUE', this.params.httpLanguages, [cs.system(), fc.property, fc.op]), 'vs-invalid', 400);
|
|
836
836
|
}
|
|
837
|
-
Extensions.checkNoModifiers(fc, 'ValueSetExpander.processCodes', 'filter');
|
|
837
|
+
Extensions.checkNoModifiers(fc, 'ValueSetExpander.processCodes', 'filter', vsSrc.vurl);
|
|
838
838
|
await cs.filter(prep, fc.property, fc.op, fc.value);
|
|
839
839
|
}
|
|
840
840
|
|
|
@@ -891,7 +891,7 @@ class ValueSetExpander {
|
|
|
891
891
|
this.worker.deadCheck('processCodes#1');
|
|
892
892
|
const valueSets = [];
|
|
893
893
|
|
|
894
|
-
Extensions.checkNoModifiers(cset, 'ValueSetExpander.processCodes', 'set');
|
|
894
|
+
Extensions.checkNoModifiers(cset, 'ValueSetExpander.processCodes', 'set', vsSrc.vurl);
|
|
895
895
|
|
|
896
896
|
if (cset.valueSet || cset.concept || (cset.filter || []).length > 1) {
|
|
897
897
|
this.canBeHierarchy = false;
|
|
@@ -978,7 +978,7 @@ class ValueSetExpander {
|
|
|
978
978
|
for (const cc of cset.concept) {
|
|
979
979
|
this.worker.deadCheck('processCodes#3');
|
|
980
980
|
cds.clear();
|
|
981
|
-
Extensions.checkNoModifiers(cc, 'ValueSetExpander.processCodes', 'set concept reference');
|
|
981
|
+
Extensions.checkNoModifiers(cc, 'ValueSetExpander.processCodes', 'set concept reference', vsSrc.vurl);
|
|
982
982
|
const cctxt = await cs.locate(cc.code, this.allAltCodes);
|
|
983
983
|
if (cctxt && cctxt.context && (!this.params.activeOnly || !await cs.isInactive(cctxt)) && await this.passesFilters(cs, cctxt, prep, filters, 0)) {
|
|
984
984
|
if (filter.passesDesignations(cds) || filter.passes(cc.code)) {
|
|
@@ -1007,7 +1007,7 @@ class ValueSetExpander {
|
|
|
1007
1007
|
|
|
1008
1008
|
for (let fc of cset.filter) {
|
|
1009
1009
|
this.worker.deadCheck('processCodes#4a');
|
|
1010
|
-
Extensions.checkNoModifiers(fc, 'ValueSetExpander.processCodes', 'filter');
|
|
1010
|
+
Extensions.checkNoModifiers(fc, 'ValueSetExpander.processCodes', 'filter', vsSrc.vurl);
|
|
1011
1011
|
await cs.filter(prep, fc.property, fc.op, fc.value);
|
|
1012
1012
|
}
|
|
1013
1013
|
|
|
@@ -1157,8 +1157,8 @@ class ValueSetExpander {
|
|
|
1157
1157
|
this.totalStatus = 'uninitialised';
|
|
1158
1158
|
this.total = 0;
|
|
1159
1159
|
|
|
1160
|
-
Extensions.checkNoImplicitRules(source,'ValueSetExpander.Expand', 'ValueSet');
|
|
1161
|
-
Extensions.checkNoModifiers(source,'ValueSetExpander.Expand', 'ValueSet');
|
|
1160
|
+
Extensions.checkNoImplicitRules(source,'ValueSetExpander.Expand', 'ValueSet', source.vurl);
|
|
1161
|
+
Extensions.checkNoModifiers(source,'ValueSetExpander.Expand', 'ValueSet', source.vurl);
|
|
1162
1162
|
this.worker.seeValueSet(source, this.params);
|
|
1163
1163
|
this.valueSet = source;
|
|
1164
1164
|
|
|
@@ -1272,7 +1272,7 @@ class ValueSetExpander {
|
|
|
1272
1272
|
|
|
1273
1273
|
let vsInfo = this.scanValueSet(source.jsonObj.compose);
|
|
1274
1274
|
try {
|
|
1275
|
-
if (source.jsonObj.compose && Extensions.checkNoModifiers(source.jsonObj.compose, 'ValueSetExpander.Expand', 'compose')
|
|
1275
|
+
if (source.jsonObj.compose && Extensions.checkNoModifiers(source.jsonObj.compose, 'ValueSetExpander.Expand', 'compose', source.vurl)
|
|
1276
1276
|
&& this.worker.checkNoLockedDate(source.url, source.jsonObj.compose)) {
|
|
1277
1277
|
await this.handleCompose(source, filter, exp, notClosed, vsInfo);
|
|
1278
1278
|
}
|
package/tx/workers/related.js
CHANGED
|
@@ -205,12 +205,12 @@ class RelatedWorker extends TerminologyWorker {
|
|
|
205
205
|
if (!thisC) {
|
|
206
206
|
return this.makeOutcome("indeterminate", `The ValueSet ${thisVS.vurl} has no compose`);
|
|
207
207
|
}
|
|
208
|
-
Extensions.checkNoModifiers(thisC, 'RelatedWorker.doRelated', 'compose')
|
|
208
|
+
Extensions.checkNoModifiers(thisC, 'RelatedWorker.doRelated', 'compose', thisVS.vurl)
|
|
209
209
|
this.checkNoLockedDate(thisVS.vurl, thisC);
|
|
210
210
|
if (!otherC) {
|
|
211
211
|
return this.makeOutcome("indeterminate", `The ValueSet ${otherVS.vurl} has no compose`);
|
|
212
212
|
}
|
|
213
|
-
Extensions.checkNoModifiers(otherC, 'RelatedWorker.doRelated', 'compose')
|
|
213
|
+
Extensions.checkNoModifiers(otherC, 'RelatedWorker.doRelated', 'compose', otherVS.vurl)
|
|
214
214
|
this.checkNoLockedDate(otherVS.vurl, otherC);
|
|
215
215
|
|
|
216
216
|
let systems = new Map(); // tracks whether they are version dependent or not
|
package/tx/workers/search.js
CHANGED
|
@@ -35,7 +35,8 @@ class SearchWorker extends TerminologyWorker {
|
|
|
35
35
|
'_offset', '_count', '_elements', '_sort', '_summary', '_total', '_format',
|
|
36
36
|
'url', 'version', 'content-mode', 'date', 'description',
|
|
37
37
|
'supplements', 'identifier', 'jurisdiction', 'name',
|
|
38
|
-
'publisher', 'status', 'system', 'title', 'text'
|
|
38
|
+
'publisher', 'status', 'system', 'title', 'text',
|
|
39
|
+
'source-system', 'target-system'
|
|
39
40
|
];
|
|
40
41
|
|
|
41
42
|
// Summary elements for _summary=true (marked elements per resource type)
|