ochre-sdk 0.20.22 → 0.20.23
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/dist/index.d.mts +8 -0
- package/dist/index.mjs +198 -78
- package/package.json +5 -5
package/dist/index.d.mts
CHANGED
|
@@ -706,6 +706,14 @@ type Query = {
|
|
|
706
706
|
language: string;
|
|
707
707
|
operator?: "AND" | "OR";
|
|
708
708
|
isNegated?: boolean;
|
|
709
|
+
} | {
|
|
710
|
+
target: "string";
|
|
711
|
+
value: string;
|
|
712
|
+
matchMode: "includes" | "exact";
|
|
713
|
+
isCaseSensitive: boolean;
|
|
714
|
+
language: string;
|
|
715
|
+
operator?: "AND" | "OR";
|
|
716
|
+
isNegated?: boolean;
|
|
709
717
|
} | {
|
|
710
718
|
target: "title" | "description" | "image" | "periods" | "bibliography";
|
|
711
719
|
value: string;
|
package/dist/index.mjs
CHANGED
|
@@ -2,18 +2,13 @@ import * as z from "zod";
|
|
|
2
2
|
import { parseISO, set } from "date-fns";
|
|
3
3
|
import { UTCDate } from "@date-fns/utc";
|
|
4
4
|
import { deepEqual } from "fast-equals";
|
|
5
|
-
|
|
6
5
|
//#region src/constants.ts
|
|
7
6
|
const BELONGS_TO_COLLECTION_UUID = "30054cb2-909a-4f34-8db9-8fe7369d691d";
|
|
8
|
-
const PRESENTATION_ITEM_UUID = "f1c131b6-1498-48a4-95bf-a9edae9fd518";
|
|
9
|
-
const TEXT_ANNOTATION_UUID = "b9ca2732-78f4-416e-b77f-dae7647e68a9";
|
|
10
7
|
const TEXT_ANNOTATION_HOVER_CARD_UUID = "c7f6a08a-f07b-49b6-bcb1-af485da3c58f";
|
|
11
8
|
const TEXT_ANNOTATION_ITEM_PAGE_VARIANT_UUID = "bf4476ab-6bc8-40d0-a001-1446213c72ce";
|
|
12
9
|
const TEXT_ANNOTATION_ENTRY_PAGE_VARIANT_UUID = "9d52db95-a9cf-45f7-a0bf-fc9ba9f0aae0";
|
|
13
|
-
const TEXT_ANNOTATION_TEXT_STYLING_UUID = "3e6f86ab-df81-45ae-8257-e2867357df56";
|
|
14
10
|
const TEXT_ANNOTATION_TEXT_STYLING_VARIANT_UUID = "e1647bef-d801-4100-bdde-d081c422f763";
|
|
15
11
|
const TEXT_ANNOTATION_TEXT_STYLING_HEADING_LEVEL_UUID = "d4266f0b-3f8d-4b32-8c15-4b229c8bb11e";
|
|
16
|
-
|
|
17
12
|
//#endregion
|
|
18
13
|
//#region src/utils/string.ts
|
|
19
14
|
const EMAIL_BRACKET_CLEANUP_REGEX = /(?<=\s|^)[([{]+|[)\]}]+(?=\s|$)/g;
|
|
@@ -180,7 +175,7 @@ function extractAnnotationMetadata(item) {
|
|
|
180
175
|
if (itemProperty == null) return result;
|
|
181
176
|
const itemPropertyLabelUuid = itemProperty.label.uuid;
|
|
182
177
|
const itemPropertyValueUuid = typeof itemProperty.value === "object" && "uuid" in itemProperty.value && itemProperty.value.uuid != null ? itemProperty.value.uuid : null;
|
|
183
|
-
if (itemPropertyLabelUuid !==
|
|
178
|
+
if (itemPropertyLabelUuid !== "f1c131b6-1498-48a4-95bf-a9edae9fd518" || itemPropertyValueUuid !== "b9ca2732-78f4-416e-b77f-dae7647e68a9") return result;
|
|
184
179
|
const textAnnotationProperties = itemProperty.property != null ? Array.isArray(itemProperty.property) ? itemProperty.property : [itemProperty.property] : [];
|
|
185
180
|
for (const textAnnotationProperty of textAnnotationProperties) {
|
|
186
181
|
const textAnnotationPropertyValueUuid = typeof textAnnotationProperty.value === "object" && "uuid" in textAnnotationProperty.value && textAnnotationProperty.value.uuid != null ? textAnnotationProperty.value.uuid : null;
|
|
@@ -194,7 +189,7 @@ function extractAnnotationMetadata(item) {
|
|
|
194
189
|
case TEXT_ANNOTATION_ENTRY_PAGE_VARIANT_UUID:
|
|
195
190
|
result.linkVariant = "entry-page";
|
|
196
191
|
break;
|
|
197
|
-
default: if (textAnnotationPropertyValueUuid ===
|
|
192
|
+
default: if (textAnnotationPropertyValueUuid === "3e6f86ab-df81-45ae-8257-e2867357df56" && textAnnotationProperty.property != null) {
|
|
198
193
|
let textStylingVariant = "block";
|
|
199
194
|
let textStylingSize = "md";
|
|
200
195
|
let textStylingHeadingLevel = null;
|
|
@@ -211,7 +206,7 @@ function extractAnnotationMetadata(item) {
|
|
|
211
206
|
}
|
|
212
207
|
const textStylingHeadingLevelProperty = textStylingProperties.find((property) => property.label.uuid === TEXT_ANNOTATION_TEXT_STYLING_HEADING_LEVEL_UUID);
|
|
213
208
|
if (textStylingHeadingLevelProperty != null) textStylingHeadingLevel = parseFakeString(textStylingHeadingLevelProperty.value.content);
|
|
214
|
-
const textStylingCssProperties = textStylingProperties.filter((property) => property.label.uuid !==
|
|
209
|
+
const textStylingCssProperties = textStylingProperties.filter((property) => property.label.uuid !== "e1647bef-d801-4100-bdde-d081c422f763" && property.label.uuid !== "d4266f0b-3f8d-4b32-8c15-4b229c8bb11e");
|
|
215
210
|
if (textStylingCssProperties.length > 0) textStylingCss = textStylingCssProperties.map((property) => ({
|
|
216
211
|
label: parseFakeString(property.label.content),
|
|
217
212
|
value: parseFakeString(property.value.content)
|
|
@@ -371,10 +366,10 @@ function parseStringDocumentItem(item) {
|
|
|
371
366
|
if (itemProperty != null) {
|
|
372
367
|
const itemPropertyLabelUuid = itemProperty.label.uuid;
|
|
373
368
|
const itemPropertyValueUuid = typeof itemProperty.value === "object" && "uuid" in itemProperty.value && itemProperty.value.uuid != null ? itemProperty.value.uuid : null;
|
|
374
|
-
if (itemPropertyLabelUuid ===
|
|
369
|
+
if (itemPropertyLabelUuid === "f1c131b6-1498-48a4-95bf-a9edae9fd518" && itemPropertyValueUuid === "b9ca2732-78f4-416e-b77f-dae7647e68a9") {
|
|
375
370
|
const textAnnotationProperty = itemProperty.property != null ? Array.isArray(itemProperty.property) ? itemProperty.property[0] : itemProperty.property : null;
|
|
376
371
|
if (textAnnotationProperty != null) {
|
|
377
|
-
if ((typeof textAnnotationProperty.value === "object" && "uuid" in textAnnotationProperty.value && textAnnotationProperty.value.uuid != null ? textAnnotationProperty.value.uuid : null) ===
|
|
372
|
+
if ((typeof textAnnotationProperty.value === "object" && "uuid" in textAnnotationProperty.value && textAnnotationProperty.value.uuid != null ? textAnnotationProperty.value.uuid : null) === "3e6f86ab-df81-45ae-8257-e2867357df56" && textAnnotationProperty.property != null) {
|
|
378
373
|
const textStylingType = "text-styling";
|
|
379
374
|
let textStylingVariant = "block";
|
|
380
375
|
let textStylingSize = "md";
|
|
@@ -391,7 +386,7 @@ function parseStringDocumentItem(item) {
|
|
|
391
386
|
}
|
|
392
387
|
const textStylingHeadingLevelProperty = textStylingProperties.find((property) => property.label.uuid === TEXT_ANNOTATION_TEXT_STYLING_HEADING_LEVEL_UUID);
|
|
393
388
|
if (textStylingHeadingLevelProperty != null) textStylingHeadingLevel = parseFakeString(textStylingHeadingLevelProperty.value.content);
|
|
394
|
-
const textStylingCssProperties = textStylingProperties.filter((property) => property.label.uuid !==
|
|
389
|
+
const textStylingCssProperties = textStylingProperties.filter((property) => property.label.uuid !== "e1647bef-d801-4100-bdde-d081c422f763" && property.label.uuid !== "d4266f0b-3f8d-4b32-8c15-4b229c8bb11e");
|
|
395
390
|
if (textStylingCssProperties.length > 0) textStylingCss = textStylingCssProperties.map((property) => ({
|
|
396
391
|
label: parseFakeString(property.label.content),
|
|
397
392
|
value: parseFakeString(property.value.content)
|
|
@@ -442,7 +437,6 @@ function parseStringContent(content, language = "eng") {
|
|
|
442
437
|
default: return String(content.content);
|
|
443
438
|
}
|
|
444
439
|
}
|
|
445
|
-
|
|
446
440
|
//#endregion
|
|
447
441
|
//#region src/utils/internal.ts
|
|
448
442
|
const PSEUDO_UUID_REGEX = /^[\da-f]{8}(?:-[\da-f]{4}){3}-[\da-f]{12}$/i;
|
|
@@ -572,7 +566,6 @@ function cleanObject(object) {
|
|
|
572
566
|
function stringLiteral(value) {
|
|
573
567
|
return `"${value.replaceAll("\"", "\"\"")}"`;
|
|
574
568
|
}
|
|
575
|
-
|
|
576
569
|
//#endregion
|
|
577
570
|
//#region src/utils/helpers.ts
|
|
578
571
|
/**
|
|
@@ -606,7 +599,6 @@ function flattenItemProperties(item) {
|
|
|
606
599
|
properties: flattenProperties(allProperties)
|
|
607
600
|
};
|
|
608
601
|
}
|
|
609
|
-
|
|
610
602
|
//#endregion
|
|
611
603
|
//#region src/schemas.ts
|
|
612
604
|
/**
|
|
@@ -636,25 +628,13 @@ const richTextStringSchema = z.object({
|
|
|
636
628
|
]),
|
|
637
629
|
lang: z.string().optional()
|
|
638
630
|
});
|
|
639
|
-
|
|
640
|
-
* Schema for validating identification
|
|
641
|
-
* @internal
|
|
642
|
-
*/
|
|
643
|
-
const identificationSchema = z.object({
|
|
631
|
+
z.object({
|
|
644
632
|
label: z.object({ content: z.union([richTextStringSchema, z.array(richTextStringSchema)]) }),
|
|
645
633
|
abbreviation: z.object({ content: z.union([richTextStringSchema, z.array(richTextStringSchema)]).optional() }),
|
|
646
634
|
code: z.string().optional()
|
|
647
635
|
});
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
* @internal
|
|
651
|
-
*/
|
|
652
|
-
const filterSchema = z.string().optional();
|
|
653
|
-
/**
|
|
654
|
-
* Schema for validating data options
|
|
655
|
-
* @internal
|
|
656
|
-
*/
|
|
657
|
-
const dataOptionsSchema = z.object({
|
|
636
|
+
z.string().optional();
|
|
637
|
+
z.object({
|
|
658
638
|
filter: z.string().optional().default(""),
|
|
659
639
|
start: z.number().positive({ error: "Start must be positive" }).optional().default(1),
|
|
660
640
|
limit: z.number().positive({ error: "Limit must be positive" }).optional().default(40)
|
|
@@ -818,6 +798,15 @@ const setQuerySchema = z.union([
|
|
|
818
798
|
operator: z.enum(["AND", "OR"]).optional(),
|
|
819
799
|
isNegated: z.boolean().optional().default(false)
|
|
820
800
|
}).strict(),
|
|
801
|
+
z.object({
|
|
802
|
+
target: z.literal("string"),
|
|
803
|
+
value: z.string(),
|
|
804
|
+
matchMode: z.enum(["includes", "exact"]),
|
|
805
|
+
isCaseSensitive: z.boolean(),
|
|
806
|
+
language: z.string().default("eng"),
|
|
807
|
+
operator: z.enum(["AND", "OR"]).optional(),
|
|
808
|
+
isNegated: z.boolean().optional().default(false)
|
|
809
|
+
}).strict(),
|
|
821
810
|
z.object({
|
|
822
811
|
target: z.enum([
|
|
823
812
|
"title",
|
|
@@ -897,11 +886,10 @@ const setItemsParamsSchema = z.object({
|
|
|
897
886
|
queries: setQueriesSchema,
|
|
898
887
|
sort: setItemsSortSchema,
|
|
899
888
|
page: z.number().min(1, "Page must be positive").default(1),
|
|
900
|
-
pageSize: z.number().min(1, "Page size must be positive").default(
|
|
889
|
+
pageSize: z.number().min(1, "Page size must be positive").default(48)
|
|
901
890
|
}).superRefine((value, ctx) => {
|
|
902
891
|
validateSetQueriesOperators(value.queries, ctx);
|
|
903
892
|
});
|
|
904
|
-
|
|
905
893
|
//#endregion
|
|
906
894
|
//#region src/utils/parse/index.ts
|
|
907
895
|
const TRAILING_ELLIPSIS_REGEX = /\s*\.{3}$/;
|
|
@@ -1977,7 +1965,6 @@ function parseConcept(concept, metadata, persistentUrl, belongsTo) {
|
|
|
1977
1965
|
function parseConcepts(concepts) {
|
|
1978
1966
|
return concepts.map((concept) => parseConcept(concept));
|
|
1979
1967
|
}
|
|
1980
|
-
|
|
1981
1968
|
//#endregion
|
|
1982
1969
|
//#region src/utils/fetchers/gallery.ts
|
|
1983
1970
|
/**
|
|
@@ -2004,7 +1991,7 @@ const galleryParamsSchema = z.object({
|
|
|
2004
1991
|
*/
|
|
2005
1992
|
async function fetchGallery(params, options) {
|
|
2006
1993
|
try {
|
|
2007
|
-
const version = options?.version ??
|
|
1994
|
+
const version = options?.version ?? 2;
|
|
2008
1995
|
const { uuid, filter, page, pageSize } = galleryParamsSchema.parse(params);
|
|
2009
1996
|
const response = await (options?.fetch ?? fetch)(`${version === 2 ? "https://ochre.lib.uchicago.edu/ochre/v2/ochre.php" : "https://ochre.lib.uchicago.edu/ochre"}?xquery=${encodeURIComponent(`<ochre>{
|
|
2010
1997
|
for $q in ${version === 2 ? "doc()" : "input()"}/ochre[@uuid='${uuid}']
|
|
@@ -2036,7 +2023,6 @@ async function fetchGallery(params, options) {
|
|
|
2036
2023
|
};
|
|
2037
2024
|
}
|
|
2038
2025
|
}
|
|
2039
|
-
|
|
2040
2026
|
//#endregion
|
|
2041
2027
|
//#region src/utils/fetchers/uuid.ts
|
|
2042
2028
|
/**
|
|
@@ -2048,7 +2034,7 @@ async function fetchGallery(params, options) {
|
|
|
2048
2034
|
*/
|
|
2049
2035
|
async function fetchByUuid(uuid, options) {
|
|
2050
2036
|
try {
|
|
2051
|
-
const version = options?.version ??
|
|
2037
|
+
const version = options?.version ?? 2;
|
|
2052
2038
|
const parsedUuid = uuidSchema.parse(uuid);
|
|
2053
2039
|
const response = await (options?.fetch ?? fetch)(version === 2 ? `https://ochre.lib.uchicago.edu/ochre/v2/ochre.php?uuid=${parsedUuid}&format=json&lang="*"` : `https://ochre.lib.uchicago.edu/ochre?uuid=${parsedUuid}&format=json&lang="*"`);
|
|
2054
2040
|
if (!response.ok) throw new Error("Failed to fetch OCHRE data");
|
|
@@ -2059,7 +2045,6 @@ async function fetchByUuid(uuid, options) {
|
|
|
2059
2045
|
return [error instanceof Error ? error.message : "Unknown error", null];
|
|
2060
2046
|
}
|
|
2061
2047
|
}
|
|
2062
|
-
|
|
2063
2048
|
//#endregion
|
|
2064
2049
|
//#region src/utils/fetchers/item.ts
|
|
2065
2050
|
/**
|
|
@@ -2070,7 +2055,7 @@ async function fetchByUuid(uuid, options) {
|
|
|
2070
2055
|
*/
|
|
2071
2056
|
async function fetchItem(uuid, category, itemCategories, options) {
|
|
2072
2057
|
try {
|
|
2073
|
-
const version = options?.version ??
|
|
2058
|
+
const version = options?.version ?? 2;
|
|
2074
2059
|
const [error, data] = await fetchByUuid(uuid, {
|
|
2075
2060
|
fetch,
|
|
2076
2061
|
version
|
|
@@ -2144,15 +2129,16 @@ async function fetchItem(uuid, category, itemCategories, options) {
|
|
|
2144
2129
|
};
|
|
2145
2130
|
}
|
|
2146
2131
|
}
|
|
2147
|
-
|
|
2148
2132
|
//#endregion
|
|
2149
2133
|
//#region src/utils/fetchers/set/query-helpers.ts
|
|
2150
2134
|
const CTS_INCLUDES_STOP_WORDS = [
|
|
2151
|
-
"of",
|
|
2152
|
-
"the",
|
|
2153
2135
|
"and",
|
|
2136
|
+
"at",
|
|
2154
2137
|
"in",
|
|
2155
|
-
"it"
|
|
2138
|
+
"it",
|
|
2139
|
+
"of",
|
|
2140
|
+
"the",
|
|
2141
|
+
"to"
|
|
2156
2142
|
];
|
|
2157
2143
|
const CTS_INCLUDES_STOP_WORDS_VAR = "$ctsIncludesStopWords";
|
|
2158
2144
|
/**
|
|
@@ -2166,53 +2152,188 @@ function buildRawStringMatchPredicate(params) {
|
|
|
2166
2152
|
return `${comparedPath} = ${comparedValueLiteral}`;
|
|
2167
2153
|
}
|
|
2168
2154
|
/**
|
|
2155
|
+
* Build a combined raw string match predicate for multiple paths.
|
|
2156
|
+
*/
|
|
2157
|
+
function buildCombinedRawStringMatchPredicate(params) {
|
|
2158
|
+
const { paths, value, matchMode, isCaseSensitive } = params;
|
|
2159
|
+
const predicates = [];
|
|
2160
|
+
for (const path of paths) predicates.push(buildRawStringMatchPredicate({
|
|
2161
|
+
path,
|
|
2162
|
+
value,
|
|
2163
|
+
matchMode,
|
|
2164
|
+
isCaseSensitive
|
|
2165
|
+
}));
|
|
2166
|
+
if (predicates.length === 1) return predicates[0] ?? "false()";
|
|
2167
|
+
return `(${predicates.join(" or ")})`;
|
|
2168
|
+
}
|
|
2169
|
+
/**
|
|
2169
2170
|
* Build CTS word-query options for API v2 includes search.
|
|
2170
2171
|
*/
|
|
2171
2172
|
function buildCtsQueryOptionsExpression(isCaseSensitive) {
|
|
2172
2173
|
return `(${[
|
|
2173
2174
|
isCaseSensitive ? "case-sensitive" : "case-insensitive",
|
|
2174
2175
|
"diacritic-insensitive",
|
|
2175
|
-
"punctuation-insensitive"
|
|
2176
|
-
"whitespace-insensitive",
|
|
2177
|
-
"stemmed"
|
|
2176
|
+
"punctuation-insensitive"
|
|
2178
2177
|
].map((option) => stringLiteral(option)).join(", ")})`;
|
|
2179
2178
|
}
|
|
2180
2179
|
/**
|
|
2181
|
-
* Build a CTS-
|
|
2180
|
+
* Build a CTS word-query expression for an XQuery term.
|
|
2182
2181
|
*/
|
|
2183
|
-
function
|
|
2184
|
-
const {
|
|
2182
|
+
function buildCtsWordQueryExpression(params) {
|
|
2183
|
+
const { termExpression, isCaseSensitive } = params;
|
|
2184
|
+
return `cts:word-query(${termExpression}, ${buildCtsQueryOptionsExpression(isCaseSensitive)})`;
|
|
2185
|
+
}
|
|
2186
|
+
/**
|
|
2187
|
+
* Build tokenized search declarations for CTS-backed queries.
|
|
2188
|
+
*/
|
|
2189
|
+
function buildTokenizedSearchDeclarations(params) {
|
|
2190
|
+
const { value, isCaseSensitive, queryIndex } = params;
|
|
2185
2191
|
const searchStringVar = `$query${queryIndex}SearchString`;
|
|
2186
2192
|
const rawTermsVar = `$query${queryIndex}RawTerms`;
|
|
2187
2193
|
const termsVar = `$query${queryIndex}Terms`;
|
|
2194
|
+
const tokenSourceExpression = isCaseSensitive ? searchStringVar : `fn:lower-case(${searchStringVar})`;
|
|
2195
|
+
return {
|
|
2196
|
+
declarations: [
|
|
2197
|
+
`let ${searchStringVar} := ${stringLiteral(value)}`,
|
|
2198
|
+
String.raw`let ${rawTermsVar} := fn:tokenize(${tokenSourceExpression}, "\W+")`,
|
|
2199
|
+
`let ${termsVar} :=
|
|
2200
|
+
for $term in ${rawTermsVar}
|
|
2201
|
+
let $normalizedTerm := fn:lower-case($term)
|
|
2202
|
+
where $normalizedTerm ne "" and not($normalizedTerm = ${CTS_INCLUDES_STOP_WORDS_VAR})
|
|
2203
|
+
return $term`
|
|
2204
|
+
],
|
|
2205
|
+
termsVar
|
|
2206
|
+
};
|
|
2207
|
+
}
|
|
2208
|
+
/**
|
|
2209
|
+
* Build a CTS-backed field includes predicate for an XQuery string.
|
|
2210
|
+
*/
|
|
2211
|
+
function buildCtsFieldIncludesPredicate(params) {
|
|
2212
|
+
const { path, value, isCaseSensitive, queryIndex } = params;
|
|
2213
|
+
const tokenizedSearchDeclarations = buildTokenizedSearchDeclarations({
|
|
2214
|
+
value,
|
|
2215
|
+
isCaseSensitive,
|
|
2216
|
+
queryIndex
|
|
2217
|
+
});
|
|
2188
2218
|
const ctsQueryVar = `$query${queryIndex}CtsQuery`;
|
|
2189
|
-
const ctsOptionsExpression = buildCtsQueryOptionsExpression(isCaseSensitive);
|
|
2190
2219
|
const fallbackPredicate = buildRawStringMatchPredicate({
|
|
2191
2220
|
path,
|
|
2192
2221
|
value,
|
|
2193
2222
|
matchMode: "includes",
|
|
2194
2223
|
isCaseSensitive
|
|
2195
2224
|
});
|
|
2225
|
+
return {
|
|
2226
|
+
declarations: [...tokenizedSearchDeclarations.declarations, `let ${ctsQueryVar} :=
|
|
2227
|
+
if (count(${tokenizedSearchDeclarations.termsVar}) = 1)
|
|
2228
|
+
then ${buildCtsWordQueryExpression({
|
|
2229
|
+
termExpression: `${tokenizedSearchDeclarations.termsVar}[1]`,
|
|
2230
|
+
isCaseSensitive
|
|
2231
|
+
})}
|
|
2232
|
+
else if (count(${tokenizedSearchDeclarations.termsVar}) gt 1)
|
|
2233
|
+
then cts:and-query((
|
|
2234
|
+
for $term in ${tokenizedSearchDeclarations.termsVar}
|
|
2235
|
+
return ${buildCtsWordQueryExpression({
|
|
2236
|
+
termExpression: "$term",
|
|
2237
|
+
isCaseSensitive
|
|
2238
|
+
})}
|
|
2239
|
+
))
|
|
2240
|
+
else ()`],
|
|
2241
|
+
predicate: `(if (exists(${ctsQueryVar})) then cts:contains(${path}, ${ctsQueryVar}) else ${fallbackPredicate})`
|
|
2242
|
+
};
|
|
2243
|
+
}
|
|
2244
|
+
/**
|
|
2245
|
+
* Build the raw search paths for item-level string search.
|
|
2246
|
+
*/
|
|
2247
|
+
function buildItemStringSearchPaths(language) {
|
|
2248
|
+
return [`string-join(identification/label/content[@xml:lang="${language}"]/string, "")`, `string-join(properties//property/value[not(@inherited="true")]/content[@xml:lang="${language}"]/string, "")`];
|
|
2249
|
+
}
|
|
2250
|
+
/**
|
|
2251
|
+
* Build the identification branch for an item-level CTS string search.
|
|
2252
|
+
*/
|
|
2253
|
+
function buildItemStringIdentificationBranch(params) {
|
|
2254
|
+
const { termExpression, isCaseSensitive, language } = params;
|
|
2255
|
+
return `cts:element-query(xs:QName("identification"),
|
|
2256
|
+
cts:and-query((
|
|
2257
|
+
cts:element-attribute-value-query(xs:QName("content"), xs:QName("xml:lang"), ${stringLiteral(language)}),
|
|
2258
|
+
${buildCtsWordQueryExpression({
|
|
2259
|
+
termExpression,
|
|
2260
|
+
isCaseSensitive
|
|
2261
|
+
})}
|
|
2262
|
+
))
|
|
2263
|
+
)`;
|
|
2264
|
+
}
|
|
2265
|
+
/**
|
|
2266
|
+
* Build the property value branch for an item-level CTS string search.
|
|
2267
|
+
*/
|
|
2268
|
+
function buildItemStringPropertyValueBranch(params) {
|
|
2269
|
+
const { termExpression, isCaseSensitive, language } = params;
|
|
2270
|
+
return `cts:element-query(xs:QName("properties"),
|
|
2271
|
+
cts:element-query(xs:QName("property"),
|
|
2272
|
+
cts:element-query(xs:QName("value"),
|
|
2273
|
+
cts:and-query((
|
|
2274
|
+
cts:not-query(cts:element-attribute-value-query(xs:QName("value"), xs:QName("inherited"), "true")),
|
|
2275
|
+
cts:element-query(xs:QName("content"),
|
|
2276
|
+
cts:and-query((
|
|
2277
|
+
cts:element-attribute-value-query(xs:QName("content"), xs:QName("xml:lang"), ${stringLiteral(language)}),
|
|
2278
|
+
${buildCtsWordQueryExpression({
|
|
2279
|
+
termExpression,
|
|
2280
|
+
isCaseSensitive
|
|
2281
|
+
})}
|
|
2282
|
+
))
|
|
2283
|
+
)
|
|
2284
|
+
))
|
|
2285
|
+
)
|
|
2286
|
+
)
|
|
2287
|
+
)`;
|
|
2288
|
+
}
|
|
2289
|
+
/**
|
|
2290
|
+
* Build an item-level CTS string search predicate.
|
|
2291
|
+
*/
|
|
2292
|
+
function buildItemStringSearchPredicate(params) {
|
|
2293
|
+
const { query, version, queryIndex } = params;
|
|
2294
|
+
const fallbackPredicate = buildCombinedRawStringMatchPredicate({
|
|
2295
|
+
paths: buildItemStringSearchPaths(query.language),
|
|
2296
|
+
value: query.value,
|
|
2297
|
+
matchMode: query.matchMode,
|
|
2298
|
+
isCaseSensitive: query.isCaseSensitive
|
|
2299
|
+
});
|
|
2300
|
+
if (query.matchMode !== "includes" || version !== 2) return {
|
|
2301
|
+
declarations: [],
|
|
2302
|
+
predicate: fallbackPredicate
|
|
2303
|
+
};
|
|
2304
|
+
const tokenizedSearchDeclarations = buildTokenizedSearchDeclarations({
|
|
2305
|
+
value: query.value,
|
|
2306
|
+
isCaseSensitive: query.isCaseSensitive,
|
|
2307
|
+
queryIndex
|
|
2308
|
+
});
|
|
2309
|
+
const termQueriesVar = `$query${queryIndex}TermQueries`;
|
|
2310
|
+
const ctsQueryVar = `$query${queryIndex}CtsQuery`;
|
|
2196
2311
|
return {
|
|
2197
2312
|
declarations: [
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2313
|
+
...tokenizedSearchDeclarations.declarations,
|
|
2314
|
+
`let ${termQueriesVar} :=
|
|
2315
|
+
for $term in ${tokenizedSearchDeclarations.termsVar}
|
|
2316
|
+
return
|
|
2317
|
+
cts:or-query((
|
|
2318
|
+
${buildItemStringIdentificationBranch({
|
|
2319
|
+
termExpression: "$term",
|
|
2320
|
+
isCaseSensitive: query.isCaseSensitive,
|
|
2321
|
+
language: query.language
|
|
2322
|
+
})},
|
|
2323
|
+
${buildItemStringPropertyValueBranch({
|
|
2324
|
+
termExpression: "$term",
|
|
2325
|
+
isCaseSensitive: query.isCaseSensitive,
|
|
2326
|
+
language: query.language
|
|
2327
|
+
})}
|
|
2328
|
+
))`,
|
|
2205
2329
|
`let ${ctsQueryVar} :=
|
|
2206
|
-
if (count(${termsVar}) = 1)
|
|
2207
|
-
then
|
|
2208
|
-
else if (count(${termsVar}) gt 1)
|
|
2209
|
-
then cts:
|
|
2210
|
-
for $term in ${termsVar}
|
|
2211
|
-
return cts:word-query($term, ${ctsOptionsExpression})
|
|
2212
|
-
), 5, ("unordered"))
|
|
2330
|
+
if (count(${tokenizedSearchDeclarations.termsVar}) = 1)
|
|
2331
|
+
then ${termQueriesVar}[1]
|
|
2332
|
+
else if (count(${tokenizedSearchDeclarations.termsVar}) gt 1)
|
|
2333
|
+
then cts:and-query(${termQueriesVar})
|
|
2213
2334
|
else ()`
|
|
2214
2335
|
],
|
|
2215
|
-
predicate: `(if (exists(${ctsQueryVar})) then cts:contains(
|
|
2336
|
+
predicate: `(if (exists(${ctsQueryVar})) then cts:contains(., ${ctsQueryVar}) else ${fallbackPredicate})`
|
|
2216
2337
|
};
|
|
2217
2338
|
}
|
|
2218
2339
|
/**
|
|
@@ -2220,7 +2341,7 @@ function buildCtsIncludesPredicate(params) {
|
|
|
2220
2341
|
*/
|
|
2221
2342
|
function buildStringMatchPredicate(params) {
|
|
2222
2343
|
const { path, value, matchMode, isCaseSensitive, version, queryIndex } = params;
|
|
2223
|
-
if (matchMode === "includes" && version === 2) return
|
|
2344
|
+
if (matchMode === "includes" && version === 2) return buildCtsFieldIncludesPredicate({
|
|
2224
2345
|
path,
|
|
2225
2346
|
value,
|
|
2226
2347
|
isCaseSensitive,
|
|
@@ -2267,7 +2388,7 @@ function buildPropertyValuePredicate(params) {
|
|
|
2267
2388
|
predicate: `.//properties//property[value[@rawValue=${stringLiteral(query.value)}]]`
|
|
2268
2389
|
};
|
|
2269
2390
|
const compiledStringPredicate = buildStringMatchPredicate({
|
|
2270
|
-
path: `string-join(value/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2391
|
+
path: query.matchMode === "includes" && version === 2 ? `string-join(value[not(@inherited="true")]/content[@xml:lang="${query.language}"]/string, "")` : `string-join(value/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2271
2392
|
value: query.value,
|
|
2272
2393
|
matchMode: query.matchMode,
|
|
2273
2394
|
isCaseSensitive: query.isCaseSensitive,
|
|
@@ -2285,6 +2406,11 @@ function buildPropertyValuePredicate(params) {
|
|
|
2285
2406
|
function buildQueryPredicate(params) {
|
|
2286
2407
|
const { query, version, queryIndex } = params;
|
|
2287
2408
|
switch (query.target) {
|
|
2409
|
+
case "string": return buildItemStringSearchPredicate({
|
|
2410
|
+
query,
|
|
2411
|
+
version,
|
|
2412
|
+
queryIndex
|
|
2413
|
+
});
|
|
2288
2414
|
case "title": return buildStringMatchPredicate({
|
|
2289
2415
|
path: `string-join(identification/label/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2290
2416
|
value: query.value,
|
|
@@ -2378,7 +2504,6 @@ function buildQueryFilters(params) {
|
|
|
2378
2504
|
predicate: predicateParts.join(" ")
|
|
2379
2505
|
};
|
|
2380
2506
|
}
|
|
2381
|
-
|
|
2382
2507
|
//#endregion
|
|
2383
2508
|
//#region src/utils/fetchers/set/items.ts
|
|
2384
2509
|
function mapSortDirectionToXQuery(direction) {
|
|
@@ -2467,7 +2592,7 @@ function buildOrderedItemsClause(sort) {
|
|
|
2467
2592
|
* @returns An XQuery string
|
|
2468
2593
|
*/
|
|
2469
2594
|
function buildXQuery$1(params, options) {
|
|
2470
|
-
const version = options?.version ??
|
|
2595
|
+
const version = options?.version ?? 2;
|
|
2471
2596
|
const { propertyVariableUuids, queries, sort, setScopeUuids, belongsToCollectionScopeUuids, page, pageSize } = params;
|
|
2472
2597
|
const startPosition = (page - 1) * pageSize + 1;
|
|
2473
2598
|
const endPosition = page * pageSize;
|
|
@@ -2522,7 +2647,7 @@ function buildXQuery$1(params, options) {
|
|
|
2522
2647
|
*/
|
|
2523
2648
|
async function fetchSetItems(params, itemCategories, options) {
|
|
2524
2649
|
try {
|
|
2525
|
-
const version = options?.version ??
|
|
2650
|
+
const version = options?.version ?? 2;
|
|
2526
2651
|
const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, queries, sort, page, pageSize } = setItemsParamsSchema.parse(params);
|
|
2527
2652
|
const xquery = buildXQuery$1({
|
|
2528
2653
|
setScopeUuids,
|
|
@@ -2617,7 +2742,6 @@ async function fetchSetItems(params, itemCategories, options) {
|
|
|
2617
2742
|
};
|
|
2618
2743
|
}
|
|
2619
2744
|
}
|
|
2620
|
-
|
|
2621
2745
|
//#endregion
|
|
2622
2746
|
//#region src/utils/fetchers/set/property-values-by-property-variables.ts
|
|
2623
2747
|
function parsePropertyValueLabel(content) {
|
|
@@ -2770,7 +2894,7 @@ const responseSchema = z.object({ result: z.union([z.object({ ochre: z.object({
|
|
|
2770
2894
|
* @returns An XQuery string
|
|
2771
2895
|
*/
|
|
2772
2896
|
function buildXQuery(params, options) {
|
|
2773
|
-
const version = options?.version ??
|
|
2897
|
+
const version = options?.version ?? 2;
|
|
2774
2898
|
const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, queries, attributes, isLimitedToLeafPropertyValues } = params;
|
|
2775
2899
|
let setScopeFilter = "/set/items/*";
|
|
2776
2900
|
if (setScopeUuids.length > 0) setScopeFilter = `/set[(${setScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")})]/items/*`;
|
|
@@ -2843,7 +2967,7 @@ return (${returnedSequences.join(", ")})`}}</ochre>`;
|
|
|
2843
2967
|
*/
|
|
2844
2968
|
async function fetchSetPropertyValuesByPropertyVariables(params, options) {
|
|
2845
2969
|
try {
|
|
2846
|
-
const version = options?.version ??
|
|
2970
|
+
const version = options?.version ?? 2;
|
|
2847
2971
|
const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, queries, attributes, isLimitedToLeafPropertyValues } = setPropertyValuesByPropertyVariablesParamsSchema.parse(params);
|
|
2848
2972
|
const xquery = buildXQuery({
|
|
2849
2973
|
setScopeUuids,
|
|
@@ -2911,7 +3035,6 @@ async function fetchSetPropertyValuesByPropertyVariables(params, options) {
|
|
|
2911
3035
|
};
|
|
2912
3036
|
}
|
|
2913
3037
|
}
|
|
2914
|
-
|
|
2915
3038
|
//#endregion
|
|
2916
3039
|
//#region src/utils/getters.ts
|
|
2917
3040
|
const DEFAULT_OPTIONS = { includeNestedProperties: false };
|
|
@@ -3165,7 +3288,6 @@ function filterProperties(property, filter, options = DEFAULT_OPTIONS) {
|
|
|
3165
3288
|
}
|
|
3166
3289
|
return false;
|
|
3167
3290
|
}
|
|
3168
|
-
|
|
3169
3291
|
//#endregion
|
|
3170
3292
|
//#region src/utils/parse/website.ts
|
|
3171
3293
|
const SEGMENT_UNIQUE_SLUG_PREFIX_REGEX = /^\$[^-]*-/;
|
|
@@ -4416,7 +4538,7 @@ function parseContexts(contexts) {
|
|
|
4416
4538
|
}
|
|
4417
4539
|
return contextsParsed;
|
|
4418
4540
|
}
|
|
4419
|
-
function parseWebsite(websiteTree, metadata, belongsTo, { version =
|
|
4541
|
+
function parseWebsite(websiteTree, metadata, belongsTo, { version = 2 } = {}) {
|
|
4420
4542
|
if (!websiteTree.properties) throw new Error("Website properties not found");
|
|
4421
4543
|
if (typeof websiteTree.items === "string" || !("resource" in websiteTree.items)) throw new Error("Website pages not found");
|
|
4422
4544
|
const resources = ensureArray(websiteTree.items.resource);
|
|
@@ -4436,7 +4558,6 @@ function parseWebsite(websiteTree, metadata, belongsTo, { version = DEFAULT_API_
|
|
|
4436
4558
|
properties
|
|
4437
4559
|
};
|
|
4438
4560
|
}
|
|
4439
|
-
|
|
4440
4561
|
//#endregion
|
|
4441
4562
|
//#region src/utils/fetchers/website.ts
|
|
4442
4563
|
const API_VERSION_SUFFIX_REGEX = /-v\d+$/;
|
|
@@ -4449,7 +4570,7 @@ const API_VERSION_SUFFIX_REGEX = /-v\d+$/;
|
|
|
4449
4570
|
function parseApiVersionSuffix(abbreviation) {
|
|
4450
4571
|
if (!API_VERSION_SUFFIX_REGEX.test(abbreviation)) return {
|
|
4451
4572
|
abbreviation,
|
|
4452
|
-
version:
|
|
4573
|
+
version: 2
|
|
4453
4574
|
};
|
|
4454
4575
|
const result = apiVersionSuffixSchema.safeParse(abbreviation.slice(-3));
|
|
4455
4576
|
if (!result.success) throw new Error("Invalid API version suffix");
|
|
@@ -4509,6 +4630,5 @@ async function fetchWebsite(abbreviation, options) {
|
|
|
4509
4630
|
};
|
|
4510
4631
|
}
|
|
4511
4632
|
}
|
|
4512
|
-
|
|
4513
4633
|
//#endregion
|
|
4514
|
-
export { DEFAULT_API_VERSION, DEFAULT_PAGE_SIZE, fetchGallery, fetchItem, fetchSetItems, fetchSetPropertyValuesByPropertyVariables, fetchWebsite, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByLabel, getPropertyByLabelAndValue, getPropertyByLabelAndValues, getPropertyByUuid, getPropertyValueByLabel, getPropertyValueByUuid, getPropertyValuesByLabel, getPropertyValuesByUuid, getUniqueProperties, getUniquePropertyLabels };
|
|
4634
|
+
export { DEFAULT_API_VERSION, DEFAULT_PAGE_SIZE, fetchGallery, fetchItem, fetchSetItems, fetchSetPropertyValuesByPropertyVariables, fetchWebsite, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByLabel, getPropertyByLabelAndValue, getPropertyByLabelAndValues, getPropertyByUuid, getPropertyValueByLabel, getPropertyValueByUuid, getPropertyValuesByLabel, getPropertyValuesByUuid, getUniqueProperties, getUniquePropertyLabels };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ochre-sdk",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.23",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Node.js library for working with OCHRE (Online Cultural and Historical Research Environment) data",
|
|
@@ -46,12 +46,12 @@
|
|
|
46
46
|
"zod": "^4.3.6"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@antfu/eslint-config": "^7.7.
|
|
49
|
+
"@antfu/eslint-config": "^7.7.3",
|
|
50
50
|
"@types/node": "^24.12.0",
|
|
51
|
-
"bumpp": "^
|
|
52
|
-
"eslint": "^10.0.
|
|
51
|
+
"bumpp": "^11.0.1",
|
|
52
|
+
"eslint": "^10.0.3",
|
|
53
53
|
"prettier": "^3.8.1",
|
|
54
|
-
"tsdown": "^0.
|
|
54
|
+
"tsdown": "^0.21.4",
|
|
55
55
|
"typescript": "^5.9.3"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|