fhirsmith 0.4.2 → 0.5.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/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/library/cron-utilities.js +136 -0
- package/library/html-server.js +13 -29
- package/library/html.js +3 -8
- package/library/languages.js +160 -37
- package/library/package-manager.js +48 -1
- package/library/utilities.js +100 -19
- package/package.json +2 -2
- package/packages/package-crawler.js +6 -1
- package/packages/packages.js +38 -54
- package/publisher/publisher.js +19 -27
- package/registry/api.js +11 -10
- package/registry/crawler.js +31 -29
- package/registry/model.js +5 -26
- package/registry/registry.js +32 -41
- package/server.js +53 -5
- package/shl/shl.js +0 -18
- package/static/assets/js/statuspage.js +1 -9
- package/stats.js +39 -1
- package/token/token.js +14 -9
- package/translations/Messages.properties +2 -1
- package/tx/README.md +17 -6
- package/tx/cs/cs-api.js +19 -1
- package/tx/cs/cs-base.js +77 -0
- package/tx/cs/cs-country.js +46 -0
- package/tx/cs/cs-cpt.js +9 -5
- package/tx/cs/cs-cs.js +27 -13
- package/tx/cs/cs-lang.js +60 -22
- package/tx/cs/cs-loinc.js +69 -98
- package/tx/cs/cs-mimetypes.js +4 -0
- package/tx/cs/cs-ndc.js +6 -0
- package/tx/cs/cs-omop.js +16 -15
- package/tx/cs/cs-rxnorm.js +23 -1
- package/tx/cs/cs-snomed.js +283 -40
- package/tx/cs/cs-ucum.js +90 -70
- package/tx/importers/import-sct.module.js +371 -35
- package/tx/importers/readme.md +117 -7
- package/tx/library/bundle.js +5 -0
- package/tx/library/capabilitystatement.js +3 -142
- package/tx/library/codesystem.js +19 -173
- package/tx/library/conceptmap.js +4 -218
- package/tx/library/designations.js +14 -1
- package/tx/library/extensions.js +7 -0
- package/tx/library/namingsystem.js +3 -89
- package/tx/library/operation-outcome.js +8 -3
- package/tx/library/parameters.js +3 -2
- package/tx/library/renderer.js +10 -6
- package/tx/library/terminologycapabilities.js +3 -243
- package/tx/library/valueset.js +3 -235
- package/tx/library.js +100 -13
- package/tx/operation-context.js +23 -4
- package/tx/params.js +35 -38
- package/tx/provider.js +6 -5
- package/tx/sct/expressions.js +12 -3
- package/tx/tx-html.js +80 -89
- package/tx/tx.fhir.org.yml +6 -5
- package/tx/tx.js +163 -13
- package/tx/vs/vs-database.js +56 -39
- package/tx/vs/vs-package.js +21 -2
- package/tx/vs/vs-vsac.js +175 -39
- package/tx/workers/batch-validate.js +2 -0
- package/tx/workers/batch.js +2 -0
- package/tx/workers/expand.js +132 -112
- package/tx/workers/lookup.js +33 -14
- package/tx/workers/metadata.js +2 -2
- package/tx/workers/read.js +3 -2
- package/tx/workers/related.js +574 -0
- package/tx/workers/search.js +46 -9
- package/tx/workers/subsumes.js +13 -3
- package/tx/workers/translate.js +7 -3
- package/tx/workers/validate.js +258 -285
- package/tx/workers/worker.js +43 -39
- package/tx/xml/bundle-xml.js +237 -0
- package/tx/xml/xml-base.js +215 -64
- package/tx/xversion/xv-bundle.js +71 -0
- package/tx/xversion/xv-capabiliityStatement.js +137 -0
- package/tx/xversion/xv-codesystem.js +169 -0
- package/tx/xversion/xv-conceptmap.js +224 -0
- package/tx/xversion/xv-namingsystem.js +88 -0
- package/tx/xversion/xv-operationoutcome.js +27 -0
- package/tx/xversion/xv-parameters.js +87 -0
- package/tx/xversion/xv-resource.js +45 -0
- package/tx/xversion/xv-terminologyCapabilities.js +214 -0
- package/tx/xversion/xv-valueset.js +234 -0
- package/utilities/dev-proxy-server.js +126 -0
- package/utilities/explode-results.js +58 -0
- package/utilities/split-by-system.js +198 -0
- package/utilities/vsac-cs-fetcher.js +0 -0
- package/{windows-install.js → utilities/windows-install.js} +2 -0
- package/vcl/vcl.js +0 -18
- package/xig/xig.js +108 -99
package/tx/cs/cs-lang.js
CHANGED
|
@@ -89,7 +89,7 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
89
89
|
// ========== Code Information Methods ==========
|
|
90
90
|
|
|
91
91
|
async code(code) {
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
const ctxt = await this.#ensureContext(code);
|
|
94
94
|
if (ctxt instanceof Language) {
|
|
95
95
|
return ctxt.code;
|
|
@@ -98,13 +98,26 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
async display(code) {
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
const ctxt = await this.#ensureContext(code);
|
|
103
103
|
if (!ctxt) {
|
|
104
104
|
return null;
|
|
105
105
|
}
|
|
106
|
-
if (this.opContext.langs.isEnglishOrNothing()) {
|
|
107
|
-
|
|
106
|
+
if (!this.opContext.langs.isEnglishOrNothing()) {
|
|
107
|
+
// Try translated display for the primary requested language
|
|
108
|
+
const primaryLang = this.opContext.langs.getPrimary();
|
|
109
|
+
if (primaryLang && primaryLang.language) {
|
|
110
|
+
const langTranslation = this.languageDefinitions.getTranslatedDisplayForLang(ctxt.language, primaryLang.language);
|
|
111
|
+
if (langTranslation && langTranslation !== ctxt.language) {
|
|
112
|
+
if (ctxt.isLangRegion()) {
|
|
113
|
+
const regionTranslation = this.languageDefinitions.getTranslatedDisplayForRegion(ctxt.region, primaryLang.language);
|
|
114
|
+
if (regionTranslation && regionTranslation !== ctxt.region) {
|
|
115
|
+
return `${langTranslation} (${regionTranslation})`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return langTranslation;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
108
121
|
}
|
|
109
122
|
let disp = this._displayFromSupplements(ctxt.code);
|
|
110
123
|
if (disp) {
|
|
@@ -114,31 +127,26 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
114
127
|
}
|
|
115
128
|
|
|
116
129
|
async definition(code) {
|
|
117
|
-
|
|
118
130
|
await this.#ensureContext(code);
|
|
119
131
|
return null; // No definitions for language codes
|
|
120
132
|
}
|
|
121
133
|
|
|
122
134
|
async isAbstract(code) {
|
|
123
|
-
|
|
124
135
|
await this.#ensureContext(code);
|
|
125
136
|
return false; // Language codes are not abstract
|
|
126
137
|
}
|
|
127
138
|
|
|
128
139
|
async isInactive(code) {
|
|
129
|
-
|
|
130
140
|
await this.#ensureContext(code);
|
|
131
141
|
return false; // We don't track inactive language codes
|
|
132
142
|
}
|
|
133
143
|
|
|
134
144
|
async isDeprecated(code) {
|
|
135
|
-
|
|
136
145
|
await this.#ensureContext(code);
|
|
137
146
|
return false; // We don't track deprecated language codes
|
|
138
147
|
}
|
|
139
148
|
|
|
140
149
|
async designations(code, displays) {
|
|
141
|
-
|
|
142
150
|
const ctxt = await this.#ensureContext(code);
|
|
143
151
|
const designations = [];
|
|
144
152
|
if (ctxt != null) {
|
|
@@ -149,8 +157,12 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
149
157
|
const regionDisplay = this.languageDefinitions.getDisplayForRegion(ctxt.region);
|
|
150
158
|
const regionVariant = `${langDisplay} (${regionDisplay})`;
|
|
151
159
|
const regionVariant2 = `${langDisplay} (Region=${regionDisplay})`;
|
|
152
|
-
|
|
160
|
+
const regionVariant3 = `${langDisplay}-${regionDisplay}`;
|
|
161
|
+
const regionVariant4 = `${langDisplay}-${regionDisplay.toUpperCase()}`;
|
|
153
162
|
displays.addDesignation(false, 'active', 'en', CodeSystem.makeUseForDisplay(), regionVariant2);
|
|
163
|
+
displays.addDesignation(false, 'active', 'en', CodeSystem.makeUseForDisplay(), regionVariant3);
|
|
164
|
+
displays.addDesignation(false, 'active', 'en', CodeSystem.makeUseForDisplay(), regionVariant4);
|
|
165
|
+
displays.addDesignation(false, 'active', 'en', CodeSystem.makeUseForDisplay(), regionVariant);
|
|
154
166
|
}
|
|
155
167
|
// add alternative displays if available
|
|
156
168
|
const displayCount = this.languageDefinitions.displayCount(ctxt);
|
|
@@ -167,6 +179,32 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
167
179
|
}
|
|
168
180
|
}
|
|
169
181
|
}
|
|
182
|
+
// add translated designations from CSV data
|
|
183
|
+
const translationLangs = ['fr', 'de', 'es', 'ar', 'zh', 'ru', 'ja', 'sw'];
|
|
184
|
+
// languages that don't have upper/lower case distinction
|
|
185
|
+
const caselessLangs = new Set(['ar', 'zh', 'ja']);
|
|
186
|
+
|
|
187
|
+
for (const tLang of translationLangs) {
|
|
188
|
+
const langTranslation = this.languageDefinitions.getTranslatedDisplayForLang(ctxt.language, tLang);
|
|
189
|
+
if (langTranslation && langTranslation !== ctxt.language) {
|
|
190
|
+
if (ctxt.isLangRegion()) {
|
|
191
|
+
const regionTranslation = this.languageDefinitions.getTranslatedDisplayForRegion(ctxt.region, tLang);
|
|
192
|
+
if (regionTranslation && regionTranslation !== ctxt.region) {
|
|
193
|
+
const translatedDisplay = `${langTranslation} (${regionTranslation})`;
|
|
194
|
+
displays.addDesignation(false, 'active', tLang, CodeSystem.makeUseForDisplay(), translatedDisplay);
|
|
195
|
+
displays.addDesignation(false, 'active', tLang, CodeSystem.makeUseForDisplay(), `${langTranslation} (Region=${regionTranslation})`);
|
|
196
|
+
displays.addDesignation(false, 'active', tLang, CodeSystem.makeUseForDisplay(), `${langTranslation}-${regionTranslation}`);
|
|
197
|
+
if (!caselessLangs.has(tLang)) {
|
|
198
|
+
displays.addDesignation(false, 'active', tLang, CodeSystem.makeUseForDisplay(), `${langTranslation}-${regionTranslation.toUpperCase()}`);
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
displays.addDesignation(false, 'active', tLang, CodeSystem.makeUseForDisplay(), langTranslation);
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
displays.addDesignation(false, 'active', tLang, CodeSystem.makeUseForDisplay(), langTranslation);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
170
208
|
this._listSupplementDesignations(ctxt.code, displays);
|
|
171
209
|
}
|
|
172
210
|
return designations;
|
|
@@ -194,7 +232,7 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
194
232
|
// ========== Lookup Methods ==========
|
|
195
233
|
|
|
196
234
|
async locate(code) {
|
|
197
|
-
|
|
235
|
+
|
|
198
236
|
assert(!code || typeof code === 'string', 'code must be string');
|
|
199
237
|
if (!code) return { context: null, message: 'Empty code' };
|
|
200
238
|
|
|
@@ -209,7 +247,7 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
209
247
|
// ========== Filter Methods ==========
|
|
210
248
|
|
|
211
249
|
async doesFilter(prop, op, value) {
|
|
212
|
-
|
|
250
|
+
|
|
213
251
|
assert(prop != null && typeof prop === 'string', 'prop must be a non-null string');
|
|
214
252
|
assert(op != null && typeof op === 'string', 'op must be a non-null string');
|
|
215
253
|
assert(value != null && typeof value === 'string', 'value must be a non-null string');
|
|
@@ -222,7 +260,7 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
222
260
|
}
|
|
223
261
|
|
|
224
262
|
async searchFilter(filterContext, filter, sort) {
|
|
225
|
-
|
|
263
|
+
|
|
226
264
|
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
227
265
|
assert(filter && typeof filter === 'string', 'filter must be a non-null string');
|
|
228
266
|
assert(typeof sort === 'boolean', 'sort must be a boolean');
|
|
@@ -232,7 +270,7 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
232
270
|
|
|
233
271
|
|
|
234
272
|
async filter(filterContext, prop, op, value) {
|
|
235
|
-
|
|
273
|
+
|
|
236
274
|
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
237
275
|
assert(prop != null && typeof prop === 'string', 'prop must be a non-null string');
|
|
238
276
|
assert(op != null && typeof op === 'string', 'op must be a non-null string');
|
|
@@ -258,13 +296,13 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
258
296
|
}
|
|
259
297
|
|
|
260
298
|
async executeFilters(filterContext) {
|
|
261
|
-
|
|
299
|
+
|
|
262
300
|
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
263
301
|
return filterContext.filters;
|
|
264
302
|
}
|
|
265
303
|
|
|
266
304
|
async filterSize(filterContext, set) {
|
|
267
|
-
|
|
305
|
+
|
|
268
306
|
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
269
307
|
assert(set && set instanceof IETFLanguageCodeFilter, 'set must be a IETFLanguageCodeFilter');
|
|
270
308
|
|
|
@@ -272,27 +310,27 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
272
310
|
}
|
|
273
311
|
|
|
274
312
|
async filtersNotClosed(filterContext) {
|
|
275
|
-
|
|
313
|
+
|
|
276
314
|
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
277
315
|
return true; // Grammar-based system is not closed
|
|
278
316
|
}
|
|
279
317
|
|
|
280
318
|
async filterMore(filterContext, set) {
|
|
281
|
-
|
|
319
|
+
|
|
282
320
|
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
283
321
|
assert(set && set instanceof IETFLanguageCodeFilter, 'set must be a IETFLanguageCodeFilter');
|
|
284
322
|
throw new Error('Language valuesets cannot be expanded as they are based on a grammar');
|
|
285
323
|
}
|
|
286
324
|
|
|
287
325
|
async filterConcept(filterContext, set) {
|
|
288
|
-
|
|
326
|
+
|
|
289
327
|
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
290
328
|
assert(set && set instanceof IETFLanguageCodeFilter, 'set must be a IETFLanguageCodeFilter');
|
|
291
329
|
throw new Error('Language valuesets cannot be expanded as they are based on a grammar');
|
|
292
330
|
}
|
|
293
331
|
|
|
294
332
|
async filterLocate(filterContext, set, code) {
|
|
295
|
-
|
|
333
|
+
|
|
296
334
|
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
297
335
|
assert(set && set instanceof IETFLanguageCodeFilter, 'set must be a IETFLanguageCodeFilter');
|
|
298
336
|
assert(typeof code === 'string', 'code must be non-null string');
|
|
@@ -341,7 +379,7 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
341
379
|
}
|
|
342
380
|
|
|
343
381
|
async filterCheck(filterContext, set, concept) {
|
|
344
|
-
|
|
382
|
+
|
|
345
383
|
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
346
384
|
assert(set && set instanceof IETFLanguageCodeFilter, 'set must be a IETFLanguageCodeFilter');
|
|
347
385
|
const ctxt = await this.#ensureContext(concept);
|
|
@@ -386,7 +424,7 @@ class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
|
386
424
|
// ========== Additional Methods ==========
|
|
387
425
|
|
|
388
426
|
async sameConcept(a, b) {
|
|
389
|
-
|
|
427
|
+
|
|
390
428
|
const codeA = await this.code(a);
|
|
391
429
|
const codeB = await this.code(b);
|
|
392
430
|
return codeA === codeB;
|
package/tx/cs/cs-loinc.js
CHANGED
|
@@ -2,8 +2,9 @@ const sqlite3 = require('sqlite3').verbose();
|
|
|
2
2
|
const assert = require('assert');
|
|
3
3
|
const { CodeSystem } = require('../library/codesystem');
|
|
4
4
|
const { Language, Languages} = require('../../library/languages');
|
|
5
|
-
const {
|
|
5
|
+
const { CodeSystemFactoryProvider} = require('./cs-api');
|
|
6
6
|
const { validateOptionalParameter, validateArrayParameter} = require("../../library/utilities");
|
|
7
|
+
const {BaseCSServices} = require("./cs-base");
|
|
7
8
|
|
|
8
9
|
// Context kinds matching Pascal enum
|
|
9
10
|
const LoincProviderContextKind = {
|
|
@@ -13,6 +14,17 @@ const LoincProviderContextKind = {
|
|
|
13
14
|
ANSWER: 3 // lpckAnswer
|
|
14
15
|
};
|
|
15
16
|
|
|
17
|
+
const classTypes = {
|
|
18
|
+
'1': 'Laboratory class',
|
|
19
|
+
'2': 'Clinical class',
|
|
20
|
+
'3': 'Claims attachments',
|
|
21
|
+
'4': 'Surveys',
|
|
22
|
+
'Laboratory class' : '1',
|
|
23
|
+
'Clinical class' : '2',
|
|
24
|
+
'Claims attachments' : '3',
|
|
25
|
+
'Surveys' : '4'
|
|
26
|
+
};
|
|
27
|
+
|
|
16
28
|
class DescriptionCacheEntry {
|
|
17
29
|
constructor(display, lang, value, dtype) {
|
|
18
30
|
this.display = display;
|
|
@@ -96,7 +108,7 @@ class LoincPrep {
|
|
|
96
108
|
}
|
|
97
109
|
}
|
|
98
110
|
|
|
99
|
-
class LoincServices extends
|
|
111
|
+
class LoincServices extends BaseCSServices {
|
|
100
112
|
constructor(opContext, supplements, db, sharedData) {
|
|
101
113
|
super(opContext, supplements);
|
|
102
114
|
this.db = db;
|
|
@@ -293,10 +305,10 @@ class LoincServices extends CodeSystemProvider {
|
|
|
293
305
|
|
|
294
306
|
// Run all property queries in parallel — they're independent reads on the same key
|
|
295
307
|
await Promise.all([
|
|
296
|
-
this.#addRelationshipProperties(ctxt, params),
|
|
297
|
-
this.#addConceptProperties(ctxt, params),
|
|
298
|
-
this.#addStatusProperty(ctxt, params),
|
|
299
|
-
this.#addRelatedNames(ctxt, params)
|
|
308
|
+
this.#addRelationshipProperties(ctxt, props, params),
|
|
309
|
+
this.#addConceptProperties(ctxt, props,params),
|
|
310
|
+
this.#addStatusProperty(ctxt, props,params),
|
|
311
|
+
this.#addRelatedNames(ctxt, props,params)
|
|
300
312
|
]);
|
|
301
313
|
}
|
|
302
314
|
|
|
@@ -311,7 +323,7 @@ class LoincServices extends CodeSystemProvider {
|
|
|
311
323
|
}
|
|
312
324
|
}
|
|
313
325
|
|
|
314
|
-
async #addRelationshipProperties(ctxt, params) {
|
|
326
|
+
async #addRelationshipProperties(ctxt, props, params) {
|
|
315
327
|
return new Promise((resolve, reject) => {
|
|
316
328
|
const sql = `
|
|
317
329
|
SELECT RelationshipTypes.Description as Relationship, Codes.Code, Codes.Description as Value
|
|
@@ -326,7 +338,9 @@ class LoincServices extends CodeSystemProvider {
|
|
|
326
338
|
reject(err);
|
|
327
339
|
} else {
|
|
328
340
|
for (const row of rows) {
|
|
329
|
-
this
|
|
341
|
+
if (this._hasProp(props, row.Relationship, true)) {
|
|
342
|
+
this._addCodeProperty(params, 'property', row.Relationship, row.Code);
|
|
343
|
+
}
|
|
330
344
|
}
|
|
331
345
|
resolve();
|
|
332
346
|
}
|
|
@@ -334,7 +348,7 @@ class LoincServices extends CodeSystemProvider {
|
|
|
334
348
|
});
|
|
335
349
|
}
|
|
336
350
|
|
|
337
|
-
async #addConceptProperties(ctxt, params) {
|
|
351
|
+
async #addConceptProperties(ctxt, props, params) {
|
|
338
352
|
return new Promise((resolve, reject) => {
|
|
339
353
|
const sql = `
|
|
340
354
|
SELECT PropertyTypes.Description, PropertyValues.Value
|
|
@@ -349,7 +363,14 @@ class LoincServices extends CodeSystemProvider {
|
|
|
349
363
|
reject(err);
|
|
350
364
|
} else {
|
|
351
365
|
for (const row of rows) {
|
|
352
|
-
this
|
|
366
|
+
if (this._hasProp(props, row.Description, true)) {
|
|
367
|
+
if (row.Description == 'CLASSTYPE') {
|
|
368
|
+
this._addStringProperty(params, 'property', row.Description, classTypes[row.Value])
|
|
369
|
+
.part.push({name: 'description', valueString: row.Value});
|
|
370
|
+
} else {
|
|
371
|
+
this._addStringProperty(params, 'property', row.Description, row.Value);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
353
374
|
}
|
|
354
375
|
resolve();
|
|
355
376
|
}
|
|
@@ -357,7 +378,7 @@ class LoincServices extends CodeSystemProvider {
|
|
|
357
378
|
});
|
|
358
379
|
}
|
|
359
380
|
|
|
360
|
-
async #addStatusProperty(ctxt, params) {
|
|
381
|
+
async #addStatusProperty(ctxt, props, params) {
|
|
361
382
|
return new Promise((resolve, reject) => {
|
|
362
383
|
const sql = 'SELECT StatusKey FROM Codes WHERE CodeKey = ? AND StatusKey != 0';
|
|
363
384
|
|
|
@@ -367,7 +388,9 @@ class LoincServices extends CodeSystemProvider {
|
|
|
367
388
|
} else if (row) {
|
|
368
389
|
const statusDesc = this.statusCodes.get(row.StatusKey.toString());
|
|
369
390
|
if (row.StatusKey && statusDesc) {
|
|
370
|
-
this
|
|
391
|
+
if (this._hasProp(props, 'STATUS', true)) {
|
|
392
|
+
this._addStringProperty(params, 'property', 'STATUS', statusDesc);
|
|
393
|
+
}
|
|
371
394
|
}
|
|
372
395
|
resolve();
|
|
373
396
|
} else {
|
|
@@ -377,14 +400,20 @@ class LoincServices extends CodeSystemProvider {
|
|
|
377
400
|
});
|
|
378
401
|
}
|
|
379
402
|
|
|
380
|
-
async #addRelatedNames(ctxt, params) {
|
|
403
|
+
async #addRelatedNames(ctxt, props, params) {
|
|
381
404
|
const loaded = await this.#loadRelatedNames(ctxt);
|
|
382
405
|
for (let d of loaded) {
|
|
383
|
-
this
|
|
406
|
+
if (this._hasProp(props, 'RELATEDNAMES2', true)) {
|
|
407
|
+
this._addProperty(params, 'property', 'RELATEDNAMES2', d.value, d.lang);
|
|
408
|
+
}
|
|
384
409
|
}
|
|
385
410
|
}
|
|
386
411
|
|
|
387
|
-
async #addAllDesignations(ctxt, params) {
|
|
412
|
+
async #addAllDesignations(ctxt, props, params) {
|
|
413
|
+
if (!this._hasProp(props, 'designation', true)) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
|
|
388
417
|
return new Promise((resolve, reject) => {
|
|
389
418
|
const sql = `
|
|
390
419
|
SELECT Languages.Code as Lang, DescriptionTypes.Description as DType, Descriptions.Value
|
|
@@ -400,7 +429,7 @@ class LoincServices extends CodeSystemProvider {
|
|
|
400
429
|
reject(err);
|
|
401
430
|
} else {
|
|
402
431
|
for (const row of rows) {
|
|
403
|
-
this
|
|
432
|
+
this._addProperty(params, 'designation', row.dtype, row.value, row.lang);
|
|
404
433
|
}
|
|
405
434
|
resolve();
|
|
406
435
|
}
|
|
@@ -408,57 +437,6 @@ class LoincServices extends CodeSystemProvider {
|
|
|
408
437
|
});
|
|
409
438
|
}
|
|
410
439
|
|
|
411
|
-
#addProperty(params, type, name, value, language = null) {
|
|
412
|
-
|
|
413
|
-
const property = {
|
|
414
|
-
name: type,
|
|
415
|
-
part: [
|
|
416
|
-
{ name: 'code', valueCode: name },
|
|
417
|
-
{ name: 'value', valueString: value }
|
|
418
|
-
]
|
|
419
|
-
};
|
|
420
|
-
|
|
421
|
-
if (language) {
|
|
422
|
-
property.part.push({ name: 'language', valueCode: language });
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
params.push(property);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
#addCodeProperty(params, type, name, value, language = null) {
|
|
429
|
-
|
|
430
|
-
const property = {
|
|
431
|
-
name: type,
|
|
432
|
-
part: [
|
|
433
|
-
{ name: 'code', valueCode: name },
|
|
434
|
-
{ name: 'value', valueCode: value }
|
|
435
|
-
]
|
|
436
|
-
};
|
|
437
|
-
|
|
438
|
-
if (language) {
|
|
439
|
-
property.part.push({ name: 'language', valueCode: language });
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
params.push(property);
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
#addStringProperty(params, type, name, value, language = null) {
|
|
446
|
-
|
|
447
|
-
const property = {
|
|
448
|
-
name: type,
|
|
449
|
-
part: [
|
|
450
|
-
{ name: 'code', valueCode: name },
|
|
451
|
-
{ name: 'value', valueString: value }
|
|
452
|
-
]
|
|
453
|
-
};
|
|
454
|
-
|
|
455
|
-
if (language) {
|
|
456
|
-
property.part.push({ name: 'language', valueCode: language });
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
params.push(property);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
440
|
async #getDisplaysForContext(ctxt, langs) {
|
|
463
441
|
validateOptionalParameter(langs, "langs", Languages);
|
|
464
442
|
const displays = [new LoincDisplay('en-US', ctxt.desc)];
|
|
@@ -689,11 +667,11 @@ class LoincServices extends CodeSystemProvider {
|
|
|
689
667
|
|
|
690
668
|
// LIST filter
|
|
691
669
|
if (prop === 'LIST' && op === '=' && this.codes.has(value)) {
|
|
692
|
-
sql = `SELECT TargetKey as Key FROM Relationships
|
|
670
|
+
sql = `SELECT DISTINCT TargetKey as Key FROM Relationships
|
|
693
671
|
WHERE RelationshipTypeKey = ${this.relationships.get('Answer')}
|
|
694
672
|
AND SourceKey IN (SELECT CodeKey FROM Codes WHERE Code = '${this.#sqlWrapString(value)}')
|
|
695
673
|
ORDER BY SourceKey ASC`;
|
|
696
|
-
lsql = `SELECT COUNT(TargetKey) FROM Relationships
|
|
674
|
+
lsql = `SELECT COUNT(DISTINCT TargetKey) FROM Relationships
|
|
697
675
|
WHERE RelationshipTypeKey = ${this.relationships.get('Answer')}
|
|
698
676
|
AND SourceKey IN (SELECT CodeKey FROM Codes WHERE Code = '${this.#sqlWrapString(value)}')
|
|
699
677
|
AND TargetKey = `;
|
|
@@ -701,16 +679,16 @@ class LoincServices extends CodeSystemProvider {
|
|
|
701
679
|
// answers-for filter
|
|
702
680
|
else if (prop === 'answers-for' && op === '=') {
|
|
703
681
|
if (value.startsWith('LL')) {
|
|
704
|
-
sql = `SELECT TargetKey as Key FROM Relationships
|
|
682
|
+
sql = `SELECT DISTINCT TargetKey as Key FROM Relationships
|
|
705
683
|
WHERE RelationshipTypeKey = ${this.relationships.get('Answer')}
|
|
706
684
|
AND SourceKey IN (SELECT CodeKey FROM Codes WHERE Code = '${this.#sqlWrapString(value)}')
|
|
707
685
|
ORDER BY SourceKey ASC`;
|
|
708
|
-
lsql = `SELECT COUNT(TargetKey) FROM Relationships
|
|
686
|
+
lsql = `SELECT COUNT(DISTINCT TargetKey) FROM Relationships
|
|
709
687
|
WHERE RelationshipTypeKey = ${this.relationships.get('Answer')}
|
|
710
688
|
AND SourceKey IN (SELECT CodeKey FROM Codes WHERE Code = '${this.#sqlWrapString(value)}')
|
|
711
689
|
AND TargetKey = `;
|
|
712
690
|
} else {
|
|
713
|
-
sql = `SELECT TargetKey as Key FROM Relationships
|
|
691
|
+
sql = `SELECT DISTINCT TargetKey as Key FROM Relationships
|
|
714
692
|
WHERE RelationshipTypeKey = ${this.relationships.get('Answer')}
|
|
715
693
|
AND SourceKey IN (
|
|
716
694
|
SELECT SourceKey FROM Relationships
|
|
@@ -718,7 +696,7 @@ class LoincServices extends CodeSystemProvider {
|
|
|
718
696
|
AND TargetKey IN (SELECT CodeKey FROM Codes WHERE Code = '${this.#sqlWrapString(value)}')
|
|
719
697
|
)
|
|
720
698
|
ORDER BY SourceKey ASC`;
|
|
721
|
-
lsql = `SELECT COUNT(TargetKey) FROM Relationships
|
|
699
|
+
lsql = `SELECT COUNT(DISTINCT TargetKey) FROM Relationships
|
|
722
700
|
WHERE RelationshipTypeKey = ${this.relationships.get('Answer')}
|
|
723
701
|
AND SourceKey IN (SELECT SourceKey FROM Relationships
|
|
724
702
|
WHERE RelationshipTypeKey = ${this.relationships.get('answers-for')}
|
|
@@ -729,20 +707,20 @@ class LoincServices extends CodeSystemProvider {
|
|
|
729
707
|
// Relationship equal filter
|
|
730
708
|
else if (this.relationships.has(prop) && op === '=') {
|
|
731
709
|
if (this.codes.has(value)) {
|
|
732
|
-
sql = `SELECT SourceKey as Key FROM Relationships
|
|
710
|
+
sql = `SELECT DISTINCT SourceKey as Key FROM Relationships
|
|
733
711
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
734
712
|
AND TargetKey IN (SELECT CodeKey FROM Codes WHERE Code = '${this.#sqlWrapString(value)}')
|
|
735
713
|
ORDER BY SourceKey ASC`;
|
|
736
|
-
lsql = `SELECT COUNT(SourceKey) FROM Relationships
|
|
714
|
+
lsql = `SELECT COUNT(DISTINCT SourceKey) FROM Relationships
|
|
737
715
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
738
716
|
AND TargetKey IN (SELECT CodeKey FROM Codes WHERE Code = '${this.#sqlWrapString(value)}')
|
|
739
717
|
AND SourceKey = `;
|
|
740
718
|
} else {
|
|
741
|
-
sql = `SELECT SourceKey as Key FROM Relationships
|
|
719
|
+
sql = `SELECT DISTINCT SourceKey as Key FROM Relationships
|
|
742
720
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
743
721
|
AND TargetKey IN (SELECT CodeKey FROM Codes WHERE Description = '${this.#sqlWrapString(value)}' COLLATE NOCASE)
|
|
744
722
|
ORDER BY SourceKey ASC`;
|
|
745
|
-
lsql = `SELECT COUNT(SourceKey) FROM Relationships
|
|
723
|
+
lsql = `SELECT COUNT(DISTINCT SourceKey) FROM Relationships
|
|
746
724
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
747
725
|
AND TargetKey IN (SELECT CodeKey FROM Codes WHERE Description = '${this.#sqlWrapString(value)}' COLLATE NOCASE)
|
|
748
726
|
AND SourceKey = `;
|
|
@@ -751,11 +729,11 @@ class LoincServices extends CodeSystemProvider {
|
|
|
751
729
|
// Relationship 'in' filter
|
|
752
730
|
else if (this.relationships.has(prop) && op === 'in') {
|
|
753
731
|
const codes = this.#commaListOfCodes(value);
|
|
754
|
-
sql = `SELECT SourceKey as Key FROM Relationships
|
|
732
|
+
sql = `SELECT DISTINCT SourceKey as Key FROM Relationships
|
|
755
733
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
756
734
|
AND TargetKey IN (SELECT CodeKey FROM Codes WHERE Code IN (${codes}))
|
|
757
735
|
ORDER BY SourceKey ASC`;
|
|
758
|
-
lsql = `SELECT COUNT(SourceKey) FROM Relationships
|
|
736
|
+
lsql = `SELECT COUNT(DISTINCT SourceKey) FROM Relationships
|
|
759
737
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
760
738
|
AND TargetKey IN (SELECT CodeKey FROM Codes WHERE Code IN (${codes}))
|
|
761
739
|
AND SourceKey = `;
|
|
@@ -763,20 +741,20 @@ class LoincServices extends CodeSystemProvider {
|
|
|
763
741
|
// Relationship 'exists' filter
|
|
764
742
|
else if (this.relationships.has(prop) && op === 'exists') {
|
|
765
743
|
if (this.codes.has(value)) {
|
|
766
|
-
sql = `SELECT SourceKey as Key FROM Relationships
|
|
744
|
+
sql = `SELECT DISTINCT SourceKey as Key FROM Relationships
|
|
767
745
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
768
746
|
AND EXISTS (SELECT CodeKey FROM Codes WHERE Code = '${this.#sqlWrapString(value)}')
|
|
769
747
|
ORDER BY SourceKey ASC`;
|
|
770
|
-
lsql = `SELECT COUNT(SourceKey) FROM Relationships
|
|
748
|
+
lsql = `SELECT COUNT(DISTINCT SourceKey) FROM Relationships
|
|
771
749
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
772
750
|
AND EXISTS (SELECT CodeKey FROM Codes WHERE Code = '${this.#sqlWrapString(value)}')
|
|
773
751
|
AND SourceKey = `;
|
|
774
752
|
} else {
|
|
775
|
-
sql = `SELECT SourceKey as Key FROM Relationships
|
|
753
|
+
sql = `SELECT DISTINCT SourceKey as Key FROM Relationships
|
|
776
754
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
777
755
|
AND EXISTS (SELECT CodeKey FROM Codes WHERE Description = '${this.#sqlWrapString(value)}' COLLATE NOCASE)
|
|
778
756
|
ORDER BY SourceKey ASC`;
|
|
779
|
-
lsql = `SELECT COUNT(SourceKey) FROM Relationships
|
|
757
|
+
lsql = `SELECT COUNT(DISTINCT SourceKey) FROM Relationships
|
|
780
758
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
781
759
|
AND EXISTS (SELECT CodeKey FROM Codes WHERE Description = '${this.#sqlWrapString(value)}' COLLATE NOCASE)
|
|
782
760
|
AND SourceKey = `;
|
|
@@ -791,11 +769,11 @@ class LoincServices extends CodeSystemProvider {
|
|
|
791
769
|
'Description'
|
|
792
770
|
);
|
|
793
771
|
if (matchingKeys.length > 0) {
|
|
794
|
-
sql = `SELECT SourceKey as Key FROM Relationships
|
|
772
|
+
sql = `SELECT DISTINCT SourceKey as Key FROM Relationships
|
|
795
773
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
796
774
|
AND TargetKey IN (${matchingKeys.join(',')})
|
|
797
775
|
ORDER BY SourceKey ASC`;
|
|
798
|
-
lsql = `SELECT COUNT(SourceKey) FROM Relationships
|
|
776
|
+
lsql = `SELECT COUNT(DISTINCT SourceKey) FROM Relationships
|
|
799
777
|
WHERE RelationshipTypeKey = ${this.relationships.get(prop)}
|
|
800
778
|
AND TargetKey IN (${matchingKeys.join(',')})
|
|
801
779
|
AND SourceKey = `;
|
|
@@ -805,20 +783,14 @@ class LoincServices extends CodeSystemProvider {
|
|
|
805
783
|
else if (this.propertyList.has(prop) && op === '=') {
|
|
806
784
|
let actualValue = value;
|
|
807
785
|
if (prop === 'CLASSTYPE' && ['1', '2', '3', '4'].includes(value)) {
|
|
808
|
-
const classTypes = {
|
|
809
|
-
'1': 'Laboratory class',
|
|
810
|
-
'2': 'Clinical class',
|
|
811
|
-
'3': 'Claims attachments',
|
|
812
|
-
'4': 'Surveys'
|
|
813
|
-
};
|
|
814
786
|
actualValue = classTypes[value];
|
|
815
787
|
}
|
|
816
|
-
sql = `SELECT CodeKey as Key FROM Properties, PropertyValues
|
|
788
|
+
sql = `SELECT DISTINCT CodeKey as Key FROM Properties, PropertyValues
|
|
817
789
|
WHERE Properties.PropertyTypeKey = ${this.propertyList.get(prop)}
|
|
818
790
|
AND Properties.PropertyValueKey = PropertyValues.PropertyValueKey
|
|
819
791
|
AND PropertyValues.Value = '${this.#sqlWrapString(actualValue)}' COLLATE NOCASE
|
|
820
792
|
ORDER BY CodeKey ASC`;
|
|
821
|
-
lsql = `SELECT COUNT(CodeKey) FROM Properties, PropertyValues
|
|
793
|
+
lsql = `SELECT COUNT(DISTINCT CodeKey) FROM Properties, PropertyValues
|
|
822
794
|
WHERE Properties.PropertyTypeKey = ${this.propertyList.get(prop)}
|
|
823
795
|
AND Properties.PropertyValueKey = PropertyValues.PropertyValueKey
|
|
824
796
|
AND PropertyValues.Value = '${this.#sqlWrapString(actualValue)}' COLLATE NOCASE
|
|
@@ -827,12 +799,12 @@ class LoincServices extends CodeSystemProvider {
|
|
|
827
799
|
// Property 'in' filter
|
|
828
800
|
else if (this.propertyList.has(prop) && op === 'in') {
|
|
829
801
|
const codes = this.#commaListOfCodes(value);
|
|
830
|
-
sql = `SELECT CodeKey as Key FROM Properties, PropertyValues
|
|
802
|
+
sql = `SELECT DISTINCT CodeKey as Key FROM Properties, PropertyValues
|
|
831
803
|
WHERE Properties.PropertyTypeKey = ${this.propertyList.get(prop)}
|
|
832
804
|
AND Properties.PropertyValueKey = PropertyValues.PropertyValueKey
|
|
833
805
|
AND PropertyValues.Value IN (${codes}) COLLATE NOCASE
|
|
834
806
|
ORDER BY CodeKey ASC`;
|
|
835
|
-
lsql = `SELECT COUNT(CodeKey) FROM Properties, PropertyValues
|
|
807
|
+
lsql = `SELECT COUNT(DISTINCT CodeKey) FROM Properties, PropertyValues
|
|
836
808
|
WHERE Properties.PropertyTypeKey = ${this.propertyList.get(prop)}
|
|
837
809
|
AND Properties.PropertyValueKey = PropertyValues.PropertyValueKey
|
|
838
810
|
AND PropertyValues.Value IN (${codes}) COLLATE NOCASE
|
|
@@ -857,11 +829,11 @@ class LoincServices extends CodeSystemProvider {
|
|
|
857
829
|
'PropertyValueKey'
|
|
858
830
|
);
|
|
859
831
|
if (matchingKeys.length > 0) {
|
|
860
|
-
sql = `SELECT CodeKey as Key FROM Properties
|
|
832
|
+
sql = `SELECT DISTINCT CodeKey as Key FROM Properties
|
|
861
833
|
WHERE PropertyTypeKey = ${this.propertyList.get(prop)}
|
|
862
834
|
AND PropertyValueKey IN (${matchingKeys.join(',')})
|
|
863
835
|
ORDER BY CodeKey ASC`;
|
|
864
|
-
lsql = `SELECT COUNT(CodeKey) FROM Properties
|
|
836
|
+
lsql = `SELECT COUNT(DISTINCT CodeKey) FROM Properties
|
|
865
837
|
WHERE PropertyTypeKey = ${this.propertyList.get(prop)}
|
|
866
838
|
AND PropertyValueKey IN (${matchingKeys.join(',')})
|
|
867
839
|
AND CodeKey = `;
|
|
@@ -1000,7 +972,6 @@ class LoincServices extends CodeSystemProvider {
|
|
|
1000
972
|
}
|
|
1001
973
|
|
|
1002
974
|
async filterSize(filterContext, set) {
|
|
1003
|
-
|
|
1004
975
|
return set.keys.length;
|
|
1005
976
|
}
|
|
1006
977
|
|
package/tx/cs/cs-mimetypes.js
CHANGED
package/tx/cs/cs-ndc.js
CHANGED
|
@@ -109,6 +109,12 @@ class NdcServices extends CodeSystemProvider {
|
|
|
109
109
|
return ctxt ? !ctxt.active : false;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
async getStatus(code) {
|
|
113
|
+
|
|
114
|
+
const ctxt = await this.#ensureContext(code);
|
|
115
|
+
return ctxt.active ? "active" : "inactive";
|
|
116
|
+
}
|
|
117
|
+
|
|
112
118
|
async isDeprecated(code) {
|
|
113
119
|
await this.#ensureContext(code);
|
|
114
120
|
return false; // NDC doesn't track deprecated status separately
|