ochre-sdk 0.20.14 → 0.20.16

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 CHANGED
@@ -643,6 +643,13 @@ type PropertyValueQueryItem = {
643
643
  content: string | number | boolean | null;
644
644
  label: string | null;
645
645
  };
646
+ /**
647
+ * Represents a grouped Set attribute value query item
648
+ */
649
+ type SetAttributeValueQueryItem = {
650
+ count: number;
651
+ content: string;
652
+ };
646
653
  /**
647
654
  * Represents sorting direction for Set items
648
655
  */
@@ -1262,28 +1269,41 @@ declare function fetchSetItems<U extends Array<DataCategory> = Array<DataCategor
1262
1269
  * @param params.belongsToCollectionScopeUuids - The collection scope UUIDs to filter by
1263
1270
  * @param params.propertyVariableUuids - The property variable UUIDs to query by
1264
1271
  * @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
1272
+ * @param params.attributeQueries - Whether to return values for bibliographies and periods
1273
+ * @param params.attributeQueries.bibliographies - Whether to return values for bibliographies
1274
+ * @param params.attributeQueries.periods - Whether to return values for periods
1265
1275
  * @param params.isLimitedToLeafPropertyValues - Whether to limit the property values to leaf property values
1266
1276
  * @param options - Options for the fetch
1267
1277
  * @param options.fetch - The fetch function to use
1268
1278
  * @param options.version - The version of the OCHRE API to use
1269
- * @returns The parsed Set property values by property variables or null if the fetch/parse fails
1279
+ * @returns Parsed Set property values and requested attribute values.
1280
+ * Returns empty arrays/objects when no matches are found, and null outputs on fetch/parse errors.
1270
1281
  */
1271
1282
  declare function fetchSetPropertyValuesByPropertyVariables(params: {
1272
1283
  setScopeUuids: Array<string>;
1273
1284
  belongsToCollectionScopeUuids: Array<string>;
1274
1285
  propertyVariableUuids: Array<string>;
1275
1286
  queries?: Array<Query>;
1287
+ attributeQueries?: {
1288
+ bibliographies: boolean;
1289
+ periods: boolean;
1290
+ };
1276
1291
  isLimitedToLeafPropertyValues?: boolean;
1277
1292
  }, options?: {
1278
1293
  fetch?: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response>;
1279
1294
  version?: ApiVersion;
1280
1295
  }): Promise<{
1281
- propertyValues: Array<PropertyValueQueryItem> | null;
1282
- propertyValuesByPropertyVariableUuid: Record<string, Array<PropertyValueQueryItem>> | null;
1296
+ propertyValues: Array<PropertyValueQueryItem>;
1297
+ propertyValuesByPropertyVariableUuid: Record<string, Array<PropertyValueQueryItem>>;
1298
+ attributeValues: {
1299
+ bibliographies: Array<SetAttributeValueQueryItem> | null;
1300
+ periods: Array<SetAttributeValueQueryItem> | null;
1301
+ };
1283
1302
  error: null;
1284
1303
  } | {
1285
1304
  propertyValues: null;
1286
1305
  propertyValuesByPropertyVariableUuid: null;
1306
+ attributeValues: null;
1287
1307
  error: string;
1288
1308
  }>;
1289
1309
  //#endregion
@@ -1446,4 +1466,4 @@ declare const DEFAULT_PAGE_SIZE = 48;
1446
1466
  */
1447
1467
  declare function flattenItemProperties<T extends DataCategory = DataCategory, U extends DataCategory | Array<DataCategory> = (T extends "tree" ? Exclude<DataCategory, "tree"> : T extends "set" ? Array<DataCategory> : never)>(item: Item<T, U>): Item<T, U>;
1448
1468
  //#endregion
1449
- export { ApiVersion, Bibliography, Concept, Context, ContextItem, ContextNode, Coordinate, DEFAULT_API_VERSION, DEFAULT_PAGE_SIZE, Data, DataCategory, Event, FileFormat, Gallery, Identification, Image, ImageMap, ImageMapArea, Interpretation, Item, LevelContext, LevelContextItem, License, Link, Metadata, Note, Observation, Period, Person, Property, PropertyContexts, PropertyValue, PropertyValueContent, PropertyValueContentType, PropertyValueQueryItem, PropertyVariable, Query, Resource, Scope, Section, Set, SetItemsSort, SetItemsSortDirection, SpatialUnit, Style, Text, Tree, WebBlock, WebBlockLayout, WebElement, WebElementComponent, WebImage, WebSegment, WebSegmentItem, WebTitle, Webpage, Website, WebsiteType, fetchGallery, fetchItem, fetchSetItems, fetchSetPropertyValuesByPropertyVariables, fetchWebsite, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByLabel, getPropertyByLabelAndValue, getPropertyByLabelAndValues, getPropertyByUuid, getPropertyValueByLabel, getPropertyValueByUuid, getPropertyValuesByLabel, getPropertyValuesByUuid, getUniqueProperties, getUniquePropertyLabels };
1469
+ export { ApiVersion, Bibliography, Concept, Context, ContextItem, ContextNode, Coordinate, DEFAULT_API_VERSION, DEFAULT_PAGE_SIZE, Data, DataCategory, Event, FileFormat, Gallery, Identification, Image, ImageMap, ImageMapArea, Interpretation, Item, LevelContext, LevelContextItem, License, Link, Metadata, Note, Observation, Period, Person, Property, PropertyContexts, PropertyValue, PropertyValueContent, PropertyValueContentType, PropertyValueQueryItem, PropertyVariable, Query, Resource, Scope, Section, Set, SetAttributeValueQueryItem, SetItemsSort, SetItemsSortDirection, SpatialUnit, Style, Text, Tree, WebBlock, WebBlockLayout, WebElement, WebElementComponent, WebImage, WebSegment, WebSegmentItem, WebTitle, Webpage, Website, WebsiteType, fetchGallery, fetchItem, fetchSetItems, fetchSetPropertyValuesByPropertyVariables, fetchWebsite, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByLabel, getPropertyByLabelAndValue, getPropertyByLabelAndValues, getPropertyByUuid, getPropertyValueByLabel, getPropertyValueByUuid, getPropertyValuesByLabel, getPropertyValuesByUuid, getUniqueProperties, getUniquePropertyLabels };
package/dist/index.mjs CHANGED
@@ -875,6 +875,13 @@ const setPropertyValuesByPropertyVariablesParamsSchema = z.object({
875
875
  belongsToCollectionScopeUuids: z.array(uuidSchema).default([]),
876
876
  propertyVariableUuids: z.array(uuidSchema).min(1, "At least one property variable UUID is required"),
877
877
  queries: setQueriesSchema,
878
+ attributeQueries: z.object({
879
+ bibliographies: z.boolean().default(false),
880
+ periods: z.boolean().default(false)
881
+ }).default({
882
+ bibliographies: false,
883
+ periods: false
884
+ }),
878
885
  isLimitedToLeafPropertyValues: z.boolean().default(false)
879
886
  }).superRefine((value, ctx) => {
880
887
  validateSetQueriesOperators(value.queries, ctx);
@@ -2501,6 +2508,30 @@ function aggregatePropertyValues(values) {
2501
2508
  return a.content?.toString().localeCompare(b.content?.toString() ?? "") ?? 0;
2502
2509
  });
2503
2510
  }
2511
+ function aggregateAttributeValues(values) {
2512
+ const groupedAttributeValuesMap = /* @__PURE__ */ new Map();
2513
+ for (const value of values) {
2514
+ if (value.content == null || value.content === "") continue;
2515
+ const existing = groupedAttributeValuesMap.get(value.content);
2516
+ if (existing == null) {
2517
+ groupedAttributeValuesMap.set(value.content, {
2518
+ content: value.content,
2519
+ itemUuids: new Set([value.itemUuid])
2520
+ });
2521
+ continue;
2522
+ }
2523
+ existing.itemUuids.add(value.itemUuid);
2524
+ }
2525
+ const groupedAttributeValues = [];
2526
+ for (const group of groupedAttributeValuesMap.values()) groupedAttributeValues.push({
2527
+ count: group.itemUuids.size,
2528
+ content: group.content
2529
+ });
2530
+ return groupedAttributeValues.toSorted((a, b) => {
2531
+ if (a.count !== b.count) return b.count - a.count;
2532
+ return a.content.localeCompare(b.content);
2533
+ });
2534
+ }
2504
2535
  /**
2505
2536
  * Schema for a single property value query item in the OCHRE API response
2506
2537
  */
@@ -2542,16 +2573,28 @@ const propertyValueQueryItemSchema = z.object({
2542
2573
  returnValue.label = parsePropertyValueLabel(val.content);
2543
2574
  break;
2544
2575
  default:
2545
- returnValue.content = val.rawValue != null && val.rawValue !== "" ? val.rawValue.toString() : val.content != null ? parseStringContent({ content: val.content }) : null;
2576
+ returnValue.content = val.rawValue != null && val.rawValue !== "" ? val.rawValue.toString() : val.content != null && val.content !== "<unassigned>" ? parseStringContent({ content: val.content }) : null;
2546
2577
  returnValue.label = parsePropertyValueLabel(val.content);
2547
2578
  break;
2548
2579
  }
2549
2580
  return returnValue;
2550
2581
  });
2582
+ const attributeValueQueryItemSchema = z.object({
2583
+ attributeType: z.enum(["bibliographies", "periods"]),
2584
+ itemUuid: z.string().optional(),
2585
+ content: z.string().optional()
2586
+ }).transform((val) => ({
2587
+ attributeType: val.attributeType,
2588
+ itemUuid: val.itemUuid != null && val.itemUuid !== "" ? val.itemUuid : null,
2589
+ content: val.content != null && val.content !== "" ? val.content : null
2590
+ }));
2551
2591
  /**
2552
2592
  * Schema for the property values by property variables OCHRE API response
2553
2593
  */
2554
- const responseSchema = z.object({ result: z.union([z.object({ ochre: z.object({ propertyValue: z.union([propertyValueQueryItemSchema, z.array(propertyValueQueryItemSchema)]) }) }), z.array(z.unknown()).length(0)]) });
2594
+ const responseSchema = z.object({ result: z.union([z.object({ ochre: z.object({
2595
+ propertyValue: z.union([propertyValueQueryItemSchema, z.array(propertyValueQueryItemSchema)]).optional(),
2596
+ attributeValue: z.union([attributeValueQueryItemSchema, z.array(attributeValueQueryItemSchema)]).optional()
2597
+ }) }), z.array(z.unknown()).length(0)]) });
2555
2598
  /**
2556
2599
  * Build an XQuery string to fetch property values by property variables from the OCHRE API
2557
2600
  * @param params - The parameters for the fetch
@@ -2559,6 +2602,9 @@ const responseSchema = z.object({ result: z.union([z.object({ ochre: z.object({
2559
2602
  * @param params.belongsToCollectionScopeUuids - An array of collection scope UUIDs to filter by
2560
2603
  * @param params.propertyVariableUuids - An array of property variable UUIDs to fetch
2561
2604
  * @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
2605
+ * @param params.attributeQueries - Whether to return values for bibliographies and periods
2606
+ * @param params.attributeQueries.bibliographies - Whether to return values for bibliographies
2607
+ * @param params.attributeQueries.periods - Whether to return values for periods
2562
2608
  * @param params.isLimitedToLeafPropertyValues - Whether to limit the property values to leaf property values
2563
2609
  * @param options - Options for the fetch
2564
2610
  * @param options.version - The version of the OCHRE API to use
@@ -2566,7 +2612,7 @@ const responseSchema = z.object({ result: z.union([z.object({ ochre: z.object({
2566
2612
  */
2567
2613
  function buildXQuery(params, options) {
2568
2614
  const version = options?.version ?? DEFAULT_API_VERSION;
2569
- const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, queries, isLimitedToLeafPropertyValues } = params;
2615
+ const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, queries, attributeQueries, isLimitedToLeafPropertyValues } = params;
2570
2616
  let setScopeFilter = "/set/items/*";
2571
2617
  if (setScopeUuids.length > 0) setScopeFilter = `/set[(${setScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")})]/items/*`;
2572
2618
  const propertyVariableFilters = propertyVariableUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
@@ -2574,23 +2620,46 @@ function buildXQuery(params, options) {
2574
2620
  const filterPredicates = [];
2575
2621
  if (belongsToCollectionScopeUuids.length > 0) {
2576
2622
  const belongsToCollectionScopeValues = belongsToCollectionScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
2577
- filterPredicates.push(`.//properties[property[label/@uuid="${BELONGS_TO_COLLECTION_UUID}" and value/(${belongsToCollectionScopeValues})]]`);
2623
+ filterPredicates.push(`.//properties[property[label/@uuid="${BELONGS_TO_COLLECTION_UUID}" and value[${belongsToCollectionScopeValues}]]]`);
2578
2624
  }
2579
2625
  if (queryFilters.length > 0) filterPredicates.push(`(${queryFilters})`);
2580
2626
  const itemFilters = filterPredicates.length > 0 ? `[${filterPredicates.join(" and ")}]` : "";
2581
- return `<ochre>{${`let $items := ${version === 2 ? "doc()" : "input()"}/ochre
2582
- ${setScopeFilter}
2583
- ${itemFilters}
2584
-
2585
- let $matching-props := $items//property[label/(${propertyVariableFilters})]
2627
+ const queryBlocks = [`let $matching-props := $items//property[label[${propertyVariableFilters}]]
2586
2628
 
2629
+ let $property-values :=
2587
2630
  for $p in $matching-props
2588
2631
  for $v in $p/value${isLimitedToLeafPropertyValues ? "[not(@i)]" : ""}
2589
2632
  let $item-uuid := $v/ancestor::*[parent::items]/@uuid
2590
2633
  let $variable-uuid := $p/label/@uuid
2591
2634
  return <propertyValue uuid="{$v/@uuid}" rawValue="{$v/@rawValue}" dataType="{$v/@dataType}" itemUuid="{$item-uuid}" variableUuid="{$variable-uuid}">{
2592
2635
  if ($v/content) then string-join($v/content[@xml:lang="eng"]/string, "") else $v/text()
2593
- }</propertyValue>`}}</ochre>`;
2636
+ }</propertyValue>`];
2637
+ const returnedSequences = ["$property-values"];
2638
+ if (attributeQueries.bibliographies) {
2639
+ queryBlocks.push(`let $bibliography-values :=
2640
+ for $item in $items
2641
+ for $bibliography in $item/bibliographies/bibliography
2642
+ let $label := string-join($bibliography/identification/label/content[@xml:lang="eng"]/string, "")
2643
+ where string-length($label) gt 0
2644
+ return <attributeValue attributeType="bibliographies" itemUuid="{$item/@uuid}" content="{$label}" />`);
2645
+ returnedSequences.push("$bibliography-values");
2646
+ }
2647
+ if (attributeQueries.periods) {
2648
+ queryBlocks.push(`let $period-values :=
2649
+ for $item in $items
2650
+ for $period in $item/periods/period
2651
+ let $label := string-join($period/identification/label/content[@xml:lang="eng"]/string, "")
2652
+ where string-length($label) gt 0
2653
+ return <attributeValue attributeType="periods" itemUuid="{$item/@uuid}" content="{$label}" />`);
2654
+ returnedSequences.push("$period-values");
2655
+ }
2656
+ return `<ochre>{${`let $items := ${version === 2 ? "doc()" : "input()"}/ochre
2657
+ ${setScopeFilter}
2658
+ ${itemFilters}
2659
+
2660
+ ${queryBlocks.join("\n\n")}
2661
+
2662
+ return (${returnedSequences.join(", ")})`}}</ochre>`;
2594
2663
  }
2595
2664
  /**
2596
2665
  * Fetches and parses Set property values by property variables from the OCHRE API
@@ -2600,29 +2669,38 @@ function buildXQuery(params, options) {
2600
2669
  * @param params.belongsToCollectionScopeUuids - The collection scope UUIDs to filter by
2601
2670
  * @param params.propertyVariableUuids - The property variable UUIDs to query by
2602
2671
  * @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
2672
+ * @param params.attributeQueries - Whether to return values for bibliographies and periods
2673
+ * @param params.attributeQueries.bibliographies - Whether to return values for bibliographies
2674
+ * @param params.attributeQueries.periods - Whether to return values for periods
2603
2675
  * @param params.isLimitedToLeafPropertyValues - Whether to limit the property values to leaf property values
2604
2676
  * @param options - Options for the fetch
2605
2677
  * @param options.fetch - The fetch function to use
2606
2678
  * @param options.version - The version of the OCHRE API to use
2607
- * @returns The parsed Set property values by property variables or null if the fetch/parse fails
2679
+ * @returns Parsed Set property values and requested attribute values.
2680
+ * Returns empty arrays/objects when no matches are found, and null outputs on fetch/parse errors.
2608
2681
  */
2609
2682
  async function fetchSetPropertyValuesByPropertyVariables(params, options) {
2610
2683
  try {
2611
2684
  const version = options?.version ?? DEFAULT_API_VERSION;
2612
- const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, queries, isLimitedToLeafPropertyValues } = setPropertyValuesByPropertyVariablesParamsSchema.parse(params);
2685
+ const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, queries, attributeQueries, isLimitedToLeafPropertyValues } = setPropertyValuesByPropertyVariablesParamsSchema.parse(params);
2613
2686
  const xquery = buildXQuery({
2614
2687
  setScopeUuids,
2615
2688
  belongsToCollectionScopeUuids,
2616
2689
  propertyVariableUuids,
2617
2690
  queries,
2691
+ attributeQueries,
2618
2692
  isLimitedToLeafPropertyValues
2619
2693
  }, { version });
2620
2694
  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="*"`);
2621
2695
  if (!response.ok) throw new Error(`OCHRE API responded with status: ${response.status}`);
2622
2696
  const data = await response.json();
2623
2697
  const parsedResultRaw = responseSchema.parse(data);
2624
- if (Array.isArray(parsedResultRaw.result)) throw new TypeError("No property values found");
2625
- const parsedPropertyValues = Array.isArray(parsedResultRaw.result.ochre.propertyValue) ? parsedResultRaw.result.ochre.propertyValue : [parsedResultRaw.result.ochre.propertyValue];
2698
+ const parsedPropertyValues = [];
2699
+ const parsedAttributeValues = [];
2700
+ if (!Array.isArray(parsedResultRaw.result)) {
2701
+ if (parsedResultRaw.result.ochre.propertyValue != null) parsedPropertyValues.push(...Array.isArray(parsedResultRaw.result.ochre.propertyValue) ? parsedResultRaw.result.ochre.propertyValue : [parsedResultRaw.result.ochre.propertyValue]);
2702
+ if (parsedResultRaw.result.ochre.attributeValue != null) parsedAttributeValues.push(...Array.isArray(parsedResultRaw.result.ochre.attributeValue) ? parsedResultRaw.result.ochre.attributeValue : [parsedResultRaw.result.ochre.attributeValue]);
2703
+ }
2626
2704
  const propertyValuesByPropertyVariableUuidRaw = {};
2627
2705
  const flattenedPropertyValues = [];
2628
2706
  for (const propertyValue of parsedPropertyValues) {
@@ -2641,9 +2719,18 @@ async function fetchSetPropertyValuesByPropertyVariables(params, options) {
2641
2719
  const aggregatedValues = aggregatePropertyValues(values);
2642
2720
  if (aggregatedValues.length > 0) propertyValuesByPropertyVariableUuid[propertyVariableUuid] = aggregatedValues;
2643
2721
  }
2722
+ const attributeValuesByTypeRaw = {
2723
+ bibliographies: [],
2724
+ periods: []
2725
+ };
2726
+ for (const attributeValue of parsedAttributeValues) attributeValuesByTypeRaw[attributeValue.attributeType].push(attributeValue);
2644
2727
  return {
2645
2728
  propertyValues: aggregatePropertyValues(flattenedPropertyValues),
2646
2729
  propertyValuesByPropertyVariableUuid,
2730
+ attributeValues: {
2731
+ bibliographies: attributeQueries.bibliographies ? aggregateAttributeValues(attributeValuesByTypeRaw.bibliographies) : null,
2732
+ periods: attributeQueries.periods ? aggregateAttributeValues(attributeValuesByTypeRaw.periods) : null
2733
+ },
2647
2734
  error: null
2648
2735
  };
2649
2736
  } catch (error) {
@@ -2651,6 +2738,7 @@ async function fetchSetPropertyValuesByPropertyVariables(params, options) {
2651
2738
  return {
2652
2739
  propertyValues: null,
2653
2740
  propertyValuesByPropertyVariableUuid: null,
2741
+ attributeValues: null,
2654
2742
  error: error instanceof Error ? error.message : "Failed to fetch property values by property variables"
2655
2743
  };
2656
2744
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ochre-sdk",
3
- "version": "0.20.14",
3
+ "version": "0.20.16",
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",