ezmedicationinput 0.1.43 → 0.1.44

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 (46) hide show
  1. package/README.md +4 -1
  2. package/dist/advice-rules.json +772 -0
  3. package/dist/advice-terminology.json +104 -0
  4. package/dist/advice.d.ts +16 -0
  5. package/dist/advice.js +1375 -0
  6. package/dist/event-trigger.d.ts +14 -0
  7. package/dist/event-trigger.js +501 -0
  8. package/dist/fhir-translations.d.ts +5 -0
  9. package/dist/fhir-translations.js +117 -0
  10. package/dist/fhir.d.ts +6 -4
  11. package/dist/fhir.js +566 -134
  12. package/dist/format.d.ts +4 -2
  13. package/dist/format.js +515 -218
  14. package/dist/i18n.d.ts +2 -2
  15. package/dist/i18n.js +641 -199
  16. package/dist/index.d.ts +0 -1
  17. package/dist/index.js +219 -168
  18. package/dist/internal-types.d.ts +5 -5
  19. package/dist/ir.d.ts +4 -0
  20. package/dist/ir.js +178 -0
  21. package/dist/lexer/lex.d.ts +2 -0
  22. package/dist/lexer/lex.js +401 -0
  23. package/dist/lexer/meaning.d.ts +71 -0
  24. package/dist/lexer/meaning.js +619 -0
  25. package/dist/lexer/surface.d.ts +2 -0
  26. package/dist/lexer/surface.js +62 -0
  27. package/dist/lexer/token-types.d.ts +36 -0
  28. package/dist/lexer/token-types.js +19 -0
  29. package/dist/maps.d.ts +6 -12
  30. package/dist/maps.js +793 -247
  31. package/dist/parser-state.d.ts +101 -0
  32. package/dist/parser-state.js +441 -0
  33. package/dist/parser.d.ts +7 -7
  34. package/dist/parser.js +3598 -1974
  35. package/dist/prn.d.ts +4 -0
  36. package/dist/prn.js +59 -0
  37. package/dist/schedule.js +230 -32
  38. package/dist/site-phrases.d.ts +35 -0
  39. package/dist/site-phrases.js +344 -0
  40. package/dist/timing-summary.d.ts +13 -3
  41. package/dist/timing-summary.js +7 -7
  42. package/dist/types.d.ts +237 -32
  43. package/dist/types.js +49 -1
  44. package/dist/utils/text.d.ts +3 -0
  45. package/dist/utils/text.js +48 -0
  46. package/package.json +1 -1
@@ -0,0 +1,14 @@
1
+ import { AdviceFrame, CanonicalAdditionalInstructionExpr, CanonicalEventTrigger, FhirDosage, FhirExtension } from "./types";
2
+ export declare const DOSAGE_CONDITIONS_EXTENSION_URL = "http://hl7.org/fhir/StructureDefinition/dosage-conditions";
3
+ export declare const DOSAGE_CONDITION_RELATIONSHIP_EXTENSION_URL = "urn:ezmedicationinput:dosage-condition-relationship";
4
+ export declare const DOSAGE_CONDITION_TRIGGER_CODE_EXTENSION_URL = "urn:ezmedicationinput:dosage-condition-triggerCode";
5
+ export declare const DOSAGE_CONDITION_SOURCE_TEXT_EXTENSION_URL = "urn:ezmedicationinput:dosage-condition-sourceText";
6
+ export declare function buildEventTriggerFromAdviceFrame(frame: AdviceFrame): CanonicalEventTrigger | undefined;
7
+ export declare function collectEventTriggersFromAdditionalInstructions(instructions: CanonicalAdditionalInstructionExpr[] | undefined): CanonicalEventTrigger[] | undefined;
8
+ export declare function buildEventTriggerInstructionText(trigger: CanonicalEventTrigger): string;
9
+ export declare function buildEventTriggerInstructionTextList(triggers: CanonicalEventTrigger[] | undefined): string | undefined;
10
+ export declare function buildDosageConditionExtensions(triggers: CanonicalEventTrigger[] | undefined): FhirExtension[] | undefined;
11
+ export declare function parseDosageConditionExtensions(dosage: Pick<FhirDosage, "extension" | "patientInstruction">): CanonicalEventTrigger[] | undefined;
12
+ export declare function hasUnresolvedDosageConditionExtension(dosage: Pick<FhirDosage, "extension" | "patientInstruction">): boolean;
13
+ export declare function cloneEventTriggers(triggers: CanonicalEventTrigger[] | undefined): CanonicalEventTrigger[] | undefined;
14
+ export declare function cloneDosageExtensions(extensions: FhirExtension[] | undefined): FhirExtension[] | undefined;
@@ -0,0 +1,501 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DOSAGE_CONDITION_SOURCE_TEXT_EXTENSION_URL = exports.DOSAGE_CONDITION_TRIGGER_CODE_EXTENSION_URL = exports.DOSAGE_CONDITION_RELATIONSHIP_EXTENSION_URL = exports.DOSAGE_CONDITIONS_EXTENSION_URL = void 0;
4
+ exports.buildEventTriggerFromAdviceFrame = buildEventTriggerFromAdviceFrame;
5
+ exports.collectEventTriggersFromAdditionalInstructions = collectEventTriggersFromAdditionalInstructions;
6
+ exports.buildEventTriggerInstructionText = buildEventTriggerInstructionText;
7
+ exports.buildEventTriggerInstructionTextList = buildEventTriggerInstructionTextList;
8
+ exports.buildDosageConditionExtensions = buildDosageConditionExtensions;
9
+ exports.parseDosageConditionExtensions = parseDosageConditionExtensions;
10
+ exports.hasUnresolvedDosageConditionExtension = hasUnresolvedDosageConditionExtension;
11
+ exports.cloneEventTriggers = cloneEventTriggers;
12
+ exports.cloneDosageExtensions = cloneDosageExtensions;
13
+ const types_1 = require("./types");
14
+ const advice_1 = require("./advice");
15
+ exports.DOSAGE_CONDITIONS_EXTENSION_URL = "http://hl7.org/fhir/StructureDefinition/dosage-conditions";
16
+ const WHEN_TRIGGER_SLICE_URL = "whenTrigger";
17
+ const TRIGGER_EXTENSION_URL = "trigger";
18
+ const OFFSET_EXTENSION_URL = "offset";
19
+ exports.DOSAGE_CONDITION_RELATIONSHIP_EXTENSION_URL = "urn:ezmedicationinput:dosage-condition-relationship";
20
+ exports.DOSAGE_CONDITION_TRIGGER_CODE_EXTENSION_URL = "urn:ezmedicationinput:dosage-condition-triggerCode";
21
+ exports.DOSAGE_CONDITION_SOURCE_TEXT_EXTENSION_URL = "urn:ezmedicationinput:dosage-condition-sourceText";
22
+ function isEventTriggerRelation(relation) {
23
+ switch (relation) {
24
+ case types_1.AdviceRelation.Before:
25
+ case types_1.AdviceRelation.After:
26
+ case types_1.AdviceRelation.During:
27
+ case types_1.AdviceRelation.On:
28
+ case types_1.AdviceRelation.Until:
29
+ return true;
30
+ default:
31
+ return false;
32
+ }
33
+ }
34
+ function normalizeTriggerKey(trigger) {
35
+ return `${trigger.relation}|${trigger.anchorText.trim().toLowerCase()}`;
36
+ }
37
+ function normalizeAnchorText(anchorText) {
38
+ return anchorText.replace(/^(each|every)\s+/i, "").trim();
39
+ }
40
+ function cloneOffset(offset) {
41
+ if ((offset === null || offset === void 0 ? void 0 : offset.value) === undefined || !offset.unit) {
42
+ return undefined;
43
+ }
44
+ return {
45
+ value: offset.value,
46
+ unit: offset.unit
47
+ };
48
+ }
49
+ function cloneTrigger(trigger) {
50
+ return {
51
+ relation: trigger.relation,
52
+ anchorText: trigger.anchorText,
53
+ triggerCode: cloneCodeableConcept(trigger.triggerCode),
54
+ triggerReference: trigger.triggerReference
55
+ ? {
56
+ reference: trigger.triggerReference.reference,
57
+ type: trigger.triggerReference.type,
58
+ display: trigger.triggerReference.display
59
+ }
60
+ : undefined,
61
+ sourceText: trigger.sourceText,
62
+ offset: cloneOffset(trigger.offset),
63
+ occurrencePolicy: trigger.occurrencePolicy,
64
+ resolutionStatus: trigger.resolutionStatus
65
+ };
66
+ }
67
+ function cloneCodeableConcept(concept) {
68
+ var _a, _b, _c;
69
+ if (!(concept === null || concept === void 0 ? void 0 : concept.text) && !(concept === null || concept === void 0 ? void 0 : concept._text) && !((_a = concept === null || concept === void 0 ? void 0 : concept.coding) === null || _a === void 0 ? void 0 : _a.length)) {
70
+ return undefined;
71
+ }
72
+ return {
73
+ text: concept.text,
74
+ _text: concept._text ? { extension: (_b = concept._text.extension) === null || _b === void 0 ? void 0 : _b.map((extension) => (Object.assign({}, extension))) } : undefined,
75
+ coding: (_c = concept.coding) === null || _c === void 0 ? void 0 : _c.map((coding) => {
76
+ var _a;
77
+ return ({
78
+ system: coding.system,
79
+ code: coding.code,
80
+ display: coding.display,
81
+ _display: coding._display ? { extension: (_a = coding._display.extension) === null || _a === void 0 ? void 0 : _a.map((extension) => (Object.assign({}, extension))) } : undefined,
82
+ i18n: coding.i18n ? Object.assign({}, coding.i18n) : undefined
83
+ });
84
+ })
85
+ };
86
+ }
87
+ function parseDurationUnit(quantity) {
88
+ var _a, _b, _c;
89
+ const candidate = (_b = (_a = quantity === null || quantity === void 0 ? void 0 : quantity.code) === null || _a === void 0 ? void 0 : _a.trim().toLowerCase()) !== null && _b !== void 0 ? _b : (_c = quantity === null || quantity === void 0 ? void 0 : quantity.unit) === null || _c === void 0 ? void 0 : _c.trim().toLowerCase();
90
+ switch (candidate) {
91
+ case "s":
92
+ case "sec":
93
+ case "second":
94
+ case "seconds":
95
+ return types_1.FhirPeriodUnit.Second;
96
+ case "min":
97
+ case "mins":
98
+ case "minute":
99
+ case "minutes":
100
+ return types_1.FhirPeriodUnit.Minute;
101
+ case "h":
102
+ case "hr":
103
+ case "hrs":
104
+ case "hour":
105
+ case "hours":
106
+ return types_1.FhirPeriodUnit.Hour;
107
+ case "d":
108
+ case "day":
109
+ case "days":
110
+ return types_1.FhirPeriodUnit.Day;
111
+ case "wk":
112
+ case "wks":
113
+ case "week":
114
+ case "weeks":
115
+ return types_1.FhirPeriodUnit.Week;
116
+ case "mo":
117
+ case "month":
118
+ case "months":
119
+ return types_1.FhirPeriodUnit.Month;
120
+ case "a":
121
+ case "yr":
122
+ case "yrs":
123
+ case "year":
124
+ case "years":
125
+ return types_1.FhirPeriodUnit.Year;
126
+ default:
127
+ return undefined;
128
+ }
129
+ }
130
+ function describeDurationUnit(unit, value) {
131
+ const plural = Math.abs(value) !== 1;
132
+ switch (unit) {
133
+ case types_1.FhirPeriodUnit.Second:
134
+ return plural ? "seconds" : "second";
135
+ case types_1.FhirPeriodUnit.Minute:
136
+ return plural ? "minutes" : "minute";
137
+ case types_1.FhirPeriodUnit.Hour:
138
+ return plural ? "hours" : "hour";
139
+ case types_1.FhirPeriodUnit.Day:
140
+ return plural ? "days" : "day";
141
+ case types_1.FhirPeriodUnit.Week:
142
+ return plural ? "weeks" : "week";
143
+ case types_1.FhirPeriodUnit.Month:
144
+ return plural ? "months" : "month";
145
+ case types_1.FhirPeriodUnit.Year:
146
+ return plural ? "years" : "year";
147
+ default:
148
+ return unit;
149
+ }
150
+ }
151
+ function buildOffsetDuration(trigger) {
152
+ const offset = trigger.offset;
153
+ if ((offset === null || offset === void 0 ? void 0 : offset.value) === undefined || !offset.unit) {
154
+ return {
155
+ value: 0,
156
+ unit: "seconds",
157
+ system: "http://unitsofmeasure.org",
158
+ code: types_1.FhirPeriodUnit.Second
159
+ };
160
+ }
161
+ const signedValue = trigger.relation === types_1.AdviceRelation.Before && offset.value > 0
162
+ ? -offset.value
163
+ : offset.value;
164
+ return {
165
+ value: signedValue,
166
+ unit: describeDurationUnit(offset.unit, signedValue),
167
+ system: "http://unitsofmeasure.org",
168
+ code: offset.unit
169
+ };
170
+ }
171
+ function buildSingleWhenTriggerExtension(trigger) {
172
+ var _a, _b, _c;
173
+ const nested = [];
174
+ if (((_a = trigger.triggerReference) === null || _a === void 0 ? void 0 : _a.reference) || ((_b = trigger.triggerReference) === null || _b === void 0 ? void 0 : _b.display)) {
175
+ nested.push({
176
+ url: TRIGGER_EXTENSION_URL,
177
+ valueReference: {
178
+ reference: trigger.triggerReference.reference,
179
+ type: trigger.triggerReference.type,
180
+ display: (_c = trigger.triggerReference.display) !== null && _c !== void 0 ? _c : trigger.anchorText
181
+ }
182
+ });
183
+ }
184
+ else {
185
+ nested.push({
186
+ url: TRIGGER_EXTENSION_URL,
187
+ valueString: trigger.anchorText
188
+ });
189
+ }
190
+ const offsetDuration = buildOffsetDuration(trigger);
191
+ if (offsetDuration) {
192
+ nested.push({
193
+ url: OFFSET_EXTENSION_URL,
194
+ valueDuration: offsetDuration
195
+ });
196
+ }
197
+ nested.push({
198
+ url: exports.DOSAGE_CONDITION_RELATIONSHIP_EXTENSION_URL,
199
+ valueCode: trigger.relation
200
+ });
201
+ if (trigger.triggerCode) {
202
+ nested.push({
203
+ url: exports.DOSAGE_CONDITION_TRIGGER_CODE_EXTENSION_URL,
204
+ valueCodeableConcept: cloneCodeableConcept(trigger.triggerCode)
205
+ });
206
+ }
207
+ if (trigger.sourceText) {
208
+ nested.push({
209
+ url: exports.DOSAGE_CONDITION_SOURCE_TEXT_EXTENSION_URL,
210
+ valueString: trigger.sourceText
211
+ });
212
+ }
213
+ return {
214
+ url: WHEN_TRIGGER_SLICE_URL,
215
+ extension: nested
216
+ };
217
+ }
218
+ function inferRelationFromInstructionText(anchorText, patientInstruction) {
219
+ const lowerInstruction = patientInstruction === null || patientInstruction === void 0 ? void 0 : patientInstruction.trim().toLowerCase();
220
+ const lowerAnchor = anchorText.trim().toLowerCase();
221
+ if (lowerInstruction) {
222
+ if (lowerInstruction.includes(`before ${lowerAnchor}`)) {
223
+ return types_1.AdviceRelation.Before;
224
+ }
225
+ if (lowerInstruction.includes(`during ${lowerAnchor}`)) {
226
+ return types_1.AdviceRelation.During;
227
+ }
228
+ if (lowerInstruction.includes(`on ${lowerAnchor}`)) {
229
+ return types_1.AdviceRelation.On;
230
+ }
231
+ if (lowerInstruction.includes(`until ${lowerAnchor}`)) {
232
+ return types_1.AdviceRelation.Until;
233
+ }
234
+ }
235
+ return types_1.AdviceRelation.After;
236
+ }
237
+ function buildEventTriggerFromAdviceFrame(frame) {
238
+ if (!isEventTriggerRelation(frame.relation)) {
239
+ return undefined;
240
+ }
241
+ let anchorText;
242
+ let conceptId;
243
+ for (const arg of frame.args) {
244
+ const trimmed = arg.text.trim();
245
+ if (trimmed) {
246
+ anchorText = trimmed;
247
+ conceptId = arg.conceptId;
248
+ break;
249
+ }
250
+ }
251
+ if (!anchorText) {
252
+ return undefined;
253
+ }
254
+ anchorText = normalizeAnchorText(anchorText);
255
+ if (!anchorText) {
256
+ return undefined;
257
+ }
258
+ return {
259
+ relation: frame.relation,
260
+ anchorText,
261
+ triggerCode: conceptId
262
+ ? (() => {
263
+ var _a;
264
+ const coding = (0, advice_1.getAdviceConceptCoding)(conceptId);
265
+ if (!coding) {
266
+ return undefined;
267
+ }
268
+ return {
269
+ text: (_a = coding.display) !== null && _a !== void 0 ? _a : anchorText,
270
+ coding: [coding]
271
+ };
272
+ })()
273
+ : undefined,
274
+ triggerReference: undefined,
275
+ sourceText: frame.sourceText.trim() || undefined,
276
+ offset: {
277
+ value: 0,
278
+ unit: types_1.FhirPeriodUnit.Second
279
+ },
280
+ occurrencePolicy: "next-occurrence",
281
+ resolutionStatus: "unresolved"
282
+ };
283
+ }
284
+ function collectEventTriggersFromAdditionalInstructions(instructions) {
285
+ if (!(instructions === null || instructions === void 0 ? void 0 : instructions.length)) {
286
+ return undefined;
287
+ }
288
+ const collected = [];
289
+ const seen = new Set();
290
+ for (const instruction of instructions) {
291
+ const frames = instruction.frames;
292
+ if (!(frames === null || frames === void 0 ? void 0 : frames.length)) {
293
+ continue;
294
+ }
295
+ for (const frame of frames) {
296
+ const trigger = buildEventTriggerFromAdviceFrame(frame);
297
+ if (!trigger) {
298
+ continue;
299
+ }
300
+ const key = normalizeTriggerKey(trigger);
301
+ if (seen.has(key)) {
302
+ continue;
303
+ }
304
+ seen.add(key);
305
+ collected.push(trigger);
306
+ }
307
+ }
308
+ return collected.length ? collected : undefined;
309
+ }
310
+ function buildEventTriggerInstructionText(trigger) {
311
+ return `Use ${trigger.relation} ${trigger.anchorText}`.replace(/\s+/g, " ").trim();
312
+ }
313
+ function buildEventTriggerInstructionTextList(triggers) {
314
+ if (!(triggers === null || triggers === void 0 ? void 0 : triggers.length)) {
315
+ return undefined;
316
+ }
317
+ const parts = [];
318
+ const seen = new Set();
319
+ for (const trigger of triggers) {
320
+ const text = buildEventTriggerInstructionText(trigger);
321
+ const key = text.toLowerCase();
322
+ if (!text || seen.has(key)) {
323
+ continue;
324
+ }
325
+ seen.add(key);
326
+ parts.push(text);
327
+ }
328
+ if (!parts.length) {
329
+ return undefined;
330
+ }
331
+ return parts.join("; ");
332
+ }
333
+ function buildDosageConditionExtensions(triggers) {
334
+ if (!(triggers === null || triggers === void 0 ? void 0 : triggers.length)) {
335
+ return undefined;
336
+ }
337
+ const nested = [];
338
+ const seen = new Set();
339
+ for (const trigger of triggers) {
340
+ const key = normalizeTriggerKey(trigger);
341
+ if (seen.has(key)) {
342
+ continue;
343
+ }
344
+ seen.add(key);
345
+ nested.push(buildSingleWhenTriggerExtension(trigger));
346
+ }
347
+ if (!nested.length) {
348
+ return undefined;
349
+ }
350
+ return [
351
+ {
352
+ url: exports.DOSAGE_CONDITIONS_EXTENSION_URL,
353
+ extension: nested
354
+ }
355
+ ];
356
+ }
357
+ function parseDosageConditionExtensions(dosage) {
358
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
359
+ const extensions = dosage.extension;
360
+ if (!(extensions === null || extensions === void 0 ? void 0 : extensions.length)) {
361
+ return undefined;
362
+ }
363
+ const triggers = [];
364
+ const seen = new Set();
365
+ for (const extension of extensions) {
366
+ if (extension.url !== exports.DOSAGE_CONDITIONS_EXTENSION_URL) {
367
+ continue;
368
+ }
369
+ for (const nested of (_a = extension.extension) !== null && _a !== void 0 ? _a : []) {
370
+ if (nested.url !== WHEN_TRIGGER_SLICE_URL) {
371
+ continue;
372
+ }
373
+ let anchorText;
374
+ let triggerCode;
375
+ let triggerReference;
376
+ let offset;
377
+ let relation;
378
+ let sourceText;
379
+ for (const part of (_b = nested.extension) !== null && _b !== void 0 ? _b : []) {
380
+ switch (part.url) {
381
+ case TRIGGER_EXTENSION_URL:
382
+ anchorText =
383
+ ((_c = part.valueString) === null || _c === void 0 ? void 0 : _c.trim()) ||
384
+ ((_e = (_d = part.valueReference) === null || _d === void 0 ? void 0 : _d.display) === null || _e === void 0 ? void 0 : _e.trim()) ||
385
+ ((_g = (_f = part.valueReference) === null || _f === void 0 ? void 0 : _f.reference) === null || _g === void 0 ? void 0 : _g.trim()) ||
386
+ undefined;
387
+ if (part.valueReference) {
388
+ triggerReference = {
389
+ reference: part.valueReference.reference,
390
+ type: part.valueReference.type,
391
+ display: part.valueReference.display
392
+ };
393
+ }
394
+ break;
395
+ case OFFSET_EXTENSION_URL: {
396
+ const unit = parseDurationUnit(part.valueDuration);
397
+ const value = (_h = part.valueDuration) === null || _h === void 0 ? void 0 : _h.value;
398
+ if (value !== undefined && unit) {
399
+ offset = { value, unit };
400
+ }
401
+ break;
402
+ }
403
+ case exports.DOSAGE_CONDITION_RELATIONSHIP_EXTENSION_URL:
404
+ if (isEventTriggerRelation(part.valueCode)) {
405
+ relation = part.valueCode;
406
+ }
407
+ break;
408
+ case exports.DOSAGE_CONDITION_TRIGGER_CODE_EXTENSION_URL:
409
+ triggerCode = cloneCodeableConcept(part.valueCodeableConcept);
410
+ break;
411
+ case exports.DOSAGE_CONDITION_SOURCE_TEXT_EXTENSION_URL:
412
+ sourceText = ((_j = part.valueString) === null || _j === void 0 ? void 0 : _j.trim()) || undefined;
413
+ break;
414
+ default:
415
+ break;
416
+ }
417
+ }
418
+ if (!anchorText) {
419
+ continue;
420
+ }
421
+ let resolvedRelation = relation !== null && relation !== void 0 ? relation : inferRelationFromInstructionText(anchorText, dosage.patientInstruction);
422
+ if ((offset === null || offset === void 0 ? void 0 : offset.value) !== undefined && offset.value < 0) {
423
+ if (!relation) {
424
+ resolvedRelation = types_1.AdviceRelation.Before;
425
+ }
426
+ offset = {
427
+ value: Math.abs(offset.value),
428
+ unit: offset.unit
429
+ };
430
+ }
431
+ else if (!offset) {
432
+ offset = {
433
+ value: 0,
434
+ unit: types_1.FhirPeriodUnit.Second
435
+ };
436
+ }
437
+ const trigger = {
438
+ relation: resolvedRelation,
439
+ anchorText,
440
+ triggerCode,
441
+ triggerReference,
442
+ sourceText,
443
+ offset,
444
+ occurrencePolicy: "next-occurrence",
445
+ resolutionStatus: "unresolved"
446
+ };
447
+ const key = normalizeTriggerKey(trigger);
448
+ if (seen.has(key)) {
449
+ continue;
450
+ }
451
+ seen.add(key);
452
+ triggers.push(trigger);
453
+ }
454
+ }
455
+ return triggers.length ? triggers : undefined;
456
+ }
457
+ function hasUnresolvedDosageConditionExtension(dosage) {
458
+ const triggers = parseDosageConditionExtensions(dosage);
459
+ return Boolean(triggers === null || triggers === void 0 ? void 0 : triggers.length);
460
+ }
461
+ function cloneEventTriggers(triggers) {
462
+ if (!(triggers === null || triggers === void 0 ? void 0 : triggers.length)) {
463
+ return undefined;
464
+ }
465
+ const cloned = [];
466
+ for (const trigger of triggers) {
467
+ cloned.push(cloneTrigger(trigger));
468
+ }
469
+ return cloned;
470
+ }
471
+ function cloneDosageExtensions(extensions) {
472
+ if (!(extensions === null || extensions === void 0 ? void 0 : extensions.length)) {
473
+ return undefined;
474
+ }
475
+ const cloned = [];
476
+ for (const extension of extensions) {
477
+ cloned.push({
478
+ url: extension.url,
479
+ extension: cloneDosageExtensions(extension.extension),
480
+ valueCode: extension.valueCode,
481
+ valueString: extension.valueString,
482
+ valueDuration: extension.valueDuration
483
+ ? {
484
+ value: extension.valueDuration.value,
485
+ unit: extension.valueDuration.unit,
486
+ system: extension.valueDuration.system,
487
+ code: extension.valueDuration.code
488
+ }
489
+ : undefined,
490
+ valueCodeableConcept: cloneCodeableConcept(extension.valueCodeableConcept),
491
+ valueReference: extension.valueReference
492
+ ? {
493
+ reference: extension.valueReference.reference,
494
+ type: extension.valueReference.type,
495
+ display: extension.valueReference.display
496
+ }
497
+ : undefined
498
+ });
499
+ }
500
+ return cloned;
501
+ }
@@ -0,0 +1,5 @@
1
+ import { FhirPrimitiveElement } from "./types";
2
+ export declare const FHIR_TRANSLATION_EXTENSION_URL = "http://hl7.org/fhir/StructureDefinition/translation";
3
+ export declare function clonePrimitiveElement(element: FhirPrimitiveElement | undefined): FhirPrimitiveElement | undefined;
4
+ export declare function buildTranslationPrimitiveElement(translations: Record<string, string> | undefined, base?: FhirPrimitiveElement): FhirPrimitiveElement | undefined;
5
+ export declare function getPrimitiveTranslation(element: FhirPrimitiveElement | undefined, locale: string | undefined): string | undefined;
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FHIR_TRANSLATION_EXTENSION_URL = void 0;
4
+ exports.clonePrimitiveElement = clonePrimitiveElement;
5
+ exports.buildTranslationPrimitiveElement = buildTranslationPrimitiveElement;
6
+ exports.getPrimitiveTranslation = getPrimitiveTranslation;
7
+ exports.FHIR_TRANSLATION_EXTENSION_URL = "http://hl7.org/fhir/StructureDefinition/translation";
8
+ const TRANSLATION_LANG_EXTENSION_URL = "lang";
9
+ const TRANSLATION_CONTENT_EXTENSION_URL = "content";
10
+ function normalizeLocaleKey(locale) {
11
+ const trimmed = locale === null || locale === void 0 ? void 0 : locale.trim().toLowerCase();
12
+ return trimmed || undefined;
13
+ }
14
+ function cloneExtension(extension) {
15
+ var _a;
16
+ return {
17
+ url: extension.url,
18
+ extension: (_a = extension.extension) === null || _a === void 0 ? void 0 : _a.map(cloneExtension),
19
+ valueCode: extension.valueCode,
20
+ valueString: extension.valueString
21
+ };
22
+ }
23
+ function clonePrimitiveElement(element) {
24
+ var _a;
25
+ if (!((_a = element === null || element === void 0 ? void 0 : element.extension) === null || _a === void 0 ? void 0 : _a.length)) {
26
+ return undefined;
27
+ }
28
+ return {
29
+ extension: element.extension.map(cloneExtension)
30
+ };
31
+ }
32
+ function buildTranslationExtension(locale, content) {
33
+ return {
34
+ url: exports.FHIR_TRANSLATION_EXTENSION_URL,
35
+ extension: [
36
+ {
37
+ url: TRANSLATION_LANG_EXTENSION_URL,
38
+ valueCode: locale
39
+ },
40
+ {
41
+ url: TRANSLATION_CONTENT_EXTENSION_URL,
42
+ valueString: content
43
+ }
44
+ ]
45
+ };
46
+ }
47
+ function buildTranslationPrimitiveElement(translations, base) {
48
+ var _a, _b;
49
+ const nextExtensions = [];
50
+ const baseExtensions = (_a = base === null || base === void 0 ? void 0 : base.extension) !== null && _a !== void 0 ? _a : [];
51
+ for (const extension of baseExtensions) {
52
+ if (extension.url !== exports.FHIR_TRANSLATION_EXTENSION_URL) {
53
+ nextExtensions.push(cloneExtension(extension));
54
+ }
55
+ }
56
+ if (translations) {
57
+ for (const locale in translations) {
58
+ const normalizedLocale = normalizeLocaleKey(locale);
59
+ const content = (_b = translations[locale]) === null || _b === void 0 ? void 0 : _b.trim();
60
+ if (!normalizedLocale || !content) {
61
+ continue;
62
+ }
63
+ nextExtensions.push(buildTranslationExtension(normalizedLocale, content));
64
+ }
65
+ }
66
+ if (!nextExtensions.length) {
67
+ return undefined;
68
+ }
69
+ return {
70
+ extension: nextExtensions
71
+ };
72
+ }
73
+ function getTranslationParts(extension) {
74
+ var _a, _b;
75
+ const parts = (_a = extension.extension) !== null && _a !== void 0 ? _a : [];
76
+ let locale;
77
+ let content;
78
+ for (const part of parts) {
79
+ switch (part.url) {
80
+ case TRANSLATION_LANG_EXTENSION_URL:
81
+ locale = normalizeLocaleKey(part.valueCode);
82
+ break;
83
+ case TRANSLATION_CONTENT_EXTENSION_URL:
84
+ content = ((_b = part.valueString) === null || _b === void 0 ? void 0 : _b.trim()) || undefined;
85
+ break;
86
+ default:
87
+ break;
88
+ }
89
+ }
90
+ return { locale, content };
91
+ }
92
+ function getPrimitiveTranslation(element, locale) {
93
+ var _a;
94
+ const targetLocale = normalizeLocaleKey(locale);
95
+ if (!targetLocale || !((_a = element === null || element === void 0 ? void 0 : element.extension) === null || _a === void 0 ? void 0 : _a.length)) {
96
+ return undefined;
97
+ }
98
+ let languagePrefixMatch;
99
+ for (const extension of element.extension) {
100
+ if (extension.url !== exports.FHIR_TRANSLATION_EXTENSION_URL) {
101
+ continue;
102
+ }
103
+ const parts = getTranslationParts(extension);
104
+ if (!parts.locale || !parts.content) {
105
+ continue;
106
+ }
107
+ if (parts.locale === targetLocale) {
108
+ return parts.content;
109
+ }
110
+ if (languagePrefixMatch === undefined &&
111
+ (targetLocale.startsWith(`${parts.locale}-`) ||
112
+ parts.locale.startsWith(`${targetLocale}-`))) {
113
+ languagePrefixMatch = parts.content;
114
+ }
115
+ }
116
+ return languagePrefixMatch;
117
+ }
package/dist/fhir.d.ts CHANGED
@@ -1,4 +1,6 @@
1
- import { ParsedSigInternal } from "./internal-types";
2
- import { FhirDosage } from "./types";
3
- export declare function toFhir(internal: ParsedSigInternal): FhirDosage;
4
- export declare function internalFromFhir(dosage: FhirDosage): ParsedSigInternal;
1
+ import { ParserState } from "./parser-state";
2
+ import { CanonicalSigClause, FhirDosage } from "./types";
3
+ export declare function canonicalToFhir(clause: CanonicalSigClause, textOverride?: string): FhirDosage;
4
+ export declare function toFhir(state: ParserState): FhirDosage;
5
+ export declare function canonicalFromFhir(dosage: FhirDosage): CanonicalSigClause;
6
+ export declare function parserStateFromFhir(dosage: FhirDosage): ParserState;