ochre-sdk 1.0.78 → 1.1.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 +31 -3
- package/dist/_virtual/_rolldown/runtime.mjs +13 -0
- package/dist/categories.d.mts +249 -0
- package/dist/categories.mjs +259 -0
- package/dist/constants.d.mts +14 -0
- package/dist/constants.mjs +18 -1
- package/dist/errors.d.mts +23 -0
- package/dist/{utilities.mjs → errors.mjs} +33 -84
- package/dist/fetchers/gallery.mjs +15 -51
- package/dist/fetchers/item-children.mjs +20 -66
- package/dist/fetchers/item-links.mjs +26 -79
- package/dist/fetchers/item-ocr-data.d.mts +2 -2
- package/dist/fetchers/item-ocr-data.mjs +11 -15
- package/dist/fetchers/item.d.mts +0 -15
- package/dist/fetchers/item.mjs +20 -72
- package/dist/fetchers/request.d.mts +70 -0
- package/dist/fetchers/request.mjs +100 -0
- package/dist/fetchers/set/items.mjs +27 -73
- package/dist/fetchers/set/property-values.d.mts +2 -3
- package/dist/fetchers/set/property-values.mjs +96 -130
- package/dist/fetchers/website-metadata.mjs +35 -57
- package/dist/fetchers/website.d.mts +2 -3
- package/dist/fetchers/website.mjs +22 -31
- package/dist/getters.d.mts +78 -148
- package/dist/getters.mjs +127 -208
- package/dist/helpers.d.mts +0 -4
- package/dist/helpers.mjs +19 -6
- package/dist/index.d.mts +8 -6
- package/dist/index.mjs +6 -4
- package/dist/ocr.d.mts +37 -0
- package/dist/ocr.mjs +52 -0
- package/dist/parsers/helpers.d.mts +21 -1
- package/dist/parsers/helpers.mjs +26 -6
- package/dist/parsers/index.d.mts +0 -8
- package/dist/parsers/index.mjs +118 -259
- package/dist/parsers/languages.d.mts +72 -0
- package/dist/parsers/languages.mjs +132 -0
- package/dist/parsers/multilingual.d.mts +49 -74
- package/dist/parsers/multilingual.mjs +88 -189
- package/dist/parsers/property-token.d.mts +34 -0
- package/dist/parsers/property-token.mjs +29 -0
- package/dist/parsers/string.d.mts +19 -0
- package/dist/parsers/string.mjs +45 -25
- package/dist/parsers/website/bounds.d.mts +10 -0
- package/dist/parsers/website/bounds.mjs +28 -0
- package/dist/parsers/website/components.d.mts +91 -0
- package/dist/parsers/website/components.mjs +681 -0
- package/dist/parsers/website/index.d.mts +0 -7
- package/dist/parsers/website/index.mjs +92 -1153
- package/dist/parsers/website/links.d.mts +36 -0
- package/dist/parsers/website/links.mjs +58 -0
- package/dist/parsers/website/messages.d.mts +24 -0
- package/dist/parsers/website/messages.mjs +31 -0
- package/dist/parsers/website/options.d.mts +6 -0
- package/dist/parsers/website/options.mjs +114 -0
- package/dist/parsers/website/properties.d.mts +12 -0
- package/dist/parsers/website/properties.mjs +158 -0
- package/dist/parsers/website/reader.d.mts +54 -4
- package/dist/parsers/website/reader.mjs +65 -20
- package/dist/parsers/website/slug.d.mts +64 -0
- package/dist/parsers/website/slug.mjs +82 -0
- package/dist/parsers/website/styles.d.mts +28 -0
- package/dist/parsers/website/styles.mjs +103 -0
- package/dist/parsers/website/walk.d.mts +68 -0
- package/dist/parsers/website/walk.mjs +116 -0
- package/dist/query.d.mts +66 -18
- package/dist/query.mjs +202 -48
- package/dist/reflection.d.mts +64 -0
- package/dist/reflection.mjs +79 -0
- package/dist/schemas.d.mts +7 -0
- package/dist/schemas.mjs +12 -3
- package/dist/types/index.d.mts +1 -31
- package/dist/types/utilities.d.mts +9 -0
- package/dist/types/utilities.mjs +1 -0
- package/dist/types/website.d.mts +49 -58
- package/dist/xml/metadata.d.mts +16 -0
- package/dist/xml/metadata.mjs +32 -11
- package/dist/xml/schemas.d.mts +5970 -3
- package/dist/xml/schemas.mjs +43 -45
- package/dist/xml/types.d.mts +13 -30
- package/dist/xquery.d.mts +46 -0
- package/dist/xquery.mjs +66 -0
- package/package.json +3 -3
- package/dist/utilities.d.mts +0 -54
package/dist/query.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BELONGS_TO_COLLECTION_UUID } from "./constants.mjs";
|
|
2
|
+
import { compileOchreQuery, stringLiteral } from "./xquery.mjs";
|
|
3
|
+
import { OCR_WORD_CONTENT_ATTRIBUTE, OCR_WORD_QNAMES, buildOcrWordPath } from "./ocr.mjs";
|
|
2
4
|
//#region src/query.ts
|
|
3
5
|
const CTS_INCLUDES_STOP_WORDS = /* @__PURE__ */ new Set([
|
|
4
6
|
"and",
|
|
@@ -40,6 +42,19 @@ const CONTENT_TARGET_CONTENT_ELEMENT_PATHS = {
|
|
|
40
42
|
"content"
|
|
41
43
|
]
|
|
42
44
|
};
|
|
45
|
+
const HELPER_SEARCH_VALUE_REFERENCE = "$value";
|
|
46
|
+
function searchValue(text) {
|
|
47
|
+
return {
|
|
48
|
+
text,
|
|
49
|
+
expression: stringLiteral(text)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function referencedSearchValue(text) {
|
|
53
|
+
return {
|
|
54
|
+
text,
|
|
55
|
+
expression: HELPER_SEARCH_VALUE_REFERENCE
|
|
56
|
+
};
|
|
57
|
+
}
|
|
43
58
|
function tokenizeIncludesSearchValue(parameters) {
|
|
44
59
|
const { value, isCaseSensitive } = parameters;
|
|
45
60
|
const rawTerms = (isCaseSensitive ? value : value.toLowerCase()).match(CTS_INCLUDES_TOKEN_REGEX) ?? [];
|
|
@@ -116,9 +131,9 @@ function buildRichTextPhraseOptionsExpression(parameters) {
|
|
|
116
131
|
}
|
|
117
132
|
function buildCtsWordQueryExpression(parameters) {
|
|
118
133
|
const { value, matchMode, isCaseSensitive, queryFamily, language } = parameters;
|
|
119
|
-
const isWildcarded = matchMode === "includes" && hasWildcardCharacters(value);
|
|
120
|
-
const isStemmed = matchMode === "includes" && queryFamily === "text" && !isWildcarded && shouldUseStemmedTextSearch(value);
|
|
121
|
-
return `cts:word-query(${
|
|
134
|
+
const isWildcarded = matchMode === "includes" && hasWildcardCharacters(value.text);
|
|
135
|
+
const isStemmed = matchMode === "includes" && queryFamily === "text" && !isWildcarded && shouldUseStemmedTextSearch(value.text);
|
|
136
|
+
return `cts:word-query(${value.expression}, ${buildWordQueryOptionsExpression({
|
|
122
137
|
matchMode,
|
|
123
138
|
isCaseSensitive,
|
|
124
139
|
queryFamily,
|
|
@@ -129,7 +144,7 @@ function buildCtsWordQueryExpression(parameters) {
|
|
|
129
144
|
}
|
|
130
145
|
function buildRichTextPhraseQueryExpression(parameters) {
|
|
131
146
|
const { value, isCaseSensitive } = parameters;
|
|
132
|
-
return `cts:word-query(${
|
|
147
|
+
return `cts:word-query(${value.expression}, ${buildRichTextPhraseOptionsExpression({ isCaseSensitive })})`;
|
|
133
148
|
}
|
|
134
149
|
function buildRichTextExactQueryExpression(parameters) {
|
|
135
150
|
const { value, isCaseSensitive } = parameters;
|
|
@@ -138,20 +153,20 @@ function buildRichTextExactQueryExpression(parameters) {
|
|
|
138
153
|
isCaseSensitive
|
|
139
154
|
});
|
|
140
155
|
const terms = tokenizeExactTextSearchValue({
|
|
141
|
-
value,
|
|
156
|
+
value: value.text,
|
|
142
157
|
isCaseSensitive
|
|
143
158
|
});
|
|
144
159
|
if (terms.length <= 1) return phraseQuery;
|
|
145
160
|
return buildOrCtsQueryExpressionInternal([phraseQuery, buildAndCtsQueryExpressionInternal(terms.map((term) => buildRichTextPhraseQueryExpression({
|
|
146
|
-
value: term,
|
|
161
|
+
value: searchValue(term),
|
|
147
162
|
isCaseSensitive
|
|
148
163
|
})))]);
|
|
149
164
|
}
|
|
150
165
|
function buildCtsElementWordQueryExpression(parameters) {
|
|
151
166
|
const { elementName, value, matchMode, isCaseSensitive, queryFamily, language } = parameters;
|
|
152
|
-
const isWildcarded = matchMode === "includes" && hasWildcardCharacters(value);
|
|
153
|
-
const isStemmed = matchMode === "includes" && queryFamily === "text" && !isWildcarded && shouldUseStemmedTextSearch(value);
|
|
154
|
-
return `cts:element-word-query(xs:QName("${elementName}"), ${
|
|
167
|
+
const isWildcarded = matchMode === "includes" && hasWildcardCharacters(value.text);
|
|
168
|
+
const isStemmed = matchMode === "includes" && queryFamily === "text" && !isWildcarded && shouldUseStemmedTextSearch(value.text);
|
|
169
|
+
return `cts:element-word-query(xs:QName("${elementName}"), ${value.expression}, ${buildWordQueryOptionsExpression({
|
|
155
170
|
matchMode,
|
|
156
171
|
isCaseSensitive,
|
|
157
172
|
queryFamily,
|
|
@@ -162,9 +177,9 @@ function buildCtsElementWordQueryExpression(parameters) {
|
|
|
162
177
|
}
|
|
163
178
|
function buildCtsElementAttributeWordQueryExpression(parameters) {
|
|
164
179
|
const { elementName, attributeName, value, matchMode, isCaseSensitive, queryFamily, language } = parameters;
|
|
165
|
-
const isWildcarded = matchMode === "includes" && hasWildcardCharacters(value);
|
|
166
|
-
const isStemmed = matchMode === "includes" && queryFamily === "text" && !isWildcarded && shouldUseStemmedTextSearch(value);
|
|
167
|
-
return `cts:element-attribute-word-query(xs:QName("${elementName}"), xs:QName("${attributeName}"), ${
|
|
180
|
+
const isWildcarded = matchMode === "includes" && hasWildcardCharacters(value.text);
|
|
181
|
+
const isStemmed = matchMode === "includes" && queryFamily === "text" && !isWildcarded && shouldUseStemmedTextSearch(value.text);
|
|
182
|
+
return `cts:element-attribute-word-query(xs:QName("${elementName}"), xs:QName("${attributeName}"), ${value.expression}, ${buildWordQueryOptionsExpression({
|
|
168
183
|
matchMode,
|
|
169
184
|
isCaseSensitive,
|
|
170
185
|
queryFamily,
|
|
@@ -175,21 +190,21 @@ function buildCtsElementAttributeWordQueryExpression(parameters) {
|
|
|
175
190
|
}
|
|
176
191
|
function buildCtsElementValueQueryExpression(parameters) {
|
|
177
192
|
const { elementName, value, isCaseSensitive } = parameters;
|
|
178
|
-
return `cts:element-value-query(xs:QName("${elementName}"), ${
|
|
193
|
+
return `cts:element-value-query(xs:QName("${elementName}"), ${value.expression}, ${buildWordQueryOptionsExpression({
|
|
179
194
|
matchMode: "exact",
|
|
180
195
|
isCaseSensitive
|
|
181
196
|
})})`;
|
|
182
197
|
}
|
|
183
198
|
function buildCtsElementAttributeValueQueryExpression(parameters) {
|
|
184
199
|
const { elementName, attributeName, value, isCaseSensitive } = parameters;
|
|
185
|
-
return `cts:element-attribute-value-query(xs:QName("${elementName}"), xs:QName("${attributeName}"), ${
|
|
200
|
+
return `cts:element-attribute-value-query(xs:QName("${elementName}"), xs:QName("${attributeName}"), ${value.expression}, ${buildWordQueryOptionsExpression({
|
|
186
201
|
matchMode: "exact",
|
|
187
202
|
isCaseSensitive
|
|
188
203
|
})})`;
|
|
189
204
|
}
|
|
190
205
|
function buildPlainElementAttributeValueQueryExpression(parameters) {
|
|
191
206
|
const { elementName, attributeName, value } = parameters;
|
|
192
|
-
return `cts:element-attribute-value-query(xs:QName("${elementName}"), xs:QName("${attributeName}"), ${
|
|
207
|
+
return `cts:element-attribute-value-query(xs:QName("${elementName}"), xs:QName("${attributeName}"), ${value.expression})`;
|
|
193
208
|
}
|
|
194
209
|
function buildNestedElementQuery(elementNames, queryExpression) {
|
|
195
210
|
let wrappedQueryExpression = queryExpression;
|
|
@@ -217,21 +232,21 @@ function buildContentLanguageQuery(language) {
|
|
|
217
232
|
return buildPlainElementAttributeValueQueryExpression({
|
|
218
233
|
elementName: "content",
|
|
219
234
|
attributeName: "xml:lang",
|
|
220
|
-
value: language
|
|
235
|
+
value: searchValue(language)
|
|
221
236
|
});
|
|
222
237
|
}
|
|
223
238
|
function buildPropertyLabelQuery(propertyVariable) {
|
|
224
239
|
return buildPlainElementAttributeValueQueryExpression({
|
|
225
240
|
elementName: "label",
|
|
226
241
|
attributeName: "uuid",
|
|
227
|
-
value: propertyVariable
|
|
242
|
+
value: searchValue(propertyVariable)
|
|
228
243
|
});
|
|
229
244
|
}
|
|
230
245
|
function buildValueNotIdReferenceQuery() {
|
|
231
246
|
return buildNotCtsQueryExpression(buildPlainElementAttributeValueQueryExpression({
|
|
232
247
|
elementName: "value",
|
|
233
248
|
attributeName: "dataType",
|
|
234
|
-
value: "IDREF"
|
|
249
|
+
value: searchValue("IDREF")
|
|
235
250
|
}));
|
|
236
251
|
}
|
|
237
252
|
function buildRichTextContentQueryExpression(parameters) {
|
|
@@ -327,7 +342,7 @@ function buildPropertyQueryExpression(parameters) {
|
|
|
327
342
|
if (propertyRelation != null) propertyQueryExpressions.unshift(buildPlainElementAttributeValueQueryExpression({
|
|
328
343
|
elementName: "label",
|
|
329
344
|
attributeName: "relation",
|
|
330
|
-
value: propertyRelation
|
|
345
|
+
value: searchValue(propertyRelation)
|
|
331
346
|
}));
|
|
332
347
|
return buildNestedElementQuery(["properties", "property"], buildAndCtsQueryExpressionInternal(propertyQueryExpressions));
|
|
333
348
|
}
|
|
@@ -354,7 +369,7 @@ function buildPropertyTextMatchQueryExpression(parameters) {
|
|
|
354
369
|
if (propertyRelation != null) propertyQueryExpressions.push(buildPlainElementAttributeValueQueryExpression({
|
|
355
370
|
elementName: "label",
|
|
356
371
|
attributeName: "relation",
|
|
357
|
-
value: propertyRelation
|
|
372
|
+
value: searchValue(propertyRelation)
|
|
358
373
|
}));
|
|
359
374
|
propertyQueryExpressions.push(buildNestedElementQuery(["value"], buildAndCtsQueryExpressionInternal(valueQueryExpressions)));
|
|
360
375
|
const propertyQueryExpression = buildNestedElementQuery(["properties", "property"], buildAndCtsQueryExpressionInternal(propertyQueryExpressions));
|
|
@@ -472,7 +487,6 @@ function buildItemStringQueryExpression(parameters) {
|
|
|
472
487
|
language
|
|
473
488
|
})]);
|
|
474
489
|
}
|
|
475
|
-
const OCR_STRING_QNAMES = `(xs:QName("String"), fn:QName("http://www.loc.gov/standards/alto/ns-v2#", "string"))`;
|
|
476
490
|
function tokenizeOcrExactValue(value) {
|
|
477
491
|
const terms = [];
|
|
478
492
|
for (const term of value.split(/\s+/u)) if (term !== "") terms.push(term);
|
|
@@ -492,12 +506,12 @@ function buildOcrWordQueryExpression(parameters) {
|
|
|
492
506
|
"punctuation-insensitive",
|
|
493
507
|
"whitespace-insensitive"
|
|
494
508
|
];
|
|
495
|
-
if (hasWildcardCharacters(value)) options.push("wildcarded");
|
|
496
|
-
return `cts:element-attribute-word-query(${
|
|
509
|
+
if (hasWildcardCharacters(value.text)) options.push("wildcarded");
|
|
510
|
+
return `cts:element-attribute-word-query(${OCR_WORD_QNAMES}, xs:QName(${stringLiteral(OCR_WORD_CONTENT_ATTRIBUTE)}), ${value.expression}, (${options.map((option) => stringLiteral(option)).join(", ")}))`;
|
|
497
511
|
}
|
|
498
512
|
function buildOcrValueQueryExpression(parameters) {
|
|
499
513
|
const { value, isCaseSensitive } = parameters;
|
|
500
|
-
return `cts:element-attribute-value-query(${
|
|
514
|
+
return `cts:element-attribute-value-query(${OCR_WORD_QNAMES}, xs:QName(${stringLiteral(OCR_WORD_CONTENT_ATTRIBUTE)}), ${value.expression}, ${buildWordQueryOptionsExpression({
|
|
501
515
|
matchMode: "exact",
|
|
502
516
|
isCaseSensitive
|
|
503
517
|
})})`;
|
|
@@ -523,7 +537,7 @@ function buildOcrQueryExpression(query) {
|
|
|
523
537
|
const terms = tokenizeOcrExactValue(value);
|
|
524
538
|
if (terms.length === 0) return "cts:false-query()";
|
|
525
539
|
return buildNestedElementQuery(["ocr"], buildAndCtsQueryExpressionInternal(Array.from(terms, (term) => buildOcrValueQueryExpression({
|
|
526
|
-
value: term,
|
|
540
|
+
value: searchValue(term),
|
|
527
541
|
isCaseSensitive
|
|
528
542
|
}))));
|
|
529
543
|
}
|
|
@@ -533,7 +547,7 @@ function buildOcrQueryExpression(query) {
|
|
|
533
547
|
});
|
|
534
548
|
if (terms.length === 0) return "cts:false-query()";
|
|
535
549
|
return buildNestedElementQuery(["ocr"], buildAndCtsQueryExpressionInternal(Array.from(terms, (term) => buildOcrWordQueryExpression({
|
|
536
|
-
value: term,
|
|
550
|
+
value: searchValue(term),
|
|
537
551
|
isCaseSensitive
|
|
538
552
|
}))));
|
|
539
553
|
}
|
|
@@ -547,8 +561,8 @@ function registerOcrPhraseHelper(context) {
|
|
|
547
561
|
context.helperNamesByKey.set(helperName, helperName);
|
|
548
562
|
context.helperDeclarations.push(`declare function ${helperName}($resource as node(), $terms as xs:string*, $isCaseSensitive as xs:boolean) as xs:boolean {
|
|
549
563
|
let $contents :=
|
|
550
|
-
for $word in $
|
|
551
|
-
return if ($isCaseSensitive) then string($word
|
|
564
|
+
for $word in ${buildOcrWordPath("$resource")}
|
|
565
|
+
return if ($isCaseSensitive) then string($word/@${OCR_WORD_CONTENT_ATTRIBUTE}) else lower-case(string($word/@${OCR_WORD_CONTENT_ATTRIBUTE}))
|
|
552
566
|
let $needles :=
|
|
553
567
|
for $term in $terms
|
|
554
568
|
return if ($isCaseSensitive) then $term else lower-case($term)
|
|
@@ -578,7 +592,7 @@ function registerOcrBinding(context, query) {
|
|
|
578
592
|
const queryExpression = buildOcrQueryExpression(query);
|
|
579
593
|
const phraseTerms = query.matchMode === "exact" ? tokenizeOcrExactValue(query.value) : [];
|
|
580
594
|
context.ocrBindingNamesByKey.set(key, name);
|
|
581
|
-
const searchExpression = `cts:search(/ochre/resource, ${queryExpression})`;
|
|
595
|
+
const searchExpression = `cts:search(/ochre/resource, ${buildAndCtsQueryExpressionInternal([queryExpression, `cts:document-query(${context.baseItemsExpression}/@uuid/string())`])})`;
|
|
582
596
|
const phraseHelperName = phraseTerms.length > 1 ? registerOcrPhraseHelper(context) : null;
|
|
583
597
|
context.ocrBindings.push({
|
|
584
598
|
name,
|
|
@@ -664,13 +678,14 @@ function indentBlock(value, spaces) {
|
|
|
664
678
|
const prefix = " ".repeat(spaces);
|
|
665
679
|
return value.split("\n").map((line) => line === "" ? line : `${prefix}${line}`).join("\n");
|
|
666
680
|
}
|
|
667
|
-
function createQueryCompilerContext() {
|
|
681
|
+
function createQueryCompilerContext(baseItemsExpression) {
|
|
668
682
|
return {
|
|
669
683
|
nextHelperSerial: 1,
|
|
670
684
|
helperNamesByKey: /* @__PURE__ */ new Map(),
|
|
671
685
|
helperDeclarations: [],
|
|
672
686
|
ocrBindingNamesByKey: /* @__PURE__ */ new Map(),
|
|
673
|
-
ocrBindings: []
|
|
687
|
+
ocrBindings: [],
|
|
688
|
+
baseItemsExpression
|
|
674
689
|
};
|
|
675
690
|
}
|
|
676
691
|
function registerConstantHelper(parameters) {
|
|
@@ -689,9 +704,6 @@ function registerConstantHelper(parameters) {
|
|
|
689
704
|
callExpression: `${helperName}()`
|
|
690
705
|
};
|
|
691
706
|
}
|
|
692
|
-
function replaceSampleValueLiteral(expression, sampleValue, valueReference) {
|
|
693
|
-
return expression.replaceAll(stringLiteral(sampleValue), () => valueReference);
|
|
694
|
-
}
|
|
695
707
|
function registerParameterizedHelper(parameters) {
|
|
696
708
|
const { context, key, bodyExpression } = parameters;
|
|
697
709
|
const existingName = context.helperNamesByKey.get(key);
|
|
@@ -749,7 +761,7 @@ function registerLeafHelper(parameters) {
|
|
|
749
761
|
}),
|
|
750
762
|
bodyExpression: buildLeafValueQueryExpression({
|
|
751
763
|
query,
|
|
752
|
-
value,
|
|
764
|
+
value: searchValue(value),
|
|
753
765
|
matchMode
|
|
754
766
|
})
|
|
755
767
|
});
|
|
@@ -794,11 +806,11 @@ function registerIncludesLeafHelper(parameters) {
|
|
|
794
806
|
query,
|
|
795
807
|
value: sampleValue
|
|
796
808
|
}),
|
|
797
|
-
bodyExpression:
|
|
809
|
+
bodyExpression: buildLeafValueQueryExpression({
|
|
798
810
|
query,
|
|
799
|
-
value: sampleValue,
|
|
811
|
+
value: referencedSearchValue(sampleValue),
|
|
800
812
|
matchMode: "includes"
|
|
801
|
-
})
|
|
813
|
+
})
|
|
802
814
|
});
|
|
803
815
|
}
|
|
804
816
|
function buildLeafQueryExpression(context, query) {
|
|
@@ -940,6 +952,23 @@ function buildCtsItemsPlan(queryExpression) {
|
|
|
940
952
|
};
|
|
941
953
|
}
|
|
942
954
|
/**
|
|
955
|
+
* Plan a negated leaf as an item path predicate
|
|
956
|
+
*
|
|
957
|
+
* A Set holds every one of its items in one fragment, and CTS resolves
|
|
958
|
+
* `cts:not-query` from the fragment indexes without filtering the match down to
|
|
959
|
+
* the node it came from. Negating inside the search query would therefore drop
|
|
960
|
+
* every item of a Set as soon as one of them matched, and keep every item of a
|
|
961
|
+
* Set that held no match at all. `cts:contains` evaluates the leaf against one
|
|
962
|
+
* item projection instead, which is the scope the negation is asking about.
|
|
963
|
+
*/
|
|
964
|
+
function buildNegatedItemsPlan(queryExpression) {
|
|
965
|
+
return {
|
|
966
|
+
kind: "search",
|
|
967
|
+
itemPredicates: [`[not(cts:contains(., ${queryExpression}))]`],
|
|
968
|
+
queryExpressions: []
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
943
972
|
* Splice the children of same-kind child plans into their parent, so that a
|
|
944
973
|
* nested group of the same operator does not cost an extra search
|
|
945
974
|
*/
|
|
@@ -1021,7 +1050,7 @@ function buildItemsPlan(context, query) {
|
|
|
1021
1050
|
};
|
|
1022
1051
|
}
|
|
1023
1052
|
const queryExpression = buildLeafQueryExpression(context, query);
|
|
1024
|
-
return
|
|
1053
|
+
return query.isNegated === true ? buildNegatedItemsPlan(queryExpression) : buildCtsItemsPlan(queryExpression);
|
|
1025
1054
|
}
|
|
1026
1055
|
const optimizedIncludesGroupQueries = getCompatibleIncludesGroupLeaves(query);
|
|
1027
1056
|
if (optimizedIncludesGroupQueries != null) return buildCtsItemsPlan(buildIncludesGroupQueryExpression(context, optimizedIncludesGroupQueries));
|
|
@@ -1055,7 +1084,7 @@ function buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids,
|
|
|
1055
1084
|
queryExpression: buildNestedElementQuery(["value"], buildOrCtsQueryExpressionInternal(Array.from(belongsToCollectionScopeUuids, (uuid) => buildPlainElementAttributeValueQueryExpression({
|
|
1056
1085
|
elementName: "value",
|
|
1057
1086
|
attributeName: "uuid",
|
|
1058
|
-
value: uuid
|
|
1087
|
+
value: searchValue(uuid)
|
|
1059
1088
|
}))))
|
|
1060
1089
|
});
|
|
1061
1090
|
}
|
|
@@ -1066,9 +1095,12 @@ function buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids,
|
|
|
1066
1095
|
* Most queries compile to a single `cts:search` over the Set item projections.
|
|
1067
1096
|
* An `ocr` leaf cannot: the projections drop the `<ocr>` layer, so it resolves
|
|
1068
1097
|
* to a search over the Resource documents whose matching UUIDs are joined back
|
|
1069
|
-
* in as an item path predicate.
|
|
1070
|
-
*
|
|
1071
|
-
*
|
|
1098
|
+
* in as an item path predicate. A negated leaf cannot either, because CTS
|
|
1099
|
+
* answers a negation for the whole fragment rather than for the item that
|
|
1100
|
+
* matched, so it is filtered per item instead. Path predicates only ever AND,
|
|
1101
|
+
* so such a leaf that sits under an `or` becomes its own arm of a node union
|
|
1102
|
+
* instead, and one that sits under an `and` alongside a union becomes an
|
|
1103
|
+
* intersection.
|
|
1072
1104
|
*
|
|
1073
1105
|
* The searchable path has to stay inline in `cts:search`: binding it to a
|
|
1074
1106
|
* variable first makes every query XDMP-UNSEARCHABLE.
|
|
@@ -1078,9 +1110,34 @@ function buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids,
|
|
|
1078
1110
|
* @param parameters.scopeQueryExpression - An optional CTS query ANDed into every compiled search
|
|
1079
1111
|
* @returns The prolog declaring the query helpers, and the `let` clauses binding `$items`
|
|
1080
1112
|
*/
|
|
1113
|
+
const ITEMS_VARIABLE = "$items";
|
|
1114
|
+
const SET_SCOPE_VARIABLE = "$setScopeUuids";
|
|
1115
|
+
/**
|
|
1116
|
+
* The XQuery path a Set item search runs over
|
|
1117
|
+
*
|
|
1118
|
+
* The path has to stay inline in `cts:search`: binding it to a variable first
|
|
1119
|
+
* materializes the sequence and makes every query `XDMP-UNSEARCHABLE`, even a
|
|
1120
|
+
* plain word query. It references {@link SET_SCOPE_VARIABLE}, which
|
|
1121
|
+
* {@link compileSetItemsQuery} declares.
|
|
1122
|
+
*/
|
|
1123
|
+
const SET_ITEMS_EXPRESSION = `doc()/ochre/set[@uuid = ${SET_SCOPE_VARIABLE}]/items/*`;
|
|
1124
|
+
/**
|
|
1125
|
+
* Compile a query tree into the clauses that bind the matching Set items
|
|
1126
|
+
*
|
|
1127
|
+
* The returned `itemsClause` binds {@link ITEMS_VARIABLE} and has to be placed
|
|
1128
|
+
* inside an XQuery body, with `prolog` declared ahead of it.
|
|
1129
|
+
* {@link compileSetItemsQuery} does both and is what fetchers should use;
|
|
1130
|
+
* this is exposed for tests that assert on the compiled CTS.
|
|
1131
|
+
* @param parameters - The plan parameters
|
|
1132
|
+
* @param parameters.queries - The query tree to compile, or null to match every item
|
|
1133
|
+
* @param parameters.baseItemsExpression - The inline searchable path to filter
|
|
1134
|
+
* @param parameters.scopeQueryExpression - An extra query AND-ed into every search
|
|
1135
|
+
* @returns The prolog, the clauses binding the items, and the bound CTS queries
|
|
1136
|
+
* @internal
|
|
1137
|
+
*/
|
|
1081
1138
|
function buildQueryPlan(parameters) {
|
|
1082
1139
|
const { queries, baseItemsExpression, scopeQueryExpression } = parameters;
|
|
1083
|
-
const context = createQueryCompilerContext();
|
|
1140
|
+
const context = createQueryCompilerContext(baseItemsExpression);
|
|
1084
1141
|
const plan = queries == null ? {
|
|
1085
1142
|
kind: "search",
|
|
1086
1143
|
itemPredicates: [],
|
|
@@ -1097,21 +1154,118 @@ function buildQueryPlan(parameters) {
|
|
|
1097
1154
|
});
|
|
1098
1155
|
}
|
|
1099
1156
|
const queryNamesByPlan = /* @__PURE__ */ new Map();
|
|
1157
|
+
const queryBindings = [];
|
|
1100
1158
|
const letClauses = Array.from(context.ocrBindings, (binding) => `let ${binding.name} := ${binding.expression}`);
|
|
1101
1159
|
for (const [index, boundSearchPlan] of boundSearchPlans.entries()) {
|
|
1102
1160
|
const queryName = boundSearchPlans.length === 1 ? "$query" : `$query${index + 1}`;
|
|
1103
1161
|
queryNamesByPlan.set(boundSearchPlan.plan, queryName);
|
|
1162
|
+
queryBindings.push({
|
|
1163
|
+
name: queryName,
|
|
1164
|
+
expression: boundSearchPlan.queryExpression
|
|
1165
|
+
});
|
|
1104
1166
|
letClauses.push(`let ${queryName} := ${boundSearchPlan.queryExpression}`);
|
|
1105
1167
|
}
|
|
1106
|
-
letClauses.push(`let $
|
|
1168
|
+
letClauses.push(`let ${ITEMS_VARIABLE} := ${buildItemsPlanExpression({
|
|
1107
1169
|
plan,
|
|
1108
1170
|
baseItemsExpression,
|
|
1109
1171
|
queryNamesByPlan
|
|
1110
1172
|
})}`);
|
|
1111
1173
|
return {
|
|
1112
1174
|
prolog: context.helperDeclarations.join("\n\n"),
|
|
1113
|
-
itemsClause: letClauses.join("\n ")
|
|
1175
|
+
itemsClause: letClauses.join("\n "),
|
|
1176
|
+
itemsVariable: ITEMS_VARIABLE,
|
|
1177
|
+
queryBindings
|
|
1114
1178
|
};
|
|
1115
1179
|
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Compile a Set item query into a complete XQuery document
|
|
1182
|
+
*
|
|
1183
|
+
* Owns everything a caller would otherwise have to know and restate: the
|
|
1184
|
+
* version declaration, the Set scope variable, the supplemental-stripping
|
|
1185
|
+
* prolog, the inline searchable path, where the compiled helper prolog goes and
|
|
1186
|
+
* that it is only declared when non-empty, the `<ochre>` wrapper, and the name
|
|
1187
|
+
* of the variable holding the matching items. The body receives that name.
|
|
1188
|
+
* @param parameters - The query parameters
|
|
1189
|
+
* @param parameters.setScopeUuids - The Set scope UUIDs to search within
|
|
1190
|
+
* @param parameters.belongsToCollectionScopeUuids - Collection scope UUIDs to narrow to
|
|
1191
|
+
* @param parameters.queries - The query tree to compile, or null to match every item
|
|
1192
|
+
* @param parameters.declarations - Extra prolog declarations, placed before the compiled prolog
|
|
1193
|
+
* @param parameters.body - Builds the body from the name of the variable holding the items
|
|
1194
|
+
* @returns A complete XQuery document
|
|
1195
|
+
* @internal
|
|
1196
|
+
*/
|
|
1197
|
+
function compileSetItemsQuery(parameters) {
|
|
1198
|
+
const { setScopeUuids, belongsToCollectionScopeUuids, queries, declarations = [], body } = parameters;
|
|
1199
|
+
const plan = buildQueryPlan({
|
|
1200
|
+
queries,
|
|
1201
|
+
baseItemsExpression: SET_ITEMS_EXPRESSION,
|
|
1202
|
+
scopeQueryExpression: buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids, BELONGS_TO_COLLECTION_UUID)
|
|
1203
|
+
});
|
|
1204
|
+
return compileOchreQuery({
|
|
1205
|
+
declarations: [
|
|
1206
|
+
...declarations,
|
|
1207
|
+
`declare variable ${SET_SCOPE_VARIABLE} := (${Array.from(setScopeUuids, (uuid) => stringLiteral(uuid)).join(", ")});`,
|
|
1208
|
+
...plan.prolog === "" ? [] : [plan.prolog]
|
|
1209
|
+
],
|
|
1210
|
+
body: (context) => `<ochre>{
|
|
1211
|
+
${plan.itemsClause}
|
|
1212
|
+
${body({
|
|
1213
|
+
...context,
|
|
1214
|
+
items: plan.itemsVariable
|
|
1215
|
+
})}
|
|
1216
|
+
}</ochre>`
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Reduce a property-value facet query tree to the leaves that filter items
|
|
1221
|
+
*
|
|
1222
|
+
* A facet request carries property leaves that name a variable without naming
|
|
1223
|
+
* a value, which select what to aggregate rather than which items to keep.
|
|
1224
|
+
* Those are dropped, and groups left with a single child collapse into it.
|
|
1225
|
+
* @param queries - The query tree to reduce
|
|
1226
|
+
* @returns The reduced tree, or null when nothing filters items
|
|
1227
|
+
* @internal
|
|
1228
|
+
*/
|
|
1229
|
+
function getItemFilterQueries(queries) {
|
|
1230
|
+
if (queries == null) return null;
|
|
1231
|
+
if (isQueryLeaf(queries)) {
|
|
1232
|
+
if (queries.target !== "property" || queries.dataType === "date" || queries.dataType === "dateTime") return queries;
|
|
1233
|
+
return "value" in queries && queries.value != null ? queries : null;
|
|
1234
|
+
}
|
|
1235
|
+
const filteredChildren = [];
|
|
1236
|
+
for (const childQuery of getQueryGroupChildren(queries)) {
|
|
1237
|
+
const filteredChildQuery = getItemFilterQueries(childQuery);
|
|
1238
|
+
if (filteredChildQuery != null) filteredChildren.push(filteredChildQuery);
|
|
1239
|
+
}
|
|
1240
|
+
if (filteredChildren.length <= 1) return filteredChildren[0] ?? null;
|
|
1241
|
+
return getQueryGroupOperator(queries) === "and" ? { and: filteredChildren } : { or: filteredChildren };
|
|
1242
|
+
}
|
|
1243
|
+
/**
|
|
1244
|
+
* Collect the property variables a query tree asks to be aggregated
|
|
1245
|
+
* @param queries - The query tree to walk
|
|
1246
|
+
* @returns One selector per distinct property variable and relation pair
|
|
1247
|
+
* @internal
|
|
1248
|
+
*/
|
|
1249
|
+
function getPropertyFacetSelectors(queries) {
|
|
1250
|
+
if (queries == null) return [];
|
|
1251
|
+
const selectors = /* @__PURE__ */ new Map();
|
|
1252
|
+
const pendingQueries = [queries];
|
|
1253
|
+
while (pendingQueries.length > 0) {
|
|
1254
|
+
const query = pendingQueries.shift();
|
|
1255
|
+
if (query == null) continue;
|
|
1256
|
+
if (isQueryLeaf(query)) {
|
|
1257
|
+
if (query.target === "property" && query.propertyVariable != null) {
|
|
1258
|
+
const relation = query.propertyRelation ?? null;
|
|
1259
|
+
selectors.set(`${query.propertyVariable}|${relation}`, {
|
|
1260
|
+
uuid: query.propertyVariable,
|
|
1261
|
+
relation
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
continue;
|
|
1265
|
+
}
|
|
1266
|
+
pendingQueries.push(...getQueryGroupChildren(query));
|
|
1267
|
+
}
|
|
1268
|
+
return selectors.values().toArray();
|
|
1269
|
+
}
|
|
1116
1270
|
//#endregion
|
|
1117
|
-
export { buildBelongsToCollectionQueryExpression, buildQueryPlan };
|
|
1271
|
+
export { buildBelongsToCollectionQueryExpression, buildQueryPlan, compileSetItemsQuery, getItemFilterQueries, getPropertyFacetSelectors };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//#region src/reflection.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Reading values whose shape is not known at compile time
|
|
4
|
+
*
|
|
5
|
+
* The SDK used to do this with five copies of a
|
|
6
|
+
* `value is Record<string, unknown>` predicate over
|
|
7
|
+
* `typeof value === "object" && value != null`. That predicate lies three ways:
|
|
8
|
+
* it is true for arrays, `Date`, `Map` and every other object; it claims a
|
|
9
|
+
* string index signature the value does not have, so every read produces
|
|
10
|
+
* `unknown` and callers add a second cast to get anything out of it; and being
|
|
11
|
+
* an `&&` of unrelated checks, its `false` branch does not mean "not a record",
|
|
12
|
+
* which is what a type predicate promises.
|
|
13
|
+
*
|
|
14
|
+
* These take `unknown` and hand back `unknown`. They assert nothing they have
|
|
15
|
+
* not checked, so the one unavoidable cast at the boundary lives here instead
|
|
16
|
+
* of being repeated at every call site. Where the shape *is* known, validate it
|
|
17
|
+
* with a valibot schema and `v.is` rather than reaching for these.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Whether a value is a non-null object
|
|
21
|
+
*
|
|
22
|
+
* Narrows to `object`, which is honest: arrays, `Date` and class instances are
|
|
23
|
+
* objects too. Callers that need to tell them apart still have to ask.
|
|
24
|
+
* @param value - The value to test
|
|
25
|
+
* @returns True when the value is a non-null object
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export declare function isObject(value: unknown): value is object;
|
|
29
|
+
/**
|
|
30
|
+
* Read one property from a value of unknown shape
|
|
31
|
+
*
|
|
32
|
+
* Uses `Reflect.get`, so there is no cast: a missing property, a non-object and
|
|
33
|
+
* a property holding `undefined` are all `undefined`, and the caller has to
|
|
34
|
+
* narrow whatever comes back.
|
|
35
|
+
* @param value - The value to read from
|
|
36
|
+
* @param key - The property to read
|
|
37
|
+
* @returns The property value, or undefined when there is none
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
export declare function readProperty(value: unknown, key: PropertyKey): unknown;
|
|
41
|
+
/**
|
|
42
|
+
* Read the own enumerable string-keyed entries of a value of unknown shape
|
|
43
|
+
* @param value - The value to read from
|
|
44
|
+
* @returns The entries, or an empty array when the value is not an object
|
|
45
|
+
* @internal
|
|
46
|
+
*/
|
|
47
|
+
export declare function readEntries(value: unknown): Array<[string, unknown]>;
|
|
48
|
+
/**
|
|
49
|
+
* Read a property that should hold an array, from a value of unknown shape
|
|
50
|
+
* @param value - The value to read from
|
|
51
|
+
* @param key - The property to read
|
|
52
|
+
* @returns The array, or an empty array when the property is absent or not one
|
|
53
|
+
* @internal
|
|
54
|
+
*/
|
|
55
|
+
export declare function readArrayProperty(value: unknown, key: PropertyKey): ReadonlyArray<unknown>;
|
|
56
|
+
/**
|
|
57
|
+
* Read a property that should hold a string, from a value of unknown shape
|
|
58
|
+
* @param value - The value to read from
|
|
59
|
+
* @param key - The property to read
|
|
60
|
+
* @returns The string, or null when the property is absent or not one
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
export declare function readStringProperty(value: unknown, key: PropertyKey): string | null;
|
|
64
|
+
//#endregion
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
//#region src/reflection.ts
|
|
2
|
+
/**
|
|
3
|
+
* Reading values whose shape is not known at compile time
|
|
4
|
+
*
|
|
5
|
+
* The SDK used to do this with five copies of a
|
|
6
|
+
* `value is Record<string, unknown>` predicate over
|
|
7
|
+
* `typeof value === "object" && value != null`. That predicate lies three ways:
|
|
8
|
+
* it is true for arrays, `Date`, `Map` and every other object; it claims a
|
|
9
|
+
* string index signature the value does not have, so every read produces
|
|
10
|
+
* `unknown` and callers add a second cast to get anything out of it; and being
|
|
11
|
+
* an `&&` of unrelated checks, its `false` branch does not mean "not a record",
|
|
12
|
+
* which is what a type predicate promises.
|
|
13
|
+
*
|
|
14
|
+
* These take `unknown` and hand back `unknown`. They assert nothing they have
|
|
15
|
+
* not checked, so the one unavoidable cast at the boundary lives here instead
|
|
16
|
+
* of being repeated at every call site. Where the shape *is* known, validate it
|
|
17
|
+
* with a valibot schema and `v.is` rather than reaching for these.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Whether a value is a non-null object
|
|
21
|
+
*
|
|
22
|
+
* Narrows to `object`, which is honest: arrays, `Date` and class instances are
|
|
23
|
+
* objects too. Callers that need to tell them apart still have to ask.
|
|
24
|
+
* @param value - The value to test
|
|
25
|
+
* @returns True when the value is a non-null object
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
function isObject(value) {
|
|
29
|
+
return typeof value === "object" && value !== null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Read one property from a value of unknown shape
|
|
33
|
+
*
|
|
34
|
+
* Uses `Reflect.get`, so there is no cast: a missing property, a non-object and
|
|
35
|
+
* a property holding `undefined` are all `undefined`, and the caller has to
|
|
36
|
+
* narrow whatever comes back.
|
|
37
|
+
* @param value - The value to read from
|
|
38
|
+
* @param key - The property to read
|
|
39
|
+
* @returns The property value, or undefined when there is none
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
function readProperty(value, key) {
|
|
43
|
+
if (!isObject(value)) return;
|
|
44
|
+
return Reflect.get(value, key);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Read the own enumerable string-keyed entries of a value of unknown shape
|
|
48
|
+
* @param value - The value to read from
|
|
49
|
+
* @returns The entries, or an empty array when the value is not an object
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
function readEntries(value) {
|
|
53
|
+
if (!isObject(value)) return [];
|
|
54
|
+
return Object.entries(value);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Read a property that should hold an array, from a value of unknown shape
|
|
58
|
+
* @param value - The value to read from
|
|
59
|
+
* @param key - The property to read
|
|
60
|
+
* @returns The array, or an empty array when the property is absent or not one
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
function readArrayProperty(value, key) {
|
|
64
|
+
const property = readProperty(value, key);
|
|
65
|
+
return Array.isArray(property) ? property : [];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Read a property that should hold a string, from a value of unknown shape
|
|
69
|
+
* @param value - The value to read from
|
|
70
|
+
* @param key - The property to read
|
|
71
|
+
* @returns The string, or null when the property is absent or not one
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
74
|
+
function readStringProperty(value, key) {
|
|
75
|
+
const property = readProperty(value, key);
|
|
76
|
+
return typeof property === "string" ? property : null;
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { isObject, readArrayProperty, readEntries, readProperty, readStringProperty };
|
package/dist/schemas.d.mts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { Query } from "./types/index.mjs";
|
|
2
2
|
import * as v from "valibot";
|
|
3
3
|
//#region src/schemas.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Validates a pseudo-UUID string
|
|
6
|
+
* @param value - The string to validate
|
|
7
|
+
* @returns True if the string is a valid pseudo-UUID, false otherwise
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare function isPseudoUuid(value: string): boolean;
|
|
4
11
|
/**
|
|
5
12
|
* Schema for validating UUIDs
|
|
6
13
|
* @internal
|
package/dist/schemas.mjs
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
import "./helpers.mjs";
|
|
1
|
+
import "./constants.mjs";
|
|
3
2
|
import * as v from "valibot";
|
|
4
3
|
//#region src/schemas.ts
|
|
4
|
+
const PSEUDO_UUID_REGEX = /^[\da-f]{8}(?:-[\da-f]{4}){3}-[\da-f]{12}$/i;
|
|
5
|
+
/**
|
|
6
|
+
* Validates a pseudo-UUID string
|
|
7
|
+
* @param value - The string to validate
|
|
8
|
+
* @returns True if the string is a valid pseudo-UUID, false otherwise
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
function isPseudoUuid(value) {
|
|
12
|
+
return PSEUDO_UUID_REGEX.test(value);
|
|
13
|
+
}
|
|
5
14
|
const positiveNumber = (message) => v.pipe(v.number(), v.minValue(1, message));
|
|
6
15
|
const defaultString = (value) => v.optional(v.string(), value);
|
|
7
16
|
const defaultBoolean = (value) => v.optional(v.boolean(), value);
|
|
@@ -243,4 +252,4 @@ const setItemsParametersSchema = v.object({
|
|
|
243
252
|
pageSize: v.optional(positiveNumber("Page size must be positive"), 48)
|
|
244
253
|
});
|
|
245
254
|
//#endregion
|
|
246
|
-
export { componentSchema, gallerySchema, iso639_3Schema, itemOcrDataParametersSchema, renderOptionsSchema, setItemsParametersSchema, setPropertyValuesParametersSchema, uuidSchema };
|
|
255
|
+
export { componentSchema, gallerySchema, isPseudoUuid, iso639_3Schema, itemOcrDataParametersSchema, renderOptionsSchema, setItemsParametersSchema, setPropertyValuesParametersSchema, uuidSchema };
|