@petrarca/sonnet-core 0.7.0 → 0.9.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/README.md +18 -5
- package/dist/{chunk-XAEHYRXC.js → chunk-LOWDCP73.js} +1 -1
- package/dist/chunk-ZM3U3HR2.js +98 -0
- package/dist/chunk-ZM3U3HR2.js.map +1 -0
- package/dist/config/index.d.ts +12 -10
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/entityOptions/index.d.ts +2 -2
- package/dist/hooks/index.d.ts +116 -3
- package/dist/hooks/index.js +153 -12
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +35 -11
- package/dist/index.js.map +1 -1
- package/dist/lazyTree-C0oThxCS.d.ts +139 -0
- package/dist/logger/index.d.ts +6 -0
- package/dist/logger/index.js +13 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/schema/index.d.ts +166 -378
- package/dist/schema/index.js +501 -37
- package/dist/schema/index.js.map +1 -1
- package/dist/search/index.d.ts +18 -1
- package/dist/search/index.js +26 -1
- package/dist/search/index.js.map +1 -1
- package/dist/terminology/index.d.ts +161 -0
- package/dist/terminology/index.js +178 -0
- package/dist/terminology/index.js.map +1 -0
- package/dist/{types-DJ4hb97y.d.ts → types-BiFVnfqr.d.ts} +1 -1
- package/dist/types-HhzIKd1R.d.ts +582 -0
- package/package.json +18 -10
- /package/dist/{chunk-XAEHYRXC.js.map → chunk-LOWDCP73.js.map} +0 -0
package/dist/schema/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
warnLog
|
|
3
|
-
} from "../chunk-XAEHYRXC.js";
|
|
4
1
|
import {
|
|
5
2
|
FORM_ITEM_ID_FIELD,
|
|
6
3
|
generateId,
|
|
7
4
|
isEqual
|
|
8
5
|
} from "../chunk-XCCOEUVC.js";
|
|
6
|
+
import {
|
|
7
|
+
warnLog
|
|
8
|
+
} from "../chunk-LOWDCP73.js";
|
|
9
9
|
|
|
10
10
|
// src/schema/types.ts
|
|
11
11
|
var WIDTH_TOKEN_REMS = {
|
|
@@ -41,18 +41,34 @@ function isNullableBoolean(property) {
|
|
|
41
41
|
const hasNull = property.anyOf.some((s) => s.type === "null");
|
|
42
42
|
return hasBoolean && hasNull;
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
var LIFTABLE_TYPES = /* @__PURE__ */ new Set([
|
|
45
|
+
"string",
|
|
46
|
+
"number",
|
|
47
|
+
"integer",
|
|
48
|
+
"boolean",
|
|
49
|
+
"array"
|
|
50
|
+
]);
|
|
51
|
+
function liftNullableMember(property) {
|
|
52
|
+
const members = property.anyOf;
|
|
53
|
+
if (!Array.isArray(members) || members.length !== 2) return property;
|
|
54
|
+
const nonNull = members.filter((m) => m.type !== "null");
|
|
55
|
+
if (nonNull.length !== 1) return property;
|
|
56
|
+
const [member] = nonNull;
|
|
57
|
+
if (typeof member.type !== "string" || !LIFTABLE_TYPES.has(member.type)) {
|
|
58
|
+
return property;
|
|
47
59
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
return { ...member, ...property };
|
|
61
|
+
}
|
|
62
|
+
function extractEnumValues(property) {
|
|
63
|
+
const candidates = [
|
|
64
|
+
property.enum,
|
|
65
|
+
property.type === "array" ? property.items?.enum : void 0,
|
|
66
|
+
...(property.anyOf ?? []).map((branch) => branch.enum)
|
|
67
|
+
];
|
|
68
|
+
return candidates.find(isNonEmptyEnum) ?? [];
|
|
69
|
+
}
|
|
70
|
+
function isNonEmptyEnum(values) {
|
|
71
|
+
return Array.isArray(values) && values.length > 0;
|
|
56
72
|
}
|
|
57
73
|
function getFieldTitle(fieldName, property) {
|
|
58
74
|
return property["x-ui-title"] || property.title || fieldName;
|
|
@@ -147,9 +163,31 @@ var ajv = new Ajv({
|
|
|
147
163
|
strict: false,
|
|
148
164
|
validateFormats: true,
|
|
149
165
|
// Allow unknown keywords (for x-ui-widget, x-ui-title, etc.)
|
|
150
|
-
strictSchema: false
|
|
166
|
+
strictSchema: false,
|
|
167
|
+
// Enable $data references so a keyword can reference another field's value,
|
|
168
|
+
// e.g. { "const": { "$data": "1/password" } } for "must equal password".
|
|
169
|
+
// This is the declarative path for simple cross-field rules (see the
|
|
170
|
+
// custom-validation design); complex cross-field logic uses form validators.
|
|
171
|
+
$data: true
|
|
151
172
|
});
|
|
152
173
|
addFormats(ajv);
|
|
174
|
+
var TIME_OF_DAY = /^([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d)(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})?$/i;
|
|
175
|
+
function secondsOf(time) {
|
|
176
|
+
const m = TIME_OF_DAY.exec(time);
|
|
177
|
+
if (!m) return void 0;
|
|
178
|
+
return Number(m[1]) * 3600 + Number(m[2]) * 60 + Number(m[3] ?? 0);
|
|
179
|
+
}
|
|
180
|
+
ajv.addFormat("time", {
|
|
181
|
+
type: "string",
|
|
182
|
+
validate: (time) => TIME_OF_DAY.test(time),
|
|
183
|
+
// What formatMinimum / formatMaximum compare by.
|
|
184
|
+
compare: (a, b) => {
|
|
185
|
+
const x = secondsOf(a);
|
|
186
|
+
const y = secondsOf(b);
|
|
187
|
+
if (x === void 0 || y === void 0) return void 0;
|
|
188
|
+
return x === y ? 0 : x < y ? -1 : 1;
|
|
189
|
+
}
|
|
190
|
+
});
|
|
153
191
|
function resolveSchema(schema, formData) {
|
|
154
192
|
if (!schema || typeof schema !== "object") {
|
|
155
193
|
return schema;
|
|
@@ -335,25 +373,26 @@ function evaluateUiRule(rule, formData) {
|
|
|
335
373
|
}
|
|
336
374
|
|
|
337
375
|
// src/schema/schemaUtils.ts
|
|
376
|
+
var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
377
|
+
var isGroup = (p) => !!p.properties && p.default === void 0;
|
|
378
|
+
function groupFilled(value, property) {
|
|
379
|
+
if (!isGroup(property) || value !== void 0 && !isPlainObject(value))
|
|
380
|
+
return void 0;
|
|
381
|
+
const filled = applySchemaDefaults(value ?? {}, property);
|
|
382
|
+
return value !== void 0 || Object.keys(filled).length > 0 ? filled : void 0;
|
|
383
|
+
}
|
|
338
384
|
function applySchemaDefaults(data, schema) {
|
|
339
385
|
const result = { ...data };
|
|
340
386
|
const properties = schema.properties ?? {};
|
|
341
387
|
for (const [fieldName, property] of Object.entries(properties)) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
388
|
+
const value = result[fieldName];
|
|
389
|
+
const filled = value === void 0 && property.default !== void 0 ? property.default : groupFilled(value, property);
|
|
390
|
+
if (filled !== void 0) result[fieldName] = filled;
|
|
345
391
|
}
|
|
346
392
|
return result;
|
|
347
393
|
}
|
|
348
394
|
function extractSchemaDefaults(schema) {
|
|
349
|
-
|
|
350
|
-
const properties = schema.properties ?? {};
|
|
351
|
-
for (const [fieldName, property] of Object.entries(properties)) {
|
|
352
|
-
if (property.default !== void 0) {
|
|
353
|
-
defaults[fieldName] = property.default;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
return defaults;
|
|
395
|
+
return applySchemaDefaults({}, schema);
|
|
357
396
|
}
|
|
358
397
|
function generateJsonSchemaFromVariables(variables, existingSchema) {
|
|
359
398
|
const existingProperties = existingSchema?.properties ?? {};
|
|
@@ -386,6 +425,268 @@ function toJsonSchema(schema) {
|
|
|
386
425
|
});
|
|
387
426
|
}
|
|
388
427
|
|
|
428
|
+
// src/schema/coreTypes.ts
|
|
429
|
+
var CORE_TYPES_BASE = "https://schemas.petrarca-labs.com/core/";
|
|
430
|
+
var QUANTITY_TYPE_ID = `${CORE_TYPES_BASE}quantity/v1`;
|
|
431
|
+
var UCUM_SYSTEM = "http://unitsofmeasure.org";
|
|
432
|
+
var QUANTITY_DEFINITION = {
|
|
433
|
+
type: "object",
|
|
434
|
+
title: "Quantity",
|
|
435
|
+
properties: {
|
|
436
|
+
value: { type: "number", title: "Value" },
|
|
437
|
+
unit: { type: "string", title: "Unit", minLength: 1 },
|
|
438
|
+
system: { type: "string", title: "Unit system", format: "uri" },
|
|
439
|
+
comparator: {
|
|
440
|
+
type: "string",
|
|
441
|
+
title: "Comparator",
|
|
442
|
+
enum: ["<", "<=", ">=", ">"]
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
required: ["value", "unit"],
|
|
446
|
+
additionalProperties: false,
|
|
447
|
+
// Shown as a quantity wherever it is used: a number and its unit.
|
|
448
|
+
"x-ui-widget": "quantity"
|
|
449
|
+
};
|
|
450
|
+
var QUANTITY_TYPE = {
|
|
451
|
+
id: QUANTITY_TYPE_ID,
|
|
452
|
+
label: "Quantity",
|
|
453
|
+
definition: QUANTITY_DEFINITION
|
|
454
|
+
};
|
|
455
|
+
var CODING_TYPE_ID = `${CORE_TYPES_BASE}coding/v1`;
|
|
456
|
+
function codingKey(c) {
|
|
457
|
+
return `${c.system ?? ""}|${c.code}`;
|
|
458
|
+
}
|
|
459
|
+
var CODING_DEFINITION = {
|
|
460
|
+
type: "object",
|
|
461
|
+
title: "Coded value",
|
|
462
|
+
properties: {
|
|
463
|
+
system: { type: "string", title: "Code system", minLength: 1 },
|
|
464
|
+
code: { type: "string", title: "Code", minLength: 1 },
|
|
465
|
+
version: { type: "string", title: "Version" },
|
|
466
|
+
display: { type: "string", title: "Label" }
|
|
467
|
+
},
|
|
468
|
+
required: ["system", "code"],
|
|
469
|
+
// Shown as a coded value wherever it is used: searched in its list.
|
|
470
|
+
"x-ui-widget": "coded-value"
|
|
471
|
+
};
|
|
472
|
+
var CODING_TYPE = {
|
|
473
|
+
id: CODING_TYPE_ID,
|
|
474
|
+
label: "Coded value",
|
|
475
|
+
definition: CODING_DEFINITION
|
|
476
|
+
};
|
|
477
|
+
var CODEABLE_CONCEPT_TYPE_ID = `${CORE_TYPES_BASE}codeable-concept/v1`;
|
|
478
|
+
var { "x-ui-widget": _codingWidget, ...CODING_FIELDS } = CODING_DEFINITION;
|
|
479
|
+
var CODEABLE_CONCEPT_DEFINITION = {
|
|
480
|
+
type: "object",
|
|
481
|
+
title: "Codeable concept",
|
|
482
|
+
properties: {
|
|
483
|
+
codings: {
|
|
484
|
+
type: "array",
|
|
485
|
+
title: "Codings",
|
|
486
|
+
items: {
|
|
487
|
+
...CODING_FIELDS,
|
|
488
|
+
title: "Coding",
|
|
489
|
+
properties: {
|
|
490
|
+
...CODING_FIELDS.properties,
|
|
491
|
+
userSelected: { type: "boolean", title: "Picked by a person" },
|
|
492
|
+
match: {
|
|
493
|
+
type: "string",
|
|
494
|
+
title: "Match",
|
|
495
|
+
enum: ["equivalent", "broader", "narrower"]
|
|
496
|
+
},
|
|
497
|
+
purpose: { ...CODING_FIELDS, title: "Purpose" }
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
text: { type: "string", title: "Text" }
|
|
502
|
+
},
|
|
503
|
+
// Shown as a codeable concept wherever it is used: a coded value per list.
|
|
504
|
+
"x-ui-widget": "codeable-concept"
|
|
505
|
+
};
|
|
506
|
+
var CODEABLE_CONCEPT_TYPE = {
|
|
507
|
+
id: CODEABLE_CONCEPT_TYPE_ID,
|
|
508
|
+
label: "Codeable concept",
|
|
509
|
+
definition: CODEABLE_CONCEPT_DEFINITION
|
|
510
|
+
};
|
|
511
|
+
var CORE_VALUE_TYPES = [
|
|
512
|
+
QUANTITY_TYPE,
|
|
513
|
+
CODING_TYPE,
|
|
514
|
+
CODEABLE_CONCEPT_TYPE
|
|
515
|
+
];
|
|
516
|
+
function valueTypeResolver(types) {
|
|
517
|
+
const byId = new Map(types.map((t) => [t.id, t.definition]));
|
|
518
|
+
return (ref) => byId.get(ref);
|
|
519
|
+
}
|
|
520
|
+
var resolveCore = valueTypeResolver(CORE_VALUE_TYPES);
|
|
521
|
+
function coreType(ref) {
|
|
522
|
+
return resolveCore(ref);
|
|
523
|
+
}
|
|
524
|
+
function coreTypeOf(prop) {
|
|
525
|
+
return prop.$ref && resolveCore(prop.$ref) ? prop.$ref : void 0;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// src/schema/binding.ts
|
|
529
|
+
function isAdditional(a) {
|
|
530
|
+
if (!a || typeof a !== "object") return false;
|
|
531
|
+
const { valueSet, system } = a;
|
|
532
|
+
return !!(valueSet || system);
|
|
533
|
+
}
|
|
534
|
+
function bindingOf(prop) {
|
|
535
|
+
const binding = prop["x-binding"];
|
|
536
|
+
if (!binding || typeof binding !== "object") return void 0;
|
|
537
|
+
const { valueSet, system, strength, additional, ...rest } = binding;
|
|
538
|
+
if (!valueSet && !system) return void 0;
|
|
539
|
+
const lists = Array.isArray(additional) ? additional.filter(isAdditional) : [];
|
|
540
|
+
return {
|
|
541
|
+
...rest,
|
|
542
|
+
...valueSet ? { valueSet } : {},
|
|
543
|
+
...system ? { system } : {},
|
|
544
|
+
strength: strength === "extensible" ? "extensible" : "required",
|
|
545
|
+
...lists.length ? { additional: lists } : {}
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
function bindingLists(binding) {
|
|
549
|
+
const { valueSet, system, version, title, additional = [] } = binding;
|
|
550
|
+
const first = {
|
|
551
|
+
...valueSet ? { valueSet } : {},
|
|
552
|
+
...system ? { system } : {},
|
|
553
|
+
...version ? { version } : {},
|
|
554
|
+
...title ? { title } : {}
|
|
555
|
+
};
|
|
556
|
+
return [first, ...additional];
|
|
557
|
+
}
|
|
558
|
+
var BAR = "|";
|
|
559
|
+
function parseCodeToken(token, bound) {
|
|
560
|
+
const bar = token.lastIndexOf(BAR);
|
|
561
|
+
if (bar < 0) return { ...bound ? { system: bound } : {}, code: token };
|
|
562
|
+
return { system: token.slice(0, bar), code: token.slice(bar + 1) };
|
|
563
|
+
}
|
|
564
|
+
function codeToken(coding, bound) {
|
|
565
|
+
return coding.system && coding.system !== bound ? `${coding.system}${BAR}${coding.code}` : coding.code;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// src/schema/codeableConcept.ts
|
|
569
|
+
function conceptOf(value) {
|
|
570
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
571
|
+
}
|
|
572
|
+
function codingsByList(value, lists) {
|
|
573
|
+
const codings = conceptOf(value).codings ?? [];
|
|
574
|
+
const free = new Set(codings.map((_, i) => i));
|
|
575
|
+
const claim = (pick) => {
|
|
576
|
+
const i = [...free].find((j) => pick(codings[j]));
|
|
577
|
+
if (i === void 0) return void 0;
|
|
578
|
+
free.delete(i);
|
|
579
|
+
return codings[i];
|
|
580
|
+
};
|
|
581
|
+
const bySystem = lists.map(
|
|
582
|
+
(l) => l.system ? claim((c) => c.system === l.system) : void 0
|
|
583
|
+
);
|
|
584
|
+
const byList = lists.map(
|
|
585
|
+
(l, i) => l.system ? bySystem[i] : claim(() => true)
|
|
586
|
+
);
|
|
587
|
+
return { byList, others: [...free].map((i) => codings[i]) };
|
|
588
|
+
}
|
|
589
|
+
function listTitle(list) {
|
|
590
|
+
if (list.title) return list.title;
|
|
591
|
+
if (list.purpose) return list.purpose.display ?? list.purpose.code;
|
|
592
|
+
const id = list.system ?? list.valueSet ?? "";
|
|
593
|
+
const parts = id.replace(/^[a-z]+:\/\//i, "").split(/[/#:]/).filter(Boolean);
|
|
594
|
+
return parts.at(-1) ?? id;
|
|
595
|
+
}
|
|
596
|
+
function missingLists(prop, value) {
|
|
597
|
+
const binding = bindingOf(prop);
|
|
598
|
+
if (!binding?.additional?.some((l) => l.required)) return [];
|
|
599
|
+
if (!conceptOf(value).codings?.length) return [];
|
|
600
|
+
const lists = bindingLists(binding);
|
|
601
|
+
const { byList } = codingsByList(value, lists);
|
|
602
|
+
return lists.filter((l, i) => l.required && !byList[i]);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// src/schema/valueRef.ts
|
|
606
|
+
function isPlainString(member) {
|
|
607
|
+
return Object.keys(member).length === 1 && member.type === "string";
|
|
608
|
+
}
|
|
609
|
+
function isPlainRef(member) {
|
|
610
|
+
return Object.keys(member).length === 1 && typeof member.$ref === "string";
|
|
611
|
+
}
|
|
612
|
+
function singleRefOf(prop) {
|
|
613
|
+
if (prop.$ref) return { ref: prop.$ref, orText: false };
|
|
614
|
+
const members = prop.anyOf;
|
|
615
|
+
if (!Array.isArray(members) || members.length !== 2) return void 0;
|
|
616
|
+
const [first, second] = members;
|
|
617
|
+
return isPlainRef(first) && isPlainString(second) ? { ref: first.$ref, orText: true } : void 0;
|
|
618
|
+
}
|
|
619
|
+
function itemRefOf(items) {
|
|
620
|
+
if (!items) return void 0;
|
|
621
|
+
const own = Object.keys(items);
|
|
622
|
+
const plain = own.length === 1 && (own[0] === "$ref" || own[0] === "anyOf");
|
|
623
|
+
return plain ? singleRefOf(items) : void 0;
|
|
624
|
+
}
|
|
625
|
+
function valueRefOf(prop) {
|
|
626
|
+
if (prop.type === "array") {
|
|
627
|
+
const item = itemRefOf(prop.items);
|
|
628
|
+
return item && { ...item, multiple: true };
|
|
629
|
+
}
|
|
630
|
+
const single = singleRefOf(prop);
|
|
631
|
+
return single && { ...single, multiple: false };
|
|
632
|
+
}
|
|
633
|
+
function singleKeywords(ref, orText) {
|
|
634
|
+
return orText ? { anyOf: [{ $ref: ref }, { type: "string" }] } : { $ref: ref };
|
|
635
|
+
}
|
|
636
|
+
function valueRefKeywords(ref, orText, multiple = false) {
|
|
637
|
+
const none = {
|
|
638
|
+
$ref: void 0,
|
|
639
|
+
anyOf: void 0,
|
|
640
|
+
type: void 0,
|
|
641
|
+
items: void 0
|
|
642
|
+
};
|
|
643
|
+
return multiple ? { ...none, type: "array", items: singleKeywords(ref, orText) } : { ...none, ...singleKeywords(ref, orText) };
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// src/schema/unitRanges.ts
|
|
647
|
+
function rangeEntry(unit, range) {
|
|
648
|
+
return {
|
|
649
|
+
if: { properties: { unit: { const: unit } }, required: ["unit"] },
|
|
650
|
+
then: {
|
|
651
|
+
properties: {
|
|
652
|
+
value: {
|
|
653
|
+
...range.min !== void 0 ? { minimum: range.min } : {},
|
|
654
|
+
...range.max !== void 0 ? { maximum: range.max } : {}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
var numberOrNone = (v) => v === void 0 || typeof v === "number";
|
|
661
|
+
function namedIn(entry) {
|
|
662
|
+
const value = entry.then?.properties?.value;
|
|
663
|
+
return {
|
|
664
|
+
unit: entry.if?.properties?.unit?.const,
|
|
665
|
+
min: value?.minimum,
|
|
666
|
+
max: value?.maximum
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
function readEntry(entry) {
|
|
670
|
+
const { unit, min, max } = namedIn(entry);
|
|
671
|
+
if (typeof unit !== "string" || !numberOrNone(min) || !numberOrNone(max))
|
|
672
|
+
return void 0;
|
|
673
|
+
const range = { min, max };
|
|
674
|
+
return isEqual(entry, rangeEntry(unit, range)) ? [unit, range] : void 0;
|
|
675
|
+
}
|
|
676
|
+
function unitRangesOf(prop) {
|
|
677
|
+
const ranges = {};
|
|
678
|
+
for (const entry of prop.allOf ?? []) {
|
|
679
|
+
const read = readEntry(entry);
|
|
680
|
+
if (!read) return void 0;
|
|
681
|
+
ranges[read[0]] = read[1];
|
|
682
|
+
}
|
|
683
|
+
return ranges;
|
|
684
|
+
}
|
|
685
|
+
function unitRangesKeywords(ranges) {
|
|
686
|
+
const entries = Object.entries(ranges).filter(([, r]) => r.min !== void 0 || r.max !== void 0).map(([unit, r]) => rangeEntry(unit, r));
|
|
687
|
+
return { allOf: entries.length ? entries : void 0 };
|
|
688
|
+
}
|
|
689
|
+
|
|
389
690
|
// src/schema/resolveRefs.ts
|
|
390
691
|
function extractDefName(ref) {
|
|
391
692
|
const match = ref.match(/^#\/(\$defs|definitions)\/(.+)$/);
|
|
@@ -397,6 +698,17 @@ function inDocumentResolver(defs) {
|
|
|
397
698
|
return name ? defs[name] : void 0;
|
|
398
699
|
};
|
|
399
700
|
}
|
|
701
|
+
function withOverrides(target, overrides) {
|
|
702
|
+
const merged = { ...target, ...overrides };
|
|
703
|
+
if (target.properties && overrides.properties) {
|
|
704
|
+
merged.properties = { ...target.properties };
|
|
705
|
+
for (const [key, prop] of Object.entries(overrides.properties))
|
|
706
|
+
merged.properties[key] = { ...target.properties[key], ...prop };
|
|
707
|
+
}
|
|
708
|
+
if (target.required && overrides.required)
|
|
709
|
+
merged.required = [.../* @__PURE__ */ new Set([...target.required, ...overrides.required])];
|
|
710
|
+
return merged;
|
|
711
|
+
}
|
|
400
712
|
function resolveRef(node, resolve, seen) {
|
|
401
713
|
const ref = node.$ref;
|
|
402
714
|
const resolved = resolve(ref);
|
|
@@ -406,7 +718,7 @@ function resolveRef(node, resolve, seen) {
|
|
|
406
718
|
const overrides = Object.fromEntries(
|
|
407
719
|
Object.entries(node).filter(([k]) => k !== "$ref")
|
|
408
720
|
);
|
|
409
|
-
const merged = Object.keys(overrides).length > 0 ?
|
|
721
|
+
const merged = Object.keys(overrides).length > 0 ? withOverrides(resolved, overrides) : resolved;
|
|
410
722
|
const result = resolveNode(merged, resolve, seen);
|
|
411
723
|
seen.delete(ref);
|
|
412
724
|
return result;
|
|
@@ -455,9 +767,8 @@ function resolveNode(node, resolve, seen) {
|
|
|
455
767
|
}
|
|
456
768
|
function resolveRefs(schema, resolve) {
|
|
457
769
|
const defs = schema.$defs ?? schema.definitions ?? {};
|
|
458
|
-
|
|
459
|
-
const
|
|
460
|
-
const resolver = resolve ? (ref) => resolve(ref) ?? fallback(ref) : fallback;
|
|
770
|
+
const inDocument = inDocumentResolver(defs);
|
|
771
|
+
const resolver = (ref) => resolve?.(ref) ?? coreType(ref) ?? inDocument(ref);
|
|
461
772
|
const seen = /* @__PURE__ */ new Set();
|
|
462
773
|
const resolved = resolveNode(
|
|
463
774
|
schema,
|
|
@@ -467,6 +778,76 @@ function resolveRefs(schema, resolve) {
|
|
|
467
778
|
return resolved;
|
|
468
779
|
}
|
|
469
780
|
|
|
781
|
+
// src/schema/contentValidation.ts
|
|
782
|
+
var OWNED_BY_VALIDATE_FORM_DATA = /* @__PURE__ */ new Set([
|
|
783
|
+
"required",
|
|
784
|
+
"minItems",
|
|
785
|
+
"maxItems"
|
|
786
|
+
]);
|
|
787
|
+
var WRAPPERS = /* @__PURE__ */ new Set(["if"]);
|
|
788
|
+
function unescapePointerToken(token) {
|
|
789
|
+
return token.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
790
|
+
}
|
|
791
|
+
function labelForPointer(schema, pointer) {
|
|
792
|
+
if (pointer === "") return "";
|
|
793
|
+
const tokens = pointer.split("/").slice(1).map(unescapePointerToken);
|
|
794
|
+
const parts = [];
|
|
795
|
+
let node = schema;
|
|
796
|
+
for (const token of tokens) {
|
|
797
|
+
if (/^\d+$/.test(token)) {
|
|
798
|
+
if (parts.length > 0) {
|
|
799
|
+
parts[parts.length - 1] = `${parts[parts.length - 1]}[${Number(token) + 1}]`;
|
|
800
|
+
}
|
|
801
|
+
node = node?.items;
|
|
802
|
+
continue;
|
|
803
|
+
}
|
|
804
|
+
const props = node?.properties;
|
|
805
|
+
const child = props?.[token];
|
|
806
|
+
parts.push(child ? getFieldTitle(token, child) : token);
|
|
807
|
+
node = child;
|
|
808
|
+
}
|
|
809
|
+
return parts.join(" > ");
|
|
810
|
+
}
|
|
811
|
+
var FORMAT_RANGE = {
|
|
812
|
+
formatMinimum: "or later",
|
|
813
|
+
formatExclusiveMinimum: "later",
|
|
814
|
+
formatMaximum: "or earlier",
|
|
815
|
+
formatExclusiveMaximum: "earlier"
|
|
816
|
+
};
|
|
817
|
+
function messageFor(label, err) {
|
|
818
|
+
const what = label || "Value";
|
|
819
|
+
const range = FORMAT_RANGE[err.keyword];
|
|
820
|
+
const limit = err.params.limit;
|
|
821
|
+
if (range && limit !== void 0) {
|
|
822
|
+
const prefix = err.keyword.includes("Exclusive") ? `${range} than` : "";
|
|
823
|
+
return prefix ? `${what} must be ${prefix} ${String(limit)}` : `${what} must be ${String(limit)} ${range}`;
|
|
824
|
+
}
|
|
825
|
+
return `${what} ${err.message ?? "is invalid"}`;
|
|
826
|
+
}
|
|
827
|
+
function validateContentConstraints(schema, data) {
|
|
828
|
+
let validate;
|
|
829
|
+
try {
|
|
830
|
+
validate = ajv.compile(schema);
|
|
831
|
+
} catch {
|
|
832
|
+
return [];
|
|
833
|
+
}
|
|
834
|
+
if (validate(data)) return [];
|
|
835
|
+
const out = [];
|
|
836
|
+
const seen = /* @__PURE__ */ new Set();
|
|
837
|
+
for (const err of validate.errors ?? []) {
|
|
838
|
+
if (OWNED_BY_VALIDATE_FORM_DATA.has(err.keyword) || WRAPPERS.has(err.keyword))
|
|
839
|
+
continue;
|
|
840
|
+
const pointer = err.instancePath;
|
|
841
|
+
const label = labelForPointer(schema, pointer);
|
|
842
|
+
const message = messageFor(label, err);
|
|
843
|
+
const key = `${pointer}\0${message}`;
|
|
844
|
+
if (seen.has(key)) continue;
|
|
845
|
+
seen.add(key);
|
|
846
|
+
out.push({ pointer, message });
|
|
847
|
+
}
|
|
848
|
+
return out;
|
|
849
|
+
}
|
|
850
|
+
|
|
470
851
|
// src/schema/validateFormData.ts
|
|
471
852
|
function escapePointerToken(token) {
|
|
472
853
|
return token.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
@@ -474,7 +855,7 @@ function escapePointerToken(token) {
|
|
|
474
855
|
function isEmpty(value) {
|
|
475
856
|
return value === void 0 || value === null || value === "";
|
|
476
857
|
}
|
|
477
|
-
function
|
|
858
|
+
function isPlainObject2(value) {
|
|
478
859
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
479
860
|
}
|
|
480
861
|
function childContext(parent, fieldName, property) {
|
|
@@ -507,7 +888,7 @@ function validateArray(property, value, ctx, out) {
|
|
|
507
888
|
const itemProperties = property.items.properties;
|
|
508
889
|
const itemSchema = property.items;
|
|
509
890
|
for (let i = 0; i < value.length; i++) {
|
|
510
|
-
if (
|
|
891
|
+
if (isPlainObject2(value[i])) {
|
|
511
892
|
validateObject(
|
|
512
893
|
itemProperties,
|
|
513
894
|
itemSchema,
|
|
@@ -519,13 +900,18 @@ function validateArray(property, value, ctx, out) {
|
|
|
519
900
|
}
|
|
520
901
|
}
|
|
521
902
|
function isNestedObject(property, value) {
|
|
522
|
-
return property.type === "object" && !!property.properties &&
|
|
903
|
+
return property.type === "object" && !!property.properties && isPlainObject2(value);
|
|
523
904
|
}
|
|
524
905
|
function validateField(property, value, required, ctx, out) {
|
|
525
906
|
if (required && isEmpty(value)) {
|
|
526
907
|
out.push({ pointer: ctx.pointer, message: `${ctx.label} is required` });
|
|
527
908
|
return;
|
|
528
909
|
}
|
|
910
|
+
for (const list of missingLists(property, value))
|
|
911
|
+
out.push({
|
|
912
|
+
pointer: ctx.pointer,
|
|
913
|
+
message: `${ctx.label} needs a code of ${listTitle(list)}`
|
|
914
|
+
});
|
|
529
915
|
if (isNestedObject(property, value)) {
|
|
530
916
|
validateObject(property.properties, property, value, ctx, out);
|
|
531
917
|
return;
|
|
@@ -557,6 +943,11 @@ function validateFormData(schema, data) {
|
|
|
557
943
|
{ label: "", pointer: "" },
|
|
558
944
|
fieldErrors
|
|
559
945
|
);
|
|
946
|
+
const structurallyFlagged = new Set(fieldErrors.map((e) => e.pointer));
|
|
947
|
+
for (const err of validateContentConstraints(schema, data)) {
|
|
948
|
+
if (structurallyFlagged.has(err.pointer)) continue;
|
|
949
|
+
fieldErrors.push(err);
|
|
950
|
+
}
|
|
560
951
|
return {
|
|
561
952
|
errors: fieldErrors.map((e) => e.message),
|
|
562
953
|
fieldErrors,
|
|
@@ -564,6 +955,34 @@ function validateFormData(schema, data) {
|
|
|
564
955
|
};
|
|
565
956
|
}
|
|
566
957
|
|
|
958
|
+
// src/schema/mergeFieldErrors.ts
|
|
959
|
+
function pointerRoot(pointer) {
|
|
960
|
+
const token = pointer.split("/")[1] ?? "";
|
|
961
|
+
return token.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
962
|
+
}
|
|
963
|
+
function mergeFieldErrors(...sources) {
|
|
964
|
+
const out = [];
|
|
965
|
+
const claimedFields = /* @__PURE__ */ new Set();
|
|
966
|
+
const seenFormMessages = /* @__PURE__ */ new Set();
|
|
967
|
+
for (const source of sources) {
|
|
968
|
+
for (const err of source) {
|
|
969
|
+
if (err.pointer === "") {
|
|
970
|
+
if (seenFormMessages.has(err.message)) continue;
|
|
971
|
+
seenFormMessages.add(err.message);
|
|
972
|
+
out.push(err);
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
const root = pointerRoot(err.pointer);
|
|
976
|
+
if (claimedFields.has(root)) continue;
|
|
977
|
+
out.push(err);
|
|
978
|
+
}
|
|
979
|
+
for (const err of source) {
|
|
980
|
+
if (err.pointer !== "") claimedFields.add(pointerRoot(err.pointer));
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return out;
|
|
984
|
+
}
|
|
985
|
+
|
|
567
986
|
// src/schema/diffFormData.ts
|
|
568
987
|
function areBothPlainObjects(a, b) {
|
|
569
988
|
return a !== null && b !== null && typeof a === "object" && typeof b === "object" && !Array.isArray(a) && !Array.isArray(b);
|
|
@@ -708,14 +1127,14 @@ function diffFormData(original, updated) {
|
|
|
708
1127
|
}
|
|
709
1128
|
|
|
710
1129
|
// src/schema/ensureFormItemIds.ts
|
|
711
|
-
function
|
|
1130
|
+
function isPlainObject3(v) {
|
|
712
1131
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
713
1132
|
}
|
|
714
1133
|
function isObjectArray2(property) {
|
|
715
1134
|
return property.type === "array" && !!property.items?.properties;
|
|
716
1135
|
}
|
|
717
1136
|
function stampItem(item, itemSchema) {
|
|
718
|
-
if (!
|
|
1137
|
+
if (!isPlainObject3(item)) return item;
|
|
719
1138
|
const withChildren = stampObject(item, itemSchema.properties ?? {});
|
|
720
1139
|
return FORM_ITEM_ID_FIELD in withChildren ? withChildren : { ...withChildren, [FORM_ITEM_ID_FIELD]: generateId() };
|
|
721
1140
|
}
|
|
@@ -723,7 +1142,7 @@ function stampValue(value, property) {
|
|
|
723
1142
|
if (isObjectArray2(property) && Array.isArray(value)) {
|
|
724
1143
|
return value.map((item) => stampItem(item, property.items));
|
|
725
1144
|
}
|
|
726
|
-
if (property.type === "object" && property.properties &&
|
|
1145
|
+
if (property.type === "object" && property.properties && isPlainObject3(value)) {
|
|
727
1146
|
return stampObject(value, property.properties);
|
|
728
1147
|
}
|
|
729
1148
|
return value;
|
|
@@ -744,10 +1163,43 @@ function stampObject(data, properties) {
|
|
|
744
1163
|
function ensureFormItemIds(data, schema) {
|
|
745
1164
|
return stampObject(data, getSchemaProperties(schema));
|
|
746
1165
|
}
|
|
1166
|
+
function stripFormItemIds(data) {
|
|
1167
|
+
const result = {};
|
|
1168
|
+
for (const [key, value] of Object.entries(data)) {
|
|
1169
|
+
if (key === FORM_ITEM_ID_FIELD) continue;
|
|
1170
|
+
if (Array.isArray(value)) {
|
|
1171
|
+
result[key] = value.map(
|
|
1172
|
+
(item) => isPlainObject3(item) ? stripFormItemIds(item) : item
|
|
1173
|
+
);
|
|
1174
|
+
} else if (isPlainObject3(value)) {
|
|
1175
|
+
result[key] = stripFormItemIds(value);
|
|
1176
|
+
} else {
|
|
1177
|
+
result[key] = value;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
return result;
|
|
1181
|
+
}
|
|
747
1182
|
export {
|
|
1183
|
+
CODEABLE_CONCEPT_TYPE,
|
|
1184
|
+
CODEABLE_CONCEPT_TYPE_ID,
|
|
1185
|
+
CODING_TYPE,
|
|
1186
|
+
CODING_TYPE_ID,
|
|
1187
|
+
CORE_TYPES_BASE,
|
|
1188
|
+
CORE_VALUE_TYPES,
|
|
1189
|
+
QUANTITY_TYPE,
|
|
1190
|
+
QUANTITY_TYPE_ID,
|
|
1191
|
+
UCUM_SYSTEM,
|
|
748
1192
|
WIDTH_TOKEN_REMS,
|
|
749
1193
|
ajv,
|
|
750
1194
|
applySchemaDefaults,
|
|
1195
|
+
bindingLists,
|
|
1196
|
+
bindingOf,
|
|
1197
|
+
codeToken,
|
|
1198
|
+
codingKey,
|
|
1199
|
+
codingsByList,
|
|
1200
|
+
conceptOf,
|
|
1201
|
+
coreType,
|
|
1202
|
+
coreTypeOf,
|
|
751
1203
|
diffFormData,
|
|
752
1204
|
ensureFormItemIds,
|
|
753
1205
|
evaluateUiRule,
|
|
@@ -775,11 +1227,23 @@ export {
|
|
|
775
1227
|
isFieldRequired,
|
|
776
1228
|
isNullableBoolean,
|
|
777
1229
|
isOneOf,
|
|
1230
|
+
liftNullableMember,
|
|
1231
|
+
listTitle,
|
|
778
1232
|
matchesConst,
|
|
1233
|
+
mergeFieldErrors,
|
|
1234
|
+
missingLists,
|
|
1235
|
+
parseCodeToken,
|
|
779
1236
|
resolveRefs,
|
|
780
1237
|
resolveSchema,
|
|
1238
|
+
stripFormItemIds,
|
|
781
1239
|
toJsonSchema,
|
|
1240
|
+
unitRangesKeywords,
|
|
1241
|
+
unitRangesOf,
|
|
1242
|
+
validateContentConstraints,
|
|
782
1243
|
validateFormData,
|
|
783
|
-
validateSchema
|
|
1244
|
+
validateSchema,
|
|
1245
|
+
valueRefKeywords,
|
|
1246
|
+
valueRefOf,
|
|
1247
|
+
valueTypeResolver
|
|
784
1248
|
};
|
|
785
1249
|
//# sourceMappingURL=index.js.map
|