ochre-sdk 1.0.13 → 1.0.15
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/constants.d.mts +17 -0
- package/dist/constants.mjs +85 -0
- package/dist/fetchers/gallery.d.mts +38 -0
- package/dist/fetchers/gallery.mjs +91 -0
- package/dist/fetchers/item-links.d.mts +32 -0
- package/dist/fetchers/item-links.mjs +120 -0
- package/dist/fetchers/item.d.mts +74 -0
- package/dist/fetchers/item.mjs +146 -0
- package/dist/fetchers/set/items.d.mts +48 -0
- package/dist/fetchers/set/items.mjs +268 -0
- package/dist/fetchers/set/property-values.d.mts +46 -0
- package/dist/fetchers/set/property-values.mjs +514 -0
- package/dist/fetchers/website.d.mts +25 -0
- package/dist/fetchers/website.mjs +38 -0
- package/dist/getters.d.mts +193 -0
- package/dist/getters.mjs +341 -0
- package/dist/helpers.d.mts +18 -0
- package/dist/helpers.mjs +33 -0
- package/dist/index.d.mts +12 -1971
- package/dist/index.mjs +9 -7236
- package/dist/parsers/helpers.d.mts +27 -0
- package/dist/parsers/helpers.mjs +53 -0
- package/dist/parsers/index.d.mts +65 -0
- package/dist/parsers/index.mjs +1338 -0
- package/dist/parsers/mdx.d.mts +4 -0
- package/dist/parsers/mdx.mjs +9 -0
- package/dist/parsers/multilingual.d.mts +189 -0
- package/dist/parsers/multilingual.mjs +410 -0
- package/dist/parsers/string.d.mts +29 -0
- package/dist/parsers/string.mjs +445 -0
- package/dist/parsers/website/index.d.mts +20 -0
- package/dist/parsers/website/index.mjs +1245 -0
- package/dist/parsers/website/reader.d.mts +29 -0
- package/dist/parsers/website/reader.mjs +75 -0
- package/dist/query.d.mts +13 -0
- package/dist/query.mjs +827 -0
- package/dist/schemas.d.mts +79 -0
- package/dist/schemas.mjs +223 -0
- package/dist/types/index.d.mts +840 -0
- package/dist/types/index.mjs +1 -0
- package/dist/types/website.d.mts +501 -0
- package/dist/types/website.mjs +1 -0
- package/dist/utils.d.mts +34 -0
- package/dist/utils.mjs +172 -0
- package/dist/xml/metadata.d.mts +5 -0
- package/dist/xml/metadata.mjs +30 -0
- package/dist/xml/schemas.d.mts +13 -0
- package/dist/xml/schemas.mjs +849 -0
- package/dist/xml/types.d.mts +901 -0
- package/dist/xml/types.mjs +1 -0
- package/package.json +19 -17
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { BELONGS_TO_COLLECTION_UUID, DEFAULT_LANGUAGES, XML_PARSER_OPTIONS } from "../../constants.mjs";
|
|
2
|
+
import { createSchemaValidationError, getErrorOutput, stringLiteral } from "../../utils.mjs";
|
|
3
|
+
import { iso639_3Schema, setItemsParamsSchema } from "../../schemas.mjs";
|
|
4
|
+
import { restoreXMLMetadata } from "../../xml/metadata.mjs";
|
|
5
|
+
import { parseSetItems } from "../../parsers/index.mjs";
|
|
6
|
+
import { XMLSetItemsData } from "../../xml/schemas.mjs";
|
|
7
|
+
import { buildAndCtsQueryExpression, buildBelongsToCollectionQueryExpression, buildQueryPlan } from "../../query.mjs";
|
|
8
|
+
import * as v from "valibot";
|
|
9
|
+
import { XMLParser } from "fast-xml-parser";
|
|
10
|
+
//#region src/fetchers/set/items.ts
|
|
11
|
+
function parseLanguages(languages) {
|
|
12
|
+
const parsedLanguages = [];
|
|
13
|
+
for (const language of languages) parsedLanguages.push(v.parse(iso639_3Schema, language));
|
|
14
|
+
return parsedLanguages;
|
|
15
|
+
}
|
|
16
|
+
function isRecord(value) {
|
|
17
|
+
return typeof value === "object" && value !== null;
|
|
18
|
+
}
|
|
19
|
+
function collectContentLanguages(value, languages) {
|
|
20
|
+
if (Array.isArray(value)) {
|
|
21
|
+
for (const item of value) collectContentLanguages(item, languages);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (!isRecord(value)) return;
|
|
25
|
+
const content = value.content;
|
|
26
|
+
if (Array.isArray(content)) for (const contentItem of content) {
|
|
27
|
+
if (!isRecord(contentItem)) continue;
|
|
28
|
+
const language = contentItem.lang;
|
|
29
|
+
if (typeof language === "string" && language !== "zxx") languages.add(language);
|
|
30
|
+
}
|
|
31
|
+
for (const child of Object.values(value)) collectContentLanguages(child, languages);
|
|
32
|
+
}
|
|
33
|
+
function resolveSetItemsLanguages(data, requestedLanguages) {
|
|
34
|
+
if (requestedLanguages.length > 0) return requestedLanguages;
|
|
35
|
+
const languages = /* @__PURE__ */ new Set();
|
|
36
|
+
collectContentLanguages(data.result.ochre.items, languages);
|
|
37
|
+
return languages.size > 0 ? [...languages] : [...DEFAULT_LANGUAGES];
|
|
38
|
+
}
|
|
39
|
+
function hasArray(items) {
|
|
40
|
+
return items != null && items.length > 0;
|
|
41
|
+
}
|
|
42
|
+
function hasSetItemsCategory(items, category) {
|
|
43
|
+
switch (category) {
|
|
44
|
+
case "tree": return hasArray(items.tree);
|
|
45
|
+
case "bibliography": return hasArray(items.bibliography);
|
|
46
|
+
case "concept": return hasArray(items.concept);
|
|
47
|
+
case "spatialUnit": return hasArray(items.spatialUnit);
|
|
48
|
+
case "period": return hasArray(items.period);
|
|
49
|
+
case "person": return hasArray(items.person);
|
|
50
|
+
case "propertyVariable": return hasArray(items.propertyVariable) || hasArray(items.variable);
|
|
51
|
+
case "propertyValue": return hasArray(items.propertyValue) || hasArray(items.value);
|
|
52
|
+
case "resource": return hasArray(items.resource);
|
|
53
|
+
case "text": return hasArray(items.text);
|
|
54
|
+
case "set": return hasArray(items.set);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function mapSortDirectionToXQuery(direction) {
|
|
58
|
+
return direction === "desc" ? "descending" : "ascending";
|
|
59
|
+
}
|
|
60
|
+
function buildStringOrderByClause(direction) {
|
|
61
|
+
return `($sortKey = "") ascending, lower-case($sortKey) ${direction}, $position ascending`;
|
|
62
|
+
}
|
|
63
|
+
function buildTypedOrderByClause(direction) {
|
|
64
|
+
return `empty($sortKey) ascending, $sortKey ${direction}, $position ascending`;
|
|
65
|
+
}
|
|
66
|
+
function buildPropertyValueValuePath(sort) {
|
|
67
|
+
return `$item//properties//property[label/@uuid=${stringLiteral(sort.propertyVariableUuid)}]/value[not(@i)]`;
|
|
68
|
+
}
|
|
69
|
+
function buildPropertyValueStringSortKeyExpression(sort) {
|
|
70
|
+
const languageLiteral = stringLiteral(sort.language ?? "eng");
|
|
71
|
+
return `string((for $v in ${buildPropertyValueValuePath(sort)}
|
|
72
|
+
let $candidate := string-join($v/content[@xml:lang=${languageLiteral}]/string, "")
|
|
73
|
+
where string-length($candidate) gt 0
|
|
74
|
+
return $candidate)[1])`;
|
|
75
|
+
}
|
|
76
|
+
function buildPropertyValueTypedSortKeyExpression(params) {
|
|
77
|
+
const { sort, dataType } = params;
|
|
78
|
+
const propertyValuePath = buildPropertyValueValuePath(sort);
|
|
79
|
+
switch (dataType) {
|
|
80
|
+
case "integer": return `(for $v in ${propertyValuePath}
|
|
81
|
+
let $candidate := normalize-space(string($v/@rawValue))
|
|
82
|
+
where $candidate castable as xs:integer
|
|
83
|
+
return xs:integer($candidate))[1]`;
|
|
84
|
+
case "decimal":
|
|
85
|
+
case "time": return `(for $v in ${propertyValuePath}
|
|
86
|
+
let $candidate := normalize-space(string($v/@rawValue))
|
|
87
|
+
where $candidate castable as xs:decimal
|
|
88
|
+
return xs:decimal($candidate))[1]`;
|
|
89
|
+
case "boolean": return `(for $v in ${propertyValuePath}
|
|
90
|
+
let $candidate := lower-case(normalize-space(string($v/@rawValue)))
|
|
91
|
+
where $candidate = ("true", "false", "1", "0")
|
|
92
|
+
return if ($candidate = ("true", "1")) then 1 else 0)[1]`;
|
|
93
|
+
case "date": return `(for $v in ${propertyValuePath}
|
|
94
|
+
let $candidate := normalize-space(string($v/@rawValue))
|
|
95
|
+
where $candidate castable as xs:date
|
|
96
|
+
return xs:date($candidate))[1]`;
|
|
97
|
+
case "dateTime": return `(for $v in ${propertyValuePath}
|
|
98
|
+
let $candidate := normalize-space(string($v/@rawValue))
|
|
99
|
+
where $candidate castable as xs:dateTime
|
|
100
|
+
return xs:dateTime($candidate))[1]`;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function buildPropertyValueOrderByClause(params) {
|
|
104
|
+
const { dataType, direction } = params;
|
|
105
|
+
return dataType === "string" || dataType === "IDREF" ? buildStringOrderByClause(direction) : buildTypedOrderByClause(direction);
|
|
106
|
+
}
|
|
107
|
+
function buildOrderedItemsClause(sort) {
|
|
108
|
+
if (sort.target === "none") return "let $orderedItems := $items";
|
|
109
|
+
const direction = mapSortDirectionToXQuery(sort.direction);
|
|
110
|
+
if (sort.target === "title") return `let $orderedItems :=
|
|
111
|
+
for $item at $position in $items
|
|
112
|
+
let $sortKey := ${`string-join($item/identification/label/content[@xml:lang=${stringLiteral(sort.language ?? "eng")}]/string, "")`}
|
|
113
|
+
stable order by ${buildStringOrderByClause(direction)}
|
|
114
|
+
return $item`;
|
|
115
|
+
return `let $orderedItems :=
|
|
116
|
+
for $item at $position in $items
|
|
117
|
+
let $sortKey := ${sort.dataType === "string" || sort.dataType === "IDREF" ? buildPropertyValueStringSortKeyExpression(sort) : buildPropertyValueTypedSortKeyExpression({
|
|
118
|
+
sort,
|
|
119
|
+
dataType: sort.dataType
|
|
120
|
+
})}
|
|
121
|
+
stable order by ${buildPropertyValueOrderByClause({
|
|
122
|
+
dataType: sort.dataType,
|
|
123
|
+
direction
|
|
124
|
+
})}
|
|
125
|
+
return $item`;
|
|
126
|
+
}
|
|
127
|
+
function isExactStringPropertyQuery(query) {
|
|
128
|
+
return "target" in query && query.target === "property" && query.dataType === "string" && query.value != null && query.matchMode === "exact" && query.isNegated !== true;
|
|
129
|
+
}
|
|
130
|
+
function getCtsQueriesWithoutExactStringPropertyQueries(queries) {
|
|
131
|
+
if (queries == null) return null;
|
|
132
|
+
if ("target" in queries) return isExactStringPropertyQuery(queries) ? null : queries;
|
|
133
|
+
if ("or" in queries) return queries;
|
|
134
|
+
const filteredChildren = [];
|
|
135
|
+
for (const childQuery of queries.and) {
|
|
136
|
+
const filteredChildQuery = getCtsQueriesWithoutExactStringPropertyQueries(childQuery);
|
|
137
|
+
if (filteredChildQuery != null) filteredChildren.push(filteredChildQuery);
|
|
138
|
+
}
|
|
139
|
+
if (filteredChildren.length === 0) return null;
|
|
140
|
+
return filteredChildren.length === 1 ? filteredChildren[0] ?? null : { and: filteredChildren };
|
|
141
|
+
}
|
|
142
|
+
function buildExactStringPropertyPredicate(query) {
|
|
143
|
+
const propertyPredicates = [];
|
|
144
|
+
const value = stringLiteral(query.value);
|
|
145
|
+
if (query.propertyVariable != null) propertyPredicates.push(`label/@uuid = ${stringLiteral(query.propertyVariable)}`);
|
|
146
|
+
propertyPredicates.push(`value[
|
|
147
|
+
not(@inherited = "true")
|
|
148
|
+
and (
|
|
149
|
+
content[@xml:lang = ${stringLiteral(query.language)}]/string = ${value}
|
|
150
|
+
or @rawValue = ${value}
|
|
151
|
+
or (not(content) and text() = ${value})
|
|
152
|
+
)
|
|
153
|
+
]`);
|
|
154
|
+
return `.//properties/property[${propertyPredicates.join(" and ")}]`;
|
|
155
|
+
}
|
|
156
|
+
function buildExactStringPropertyXPathFilterExpression(queries) {
|
|
157
|
+
if (queries == null) return null;
|
|
158
|
+
if ("target" in queries) return isExactStringPropertyQuery(queries) ? buildExactStringPropertyPredicate(queries) : null;
|
|
159
|
+
if ("or" in queries) return null;
|
|
160
|
+
const childExpressions = [];
|
|
161
|
+
for (const childQuery of queries.and) {
|
|
162
|
+
const childExpression = buildExactStringPropertyXPathFilterExpression(childQuery);
|
|
163
|
+
if (childExpression != null) childExpressions.push(childExpression);
|
|
164
|
+
}
|
|
165
|
+
if (childExpressions.length === 0) return null;
|
|
166
|
+
return childExpressions.join(" and ");
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Build an XQuery string to fetch Set items from the OCHRE API
|
|
170
|
+
* @param params - The parameters for the fetch
|
|
171
|
+
* @param params.setScopeUuids - An array of Set scope UUIDs to filter by
|
|
172
|
+
* @param params.belongsToCollectionScopeUuids - An array of collection scope UUIDs to filter by
|
|
173
|
+
* @param params.queries - Recursive query tree used to filter matching items
|
|
174
|
+
* @param params.sort - Optional sorting configuration applied before pagination.
|
|
175
|
+
* For propertyValue sorting, dataType is required and the sort key uses the first valid leaf value (value[not(@i)]).
|
|
176
|
+
* @param params.page - The page number (1-indexed)
|
|
177
|
+
* @param params.pageSize - The number of items per page
|
|
178
|
+
* @returns An XQuery string
|
|
179
|
+
*/
|
|
180
|
+
function buildXQuery(params) {
|
|
181
|
+
const { queries, sort, setScopeUuids, belongsToCollectionScopeUuids, page, pageSize } = params;
|
|
182
|
+
const startPosition = (page - 1) * pageSize + 1;
|
|
183
|
+
const setScopeDeclaration = `declare variable $setScopeUuids := (${setScopeUuids.map((uuid) => stringLiteral(uuid)).join(", ")});`;
|
|
184
|
+
const baseItemsExpression = "doc()/ochre/set[@uuid = $setScopeUuids]/items/*";
|
|
185
|
+
const ctsQueries = getCtsQueriesWithoutExactStringPropertyQueries(queries);
|
|
186
|
+
const exactStringPropertyXPathFilterExpression = buildExactStringPropertyXPathFilterExpression(queries);
|
|
187
|
+
const compiledQueryPlan = buildQueryPlan({ queries: ctsQueries });
|
|
188
|
+
const itemsQueryExpressions = [];
|
|
189
|
+
const belongsToCollectionQueryExpression = buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids, BELONGS_TO_COLLECTION_UUID);
|
|
190
|
+
if (compiledQueryPlan.queryExpression != null) itemsQueryExpressions.push(compiledQueryPlan.queryExpression);
|
|
191
|
+
if (belongsToCollectionQueryExpression != null) itemsQueryExpressions.push(belongsToCollectionQueryExpression);
|
|
192
|
+
const itemsQueryExpression = buildAndCtsQueryExpression(itemsQueryExpressions);
|
|
193
|
+
const orderedItemsClause = buildOrderedItemsClause(sort);
|
|
194
|
+
const xqueryDeclarations = ["xquery version \"1.0-ml\";", setScopeDeclaration];
|
|
195
|
+
if (compiledQueryPlan.prolog !== "") xqueryDeclarations.push(compiledQueryPlan.prolog);
|
|
196
|
+
const searchedItemsClause = itemsQueryExpression == null ? `let $searchedItems := ${baseItemsExpression}` : `let $query := ${itemsQueryExpression}
|
|
197
|
+
let $searchedItems := cts:search(${baseItemsExpression}, $query)`;
|
|
198
|
+
const itemsClause = exactStringPropertyXPathFilterExpression == null ? `${searchedItemsClause}
|
|
199
|
+
let $items := $searchedItems` : `${searchedItemsClause}
|
|
200
|
+
let $items := $searchedItems[${exactStringPropertyXPathFilterExpression}]`;
|
|
201
|
+
return `${xqueryDeclarations.join("\n\n")}
|
|
202
|
+
|
|
203
|
+
<ochre>{
|
|
204
|
+
${itemsClause}
|
|
205
|
+
let $totalCount := count($items)
|
|
206
|
+
${orderedItemsClause}
|
|
207
|
+
let $pagedItems := subsequence($orderedItems, ${startPosition}, ${pageSize})
|
|
208
|
+
|
|
209
|
+
return <items totalCount="{$totalCount}" page="${page}" pageSize="${pageSize}">{
|
|
210
|
+
$pagedItems
|
|
211
|
+
}</items>
|
|
212
|
+
}</ochre>`;
|
|
213
|
+
}
|
|
214
|
+
async function fetchSetItems(params, containedItemCategories, options) {
|
|
215
|
+
try {
|
|
216
|
+
const { setScopeUuids, belongsToCollectionScopeUuids, queries, sort, page, pageSize } = v.parse(setItemsParamsSchema, params);
|
|
217
|
+
const requestedLanguages = options?.languages == null ? [] : parseLanguages(options.languages);
|
|
218
|
+
const xquery = buildXQuery({
|
|
219
|
+
setScopeUuids,
|
|
220
|
+
belongsToCollectionScopeUuids,
|
|
221
|
+
queries,
|
|
222
|
+
sort,
|
|
223
|
+
page,
|
|
224
|
+
pageSize
|
|
225
|
+
});
|
|
226
|
+
const response = await (options?.fetch ?? fetch)("https://ochre.lib.uchicago.edu/ochre/v2/ochre.php?xquery&xsl=none&lang=\"*\"", {
|
|
227
|
+
method: "POST",
|
|
228
|
+
body: xquery,
|
|
229
|
+
headers: { "Content-Type": "application/xquery" }
|
|
230
|
+
});
|
|
231
|
+
if (!response.ok) throw new Error(`OCHRE API responded with status: ${response.status}`, { cause: response.statusText });
|
|
232
|
+
const dataRaw = await response.text();
|
|
233
|
+
const data = new XMLParser(XML_PARSER_OPTIONS).parse(dataRaw);
|
|
234
|
+
const { success, issues, output } = v.safeParse(XMLSetItemsData, data);
|
|
235
|
+
if (!success) throw createSchemaValidationError("Failed to parse OCHRE Set items", issues);
|
|
236
|
+
restoreXMLMetadata(output, data);
|
|
237
|
+
if (containedItemCategories != null) {
|
|
238
|
+
const missingCategories = containedItemCategories.filter((category) => !hasSetItemsCategory(output.result.ochre.items, category));
|
|
239
|
+
if (missingCategories.length > 0) throw new Error(`No Set items found for item categories: ${missingCategories.join(", ")}`, { cause: missingCategories });
|
|
240
|
+
}
|
|
241
|
+
const languages = resolveSetItemsLanguages(output, requestedLanguages);
|
|
242
|
+
const items = parseSetItems(output.result.ochre.items, {
|
|
243
|
+
containedItemCategories,
|
|
244
|
+
languages
|
|
245
|
+
});
|
|
246
|
+
const itemsByUuid = /* @__PURE__ */ new Map();
|
|
247
|
+
for (const item of items) if (!itemsByUuid.has(item.uuid)) itemsByUuid.set(item.uuid, item);
|
|
248
|
+
const uniqueItems = [...itemsByUuid.values()];
|
|
249
|
+
return {
|
|
250
|
+
totalCount: output.result.ochre.items.totalCount,
|
|
251
|
+
page: output.result.ochre.items.page,
|
|
252
|
+
pageSize: output.result.ochre.items.pageSize,
|
|
253
|
+
items: uniqueItems,
|
|
254
|
+
error: null,
|
|
255
|
+
detailedError: null
|
|
256
|
+
};
|
|
257
|
+
} catch (error) {
|
|
258
|
+
return {
|
|
259
|
+
totalCount: null,
|
|
260
|
+
page: null,
|
|
261
|
+
pageSize: null,
|
|
262
|
+
items: null,
|
|
263
|
+
...getErrorOutput(error, "Failed to fetch Set items")
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
//#endregion
|
|
268
|
+
export { fetchSetItems };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { PropertyValueQueryItem, Query, SetAttributeValueQueryItem } from "../../types/index.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/fetchers/set/property-values.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Fetches and parses Set property values from the OCHRE API
|
|
6
|
+
*
|
|
7
|
+
* @param params - The parameters for the fetch
|
|
8
|
+
* @param params.setScopeUuids - An array of set scope UUIDs to filter by
|
|
9
|
+
* @param params.queries - Recursive query tree used to filter matching items
|
|
10
|
+
* @param params.attributes - Whether to return values for bibliographies and periods
|
|
11
|
+
* @param params.attributes.bibliographies - Whether to return values for bibliographies
|
|
12
|
+
* @param params.attributes.periods - Whether to return values for periods
|
|
13
|
+
* @param params.isLimitedToLeafPropertyValues - Whether to limit the property values to leaf property values
|
|
14
|
+
* @param options - Options for the fetch
|
|
15
|
+
* @param options.fetch - The fetch function to use
|
|
16
|
+
* @returns Parsed Set property values and requested attribute values.
|
|
17
|
+
* Returns empty arrays/objects when no matches are found, and null outputs on fetch/parse errors.
|
|
18
|
+
*/
|
|
19
|
+
declare function fetchSetPropertyValues(params: {
|
|
20
|
+
setScopeUuids: Array<string>;
|
|
21
|
+
queries?: Query | null;
|
|
22
|
+
attributes?: {
|
|
23
|
+
bibliographies: boolean;
|
|
24
|
+
periods: boolean;
|
|
25
|
+
};
|
|
26
|
+
isLimitedToLeafPropertyValues?: boolean;
|
|
27
|
+
}, options?: {
|
|
28
|
+
fetch?: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response>;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
propertyValues: Array<PropertyValueQueryItem>;
|
|
31
|
+
propertyValuesByPropertyVariableUuid: Record<string, Array<PropertyValueQueryItem>>;
|
|
32
|
+
attributeValues: {
|
|
33
|
+
bibliographies: Array<SetAttributeValueQueryItem> | null;
|
|
34
|
+
periods: Array<SetAttributeValueQueryItem> | null;
|
|
35
|
+
};
|
|
36
|
+
error: null;
|
|
37
|
+
detailedError: null;
|
|
38
|
+
} | {
|
|
39
|
+
propertyValues: null;
|
|
40
|
+
propertyValuesByPropertyVariableUuid: null;
|
|
41
|
+
attributeValues: null;
|
|
42
|
+
error: string;
|
|
43
|
+
detailedError: string;
|
|
44
|
+
}>;
|
|
45
|
+
//#endregion
|
|
46
|
+
export { fetchSetPropertyValues };
|