ochre-sdk 0.20.7 → 0.20.11
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 +3 -9
- package/dist/index.mjs +138 -152
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -951,7 +951,7 @@ type WebElementComponent = {
|
|
|
951
951
|
isResultsBarDisplayed: boolean;
|
|
952
952
|
isMapDisplayed: boolean;
|
|
953
953
|
isInputDisplayed: boolean;
|
|
954
|
-
|
|
954
|
+
isLimitedToInputFilter: boolean;
|
|
955
955
|
isLimitedToLeafPropertyValues: boolean;
|
|
956
956
|
sidebarSort: "default" | "alphabetical";
|
|
957
957
|
};
|
|
@@ -1231,12 +1231,6 @@ declare function fetchSetItems<U extends Array<DataCategory> = Array<DataCategor
|
|
|
1231
1231
|
}>;
|
|
1232
1232
|
//#endregion
|
|
1233
1233
|
//#region src/utils/fetchers/set/property-values-by-property-variables.d.ts
|
|
1234
|
-
type SetPropertyValuesByPropertyVariablesTitleQueryInput = {
|
|
1235
|
-
value: string;
|
|
1236
|
-
matchMode: "includes" | "exact";
|
|
1237
|
-
isCaseSensitive: boolean;
|
|
1238
|
-
language?: string;
|
|
1239
|
-
};
|
|
1240
1234
|
/**
|
|
1241
1235
|
* Fetches and parses Set property values by property variables from the OCHRE API
|
|
1242
1236
|
*
|
|
@@ -1244,7 +1238,7 @@ type SetPropertyValuesByPropertyVariablesTitleQueryInput = {
|
|
|
1244
1238
|
* @param params.setScopeUuids - An array of set scope UUIDs to filter by
|
|
1245
1239
|
* @param params.belongsToCollectionScopeUuids - The collection scope UUIDs to filter by
|
|
1246
1240
|
* @param params.propertyVariableUuids - The property variable UUIDs to query by
|
|
1247
|
-
* @param params.
|
|
1241
|
+
* @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
|
|
1248
1242
|
* @param params.isLimitedToLeafPropertyValues - Whether to limit the property values to leaf property values
|
|
1249
1243
|
* @param options - Options for the fetch
|
|
1250
1244
|
* @param options.fetch - The fetch function to use
|
|
@@ -1255,7 +1249,7 @@ declare function fetchSetPropertyValuesByPropertyVariables(params: {
|
|
|
1255
1249
|
setScopeUuids: Array<string>;
|
|
1256
1250
|
belongsToCollectionScopeUuids: Array<string>;
|
|
1257
1251
|
propertyVariableUuids: Array<string>;
|
|
1258
|
-
|
|
1252
|
+
queries?: Array<Query>;
|
|
1259
1253
|
isLimitedToLeafPropertyValues?: boolean;
|
|
1260
1254
|
}, options?: {
|
|
1261
1255
|
fetch?: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response>;
|
package/dist/index.mjs
CHANGED
|
@@ -28,6 +28,15 @@ function getStringItemByLanguage(content, language) {
|
|
|
28
28
|
return content.find((item) => item.lang === language) ?? null;
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
+
* Transforms a permanent identification URL to a OCHRE API URL
|
|
32
|
+
*
|
|
33
|
+
* @param url - The permanent identification URL to transform
|
|
34
|
+
* @returns The OCHRE API URL
|
|
35
|
+
*/
|
|
36
|
+
function transformPermanentIdentificationUrl(url) {
|
|
37
|
+
return url.replace("https://pi.lib.uchicago.edu/1001/org/ochre/", "https://ochre.lib.uchicago.edu/ochre/v2/ochre.php?uuid=");
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
31
40
|
* Parses email addresses in a string into HTML links
|
|
32
41
|
*
|
|
33
42
|
* @param string - Input string to parse
|
|
@@ -37,7 +46,7 @@ function parseEmail(string) {
|
|
|
37
46
|
const splitString = string.split(" ");
|
|
38
47
|
const returnSplitString = [];
|
|
39
48
|
for (const string of splitString) {
|
|
40
|
-
const cleanString = string.replaceAll(/(?<=\s|^)[([{]+|[)\]}]+(?=\s|$)/g, "").replaceAll(/[!),:;?\]]/g, "").replace(/\.$/, "");
|
|
49
|
+
const cleanString = transformPermanentIdentificationUrl(string).replaceAll(/(?<=\s|^)[([{]+|[)\]}]+(?=\s|$)/g, "").replaceAll(/[!),:;?\]]/g, "").replace(/\.$/, "");
|
|
41
50
|
const index = string.indexOf(cleanString);
|
|
42
51
|
const before = string.slice(0, index);
|
|
43
52
|
const after = string.slice(index + cleanString.length);
|
|
@@ -321,9 +330,9 @@ function parseStringDocumentItem(item) {
|
|
|
321
330
|
}
|
|
322
331
|
return applyWhitespaceToResult(linkElement, itemWhitespace);
|
|
323
332
|
}
|
|
324
|
-
case "externalDocument": if (linkResource.publicationDateTime != null) return applyWhitespaceToResult(String.raw`<ExternalLink href="https:\/\/ochre.lib.uchicago.edu/ochre?uuid=${linkResource.uuid}&load" ${linkContent !== null ? `content="${linkContent}"` : ""}>${itemString}</ExternalLink>`, itemWhitespace);
|
|
333
|
+
case "externalDocument": if (linkResource.publicationDateTime != null) return applyWhitespaceToResult(String.raw`<ExternalLink href="https:\/\/ochre.lib.uchicago.edu/ochre/v2/ochre.php?uuid=${linkResource.uuid}&load" ${linkContent !== null ? `content="${linkContent}"` : ""}>${itemString}</ExternalLink>`, itemWhitespace);
|
|
325
334
|
else return applyWhitespaceToResult(`<TooltipSpan${linkContent !== null ? ` content="${linkContent}"` : ""}>${itemString}</TooltipSpan>`, itemWhitespace);
|
|
326
|
-
case "webpage": return applyWhitespaceToResult(`<ExternalLink href="${linkResource.href}" ${linkContent !== null ? `content="${linkContent}"` : ""}>${itemString}</ExternalLink>`, itemWhitespace);
|
|
335
|
+
case "webpage": return applyWhitespaceToResult(`<ExternalLink href="${linkResource.href != null ? transformPermanentIdentificationUrl(linkResource.href) : "#"}" ${linkContent !== null ? `content="${linkContent}"` : ""}>${itemString}</ExternalLink>`, itemWhitespace);
|
|
327
336
|
default: return "";
|
|
328
337
|
}
|
|
329
338
|
} else if ("spatialUnit" in link) {
|
|
@@ -760,87 +769,70 @@ const boundsSchema = z.string().transform((str, ctx) => {
|
|
|
760
769
|
}
|
|
761
770
|
}).pipe(z.tuple([z.tuple([z.number(), z.number()]), z.tuple([z.number(), z.number()])], { message: "Must contain exactly 2 coordinate pairs" }));
|
|
762
771
|
/**
|
|
763
|
-
*
|
|
772
|
+
* Shared schema for Set queries
|
|
764
773
|
* @internal
|
|
765
774
|
*/
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
775
|
+
const setQuerySchema = z.union([
|
|
776
|
+
z.object({
|
|
777
|
+
target: z.literal("propertyValue"),
|
|
778
|
+
dataType: z.enum([
|
|
779
|
+
"string",
|
|
780
|
+
"integer",
|
|
781
|
+
"decimal",
|
|
782
|
+
"boolean",
|
|
783
|
+
"time",
|
|
784
|
+
"IDREF"
|
|
785
|
+
]),
|
|
771
786
|
value: z.string(),
|
|
772
787
|
matchMode: z.enum(["includes", "exact"]),
|
|
773
788
|
isCaseSensitive: z.boolean(),
|
|
774
|
-
language: z.string().default("eng")
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
})
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
z.
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
z.
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
z.
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
operator: z.enum(["AND", "OR"]).optional(),
|
|
822
|
-
isNegated: z.boolean().optional().default(false)
|
|
823
|
-
}).strict(),
|
|
824
|
-
z.object({
|
|
825
|
-
target: z.enum([
|
|
826
|
-
"title",
|
|
827
|
-
"description",
|
|
828
|
-
"image",
|
|
829
|
-
"periods",
|
|
830
|
-
"bibliography"
|
|
831
|
-
]),
|
|
832
|
-
value: z.string(),
|
|
833
|
-
matchMode: z.enum(["includes", "exact"]),
|
|
834
|
-
isCaseSensitive: z.boolean(),
|
|
835
|
-
language: z.string().default("eng"),
|
|
836
|
-
operator: z.enum(["AND", "OR"]).optional(),
|
|
837
|
-
isNegated: z.boolean().optional().default(false)
|
|
838
|
-
}).strict()
|
|
839
|
-
])).default([]),
|
|
840
|
-
page: z.number().min(1, "Page must be positive").default(1),
|
|
841
|
-
pageSize: z.number().min(1, "Page size must be positive").default(DEFAULT_PAGE_SIZE)
|
|
842
|
-
}).superRefine((value, ctx) => {
|
|
843
|
-
for (const [index, query] of value.queries.entries()) {
|
|
789
|
+
language: z.string().default("eng"),
|
|
790
|
+
operator: z.enum(["AND", "OR"]).optional(),
|
|
791
|
+
isNegated: z.boolean().optional().default(false)
|
|
792
|
+
}).strict(),
|
|
793
|
+
z.object({
|
|
794
|
+
target: z.literal("propertyValue"),
|
|
795
|
+
dataType: z.enum(["date", "dateTime"]),
|
|
796
|
+
value: z.string(),
|
|
797
|
+
from: z.string(),
|
|
798
|
+
to: z.string().optional(),
|
|
799
|
+
matchMode: z.enum(["includes", "exact"]),
|
|
800
|
+
isCaseSensitive: z.boolean(),
|
|
801
|
+
language: z.string().default("eng"),
|
|
802
|
+
operator: z.enum(["AND", "OR"]).optional(),
|
|
803
|
+
isNegated: z.boolean().optional().default(false)
|
|
804
|
+
}).strict(),
|
|
805
|
+
z.object({
|
|
806
|
+
target: z.literal("propertyValue"),
|
|
807
|
+
dataType: z.enum(["date", "dateTime"]),
|
|
808
|
+
value: z.string(),
|
|
809
|
+
from: z.string().optional(),
|
|
810
|
+
to: z.string(),
|
|
811
|
+
matchMode: z.enum(["includes", "exact"]),
|
|
812
|
+
isCaseSensitive: z.boolean(),
|
|
813
|
+
language: z.string().default("eng"),
|
|
814
|
+
operator: z.enum(["AND", "OR"]).optional(),
|
|
815
|
+
isNegated: z.boolean().optional().default(false)
|
|
816
|
+
}).strict(),
|
|
817
|
+
z.object({
|
|
818
|
+
target: z.enum([
|
|
819
|
+
"title",
|
|
820
|
+
"description",
|
|
821
|
+
"image",
|
|
822
|
+
"periods",
|
|
823
|
+
"bibliography"
|
|
824
|
+
]),
|
|
825
|
+
value: z.string(),
|
|
826
|
+
matchMode: z.enum(["includes", "exact"]),
|
|
827
|
+
isCaseSensitive: z.boolean(),
|
|
828
|
+
language: z.string().default("eng"),
|
|
829
|
+
operator: z.enum(["AND", "OR"]).optional(),
|
|
830
|
+
isNegated: z.boolean().optional().default(false)
|
|
831
|
+
}).strict()
|
|
832
|
+
]);
|
|
833
|
+
const setQueriesSchema = z.array(setQuerySchema).default([]);
|
|
834
|
+
function validateSetQueriesOperators(queries, ctx) {
|
|
835
|
+
for (const [index, query] of queries.entries()) {
|
|
844
836
|
if (index === 0 && query.operator != null) ctx.addIssue({
|
|
845
837
|
code: "custom",
|
|
846
838
|
path: [
|
|
@@ -860,6 +852,29 @@ const setItemsParamsSchema = z.object({
|
|
|
860
852
|
message: "Query rules after the first must include an operator"
|
|
861
853
|
});
|
|
862
854
|
}
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Schema for validating the parameters for the Set property values by property variables fetching function
|
|
858
|
+
* @internal
|
|
859
|
+
*/
|
|
860
|
+
const setPropertyValuesByPropertyVariablesParamsSchema = z.object({
|
|
861
|
+
setScopeUuids: z.array(uuidSchema).min(1, "At least one set scope UUID is required"),
|
|
862
|
+
belongsToCollectionScopeUuids: z.array(uuidSchema).default([]),
|
|
863
|
+
propertyVariableUuids: z.array(uuidSchema).min(1, "At least one property variable UUID is required"),
|
|
864
|
+
queries: setQueriesSchema,
|
|
865
|
+
isLimitedToLeafPropertyValues: z.boolean().default(false)
|
|
866
|
+
}).superRefine((value, ctx) => {
|
|
867
|
+
validateSetQueriesOperators(value.queries, ctx);
|
|
868
|
+
});
|
|
869
|
+
const setItemsParamsSchema = z.object({
|
|
870
|
+
setScopeUuids: z.array(uuidSchema).min(1, "At least one set scope UUID is required"),
|
|
871
|
+
belongsToCollectionScopeUuids: z.array(uuidSchema).default([]),
|
|
872
|
+
propertyVariableUuids: z.array(uuidSchema).default([]),
|
|
873
|
+
queries: setQueriesSchema,
|
|
874
|
+
page: z.number().min(1, "Page must be positive").default(1),
|
|
875
|
+
pageSize: z.number().min(1, "Page size must be positive").default(DEFAULT_PAGE_SIZE)
|
|
876
|
+
}).superRefine((value, ctx) => {
|
|
877
|
+
validateSetQueriesOperators(value.queries, ctx);
|
|
863
878
|
});
|
|
864
879
|
|
|
865
880
|
//#endregion
|
|
@@ -1069,7 +1084,7 @@ function parseLink(linkRaw) {
|
|
|
1069
1084
|
const returnLink = {
|
|
1070
1085
|
category: categoryKey,
|
|
1071
1086
|
content: "content" in link && link.content != null ? parseFakeString(link.content) : null,
|
|
1072
|
-
href: "href" in link && link.href != null ? link.href : null,
|
|
1087
|
+
href: "href" in link && link.href != null ? transformPermanentIdentificationUrl(link.href) : null,
|
|
1073
1088
|
fileFormat: "fileFormat" in link && link.fileFormat != null ? link.fileFormat : null,
|
|
1074
1089
|
fileSize: "fileSize" in link && link.fileSize != null ? link.fileSize : null,
|
|
1075
1090
|
uuid: link.uuid ?? null,
|
|
@@ -1126,9 +1141,9 @@ function parseImage(image) {
|
|
|
1126
1141
|
return {
|
|
1127
1142
|
publicationDateTime: parseOptionalDate(image.publicationDateTime),
|
|
1128
1143
|
identification: image.identification ? parseIdentification(image.identification) : null,
|
|
1129
|
-
url: image.href
|
|
1144
|
+
url: image.href != null ? transformPermanentIdentificationUrl(image.href) : image.htmlImgSrcPrefix == null && image.content != null ? transformPermanentIdentificationUrl(parseFakeString(image.content)) : null,
|
|
1130
1145
|
htmlPrefix: image.htmlImgSrcPrefix ?? null,
|
|
1131
|
-
content: image.htmlImgSrcPrefix != null && image.content != null ? parseFakeString(image.content) : null,
|
|
1146
|
+
content: image.htmlImgSrcPrefix != null && image.content != null ? transformPermanentIdentificationUrl(parseFakeString(image.content)) : null,
|
|
1132
1147
|
widthPreview: image.widthPreview ?? null,
|
|
1133
1148
|
heightPreview: image.heightPreview ?? null,
|
|
1134
1149
|
width: image.width ?? null,
|
|
@@ -1363,7 +1378,7 @@ function parseProperty(property, language = "eng") {
|
|
|
1363
1378
|
height: value.height ?? null,
|
|
1364
1379
|
width: value.width ?? null,
|
|
1365
1380
|
fileSize: value.fileSize ?? null,
|
|
1366
|
-
href: value.href
|
|
1381
|
+
href: value.href != null ? transformPermanentIdentificationUrl(value.href) : null,
|
|
1367
1382
|
slug: value.slug ?? null
|
|
1368
1383
|
};
|
|
1369
1384
|
}
|
|
@@ -1465,7 +1480,7 @@ function parseBibliography(bibliography, metadata, persistentUrl, belongsTo) {
|
|
|
1465
1480
|
publicationDateTime: parseISO(resource.publicationDateTime),
|
|
1466
1481
|
type: resource.type,
|
|
1467
1482
|
identification: parseIdentification(resource.identification),
|
|
1468
|
-
href: resource.href
|
|
1483
|
+
href: resource.href != null ? transformPermanentIdentificationUrl(resource.href) : null
|
|
1469
1484
|
})) : [];
|
|
1470
1485
|
return {
|
|
1471
1486
|
uuid: bibliography.uuid ?? null,
|
|
@@ -1844,7 +1859,7 @@ function parseResource(resource, metadata, persistentUrl, belongsTo) {
|
|
|
1844
1859
|
description: resource.description ? parseFakeStringOrContent(resource.description) : "",
|
|
1845
1860
|
coordinates: resource.coordinates ? parseCoordinates(resource.coordinates) : [],
|
|
1846
1861
|
document: resource.document && "content" in resource.document ? parseDocument(resource.document.content) : null,
|
|
1847
|
-
href: resource.href
|
|
1862
|
+
href: resource.href != null ? transformPermanentIdentificationUrl(resource.href) : null,
|
|
1848
1863
|
imageMap: resource.imagemap ? parseImageMap(resource.imagemap) : null,
|
|
1849
1864
|
periods: resource.periods ? parsePeriods(ensureArray(resource.periods.period)) : [],
|
|
1850
1865
|
links: resource.links ? parseLinks(ensureArray(resource.links)) : [],
|
|
@@ -2105,17 +2120,11 @@ async function fetchItem(uuid, category, itemCategories, options) {
|
|
|
2105
2120
|
}
|
|
2106
2121
|
|
|
2107
2122
|
//#endregion
|
|
2108
|
-
//#region src/utils/fetchers/set/
|
|
2123
|
+
//#region src/utils/fetchers/set/query-helpers.ts
|
|
2109
2124
|
/**
|
|
2110
2125
|
* Build a string match predicate for an XQuery string
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
* @param params.value - The value to match
|
|
2114
|
-
* @param params.matchMode - The match mode (includes or exact)
|
|
2115
|
-
* @param params.isCaseSensitive - Whether to match case-sensitively
|
|
2116
|
-
* @returns The string match predicate
|
|
2117
|
-
*/
|
|
2118
|
-
function buildStringMatchPredicate$1(params) {
|
|
2126
|
+
*/
|
|
2127
|
+
function buildStringMatchPredicate(params) {
|
|
2119
2128
|
const { path, value, matchMode, isCaseSensitive } = params;
|
|
2120
2129
|
const comparedPath = isCaseSensitive ? path : `lower-case(${path})`;
|
|
2121
2130
|
const comparedValueLiteral = stringLiteral(isCaseSensitive ? value : value.toLowerCase());
|
|
@@ -2134,8 +2143,6 @@ function buildDateRangePredicate(params) {
|
|
|
2134
2143
|
}
|
|
2135
2144
|
/**
|
|
2136
2145
|
* Build a property value predicate for an XQuery string
|
|
2137
|
-
* @param query - The propertyValue query
|
|
2138
|
-
* @returns The property value predicate
|
|
2139
2146
|
*/
|
|
2140
2147
|
function buildPropertyValuePredicate(query) {
|
|
2141
2148
|
if (query.dataType === "IDREF") return `.//properties//property[value[@uuid=${stringLiteral(query.value)}]]`;
|
|
@@ -2144,7 +2151,7 @@ function buildPropertyValuePredicate(query) {
|
|
|
2144
2151
|
to: query.to
|
|
2145
2152
|
})}]`;
|
|
2146
2153
|
if (query.dataType === "time" || query.dataType === "integer" || query.dataType === "decimal" || query.dataType === "boolean") return `.//properties//property[value[@rawValue=${stringLiteral(query.value)}]]`;
|
|
2147
|
-
return `.//properties//property[${buildStringMatchPredicate
|
|
2154
|
+
return `.//properties//property[${buildStringMatchPredicate({
|
|
2148
2155
|
path: `string-join(value/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2149
2156
|
value: query.value,
|
|
2150
2157
|
matchMode: query.matchMode,
|
|
@@ -2153,36 +2160,34 @@ function buildPropertyValuePredicate(query) {
|
|
|
2153
2160
|
}
|
|
2154
2161
|
/**
|
|
2155
2162
|
* Build a query predicate for an XQuery string
|
|
2156
|
-
* @param query - The query to build the predicate for
|
|
2157
|
-
* @returns The query predicate
|
|
2158
2163
|
*/
|
|
2159
2164
|
function buildQueryPredicate(query) {
|
|
2160
2165
|
switch (query.target) {
|
|
2161
|
-
case "title": return buildStringMatchPredicate
|
|
2166
|
+
case "title": return buildStringMatchPredicate({
|
|
2162
2167
|
path: `string-join(identification/label/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2163
2168
|
value: query.value,
|
|
2164
2169
|
matchMode: query.matchMode,
|
|
2165
2170
|
isCaseSensitive: query.isCaseSensitive
|
|
2166
2171
|
});
|
|
2167
|
-
case "description": return buildStringMatchPredicate
|
|
2172
|
+
case "description": return buildStringMatchPredicate({
|
|
2168
2173
|
path: `string-join(description/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2169
2174
|
value: query.value,
|
|
2170
2175
|
matchMode: query.matchMode,
|
|
2171
2176
|
isCaseSensitive: query.isCaseSensitive
|
|
2172
2177
|
});
|
|
2173
|
-
case "periods": return buildStringMatchPredicate
|
|
2178
|
+
case "periods": return buildStringMatchPredicate({
|
|
2174
2179
|
path: `string-join(periods/period/identification/label/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2175
2180
|
value: query.value,
|
|
2176
2181
|
matchMode: query.matchMode,
|
|
2177
2182
|
isCaseSensitive: query.isCaseSensitive
|
|
2178
2183
|
});
|
|
2179
|
-
case "bibliography": return buildStringMatchPredicate
|
|
2184
|
+
case "bibliography": return buildStringMatchPredicate({
|
|
2180
2185
|
path: `string-join(bibliographies/bibliography/identification/label/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2181
2186
|
value: query.value,
|
|
2182
2187
|
matchMode: query.matchMode,
|
|
2183
2188
|
isCaseSensitive: query.isCaseSensitive
|
|
2184
2189
|
});
|
|
2185
|
-
case "image": return buildStringMatchPredicate
|
|
2190
|
+
case "image": return buildStringMatchPredicate({
|
|
2186
2191
|
path: `string-join(image/identification/label/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2187
2192
|
value: query.value,
|
|
2188
2193
|
matchMode: query.matchMode,
|
|
@@ -2199,6 +2204,19 @@ function buildBooleanQueryClause(query) {
|
|
|
2199
2204
|
return query.isNegated ? `not(${baseClause})` : baseClause;
|
|
2200
2205
|
}
|
|
2201
2206
|
/**
|
|
2207
|
+
* Build query filters for an XQuery string.
|
|
2208
|
+
*/
|
|
2209
|
+
function buildQueryFilters(queries) {
|
|
2210
|
+
return queries.map((query, index) => {
|
|
2211
|
+
const clause = buildBooleanQueryClause(query);
|
|
2212
|
+
if (index === 0) return clause;
|
|
2213
|
+
return `${query.operator === "OR" ? "or" : "and"} ${clause}`;
|
|
2214
|
+
}).join(" ");
|
|
2215
|
+
}
|
|
2216
|
+
|
|
2217
|
+
//#endregion
|
|
2218
|
+
//#region src/utils/fetchers/set/items.ts
|
|
2219
|
+
/**
|
|
2202
2220
|
* Build an XQuery string to fetch Set items from the OCHRE API
|
|
2203
2221
|
* @param params - The parameters for the fetch
|
|
2204
2222
|
* @param params.setScopeUuids - An array of Set scope UUIDs to filter by
|
|
@@ -2217,11 +2235,7 @@ function buildXQuery$1(params, options) {
|
|
|
2217
2235
|
const startPosition = (page - 1) * pageSize + 1;
|
|
2218
2236
|
const endPosition = page * pageSize;
|
|
2219
2237
|
const setScopeFilter = `/set[(${setScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")})]/items/*`;
|
|
2220
|
-
const queryFilters = queries
|
|
2221
|
-
const clause = buildBooleanQueryClause(query);
|
|
2222
|
-
if (index === 0) return clause;
|
|
2223
|
-
return `${query.operator === "OR" ? "or" : "and"} ${clause}`;
|
|
2224
|
-
}).join(" ");
|
|
2238
|
+
const queryFilters = buildQueryFilters(queries);
|
|
2225
2239
|
const filterPredicates = [];
|
|
2226
2240
|
if (belongsToCollectionScopeUuids.length > 0) {
|
|
2227
2241
|
const belongsToCollectionScopeValues = belongsToCollectionScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
|
|
@@ -2397,35 +2411,6 @@ function aggregatePropertyValues(values) {
|
|
|
2397
2411
|
});
|
|
2398
2412
|
}
|
|
2399
2413
|
/**
|
|
2400
|
-
* Build a string match predicate for an XQuery string
|
|
2401
|
-
* @param params - The parameters for the predicate
|
|
2402
|
-
* @param params.path - The path to the string
|
|
2403
|
-
* @param params.value - The value to match
|
|
2404
|
-
* @param params.matchMode - The match mode (includes or exact)
|
|
2405
|
-
* @param params.isCaseSensitive - Whether to match case-sensitively
|
|
2406
|
-
* @returns The string match predicate
|
|
2407
|
-
*/
|
|
2408
|
-
function buildStringMatchPredicate(params) {
|
|
2409
|
-
const { path, value, matchMode, isCaseSensitive } = params;
|
|
2410
|
-
const comparedPath = isCaseSensitive ? path : `lower-case(${path})`;
|
|
2411
|
-
const comparedValueLiteral = stringLiteral(isCaseSensitive ? value : value.toLowerCase());
|
|
2412
|
-
if (matchMode === "includes") return `contains(${comparedPath}, ${comparedValueLiteral})`;
|
|
2413
|
-
return `${comparedPath} = ${comparedValueLiteral}`;
|
|
2414
|
-
}
|
|
2415
|
-
/**
|
|
2416
|
-
* Build a title predicate for an XQuery string
|
|
2417
|
-
* @param titleQuery - The title query
|
|
2418
|
-
* @returns The title predicate
|
|
2419
|
-
*/
|
|
2420
|
-
function buildTitlePredicate(titleQuery) {
|
|
2421
|
-
return buildStringMatchPredicate({
|
|
2422
|
-
path: `string-join(identification/label/content[@xml:lang="${titleQuery.language}"]/string, "")`,
|
|
2423
|
-
value: titleQuery.value,
|
|
2424
|
-
matchMode: titleQuery.matchMode,
|
|
2425
|
-
isCaseSensitive: titleQuery.isCaseSensitive
|
|
2426
|
-
});
|
|
2427
|
-
}
|
|
2428
|
-
/**
|
|
2429
2414
|
* Schema for a single property value query item in the OCHRE API response
|
|
2430
2415
|
*/
|
|
2431
2416
|
const propertyValueQueryItemSchema = z.object({
|
|
@@ -2482,7 +2467,7 @@ const responseSchema = z.object({ result: z.union([z.object({ ochre: z.object({
|
|
|
2482
2467
|
* @param params.setScopeUuids - An array of set scope UUIDs to filter by
|
|
2483
2468
|
* @param params.belongsToCollectionScopeUuids - An array of collection scope UUIDs to filter by
|
|
2484
2469
|
* @param params.propertyVariableUuids - An array of property variable UUIDs to fetch
|
|
2485
|
-
* @param params.
|
|
2470
|
+
* @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
|
|
2486
2471
|
* @param params.isLimitedToLeafPropertyValues - Whether to limit the property values to leaf property values
|
|
2487
2472
|
* @param options - Options for the fetch
|
|
2488
2473
|
* @param options.version - The version of the OCHRE API to use
|
|
@@ -2490,16 +2475,17 @@ const responseSchema = z.object({ result: z.union([z.object({ ochre: z.object({
|
|
|
2490
2475
|
*/
|
|
2491
2476
|
function buildXQuery(params, options) {
|
|
2492
2477
|
const version = options?.version ?? DEFAULT_API_VERSION;
|
|
2493
|
-
const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids,
|
|
2478
|
+
const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, queries, isLimitedToLeafPropertyValues } = params;
|
|
2494
2479
|
let setScopeFilter = "/set/items/*";
|
|
2495
2480
|
if (setScopeUuids.length > 0) setScopeFilter = `/set[(${setScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")})]/items/*`;
|
|
2496
2481
|
const propertyVariableFilters = propertyVariableUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
|
|
2482
|
+
const queryFilters = buildQueryFilters(queries);
|
|
2497
2483
|
const filterPredicates = [];
|
|
2498
2484
|
if (belongsToCollectionScopeUuids.length > 0) {
|
|
2499
2485
|
const belongsToCollectionScopeValues = belongsToCollectionScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
|
|
2500
2486
|
filterPredicates.push(`.//properties[property[label/@uuid="${BELONGS_TO_COLLECTION_UUID}" and value/(${belongsToCollectionScopeValues})]]`);
|
|
2501
2487
|
}
|
|
2502
|
-
if (
|
|
2488
|
+
if (queryFilters.length > 0) filterPredicates.push(`(${queryFilters})`);
|
|
2503
2489
|
const itemFilters = filterPredicates.length > 0 ? `[${filterPredicates.join(" and ")}]` : "";
|
|
2504
2490
|
return `<ochre>{${`let $items := ${version === 2 ? "doc()" : "input()"}/ochre
|
|
2505
2491
|
${setScopeFilter}
|
|
@@ -2522,7 +2508,7 @@ function buildXQuery(params, options) {
|
|
|
2522
2508
|
* @param params.setScopeUuids - An array of set scope UUIDs to filter by
|
|
2523
2509
|
* @param params.belongsToCollectionScopeUuids - The collection scope UUIDs to filter by
|
|
2524
2510
|
* @param params.propertyVariableUuids - The property variable UUIDs to query by
|
|
2525
|
-
* @param params.
|
|
2511
|
+
* @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
|
|
2526
2512
|
* @param params.isLimitedToLeafPropertyValues - Whether to limit the property values to leaf property values
|
|
2527
2513
|
* @param options - Options for the fetch
|
|
2528
2514
|
* @param options.fetch - The fetch function to use
|
|
@@ -2532,12 +2518,12 @@ function buildXQuery(params, options) {
|
|
|
2532
2518
|
async function fetchSetPropertyValuesByPropertyVariables(params, options) {
|
|
2533
2519
|
try {
|
|
2534
2520
|
const version = options?.version ?? DEFAULT_API_VERSION;
|
|
2535
|
-
const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids,
|
|
2521
|
+
const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, queries, isLimitedToLeafPropertyValues } = setPropertyValuesByPropertyVariablesParamsSchema.parse(params);
|
|
2536
2522
|
const xquery = buildXQuery({
|
|
2537
2523
|
setScopeUuids,
|
|
2538
2524
|
belongsToCollectionScopeUuids,
|
|
2539
2525
|
propertyVariableUuids,
|
|
2540
|
-
|
|
2526
|
+
queries,
|
|
2541
2527
|
isLimitedToLeafPropertyValues
|
|
2542
2528
|
}, { version });
|
|
2543
2529
|
const response = await (options?.fetch ?? fetch)(version === 2 ? `https://ochre.lib.uchicago.edu/ochre/v2/ochre.php?xquery=${encodeURIComponent(xquery)}&format=json&lang="*"` : `https://ochre.lib.uchicago.edu/ochre?xquery=${encodeURIComponent(xquery)}&format=json&lang="*"`);
|
|
@@ -2939,7 +2925,7 @@ function parseWebElementProperties(componentProperty, elementResource) {
|
|
|
2939
2925
|
case "advanced-search": {
|
|
2940
2926
|
const boundElementPropertyUuid = getPropertyByLabel(componentProperty.properties, "bound-element")?.values[0]?.uuid ?? null;
|
|
2941
2927
|
const linkToProperty = getPropertyByLabel(componentProperty.properties, "link-to");
|
|
2942
|
-
const href = linkToProperty?.values[0]?.href
|
|
2928
|
+
const href = linkToProperty?.values[0]?.href != null ? transformPermanentIdentificationUrl(linkToProperty.values[0].href) : linkToProperty?.values[0]?.slug ?? null;
|
|
2943
2929
|
if (boundElementPropertyUuid == null && href == null) throw new Error(`Bound element or href not found for the following component: “${componentName}”`);
|
|
2944
2930
|
properties = {
|
|
2945
2931
|
component: "advanced-search",
|
|
@@ -3018,10 +3004,10 @@ function parseWebElementProperties(componentProperty, elementResource) {
|
|
|
3018
3004
|
variant ??= "default";
|
|
3019
3005
|
let isExternal = false;
|
|
3020
3006
|
const navigateToProperty = getPropertyByLabel(componentProperty.properties, "navigate-to");
|
|
3021
|
-
let href = navigateToProperty?.values[0]?.href
|
|
3007
|
+
let href = navigateToProperty?.values[0]?.href != null ? transformPermanentIdentificationUrl(navigateToProperty.values[0].href) : navigateToProperty?.values[0]?.slug ?? null;
|
|
3022
3008
|
if (href === null) {
|
|
3023
3009
|
const linkToProperty = getPropertyByLabel(componentProperty.properties, "link-to");
|
|
3024
|
-
href = linkToProperty?.values[0]?.href
|
|
3010
|
+
href = linkToProperty?.values[0]?.href != null ? transformPermanentIdentificationUrl(linkToProperty.values[0].href) : linkToProperty?.values[0]?.slug ?? null;
|
|
3025
3011
|
if (href === null) throw new Error(`Properties “navigate-to” or “link-to” not found for the following component: “${componentName}”`);
|
|
3026
3012
|
else isExternal = true;
|
|
3027
3013
|
}
|
|
@@ -3071,8 +3057,8 @@ function parseWebElementProperties(componentProperty, elementResource) {
|
|
|
3071
3057
|
isFilterMapDisplayed ??= false;
|
|
3072
3058
|
let isFilterInputDisplayed = getPropertyValueByLabel(componentProperty.properties, "filter-input-displayed");
|
|
3073
3059
|
isFilterInputDisplayed ??= false;
|
|
3074
|
-
let
|
|
3075
|
-
|
|
3060
|
+
let isFilterLimitedToInputFilter = getPropertyValueByLabel(componentProperty.properties, "filter-limit-to-input-filter");
|
|
3061
|
+
isFilterLimitedToInputFilter ??= false;
|
|
3076
3062
|
let isFilterLimitedToLeafPropertyValues = getPropertyValueByLabel(componentProperty.properties, "filter-limit-to-leaf-property-values");
|
|
3077
3063
|
isFilterLimitedToLeafPropertyValues ??= false;
|
|
3078
3064
|
let isSortDisplayed = getPropertyValueByLabel(componentProperty.properties, "sort-displayed");
|
|
@@ -3122,7 +3108,7 @@ function parseWebElementProperties(componentProperty, elementResource) {
|
|
|
3122
3108
|
isResultsBarDisplayed: isFilterResultsBarDisplayed,
|
|
3123
3109
|
isMapDisplayed: isFilterMapDisplayed,
|
|
3124
3110
|
isInputDisplayed: isFilterInputDisplayed,
|
|
3125
|
-
|
|
3111
|
+
isLimitedToInputFilter: isFilterLimitedToInputFilter,
|
|
3126
3112
|
isLimitedToLeafPropertyValues: isFilterLimitedToLeafPropertyValues,
|
|
3127
3113
|
sidebarSort: filterSidebarSort
|
|
3128
3114
|
},
|
|
@@ -3162,7 +3148,7 @@ function parseWebElementProperties(componentProperty, elementResource) {
|
|
|
3162
3148
|
const width = getPropertyValueByLabel(componentProperty.properties, "width");
|
|
3163
3149
|
properties = {
|
|
3164
3150
|
component: "iframe",
|
|
3165
|
-
href,
|
|
3151
|
+
href: transformPermanentIdentificationUrl(href),
|
|
3166
3152
|
height: height?.toString() ?? null,
|
|
3167
3153
|
width: width?.toString() ?? null
|
|
3168
3154
|
};
|
|
@@ -3393,7 +3379,7 @@ function parseWebElementProperties(componentProperty, elementResource) {
|
|
|
3393
3379
|
queryVariant ??= "submit";
|
|
3394
3380
|
const boundElementUuid = getPropertyByLabel(componentProperty.properties, "bound-element")?.values[0]?.uuid ?? null;
|
|
3395
3381
|
const linkToProperty = getPropertyByLabel(componentProperty.properties, "link-to");
|
|
3396
|
-
const href = linkToProperty?.values[0]?.href
|
|
3382
|
+
const href = linkToProperty?.values[0]?.href != null ? transformPermanentIdentificationUrl(linkToProperty.values[0].href) : linkToProperty?.values[0]?.slug ?? null;
|
|
3397
3383
|
if (!boundElementUuid && !href) throw new Error(`Bound element or href not found for the following component: “${componentName}”`);
|
|
3398
3384
|
let placeholder = getPropertyValueByLabel(componentProperty.properties, "placeholder-text");
|
|
3399
3385
|
placeholder ??= null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ochre-sdk",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.11",
|
|
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",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@antfu/eslint-config": "^7.6.1",
|
|
50
|
-
"@types/node": "^24.10.
|
|
50
|
+
"@types/node": "^24.10.15",
|
|
51
51
|
"bumpp": "^10.4.1",
|
|
52
52
|
"eslint": "^10.0.2",
|
|
53
53
|
"prettier": "^3.8.1",
|