ochre-sdk 0.20.20 → 0.20.22
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 +0 -4
- package/dist/index.mjs +215 -50
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1223,7 +1223,6 @@ declare function fetchItem<T extends DataCategory = DataCategory, U extends Data
|
|
|
1223
1223
|
*
|
|
1224
1224
|
* @param params - The parameters for the fetch
|
|
1225
1225
|
* @param params.setScopeUuids - The Set scope UUIDs to filter by
|
|
1226
|
-
* @param params.belongsToCollectionScopeUuids - The collection scope UUIDs to filter by
|
|
1227
1226
|
* @param params.propertyVariableUuids - The property variable UUIDs to filter by
|
|
1228
1227
|
* @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
|
|
1229
1228
|
* @param params.sort - Optional sorting configuration applied before pagination.
|
|
@@ -1238,7 +1237,6 @@ declare function fetchItem<T extends DataCategory = DataCategory, U extends Data
|
|
|
1238
1237
|
*/
|
|
1239
1238
|
declare function fetchSetItems<U extends Array<DataCategory> = Array<DataCategory>>(params: {
|
|
1240
1239
|
setScopeUuids: Array<string>;
|
|
1241
|
-
belongsToCollectionScopeUuids: Array<string>;
|
|
1242
1240
|
propertyVariableUuids: Array<string>;
|
|
1243
1241
|
queries: Array<Query>;
|
|
1244
1242
|
sort?: SetItemsSort;
|
|
@@ -1267,7 +1265,6 @@ declare function fetchSetItems<U extends Array<DataCategory> = Array<DataCategor
|
|
|
1267
1265
|
*
|
|
1268
1266
|
* @param params - The parameters for the fetch
|
|
1269
1267
|
* @param params.setScopeUuids - An array of set scope UUIDs to filter by
|
|
1270
|
-
* @param params.belongsToCollectionScopeUuids - The collection scope UUIDs to filter by
|
|
1271
1268
|
* @param params.propertyVariableUuids - The property variable UUIDs to query by
|
|
1272
1269
|
* @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
|
|
1273
1270
|
* @param params.attributes - Whether to return values for bibliographies and periods
|
|
@@ -1282,7 +1279,6 @@ declare function fetchSetItems<U extends Array<DataCategory> = Array<DataCategor
|
|
|
1282
1279
|
*/
|
|
1283
1280
|
declare function fetchSetPropertyValuesByPropertyVariables(params: {
|
|
1284
1281
|
setScopeUuids: Array<string>;
|
|
1285
|
-
belongsToCollectionScopeUuids: Array<string>;
|
|
1286
1282
|
propertyVariableUuids: Array<string>;
|
|
1287
1283
|
queries?: Array<Query>;
|
|
1288
1284
|
attributes?: {
|
package/dist/index.mjs
CHANGED
|
@@ -16,6 +16,9 @@ const TEXT_ANNOTATION_TEXT_STYLING_HEADING_LEVEL_UUID = "d4266f0b-3f8d-4b32-8c15
|
|
|
16
16
|
|
|
17
17
|
//#endregion
|
|
18
18
|
//#region src/utils/string.ts
|
|
19
|
+
const EMAIL_BRACKET_CLEANUP_REGEX = /(?<=\s|^)[([{]+|[)\]}]+(?=\s|$)/g;
|
|
20
|
+
const EMAIL_PUNCTUATION_CLEANUP_REGEX = /[!),:;?\]]/g;
|
|
21
|
+
const EMAIL_TRAILING_PERIOD_REGEX = /\.$/;
|
|
19
22
|
/**
|
|
20
23
|
* Finds a string item in an array by language code
|
|
21
24
|
*
|
|
@@ -46,7 +49,7 @@ function parseEmail(string) {
|
|
|
46
49
|
const splitString = string.split(" ");
|
|
47
50
|
const returnSplitString = [];
|
|
48
51
|
for (const string of splitString) {
|
|
49
|
-
const cleanString = transformPermanentIdentificationUrl(string).replaceAll(
|
|
52
|
+
const cleanString = transformPermanentIdentificationUrl(string).replaceAll(EMAIL_BRACKET_CLEANUP_REGEX, "").replaceAll(EMAIL_PUNCTUATION_CLEANUP_REGEX, "").replace(EMAIL_TRAILING_PERIOD_REGEX, "");
|
|
50
53
|
const index = string.indexOf(cleanString);
|
|
51
54
|
const before = string.slice(0, index);
|
|
52
55
|
const after = string.slice(index + cleanString.length);
|
|
@@ -442,6 +445,7 @@ function parseStringContent(content, language = "eng") {
|
|
|
442
445
|
|
|
443
446
|
//#endregion
|
|
444
447
|
//#region src/utils/internal.ts
|
|
448
|
+
const PSEUDO_UUID_REGEX = /^[\da-f]{8}(?:-[\da-f]{4}){3}-[\da-f]{12}$/i;
|
|
445
449
|
/**
|
|
446
450
|
* Get the category of an item from the OCHRE API response
|
|
447
451
|
* @param keys - The keys of the OCHRE API response
|
|
@@ -481,7 +485,7 @@ function getItemCategories(keys) {
|
|
|
481
485
|
* @internal
|
|
482
486
|
*/
|
|
483
487
|
function isPseudoUuid(value) {
|
|
484
|
-
return
|
|
488
|
+
return PSEUDO_UUID_REGEX.test(value);
|
|
485
489
|
}
|
|
486
490
|
/**
|
|
487
491
|
* Flatten a properties array
|
|
@@ -900,6 +904,7 @@ const setItemsParamsSchema = z.object({
|
|
|
900
904
|
|
|
901
905
|
//#endregion
|
|
902
906
|
//#region src/utils/parse/index.ts
|
|
907
|
+
const TRAILING_ELLIPSIS_REGEX = /\s*\.{3}$/;
|
|
903
908
|
/**
|
|
904
909
|
* Parses raw identification data into the standardized Identification type
|
|
905
910
|
*
|
|
@@ -1406,7 +1411,7 @@ function parseProperty(property, language = "eng") {
|
|
|
1406
1411
|
});
|
|
1407
1412
|
return {
|
|
1408
1413
|
uuid: property.label.uuid,
|
|
1409
|
-
label: parseStringContent(property.label, language).replace(
|
|
1414
|
+
label: parseStringContent(property.label, language).replace(TRAILING_ELLIPSIS_REGEX, "").trim(),
|
|
1410
1415
|
values,
|
|
1411
1416
|
comment: property.comment != null ? parseStringContent(property.comment) : null,
|
|
1412
1417
|
properties: property.property ? parseProperties(ensureArray(property.property)) : []
|
|
@@ -2142,10 +2147,18 @@ async function fetchItem(uuid, category, itemCategories, options) {
|
|
|
2142
2147
|
|
|
2143
2148
|
//#endregion
|
|
2144
2149
|
//#region src/utils/fetchers/set/query-helpers.ts
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2150
|
+
const CTS_INCLUDES_STOP_WORDS = [
|
|
2151
|
+
"of",
|
|
2152
|
+
"the",
|
|
2153
|
+
"and",
|
|
2154
|
+
"in",
|
|
2155
|
+
"it"
|
|
2156
|
+
];
|
|
2157
|
+
const CTS_INCLUDES_STOP_WORDS_VAR = "$ctsIncludesStopWords";
|
|
2158
|
+
/**
|
|
2159
|
+
* Build a string match predicate for an XQuery string.
|
|
2160
|
+
*/
|
|
2161
|
+
function buildRawStringMatchPredicate(params) {
|
|
2149
2162
|
const { path, value, matchMode, isCaseSensitive } = params;
|
|
2150
2163
|
const comparedPath = isCaseSensitive ? path : `lower-case(${path})`;
|
|
2151
2164
|
const comparedValueLiteral = stringLiteral(isCaseSensitive ? value : value.toLowerCase());
|
|
@@ -2153,6 +2166,77 @@ function buildStringMatchPredicate(params) {
|
|
|
2153
2166
|
return `${comparedPath} = ${comparedValueLiteral}`;
|
|
2154
2167
|
}
|
|
2155
2168
|
/**
|
|
2169
|
+
* Build CTS word-query options for API v2 includes search.
|
|
2170
|
+
*/
|
|
2171
|
+
function buildCtsQueryOptionsExpression(isCaseSensitive) {
|
|
2172
|
+
return `(${[
|
|
2173
|
+
isCaseSensitive ? "case-sensitive" : "case-insensitive",
|
|
2174
|
+
"diacritic-insensitive",
|
|
2175
|
+
"punctuation-insensitive",
|
|
2176
|
+
"whitespace-insensitive",
|
|
2177
|
+
"stemmed"
|
|
2178
|
+
].map((option) => stringLiteral(option)).join(", ")})`;
|
|
2179
|
+
}
|
|
2180
|
+
/**
|
|
2181
|
+
* Build a CTS-backed includes predicate for an XQuery string.
|
|
2182
|
+
*/
|
|
2183
|
+
function buildCtsIncludesPredicate(params) {
|
|
2184
|
+
const { path, value, isCaseSensitive, queryIndex } = params;
|
|
2185
|
+
const searchStringVar = `$query${queryIndex}SearchString`;
|
|
2186
|
+
const rawTermsVar = `$query${queryIndex}RawTerms`;
|
|
2187
|
+
const termsVar = `$query${queryIndex}Terms`;
|
|
2188
|
+
const ctsQueryVar = `$query${queryIndex}CtsQuery`;
|
|
2189
|
+
const ctsOptionsExpression = buildCtsQueryOptionsExpression(isCaseSensitive);
|
|
2190
|
+
const fallbackPredicate = buildRawStringMatchPredicate({
|
|
2191
|
+
path,
|
|
2192
|
+
value,
|
|
2193
|
+
matchMode: "includes",
|
|
2194
|
+
isCaseSensitive
|
|
2195
|
+
});
|
|
2196
|
+
return {
|
|
2197
|
+
declarations: [
|
|
2198
|
+
`let ${searchStringVar} := ${stringLiteral(value)}`,
|
|
2199
|
+
String.raw`let ${rawTermsVar} := fn:tokenize(${searchStringVar}, "\W+")`,
|
|
2200
|
+
`let ${termsVar} :=
|
|
2201
|
+
for $term in ${rawTermsVar}
|
|
2202
|
+
let $normalizedTerm := fn:lower-case($term)
|
|
2203
|
+
where $normalizedTerm ne "" and not($normalizedTerm = ${CTS_INCLUDES_STOP_WORDS_VAR})
|
|
2204
|
+
return ${isCaseSensitive ? "$term" : "$normalizedTerm"}`,
|
|
2205
|
+
`let ${ctsQueryVar} :=
|
|
2206
|
+
if (count(${termsVar}) = 1)
|
|
2207
|
+
then cts:word-query(${termsVar}[1], ${ctsOptionsExpression})
|
|
2208
|
+
else if (count(${termsVar}) gt 1)
|
|
2209
|
+
then cts:near-query((
|
|
2210
|
+
for $term in ${termsVar}
|
|
2211
|
+
return cts:word-query($term, ${ctsOptionsExpression})
|
|
2212
|
+
), 5, ("unordered"))
|
|
2213
|
+
else ()`
|
|
2214
|
+
],
|
|
2215
|
+
predicate: `(if (exists(${ctsQueryVar})) then cts:contains(${path}, ${ctsQueryVar}) else ${fallbackPredicate})`
|
|
2216
|
+
};
|
|
2217
|
+
}
|
|
2218
|
+
/**
|
|
2219
|
+
* Build a string match predicate for an XQuery string.
|
|
2220
|
+
*/
|
|
2221
|
+
function buildStringMatchPredicate(params) {
|
|
2222
|
+
const { path, value, matchMode, isCaseSensitive, version, queryIndex } = params;
|
|
2223
|
+
if (matchMode === "includes" && version === 2) return buildCtsIncludesPredicate({
|
|
2224
|
+
path,
|
|
2225
|
+
value,
|
|
2226
|
+
isCaseSensitive,
|
|
2227
|
+
queryIndex
|
|
2228
|
+
});
|
|
2229
|
+
return {
|
|
2230
|
+
declarations: [],
|
|
2231
|
+
predicate: buildRawStringMatchPredicate({
|
|
2232
|
+
path,
|
|
2233
|
+
value,
|
|
2234
|
+
matchMode,
|
|
2235
|
+
isCaseSensitive
|
|
2236
|
+
})
|
|
2237
|
+
};
|
|
2238
|
+
}
|
|
2239
|
+
/**
|
|
2156
2240
|
* Build a date/dateTime range predicate for an XQuery string.
|
|
2157
2241
|
*/
|
|
2158
2242
|
function buildDateRangePredicate(params) {
|
|
@@ -2163,76 +2247,136 @@ function buildDateRangePredicate(params) {
|
|
|
2163
2247
|
return conditions.join(" and ");
|
|
2164
2248
|
}
|
|
2165
2249
|
/**
|
|
2166
|
-
* Build a property value predicate for an XQuery string
|
|
2250
|
+
* Build a property value predicate for an XQuery string.
|
|
2167
2251
|
*/
|
|
2168
|
-
function buildPropertyValuePredicate(
|
|
2169
|
-
|
|
2170
|
-
if (query.dataType === "
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
}
|
|
2174
|
-
if (query.dataType === "
|
|
2175
|
-
|
|
2252
|
+
function buildPropertyValuePredicate(params) {
|
|
2253
|
+
const { query, version, queryIndex } = params;
|
|
2254
|
+
if (query.dataType === "IDREF") return {
|
|
2255
|
+
declarations: [],
|
|
2256
|
+
predicate: `.//properties//property[value[@uuid=${stringLiteral(query.value)}]]`
|
|
2257
|
+
};
|
|
2258
|
+
if (query.dataType === "date" || query.dataType === "dateTime") return {
|
|
2259
|
+
declarations: [],
|
|
2260
|
+
predicate: `.//properties//property[(label/@uuid=${stringLiteral(query.value)}) and ${buildDateRangePredicate({
|
|
2261
|
+
from: query.from,
|
|
2262
|
+
to: query.to
|
|
2263
|
+
})}]`
|
|
2264
|
+
};
|
|
2265
|
+
if (query.dataType === "time" || query.dataType === "integer" || query.dataType === "decimal" || query.dataType === "boolean") return {
|
|
2266
|
+
declarations: [],
|
|
2267
|
+
predicate: `.//properties//property[value[@rawValue=${stringLiteral(query.value)}]]`
|
|
2268
|
+
};
|
|
2269
|
+
const compiledStringPredicate = buildStringMatchPredicate({
|
|
2176
2270
|
path: `string-join(value/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2177
2271
|
value: query.value,
|
|
2178
2272
|
matchMode: query.matchMode,
|
|
2179
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2180
|
-
|
|
2273
|
+
isCaseSensitive: query.isCaseSensitive,
|
|
2274
|
+
version,
|
|
2275
|
+
queryIndex
|
|
2276
|
+
});
|
|
2277
|
+
return {
|
|
2278
|
+
declarations: compiledStringPredicate.declarations,
|
|
2279
|
+
predicate: `.//properties//property[${compiledStringPredicate.predicate}]`
|
|
2280
|
+
};
|
|
2181
2281
|
}
|
|
2182
2282
|
/**
|
|
2183
|
-
* Build a query predicate for an XQuery string
|
|
2283
|
+
* Build a query predicate for an XQuery string.
|
|
2184
2284
|
*/
|
|
2185
|
-
function buildQueryPredicate(
|
|
2285
|
+
function buildQueryPredicate(params) {
|
|
2286
|
+
const { query, version, queryIndex } = params;
|
|
2186
2287
|
switch (query.target) {
|
|
2187
2288
|
case "title": return buildStringMatchPredicate({
|
|
2188
2289
|
path: `string-join(identification/label/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2189
2290
|
value: query.value,
|
|
2190
2291
|
matchMode: query.matchMode,
|
|
2191
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2292
|
+
isCaseSensitive: query.isCaseSensitive,
|
|
2293
|
+
version,
|
|
2294
|
+
queryIndex
|
|
2192
2295
|
});
|
|
2193
2296
|
case "description": return buildStringMatchPredicate({
|
|
2194
2297
|
path: `string-join(description/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2195
2298
|
value: query.value,
|
|
2196
2299
|
matchMode: query.matchMode,
|
|
2197
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2300
|
+
isCaseSensitive: query.isCaseSensitive,
|
|
2301
|
+
version,
|
|
2302
|
+
queryIndex
|
|
2198
2303
|
});
|
|
2199
2304
|
case "periods": return buildStringMatchPredicate({
|
|
2200
2305
|
path: `string-join(periods/period/identification/label/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2201
2306
|
value: query.value,
|
|
2202
2307
|
matchMode: query.matchMode,
|
|
2203
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2308
|
+
isCaseSensitive: query.isCaseSensitive,
|
|
2309
|
+
version,
|
|
2310
|
+
queryIndex
|
|
2204
2311
|
});
|
|
2205
2312
|
case "bibliography": return buildStringMatchPredicate({
|
|
2206
2313
|
path: `string-join(bibliographies/bibliography/identification/label/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2207
2314
|
value: query.value,
|
|
2208
2315
|
matchMode: query.matchMode,
|
|
2209
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2316
|
+
isCaseSensitive: query.isCaseSensitive,
|
|
2317
|
+
version,
|
|
2318
|
+
queryIndex
|
|
2210
2319
|
});
|
|
2211
2320
|
case "image": return buildStringMatchPredicate({
|
|
2212
2321
|
path: `string-join(image/identification/label/content[@xml:lang="${query.language}"]/string, "")`,
|
|
2213
2322
|
value: query.value,
|
|
2214
2323
|
matchMode: query.matchMode,
|
|
2215
|
-
isCaseSensitive: query.isCaseSensitive
|
|
2324
|
+
isCaseSensitive: query.isCaseSensitive,
|
|
2325
|
+
version,
|
|
2326
|
+
queryIndex
|
|
2327
|
+
});
|
|
2328
|
+
case "propertyValue": return buildPropertyValuePredicate({
|
|
2329
|
+
query,
|
|
2330
|
+
version,
|
|
2331
|
+
queryIndex
|
|
2216
2332
|
});
|
|
2217
|
-
case "propertyValue": return buildPropertyValuePredicate(query);
|
|
2218
2333
|
}
|
|
2219
2334
|
}
|
|
2220
2335
|
/**
|
|
2221
2336
|
* Build a boolean query clause for an XQuery string.
|
|
2222
2337
|
*/
|
|
2223
|
-
function buildBooleanQueryClause(
|
|
2224
|
-
const
|
|
2225
|
-
|
|
2338
|
+
function buildBooleanQueryClause(params) {
|
|
2339
|
+
const { query, version, queryIndex } = params;
|
|
2340
|
+
const compiledQueryPredicate = buildQueryPredicate({
|
|
2341
|
+
query,
|
|
2342
|
+
version,
|
|
2343
|
+
queryIndex
|
|
2344
|
+
});
|
|
2345
|
+
const baseClause = `(${compiledQueryPredicate.predicate})`;
|
|
2346
|
+
return {
|
|
2347
|
+
declarations: compiledQueryPredicate.declarations,
|
|
2348
|
+
predicate: query.isNegated ? `not(${baseClause})` : baseClause
|
|
2349
|
+
};
|
|
2226
2350
|
}
|
|
2227
2351
|
/**
|
|
2228
2352
|
* Build query filters for an XQuery string.
|
|
2229
2353
|
*/
|
|
2230
|
-
function buildQueryFilters(
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2354
|
+
function buildQueryFilters(params) {
|
|
2355
|
+
const { queries, version } = params;
|
|
2356
|
+
const declarations = [];
|
|
2357
|
+
const predicateParts = [];
|
|
2358
|
+
let hasCtsIncludesClauses = false;
|
|
2359
|
+
for (const [index, query] of queries.entries()) {
|
|
2360
|
+
const compiledClause = buildBooleanQueryClause({
|
|
2361
|
+
query,
|
|
2362
|
+
version,
|
|
2363
|
+
queryIndex: index + 1
|
|
2364
|
+
});
|
|
2365
|
+
if (compiledClause.declarations.length > 0) {
|
|
2366
|
+
hasCtsIncludesClauses = true;
|
|
2367
|
+
declarations.push(...compiledClause.declarations);
|
|
2368
|
+
}
|
|
2369
|
+
if (index === 0) {
|
|
2370
|
+
predicateParts.push(compiledClause.predicate);
|
|
2371
|
+
continue;
|
|
2372
|
+
}
|
|
2373
|
+
predicateParts.push(`${query.operator === "AND" ? "and" : "or"} ${compiledClause.predicate}`);
|
|
2374
|
+
}
|
|
2375
|
+
if (hasCtsIncludesClauses) declarations.unshift(`let ${CTS_INCLUDES_STOP_WORDS_VAR} := (${CTS_INCLUDES_STOP_WORDS.map((stopWord) => stringLiteral(stopWord)).join(", ")})`);
|
|
2376
|
+
return {
|
|
2377
|
+
declarations,
|
|
2378
|
+
predicate: predicateParts.join(" ")
|
|
2379
|
+
};
|
|
2236
2380
|
}
|
|
2237
2381
|
|
|
2238
2382
|
//#endregion
|
|
@@ -2328,7 +2472,11 @@ function buildXQuery$1(params, options) {
|
|
|
2328
2472
|
const startPosition = (page - 1) * pageSize + 1;
|
|
2329
2473
|
const endPosition = page * pageSize;
|
|
2330
2474
|
const setScopeFilter = `/set[(${setScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")})]/items/*`;
|
|
2331
|
-
const
|
|
2475
|
+
const compiledQueryFilters = buildQueryFilters({
|
|
2476
|
+
queries,
|
|
2477
|
+
version
|
|
2478
|
+
});
|
|
2479
|
+
const queryFilterDeclarations = compiledQueryFilters.declarations.length > 0 ? `${compiledQueryFilters.declarations.join("\n")}\n\n` : "";
|
|
2332
2480
|
const filterPredicates = [];
|
|
2333
2481
|
if (belongsToCollectionScopeUuids.length > 0) {
|
|
2334
2482
|
const belongsToCollectionScopeValues = belongsToCollectionScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
|
|
@@ -2338,10 +2486,10 @@ function buildXQuery$1(params, options) {
|
|
|
2338
2486
|
const propertyVariables = propertyVariableUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
|
|
2339
2487
|
filterPredicates.push(`.//properties//property[label[${propertyVariables}]]`);
|
|
2340
2488
|
}
|
|
2341
|
-
if (
|
|
2489
|
+
if (compiledQueryFilters.predicate.length > 0) filterPredicates.push(`(${compiledQueryFilters.predicate})`);
|
|
2342
2490
|
const itemFilters = filterPredicates.length > 0 ? `[${filterPredicates.join(" and ")}]` : "";
|
|
2343
2491
|
const orderedItemsClause = buildOrderedItemsClause(sort);
|
|
2344
|
-
return `<ochre>{${
|
|
2492
|
+
return `<ochre>{${`${queryFilterDeclarations}let $items := ${version === 2 ? "doc()" : "input()"}/ochre
|
|
2345
2493
|
${setScopeFilter}
|
|
2346
2494
|
${itemFilters}
|
|
2347
2495
|
|
|
@@ -2360,7 +2508,6 @@ function buildXQuery$1(params, options) {
|
|
|
2360
2508
|
*
|
|
2361
2509
|
* @param params - The parameters for the fetch
|
|
2362
2510
|
* @param params.setScopeUuids - The Set scope UUIDs to filter by
|
|
2363
|
-
* @param params.belongsToCollectionScopeUuids - The collection scope UUIDs to filter by
|
|
2364
2511
|
* @param params.propertyVariableUuids - The property variable UUIDs to filter by
|
|
2365
2512
|
* @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
|
|
2366
2513
|
* @param params.sort - Optional sorting configuration applied before pagination.
|
|
@@ -2386,7 +2533,13 @@ async function fetchSetItems(params, itemCategories, options) {
|
|
|
2386
2533
|
page,
|
|
2387
2534
|
pageSize
|
|
2388
2535
|
}, { version });
|
|
2389
|
-
|
|
2536
|
+
let response;
|
|
2537
|
+
if (version === 2) response = await (options?.fetch ?? fetch)("https://ochre.lib.uchicago.edu/ochre/v2/ochre.php?xquery&format=json", {
|
|
2538
|
+
method: "POST",
|
|
2539
|
+
body: xquery,
|
|
2540
|
+
headers: { "Content-Type": "application/xquery" }
|
|
2541
|
+
});
|
|
2542
|
+
else response = await (options?.fetch ?? fetch)(`https://ochre.lib.uchicago.edu/ochre?xquery=${encodeURIComponent(xquery)}&format=json&lang="*"`);
|
|
2390
2543
|
if (!response.ok) throw new Error(`OCHRE API responded with status: ${response.status}`);
|
|
2391
2544
|
const data = await response.json();
|
|
2392
2545
|
if (Array.isArray(data.result) || Object.keys(data.result).length === 0) throw new Error("No items found");
|
|
@@ -2622,13 +2775,17 @@ function buildXQuery(params, options) {
|
|
|
2622
2775
|
let setScopeFilter = "/set/items/*";
|
|
2623
2776
|
if (setScopeUuids.length > 0) setScopeFilter = `/set[(${setScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")})]/items/*`;
|
|
2624
2777
|
const propertyVariableFilters = propertyVariableUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
|
|
2625
|
-
const
|
|
2778
|
+
const compiledQueryFilters = buildQueryFilters({
|
|
2779
|
+
queries,
|
|
2780
|
+
version
|
|
2781
|
+
});
|
|
2782
|
+
const queryFilterDeclarations = compiledQueryFilters.declarations.length > 0 ? `${compiledQueryFilters.declarations.join("\n")}\n\n` : "";
|
|
2626
2783
|
const filterPredicates = [];
|
|
2627
2784
|
if (belongsToCollectionScopeUuids.length > 0) {
|
|
2628
2785
|
const belongsToCollectionScopeValues = belongsToCollectionScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
|
|
2629
2786
|
filterPredicates.push(`.//properties[property[label/@uuid="${BELONGS_TO_COLLECTION_UUID}" and value[${belongsToCollectionScopeValues}]]]`);
|
|
2630
2787
|
}
|
|
2631
|
-
if (
|
|
2788
|
+
if (compiledQueryFilters.predicate.length > 0) filterPredicates.push(`(${compiledQueryFilters.predicate})`);
|
|
2632
2789
|
const itemFilters = filterPredicates.length > 0 ? `[${filterPredicates.join(" and ")}]` : "";
|
|
2633
2790
|
const queryBlocks = [`let $matching-props := $items//property[label[${propertyVariableFilters}]]
|
|
2634
2791
|
|
|
@@ -2659,7 +2816,7 @@ let $property-values :=
|
|
|
2659
2816
|
return <attributeValue attributeType="periods" itemUuid="{$item/@uuid}" content="{$label}" />`);
|
|
2660
2817
|
returnedSequences.push("$period-values");
|
|
2661
2818
|
}
|
|
2662
|
-
return `<ochre>{${
|
|
2819
|
+
return `<ochre>{${`${queryFilterDeclarations}let $items := ${version === 2 ? "doc()" : "input()"}/ochre
|
|
2663
2820
|
${setScopeFilter}
|
|
2664
2821
|
${itemFilters}
|
|
2665
2822
|
|
|
@@ -2672,7 +2829,6 @@ return (${returnedSequences.join(", ")})`}}</ochre>`;
|
|
|
2672
2829
|
*
|
|
2673
2830
|
* @param params - The parameters for the fetch
|
|
2674
2831
|
* @param params.setScopeUuids - An array of set scope UUIDs to filter by
|
|
2675
|
-
* @param params.belongsToCollectionScopeUuids - The collection scope UUIDs to filter by
|
|
2676
2832
|
* @param params.propertyVariableUuids - The property variable UUIDs to query by
|
|
2677
2833
|
* @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
|
|
2678
2834
|
* @param params.attributes - Whether to return values for bibliographies and periods
|
|
@@ -2697,7 +2853,13 @@ async function fetchSetPropertyValuesByPropertyVariables(params, options) {
|
|
|
2697
2853
|
attributes,
|
|
2698
2854
|
isLimitedToLeafPropertyValues
|
|
2699
2855
|
}, { version });
|
|
2700
|
-
|
|
2856
|
+
let response;
|
|
2857
|
+
if (version === 2) response = await (options?.fetch ?? fetch)("https://ochre.lib.uchicago.edu/ochre/v2/ochre.php?xquery&format=json", {
|
|
2858
|
+
method: "POST",
|
|
2859
|
+
body: xquery,
|
|
2860
|
+
headers: { "Content-Type": "application/xquery" }
|
|
2861
|
+
});
|
|
2862
|
+
else response = await (options?.fetch ?? fetch)(`https://ochre.lib.uchicago.edu/ochre?xquery=${encodeURIComponent(xquery)}&format=json&lang="*"`);
|
|
2701
2863
|
if (!response.ok) throw new Error(`OCHRE API responded with status: ${response.status}`);
|
|
2702
2864
|
const data = await response.json();
|
|
2703
2865
|
const parsedResultRaw = responseSchema.parse(data);
|
|
@@ -3006,6 +3168,8 @@ function filterProperties(property, filter, options = DEFAULT_OPTIONS) {
|
|
|
3006
3168
|
|
|
3007
3169
|
//#endregion
|
|
3008
3170
|
//#region src/utils/parse/website.ts
|
|
3171
|
+
const SEGMENT_UNIQUE_SLUG_PREFIX_REGEX = /^\$[^-]*-/;
|
|
3172
|
+
const TRAILING_SLASH_REGEX = /\/$/;
|
|
3009
3173
|
/**
|
|
3010
3174
|
* Extracts CSS style properties for a given presentation variant.
|
|
3011
3175
|
*
|
|
@@ -3726,13 +3890,13 @@ function parseWebpage(webpageResource, slugPrefix) {
|
|
|
3726
3890
|
const webpageProperties = webpageResource.properties ? parseProperties(ensureArray(webpageResource.properties.property)) : [];
|
|
3727
3891
|
if (webpageProperties.length === 0 || getPropertyValueByLabel(webpageProperties, "presentation") !== "page") return null;
|
|
3728
3892
|
const identification = parseIdentification(webpageResource.identification);
|
|
3729
|
-
const slug = webpageResource.slug?.replace(
|
|
3893
|
+
const slug = webpageResource.slug?.replace(SEGMENT_UNIQUE_SLUG_PREFIX_REGEX, "") ?? null;
|
|
3730
3894
|
if (slug == null) throw new Error(`Slug not found for page “${identification.label}”`);
|
|
3731
3895
|
const returnWebpage = {
|
|
3732
3896
|
uuid: webpageResource.uuid,
|
|
3733
3897
|
type: "page",
|
|
3734
3898
|
title: identification.label,
|
|
3735
|
-
slug: slugPrefix != null ? `${slugPrefix}/${slug}`.replace(
|
|
3899
|
+
slug: slugPrefix != null ? `${slugPrefix}/${slug}`.replace(TRAILING_SLASH_REGEX, "") : slug,
|
|
3736
3900
|
publicationDateTime: parseOptionalDate(webpageResource.publicationDateTime),
|
|
3737
3901
|
items: [],
|
|
3738
3902
|
properties: {
|
|
@@ -3831,7 +3995,7 @@ function parseWebSegment(segmentResource, slugPrefix) {
|
|
|
3831
3995
|
publicationDateTime: parseOptionalDate(segmentResource.publicationDateTime),
|
|
3832
3996
|
items: []
|
|
3833
3997
|
};
|
|
3834
|
-
returnSegment.items = parseWebSegmentItems(segmentResource.resource ? ensureArray(segmentResource.resource) : [], slugPrefix != null ? `${slugPrefix}/${slug}`.replace(
|
|
3998
|
+
returnSegment.items = parseWebSegmentItems(segmentResource.resource ? ensureArray(segmentResource.resource) : [], slugPrefix != null ? `${slugPrefix}/${slug}`.replace(TRAILING_SLASH_REGEX, "") : slug);
|
|
3835
3999
|
return returnSegment;
|
|
3836
4000
|
}
|
|
3837
4001
|
/**
|
|
@@ -3869,7 +4033,7 @@ function parseWebSegmentItem(segmentItemResource, slugPrefix) {
|
|
|
3869
4033
|
items: []
|
|
3870
4034
|
};
|
|
3871
4035
|
const resources = segmentItemResource.resource ? ensureArray(segmentItemResource.resource) : [];
|
|
3872
|
-
returnSegmentItem.items.push(...parseWebpages(resources, slugPrefix != null ? `${slugPrefix}/${slug}`.replace(
|
|
4036
|
+
returnSegmentItem.items.push(...parseWebpages(resources, slugPrefix != null ? `${slugPrefix}/${slug}`.replace(TRAILING_SLASH_REGEX, "") : slug), ...parseSegments(resources, slugPrefix != null ? `${slugPrefix}/${slug}`.replace(TRAILING_SLASH_REGEX, "") : slug));
|
|
3873
4037
|
return returnSegmentItem;
|
|
3874
4038
|
}
|
|
3875
4039
|
/**
|
|
@@ -4275,6 +4439,7 @@ function parseWebsite(websiteTree, metadata, belongsTo, { version = DEFAULT_API_
|
|
|
4275
4439
|
|
|
4276
4440
|
//#endregion
|
|
4277
4441
|
//#region src/utils/fetchers/website.ts
|
|
4442
|
+
const API_VERSION_SUFFIX_REGEX = /-v\d+$/;
|
|
4278
4443
|
/**
|
|
4279
4444
|
* Parses the version suffix from an API abbreviation
|
|
4280
4445
|
*
|
|
@@ -4282,7 +4447,7 @@ function parseWebsite(websiteTree, metadata, belongsTo, { version = DEFAULT_API_
|
|
|
4282
4447
|
* @returns The parsed abbreviation and API version
|
|
4283
4448
|
*/
|
|
4284
4449
|
function parseApiVersionSuffix(abbreviation) {
|
|
4285
|
-
if (
|
|
4450
|
+
if (!API_VERSION_SUFFIX_REGEX.test(abbreviation)) return {
|
|
4286
4451
|
abbreviation,
|
|
4287
4452
|
version: DEFAULT_API_VERSION
|
|
4288
4453
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ochre-sdk",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.22",
|
|
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,8 +46,8 @@
|
|
|
46
46
|
"zod": "^4.3.6"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@antfu/eslint-config": "^7.
|
|
50
|
-
"@types/node": "^24.
|
|
49
|
+
"@antfu/eslint-config": "^7.7.0",
|
|
50
|
+
"@types/node": "^24.12.0",
|
|
51
51
|
"bumpp": "^10.4.1",
|
|
52
52
|
"eslint": "^10.0.2",
|
|
53
53
|
"prettier": "^3.8.1",
|