ochre-sdk 1.0.78 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +31 -3
  2. package/dist/_virtual/_rolldown/runtime.mjs +13 -0
  3. package/dist/categories.d.mts +249 -0
  4. package/dist/categories.mjs +259 -0
  5. package/dist/constants.d.mts +14 -0
  6. package/dist/constants.mjs +18 -1
  7. package/dist/errors.d.mts +23 -0
  8. package/dist/{utilities.mjs → errors.mjs} +33 -84
  9. package/dist/fetchers/gallery.mjs +15 -51
  10. package/dist/fetchers/item-children.mjs +20 -66
  11. package/dist/fetchers/item-links.mjs +26 -79
  12. package/dist/fetchers/item-ocr-data.d.mts +2 -2
  13. package/dist/fetchers/item-ocr-data.mjs +11 -15
  14. package/dist/fetchers/item.d.mts +0 -15
  15. package/dist/fetchers/item.mjs +20 -72
  16. package/dist/fetchers/request.d.mts +70 -0
  17. package/dist/fetchers/request.mjs +100 -0
  18. package/dist/fetchers/set/items.mjs +27 -73
  19. package/dist/fetchers/set/property-values.d.mts +2 -3
  20. package/dist/fetchers/set/property-values.mjs +96 -130
  21. package/dist/fetchers/website-metadata.mjs +35 -57
  22. package/dist/fetchers/website.d.mts +2 -3
  23. package/dist/fetchers/website.mjs +22 -31
  24. package/dist/getters.d.mts +78 -148
  25. package/dist/getters.mjs +127 -208
  26. package/dist/helpers.d.mts +0 -4
  27. package/dist/helpers.mjs +19 -6
  28. package/dist/index.d.mts +8 -6
  29. package/dist/index.mjs +6 -4
  30. package/dist/ocr.d.mts +37 -0
  31. package/dist/ocr.mjs +52 -0
  32. package/dist/parsers/helpers.d.mts +21 -1
  33. package/dist/parsers/helpers.mjs +26 -6
  34. package/dist/parsers/index.d.mts +0 -8
  35. package/dist/parsers/index.mjs +118 -259
  36. package/dist/parsers/languages.d.mts +72 -0
  37. package/dist/parsers/languages.mjs +132 -0
  38. package/dist/parsers/multilingual.d.mts +49 -74
  39. package/dist/parsers/multilingual.mjs +88 -189
  40. package/dist/parsers/property-token.d.mts +34 -0
  41. package/dist/parsers/property-token.mjs +29 -0
  42. package/dist/parsers/string.d.mts +19 -0
  43. package/dist/parsers/string.mjs +45 -25
  44. package/dist/parsers/website/bounds.d.mts +10 -0
  45. package/dist/parsers/website/bounds.mjs +28 -0
  46. package/dist/parsers/website/components.d.mts +91 -0
  47. package/dist/parsers/website/components.mjs +681 -0
  48. package/dist/parsers/website/index.d.mts +0 -7
  49. package/dist/parsers/website/index.mjs +92 -1153
  50. package/dist/parsers/website/links.d.mts +36 -0
  51. package/dist/parsers/website/links.mjs +58 -0
  52. package/dist/parsers/website/messages.d.mts +24 -0
  53. package/dist/parsers/website/messages.mjs +31 -0
  54. package/dist/parsers/website/options.d.mts +6 -0
  55. package/dist/parsers/website/options.mjs +114 -0
  56. package/dist/parsers/website/properties.d.mts +12 -0
  57. package/dist/parsers/website/properties.mjs +158 -0
  58. package/dist/parsers/website/reader.d.mts +54 -4
  59. package/dist/parsers/website/reader.mjs +65 -20
  60. package/dist/parsers/website/slug.d.mts +64 -0
  61. package/dist/parsers/website/slug.mjs +82 -0
  62. package/dist/parsers/website/styles.d.mts +28 -0
  63. package/dist/parsers/website/styles.mjs +103 -0
  64. package/dist/parsers/website/walk.d.mts +68 -0
  65. package/dist/parsers/website/walk.mjs +116 -0
  66. package/dist/query.d.mts +66 -18
  67. package/dist/query.mjs +202 -48
  68. package/dist/reflection.d.mts +64 -0
  69. package/dist/reflection.mjs +79 -0
  70. package/dist/schemas.d.mts +7 -0
  71. package/dist/schemas.mjs +12 -3
  72. package/dist/types/index.d.mts +1 -31
  73. package/dist/types/utilities.d.mts +9 -0
  74. package/dist/types/utilities.mjs +1 -0
  75. package/dist/types/website.d.mts +49 -58
  76. package/dist/xml/metadata.d.mts +16 -0
  77. package/dist/xml/metadata.mjs +32 -11
  78. package/dist/xml/schemas.d.mts +5970 -3
  79. package/dist/xml/schemas.mjs +43 -45
  80. package/dist/xml/types.d.mts +13 -30
  81. package/dist/xquery.d.mts +46 -0
  82. package/dist/xquery.mjs +66 -0
  83. package/package.json +3 -3
  84. package/dist/utilities.d.mts +0 -54
@@ -1,27 +1,14 @@
1
- import { XML_PARSER_OPTIONS } from "../constants.mjs";
2
- import { SUPPLEMENTAL_XQUERY_PROLOG, createSchemaValidationError, getErrorOutput, omitSupplemental, stringLiteral } from "../utilities.mjs";
3
- import { iso639_3Schema, uuidSchema } from "../schemas.mjs";
4
- import { restoreXMLMetadata } from "../xml/metadata.mjs";
1
+ import { ITEM_CATEGORIES_WITH_EMBEDDED_ITEMS, ITEM_CONTAINER_CATEGORIES, isItemCategoryWithEmbeddedItems, isItemContainerCategory } from "../categories.mjs";
2
+ import { getErrorOutput } from "../errors.mjs";
3
+ import { requestOchre } from "./request.mjs";
4
+ import { uuidSchema } from "../schemas.mjs";
5
+ import { parseRequestedLanguages } from "../parsers/languages.mjs";
5
6
  import { parseItem } from "../parsers/index.mjs";
6
7
  import { XMLData } from "../xml/schemas.mjs";
8
+ import { compileOchreQuery, stringLiteral } from "../xquery.mjs";
7
9
  import { parseWebpageView } from "../parsers/website/index.mjs";
8
10
  import * as v from "valibot";
9
- import { XMLParser } from "fast-xml-parser";
10
11
  //#region src/fetchers/item.ts
11
- function isItemContainerCategory(category) {
12
- return category === "tree" || category === "set";
13
- }
14
- function isItemCategoryWithEmbeddedItems(category) {
15
- return [
16
- "tree",
17
- "bibliography",
18
- "concept",
19
- "spatialUnit",
20
- "period",
21
- "resource",
22
- "set"
23
- ].includes(category);
24
- }
25
12
  function isItemWithEmbeddedItems(item) {
26
13
  return isItemCategoryWithEmbeddedItems(item.category);
27
14
  }
@@ -49,14 +36,8 @@ function buildXQuery(parameters) {
49
36
  let itemNodesExpression = "$ochre/node()";
50
37
  if (shouldOmitEmbeddedItems) {
51
38
  letClauses.push(`let $item := (
52
- $ochre/tree,
53
- $ochre/bibliography,
54
- $ochre/concept,
55
- $ochre/spatialUnit,
56
- $ochre/period,
57
- $ochre/resource,
58
- $ochre/set
59
- )[1]`, `let $embedded-child-name := if (local-name($item) = ("tree", "set")) then "items" else local-name($item)`);
39
+ ${ITEM_CATEGORIES_WITH_EMBEDDED_ITEMS.map((category) => ` $ochre/${category}`).join(",\n")}
40
+ )[1]`, `let $embedded-child-name := if (local-name($item) = (${ITEM_CONTAINER_CATEGORIES.map((category) => stringLiteral(category)).join(", ")})) then "items" else local-name($item)`);
60
41
  itemNodesExpression = `(
61
42
  for $node in $ochre/node()
62
43
  return
@@ -65,69 +46,36 @@ function buildXQuery(parameters) {
65
46
  else $node
66
47
  )`;
67
48
  }
68
- return `xquery version "1.0-ml";
69
-
70
- ${SUPPLEMENTAL_XQUERY_PROLOG}
71
-
72
- ${letClauses.join("\n")}
49
+ return compileOchreQuery({ body: ({ omitSupplemental }) => `${letClauses.join("\n")}
73
50
  return
74
51
  if (empty($ochre)) then ()
75
52
  else element ochre {
76
53
  $ochre/@*,
77
54
  ${omitSupplemental(itemNodesExpression)}
78
- }`;
55
+ }` });
79
56
  }
80
57
  function omitEmbeddedItems(item) {
81
58
  const { items: _items, ...itemWithoutEmbeddedItems } = item;
82
59
  return itemWithoutEmbeddedItems;
83
60
  }
84
- /**
85
- * Validate language codes while preserving literal tuple inference.
86
- */
87
- function parseLanguages(languages) {
88
- for (const language of languages) v.parse(iso639_3Schema, language);
89
- return languages;
90
- }
91
- /**
92
- * Defines a reusable languages tuple with validation and literal type inference.
93
- *
94
- * Inline arrays can be passed directly to fetchItem:
95
- * `fetchItem(uuid, { languages: ["eng", "spa"] })`.
96
- *
97
- * Use this helper when the language set is stored separately:
98
- * `const languages = defineLanguages("eng", "spa")`.
99
- */
100
- function defineLanguages(...languages) {
101
- return parseLanguages(languages);
102
- }
103
- /**
104
- * @deprecated Pass inline language arrays directly to fetchItem, or use
105
- * defineLanguages("eng", "spa") for reusable language tuples.
106
- */
107
- function withLanguages(languages) {
108
- return parseLanguages(languages);
109
- }
110
61
  async function fetchItem(uuid, options) {
111
62
  try {
112
63
  const parsedUuid = v.parse(uuidSchema, uuid);
113
64
  assertItemCategoryAllowed(options?.category, options?.containedItemCategory);
114
65
  const shouldOmitEmbeddedItems = options?.shouldOmitEmbeddedItems === true;
115
- const languages = options?.languages == null ? [] : parseLanguages(options.languages);
116
- const response = await (options?.fetch ?? fetch)("https://ochre.lib.uchicago.edu/ochre/v2/ochre.php?xquery&xsl=none&lang=\"*\"", {
117
- method: "POST",
118
- body: buildXQuery({
66
+ const languages = parseRequestedLanguages(options?.languages);
67
+ const output = await requestOchre({
68
+ xquery: buildXQuery({
119
69
  uuid: parsedUuid,
120
70
  shouldOmitEmbeddedItems
121
71
  }),
122
- headers: { "Content-Type": "application/xquery" }
72
+ schema: XMLData,
73
+ label: "OCHRE item",
74
+ options,
75
+ checkRawData: (data) => {
76
+ if (data.result?.ochre?.uuid == null) throw new Error(`No OCHRE item found for UUID "${parsedUuid}"`, { cause: data });
77
+ }
123
78
  });
124
- if (!response.ok) throw new Error("Failed to fetch OCHRE data", { cause: response.statusText });
125
- const dataRaw = await response.text();
126
- const data = new XMLParser(XML_PARSER_OPTIONS).parse(dataRaw);
127
- if (data.result?.ochre?.uuid == null) throw new Error(`No OCHRE item found for UUID "${parsedUuid}"`, { cause: dataRaw });
128
- const { success, issues, output } = v.safeParse(XMLData, data);
129
- if (!success) throw createSchemaValidationError("Failed to parse OCHRE data", issues);
130
- restoreXMLMetadata(output, data);
131
79
  const parsedItem = parseItem(output, {
132
80
  category: options?.category,
133
81
  containedItemCategory: options?.containedItemCategory,
@@ -148,4 +96,4 @@ async function fetchItem(uuid, options) {
148
96
  }
149
97
  }
150
98
  //#endregion
151
- export { defineLanguages, fetchItem, withLanguages };
99
+ export { fetchItem };
@@ -0,0 +1,70 @@
1
+ import { FetchFunction } from "../parsers/helpers.mjs";
2
+ import * as v from "valibot";
3
+ //#region src/fetchers/request.d.ts
4
+ export type OchreRequestOptions = {
5
+ fetch?: FetchFunction;
6
+ signal?: AbortSignal;
7
+ timeoutMilliseconds?: number;
8
+ };
9
+ /**
10
+ * Turn an OCHRE XML response into validated data
11
+ *
12
+ * The XML parser, the schema check and the metadata graft are one step: the
13
+ * graft has to follow validation because `v.safeParse` drops the
14
+ * non-enumerable source offsets `fast-xml-parser` records, and skipping it
15
+ * leaves a value that is the right shape but has lost its source order. Kept
16
+ * separate from the request so a caller holding an XML string, such as a test,
17
+ * gets exactly what the network path produces.
18
+ * @param parameters - The decode parameters
19
+ * @param parameters.xml - The raw XML response body
20
+ * @param parameters.schema - The schema the response must satisfy
21
+ * @param parameters.label - What is being decoded, used in failure messages
22
+ * @param parameters.checkRawData - Guard run against the parsed XML before validation
23
+ * @returns The validated response, with XML source metadata restored
24
+ * @throws When the guard rejects or validation fails
25
+ * @internal
26
+ */
27
+ export declare function decodeOchreResponse<TOutput>(parameters: {
28
+ xml: string;
29
+ schema: v.GenericSchema<unknown, TOutput>;
30
+ label: string;
31
+ checkRawData?: (data: unknown) => void;
32
+ }): TOutput;
33
+ /**
34
+ * Post an XQuery to the OCHRE API and validate the response
35
+ *
36
+ * Owns every fact about talking to OCHRE: the endpoint, the request shape and
37
+ * the failure policy. Decoding the body is {@link decodeOchreResponse}.
38
+ * @param parameters - The request parameters
39
+ * @param parameters.xquery - The XQuery to post
40
+ * @param parameters.schema - The schema the response must satisfy
41
+ * @param parameters.label - What is being fetched, used in failure messages
42
+ * @param parameters.options - Transport options
43
+ * @param parameters.checkRawData - Guard run against the parsed XML before validation
44
+ * @returns The validated response, with XML source metadata restored
45
+ * @throws When the request fails, the guard rejects, or validation fails
46
+ * @internal
47
+ */
48
+ export declare function requestOchre<TOutput>(parameters: {
49
+ xquery: string;
50
+ schema: v.GenericSchema<unknown, TOutput>;
51
+ label: string;
52
+ options?: OchreRequestOptions;
53
+ checkRawData?: (data: unknown) => void;
54
+ }): Promise<TOutput>;
55
+ /**
56
+ * Post a JSON payload to the OCHRE API
57
+ * @param parameters - The request parameters
58
+ * @param parameters.body - The JSON payload to post
59
+ * @param parameters.label - What is being posted, used in failure messages
60
+ * @param parameters.options - Transport options
61
+ * @returns Whether the API accepted the payload
62
+ * @throws When the request cannot be completed at all
63
+ * @internal
64
+ */
65
+ export declare function isOchreJsonAccepted(parameters: {
66
+ body: unknown;
67
+ label: string;
68
+ options?: OchreRequestOptions;
69
+ }): Promise<boolean>;
70
+ //#endregion
@@ -0,0 +1,100 @@
1
+ import { OCHRE_ENDPOINT, XML_PARSER_OPTIONS } from "../constants.mjs";
2
+ import { createSchemaValidationError } from "../errors.mjs";
3
+ import { restoreXMLMetadata } from "../xml/metadata.mjs";
4
+ import * as v from "valibot";
5
+ import { XMLParser } from "fast-xml-parser";
6
+ //#region src/fetchers/request.ts
7
+ const OCHRE_XQUERY_ENDPOINT = `${OCHRE_ENDPOINT}?xquery&xsl=none&lang="*"`;
8
+ const xmlParser = new XMLParser(XML_PARSER_OPTIONS);
9
+ function resolveSignal(options) {
10
+ const { signal, timeoutMilliseconds } = options ?? {};
11
+ if (timeoutMilliseconds == null) return signal;
12
+ const timeoutSignal = AbortSignal.timeout(timeoutMilliseconds);
13
+ return signal == null ? timeoutSignal : AbortSignal.any([signal, timeoutSignal]);
14
+ }
15
+ /**
16
+ * Turn an OCHRE XML response into validated data
17
+ *
18
+ * The XML parser, the schema check and the metadata graft are one step: the
19
+ * graft has to follow validation because `v.safeParse` drops the
20
+ * non-enumerable source offsets `fast-xml-parser` records, and skipping it
21
+ * leaves a value that is the right shape but has lost its source order. Kept
22
+ * separate from the request so a caller holding an XML string, such as a test,
23
+ * gets exactly what the network path produces.
24
+ * @param parameters - The decode parameters
25
+ * @param parameters.xml - The raw XML response body
26
+ * @param parameters.schema - The schema the response must satisfy
27
+ * @param parameters.label - What is being decoded, used in failure messages
28
+ * @param parameters.checkRawData - Guard run against the parsed XML before validation
29
+ * @returns The validated response, with XML source metadata restored
30
+ * @throws When the guard rejects or validation fails
31
+ * @internal
32
+ */
33
+ function decodeOchreResponse(parameters) {
34
+ const { xml, schema, label, checkRawData } = parameters;
35
+ const data = xmlParser.parse(xml);
36
+ checkRawData?.(data);
37
+ const { success, issues, output } = v.safeParse(schema, data);
38
+ if (!success) throw createSchemaValidationError(`Failed to parse ${label}`, issues);
39
+ restoreXMLMetadata(output, data);
40
+ return output;
41
+ }
42
+ /**
43
+ * Post an XQuery to the OCHRE API and validate the response
44
+ *
45
+ * Owns every fact about talking to OCHRE: the endpoint, the request shape and
46
+ * the failure policy. Decoding the body is {@link decodeOchreResponse}.
47
+ * @param parameters - The request parameters
48
+ * @param parameters.xquery - The XQuery to post
49
+ * @param parameters.schema - The schema the response must satisfy
50
+ * @param parameters.label - What is being fetched, used in failure messages
51
+ * @param parameters.options - Transport options
52
+ * @param parameters.checkRawData - Guard run against the parsed XML before validation
53
+ * @returns The validated response, with XML source metadata restored
54
+ * @throws When the request fails, the guard rejects, or validation fails
55
+ * @internal
56
+ */
57
+ async function requestOchre(parameters) {
58
+ const { xquery, schema, label, options, checkRawData } = parameters;
59
+ const response = await (options?.fetch ?? fetch)(OCHRE_XQUERY_ENDPOINT, {
60
+ method: "POST",
61
+ body: xquery,
62
+ headers: { "Content-Type": "application/xquery" },
63
+ signal: resolveSignal(options)
64
+ });
65
+ if (!response.ok) throw new Error(`Failed to fetch ${label}: OCHRE API responded with status ${response.status}`, { cause: response.statusText });
66
+ return decodeOchreResponse({
67
+ xml: await response.text(),
68
+ schema,
69
+ label,
70
+ checkRawData
71
+ });
72
+ }
73
+ /**
74
+ * Post a JSON payload to the OCHRE API
75
+ * @param parameters - The request parameters
76
+ * @param parameters.body - The JSON payload to post
77
+ * @param parameters.label - What is being posted, used in failure messages
78
+ * @param parameters.options - Transport options
79
+ * @returns Whether the API accepted the payload
80
+ * @throws When the request cannot be completed at all
81
+ * @internal
82
+ */
83
+ async function isOchreJsonAccepted(parameters) {
84
+ const { body, label, options } = parameters;
85
+ let response;
86
+ try {
87
+ response = await (options?.fetch ?? fetch)(OCHRE_ENDPOINT, {
88
+ method: "POST",
89
+ body: JSON.stringify(body),
90
+ headers: { "Content-Type": "application/json" },
91
+ signal: resolveSignal(options)
92
+ });
93
+ } catch (error) {
94
+ throw new Error(`Failed to post ${label}`, { cause: error });
95
+ }
96
+ if (response.status >= 500) throw new Error(`Failed to post ${label}: OCHRE API responded with status ${response.status}`, { cause: response.statusText });
97
+ return response.ok;
98
+ }
99
+ //#endregion
100
+ export { decodeOchreResponse, isOchreJsonAccepted, requestOchre };
@@ -1,40 +1,13 @@
1
- import { BELONGS_TO_COLLECTION_UUID, DEFAULT_LANGUAGES, XML_PARSER_OPTIONS } from "../../constants.mjs";
2
- import { SUPPLEMENTAL_XQUERY_PROLOG, createSchemaValidationError, getErrorOutput, omitSupplemental, stringLiteral } from "../../utilities.mjs";
3
- import { iso639_3Schema, setItemsParametersSchema } from "../../schemas.mjs";
4
- import { restoreXMLMetadata } from "../../xml/metadata.mjs";
1
+ import { getErrorOutput } from "../../errors.mjs";
2
+ import { requestOchre } from "../request.mjs";
3
+ import { setItemsParametersSchema } from "../../schemas.mjs";
4
+ import { parseRequestedLanguages, resolveContentLanguages } from "../../parsers/languages.mjs";
5
5
  import { parseSetItems } from "../../parsers/index.mjs";
6
6
  import { XMLSetItemsData } from "../../xml/schemas.mjs";
7
- import { buildBelongsToCollectionQueryExpression, buildQueryPlan } from "../../query.mjs";
7
+ import { stringLiteral } from "../../xquery.mjs";
8
+ import { compileSetItemsQuery } from "../../query.mjs";
8
9
  import * as v from "valibot";
9
- import { XMLParser } from "fast-xml-parser";
10
10
  //#region src/fetchers/set/items.ts
11
- function parseLanguages(languages) {
12
- for (const language of languages) v.parse(iso639_3Schema, language);
13
- return languages;
14
- }
15
- function isRecord(value) {
16
- return typeof value === "object" && value !== null;
17
- }
18
- function collectContentLanguages(value, languages) {
19
- if (Array.isArray(value)) {
20
- for (const item of value) collectContentLanguages(item, languages);
21
- return;
22
- }
23
- if (!isRecord(value)) return;
24
- const content = value.content;
25
- if (Array.isArray(content)) for (const contentItem of content) {
26
- if (!isRecord(contentItem)) continue;
27
- const language = contentItem.lang;
28
- if (typeof language === "string" && language !== "zxx") languages.add(language);
29
- }
30
- for (const child of Object.values(value)) collectContentLanguages(child, languages);
31
- }
32
- function resolveSetItemsLanguages(data, requestedLanguages) {
33
- if (requestedLanguages.length > 0) return requestedLanguages;
34
- const languages = /* @__PURE__ */ new Set();
35
- collectContentLanguages(data.result.ochre.items, languages);
36
- return languages.size > 0 ? [...languages] : [...DEFAULT_LANGUAGES];
37
- }
38
11
  function hasArray(items) {
39
12
  return items != null && items.length > 0;
40
13
  }
@@ -138,60 +111,41 @@ function buildOrderedItemsClause(sort) {
138
111
  function buildXQuery(parameters) {
139
112
  const { queries, sort, setScopeUuids, belongsToCollectionScopeUuids, page, pageSize } = parameters;
140
113
  const startPosition = (page - 1) * pageSize + 1;
141
- const setScopeDeclaration = `declare variable $setScopeUuids := (${setScopeUuids.map((uuid) => stringLiteral(uuid)).join(", ")});`;
142
- const compiledQueryPlan = buildQueryPlan({
114
+ return compileSetItemsQuery({
115
+ setScopeUuids,
116
+ belongsToCollectionScopeUuids,
143
117
  queries,
144
- baseItemsExpression: "doc()/ochre/set[@uuid = $setScopeUuids]/items/*",
145
- scopeQueryExpression: buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids, BELONGS_TO_COLLECTION_UUID)
146
- });
147
- const orderedItemsClause = buildOrderedItemsClause(sort);
148
- const xqueryDeclarations = [
149
- "xquery version \"1.0-ml\";",
150
- setScopeDeclaration,
151
- SUPPLEMENTAL_XQUERY_PROLOG
152
- ];
153
- if (compiledQueryPlan.prolog !== "") xqueryDeclarations.push(compiledQueryPlan.prolog);
154
- return `${xqueryDeclarations.join("\n\n")}
155
-
156
- <ochre>{
157
- ${compiledQueryPlan.itemsClause}
158
- let $totalCount := count($items)
159
- ${orderedItemsClause}
118
+ body: ({ items, omitSupplemental }) => ` let $totalCount := count(${items})
119
+ ${buildOrderedItemsClause(sort)}
160
120
  let $pagedItems := subsequence($orderedItems, ${startPosition}, ${pageSize})
161
121
 
162
122
  return <items totalCount="{$totalCount}" page="${page}" pageSize="${pageSize}">{
163
123
  ${omitSupplemental("$pagedItems")}
164
- }</items>
165
- }</ochre>`;
124
+ }</items>`
125
+ });
166
126
  }
167
127
  async function fetchSetItems(parameters, containedItemCategories, options) {
168
128
  try {
169
129
  const { setScopeUuids, belongsToCollectionScopeUuids, queries, sort, page, pageSize } = v.parse(setItemsParametersSchema, parameters);
170
- const requestedLanguages = options?.languages == null ? [] : parseLanguages(options.languages);
171
- const xquery = buildXQuery({
172
- setScopeUuids,
173
- belongsToCollectionScopeUuids,
174
- queries,
175
- sort,
176
- page,
177
- pageSize
178
- });
179
- const response = await (options?.fetch ?? fetch)("https://ochre.lib.uchicago.edu/ochre/v2/ochre.php?xquery&xsl=none&lang=\"*\"", {
180
- method: "POST",
181
- body: xquery,
182
- headers: { "Content-Type": "application/xquery" }
130
+ const requestedLanguages = parseRequestedLanguages(options?.languages);
131
+ const output = await requestOchre({
132
+ xquery: buildXQuery({
133
+ setScopeUuids,
134
+ belongsToCollectionScopeUuids,
135
+ queries,
136
+ sort,
137
+ page,
138
+ pageSize
139
+ }),
140
+ schema: XMLSetItemsData,
141
+ label: "OCHRE Set items",
142
+ options
183
143
  });
184
- if (!response.ok) throw new Error(`OCHRE API responded with status: ${response.status}`, { cause: response.statusText });
185
- const dataRaw = await response.text();
186
- const data = new XMLParser(XML_PARSER_OPTIONS).parse(dataRaw);
187
- const { success, issues, output } = v.safeParse(XMLSetItemsData, data);
188
- if (!success) throw createSchemaValidationError("Failed to parse OCHRE Set items", issues);
189
- restoreXMLMetadata(output, data);
190
144
  if (containedItemCategories != null) {
191
145
  const missingCategories = containedItemCategories.filter((category) => !hasSetItemsCategory(output.result.ochre.items, category));
192
146
  if (missingCategories.length > 0) throw new Error(`No Set items found for item categories: ${missingCategories.join(", ")}`, { cause: missingCategories });
193
147
  }
194
- const languages = resolveSetItemsLanguages(output, requestedLanguages);
148
+ const languages = resolveContentLanguages(output.result.ochre.items, requestedLanguages);
195
149
  const items = parseSetItems(output.result.ochre.items, {
196
150
  containedItemCategories,
197
151
  languages
@@ -1,4 +1,5 @@
1
1
  import { PropertyValueQueryItem, Query, SetAttributeValueQueryItem } from "../../types/index.mjs";
2
+ import { OchreRequestOptions } from "../request.mjs";
2
3
  //#region src/fetchers/set/property-values.d.ts
3
4
  /**
4
5
  * Fetches and parses Set property values from the OCHRE API
@@ -23,9 +24,7 @@ export declare function fetchSetPropertyValues(parameters: {
23
24
  periods: boolean;
24
25
  };
25
26
  isLimitedToLeafPropertyValues?: boolean;
26
- }, options?: {
27
- fetch?: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response>;
28
- }): Promise<{
27
+ }, options?: OchreRequestOptions): Promise<{
29
28
  propertyValues: Array<PropertyValueQueryItem>;
30
29
  propertyValuesByPropertyVariableUuid: Record<string, Array<PropertyValueQueryItem>>;
31
30
  attributeValues: {