@digitalculture/ochre-sdk 0.18.4 → 0.18.6

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
@@ -602,10 +602,10 @@ type Gallery = {
602
602
  * Represents a property query item with its UUID, raw value, count, and content
603
603
  */
604
604
  type PropertyValueQueryItem = {
605
- uuid: string | null;
606
605
  count: number;
607
- label: string | null;
606
+ dataType: Exclude<PropertyValueContentType, "coordinate">;
608
607
  content: string | number | boolean | null;
608
+ label: string | null;
609
609
  };
610
610
  /**
611
611
  * Represents a metadata object given a UUID
@@ -1105,6 +1105,7 @@ declare function fetchItem<T extends DataCategory = DataCategory, U extends Data
1105
1105
  * @param params.propertyVariableUuids - The property variable UUIDs to query by
1106
1106
  * @param params.propertyValues - The property values to query by
1107
1107
  * @param params.itemCategory - The category of the items to fetch
1108
+ * @param params.includeChildItems - Whether to include child items of the same category
1108
1109
  * @param categoryParams - The category parameters for the fetch
1109
1110
  * @param categoryParams.category - The category of the items to fetch
1110
1111
  * @param categoryParams.itemCategories - The categories of the items to fetch
@@ -1122,6 +1123,7 @@ declare function fetchItemsByPropertyValues<T extends DataCategory = DataCategor
1122
1123
  value: string;
1123
1124
  }>;
1124
1125
  itemCategory?: "resource" | "spatialUnit" | "concept" | "text";
1126
+ includeChildItems?: boolean;
1125
1127
  }, categoryParams?: {
1126
1128
  category?: T;
1127
1129
  itemCategories?: U;
@@ -1129,9 +1131,15 @@ declare function fetchItemsByPropertyValues<T extends DataCategory = DataCategor
1129
1131
  customFetch?: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response>;
1130
1132
  version: ApiVersion;
1131
1133
  }): Promise<{
1134
+ totalCount: number;
1135
+ page: number;
1136
+ pageSize: number;
1132
1137
  items: Array<Item<T, U>>;
1133
1138
  error: null;
1134
1139
  } | {
1140
+ totalCount: null;
1141
+ page: null;
1142
+ pageSize: null;
1135
1143
  items: null;
1136
1144
  error: string;
1137
1145
  }>;
@@ -1389,7 +1397,21 @@ declare function filterProperties(property: Property, filter: {
1389
1397
  }, options?: PropertyOptions): boolean;
1390
1398
  //#endregion
1391
1399
  //#region src/utils/helpers.d.ts
1400
+ /**
1401
+ * The default API version to use
1402
+ *
1403
+ * @remarks
1404
+ * Version 1 of the OCHRE API is deprecated and will be removed in the future.
1405
+ * It points to the old Tamino server.
1406
+ *
1407
+ * Version 2 of the OCHRE API is the current version and is the default.
1408
+ * It points to the new MarkLogic server.
1409
+ */
1392
1410
  declare const DEFAULT_API_VERSION = 2;
1411
+ /**
1412
+ * The default page size to use for fetching paginated items
1413
+ */
1414
+ declare const DEFAULT_PAGE_SIZE = 48;
1393
1415
  /**
1394
1416
  * Flatten the properties of an item
1395
1417
  * @param item - The item whose properties to flatten
@@ -1403,4 +1425,4 @@ declare function flattenItemProperties<T extends DataCategory = DataCategory, U
1403
1425
  */
1404
1426
  declare function getLeafPropertyValues<T extends PropertyValueContentType = PropertyValueContentType>(propertyValues: Array<PropertyValueContent<T>>): Array<PropertyValueContent<T>>;
1405
1427
  //#endregion
1406
- export { ApiVersion, Bibliography, Concept, Context, ContextItem, ContextNode, Coordinate, DEFAULT_API_VERSION, 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, Resource, Scope, Section, Set, SpatialUnit, Style, Text, Tree, UuidMetadata, WebBlock, WebBlockLayout, WebElement, WebElementComponent, WebImage, WebTitle, Webpage, Website, fetchByUuidMetadata, fetchGallery, fetchItem, fetchItemsByPropertyValues, fetchPropertyValuesByPropertyVariables, fetchWebsite, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByLabel, getPropertyByUuid, getPropertyValueByLabel, getPropertyValueByUuid, getPropertyValuesByLabel, getPropertyValuesByUuid, getUniqueProperties, getUniquePropertyLabels };
1428
+ 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, Resource, Scope, Section, Set, SpatialUnit, Style, Text, Tree, UuidMetadata, WebBlock, WebBlockLayout, WebElement, WebElementComponent, WebImage, WebTitle, Webpage, Website, fetchByUuidMetadata, fetchGallery, fetchItem, fetchItemsByPropertyValues, fetchPropertyValuesByPropertyVariables, fetchWebsite, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByLabel, getPropertyByUuid, getPropertyValueByLabel, getPropertyValueByUuid, getPropertyValuesByLabel, getPropertyValuesByUuid, getUniqueProperties, getUniquePropertyLabels };
package/dist/index.mjs CHANGED
@@ -99,8 +99,8 @@ const richTextStringSchema = z.object({
99
99
  * @internal
100
100
  */
101
101
  const identificationSchema = z.object({
102
- label: z.object({ content: richTextStringSchema }),
103
- abbreviation: z.object({ content: richTextStringSchema }).optional(),
102
+ label: z.object({ content: z.union([richTextStringSchema, z.array(richTextStringSchema)]) }),
103
+ abbreviation: z.object({ content: z.union([richTextStringSchema, z.array(richTextStringSchema)]).optional() }),
104
104
  code: z.string().optional()
105
105
  });
106
106
  /**
@@ -990,8 +990,22 @@ function parseStringContent(content, language = "eng") {
990
990
 
991
991
  //#endregion
992
992
  //#region src/utils/helpers.ts
993
+ /**
994
+ * The default API version to use
995
+ *
996
+ * @remarks
997
+ * Version 1 of the OCHRE API is deprecated and will be removed in the future.
998
+ * It points to the old Tamino server.
999
+ *
1000
+ * Version 2 of the OCHRE API is the current version and is the default.
1001
+ * It points to the new MarkLogic server.
1002
+ */
993
1003
  const DEFAULT_API_VERSION = 2;
994
1004
  /**
1005
+ * The default page size to use for fetching paginated items
1006
+ */
1007
+ const DEFAULT_PAGE_SIZE = 48;
1008
+ /**
995
1009
  * Flatten the properties of an item
996
1010
  * @param item - The item whose properties to flatten
997
1011
  * @returns The item with the properties flattened
@@ -3559,26 +3573,30 @@ async function fetchItem(uuid, category, itemCategories, options) {
3559
3573
  * @param params.propertyVariableUuids - An array of property variable UUIDs to fetch
3560
3574
  * @param params.propertyValues - An array of property values to fetch
3561
3575
  * @param params.itemCategory - The category of the items to fetch
3576
+ * @param params.page - The page number (1-indexed)
3577
+ * @param params.pageSize - The number of items per page
3578
+ * @param params.includeChildItems - Whether to include child items of the same category
3562
3579
  * @param options - Options for the fetch
3563
3580
  * @param options.version - The version of the OCHRE API to use
3564
3581
  * @returns An XQuery string
3565
3582
  */
3566
3583
  function buildXQuery$1(params, options) {
3567
3584
  const version = options?.version ?? DEFAULT_API_VERSION;
3568
- const { propertyVariableUuids, propertyValues, projectScopeUuid, belongsToCollectionScopeUuids, itemCategory } = params;
3585
+ const { propertyVariableUuids, propertyValues, projectScopeUuid, belongsToCollectionScopeUuids, itemCategory, page = 1, pageSize = DEFAULT_PAGE_SIZE, includeChildItems = false } = params;
3586
+ const startPos = (page - 1) * pageSize + 1;
3587
+ const endPos = page * pageSize;
3569
3588
  let belongsToCollectionScopeFilter = "";
3570
3589
  if (belongsToCollectionScopeUuids.length > 0) belongsToCollectionScopeFilter = `[properties/property[label/@uuid="${BELONG_TO_COLLECTION_UUID}"][value[${belongsToCollectionScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")}]]]`;
3571
3590
  const propertyVariables = propertyVariableUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
3572
3591
  const propertyValuesFilters = propertyValues.map(({ dataType, value }) => {
3573
- if (dataType === "IDREF") return `value/@uuid="${value}"`;
3574
- if (dataType === "date" || dataType === "dateTime" || dataType === "time" || dataType === "integer" || dataType === "decimal" || dataType === "boolean") return `value/@rawValue="${value}"`;
3575
- return `value="${value}"`;
3592
+ if (dataType === "IDREF") return `value[@uuid="${value}"]`;
3593
+ if (dataType === "date" || dataType === "dateTime" || dataType === "time" || dataType === "integer" || dataType === "decimal" || dataType === "boolean") return `value[@rawValue="${value}"]`;
3594
+ return `value[.="${value}"]`;
3576
3595
  }).join(" or ");
3577
3596
  return `<ochre>{${`let $match-uuids := distinct-values(
3578
3597
  ${version === 2 ? "doc()" : "input()"}/ochre[@uuidBelongsTo="${projectScopeUuid}"]
3579
3598
  /*${belongsToCollectionScopeFilter}
3580
- [properties//property/label[${propertyVariables}]
3581
- [${propertyValuesFilters}]]
3599
+ [properties//property[label[${propertyVariables}]][${propertyValuesFilters}]]
3582
3600
  /@uuid
3583
3601
  )
3584
3602
 
@@ -3587,15 +3605,16 @@ function buildXQuery$1(params, options) {
3587
3605
  or bibliographies/bibliography/@uuid = $match-uuids]
3588
3606
 
3589
3607
  let $unique-uuids := distinct-values($items/@uuid)
3608
+ let $totalCount := count($unique-uuids)
3590
3609
 
3591
- for $uuid in $unique-uuids
3592
- let $item := $items[@uuid = $uuid][1]
3593
- let $category := local-name($item)
3594
-
3595
- return element { node-name($item) } {
3596
- $item/@*,
3597
- $item/node()[not(local-name(.) = $category)]
3598
- }`}}</ochre>`;
3610
+ return <items totalCount="{$totalCount}" page="${page}" pageSize="${pageSize}">{
3611
+ for $uuid in $unique-uuids[position() ge ${startPos} and position() le ${endPos}]
3612
+ let $item := ($items[@uuid = $uuid])[1]
3613
+ let $category := local-name($item)
3614
+ return element { node-name($item) } {
3615
+ $item/@*, ${includeChildItems ? "$item/node()" : "$item/node()[not(local-name(.) = $category)]"}
3616
+ }
3617
+ }</items>`}}</ochre>`;
3599
3618
  }
3600
3619
  /**
3601
3620
  * Fetches and parses items by property values from the OCHRE API
@@ -3606,6 +3625,7 @@ function buildXQuery$1(params, options) {
3606
3625
  * @param params.propertyVariableUuids - The property variable UUIDs to query by
3607
3626
  * @param params.propertyValues - The property values to query by
3608
3627
  * @param params.itemCategory - The category of the items to fetch
3628
+ * @param params.includeChildItems - Whether to include child items of the same category
3609
3629
  * @param categoryParams - The category parameters for the fetch
3610
3630
  * @param categoryParams.category - The category of the items to fetch
3611
3631
  * @param categoryParams.itemCategories - The categories of the items to fetch
@@ -3618,69 +3638,76 @@ async function fetchItemsByPropertyValues(params, categoryParams, options) {
3618
3638
  try {
3619
3639
  const customFetch = options?.customFetch;
3620
3640
  const version = options?.version ?? DEFAULT_API_VERSION;
3621
- const { propertyVariableUuids, propertyValues, projectScopeUuid, belongsToCollectionScopeUuids, itemCategory } = params;
3641
+ const { propertyVariableUuids, propertyValues, projectScopeUuid, belongsToCollectionScopeUuids, itemCategory, includeChildItems } = params;
3622
3642
  const { category, itemCategories } = categoryParams ?? {};
3623
3643
  const xquery = buildXQuery$1({
3624
3644
  projectScopeUuid,
3625
3645
  belongsToCollectionScopeUuids,
3626
3646
  propertyVariableUuids,
3627
3647
  propertyValues,
3628
- itemCategory
3648
+ itemCategory,
3649
+ includeChildItems
3629
3650
  }, { version });
3630
3651
  const response = await (customFetch ?? 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="*"`);
3631
3652
  if (!response.ok) throw new Error(`OCHRE API responded with status: ${response.status}`);
3632
3653
  const data = await response.json();
3633
3654
  if (Array.isArray(data.result) || Object.keys(data.result.ochre).length === 0) throw new Error("No items found");
3634
- if (category != null && data.result.ochre[category] == null) throw new Error(`No items found for category: ${category}`);
3635
- if ((category === "set" || category === "tree") && itemCategories != null && "items" in data.result.ochre[category] && Array.isArray(data.result.ochre[category].items) && data.result.ochre[category].items.every((item) => item.category !== itemCategories)) throw new Error(`No items found for category: ${category} and item categories: ${itemCategories}`);
3655
+ if (category != null && data.result.ochre.items[category] == null) throw new Error(`No items found for category: ${category}`);
3656
+ if ((category === "set" || category === "tree") && itemCategories != null && "items" in data.result.ochre.items[category] && Array.isArray(data.result.ochre.items[category].items) && data.result.ochre.items[category].items.every((item) => item.category !== itemCategories)) throw new Error(`No items found for category: ${category} and item categories: ${itemCategories}`);
3636
3657
  const items = [];
3637
- if ("resource" in data.result.ochre && data.result.ochre.resource != null) {
3638
- const resources = parseResources(Array.isArray(data.result.ochre.resource) ? data.result.ochre.resource : [data.result.ochre.resource]);
3658
+ if ("resource" in data.result.ochre.items && data.result.ochre.items.resource != null) {
3659
+ const resources = parseResources(Array.isArray(data.result.ochre.items.resource) ? data.result.ochre.items.resource : [data.result.ochre.items.resource]);
3639
3660
  items.push(...resources);
3640
3661
  }
3641
- if ("spatialUnit" in data.result.ochre && data.result.ochre.spatialUnit != null) {
3642
- const spatialUnits = parseSpatialUnits(Array.isArray(data.result.ochre.spatialUnit) ? data.result.ochre.spatialUnit : [data.result.ochre.spatialUnit]);
3662
+ if ("spatialUnit" in data.result.ochre.items && data.result.ochre.items.spatialUnit != null) {
3663
+ const spatialUnits = parseSpatialUnits(Array.isArray(data.result.ochre.items.spatialUnit) ? data.result.ochre.items.spatialUnit : [data.result.ochre.items.spatialUnit]);
3643
3664
  items.push(...spatialUnits);
3644
3665
  }
3645
- if ("concept" in data.result.ochre && data.result.ochre.concept != null) {
3646
- const concepts = parseConcepts(Array.isArray(data.result.ochre.concept) ? data.result.ochre.concept : [data.result.ochre.concept]);
3666
+ if ("concept" in data.result.ochre.items && data.result.ochre.items.concept != null) {
3667
+ const concepts = parseConcepts(Array.isArray(data.result.ochre.items.concept) ? data.result.ochre.items.concept : [data.result.ochre.items.concept]);
3647
3668
  items.push(...concepts);
3648
3669
  }
3649
- if ("period" in data.result.ochre && data.result.ochre.period != null) {
3650
- const periods = parsePeriods(Array.isArray(data.result.ochre.period) ? data.result.ochre.period : [data.result.ochre.period]);
3670
+ if ("period" in data.result.ochre.items && data.result.ochre.items.period != null) {
3671
+ const periods = parsePeriods(Array.isArray(data.result.ochre.items.period) ? data.result.ochre.items.period : [data.result.ochre.items.period]);
3651
3672
  items.push(...periods);
3652
3673
  }
3653
- if ("bibliography" in data.result.ochre && data.result.ochre.bibliography != null) {
3654
- const bibliographies = parseBibliographies(Array.isArray(data.result.ochre.bibliography) ? data.result.ochre.bibliography : [data.result.ochre.bibliography]);
3674
+ if ("bibliography" in data.result.ochre.items && data.result.ochre.items.bibliography != null) {
3675
+ const bibliographies = parseBibliographies(Array.isArray(data.result.ochre.items.bibliography) ? data.result.ochre.items.bibliography : [data.result.ochre.items.bibliography]);
3655
3676
  items.push(...bibliographies);
3656
3677
  }
3657
- if ("person" in data.result.ochre && data.result.ochre.person != null) {
3658
- const persons = parsePersons(Array.isArray(data.result.ochre.person) ? data.result.ochre.person : [data.result.ochre.person]);
3678
+ if ("person" in data.result.ochre.items && data.result.ochre.items.person != null) {
3679
+ const persons = parsePersons(Array.isArray(data.result.ochre.items.person) ? data.result.ochre.items.person : [data.result.ochre.items.person]);
3659
3680
  items.push(...persons);
3660
3681
  }
3661
- if ("propertyValue" in data.result.ochre && data.result.ochre.propertyValue != null) {
3662
- const propertyValues = parsePropertyValues(Array.isArray(data.result.ochre.propertyValue) ? data.result.ochre.propertyValue : [data.result.ochre.propertyValue]);
3682
+ if ("propertyValue" in data.result.ochre.items && data.result.ochre.items.propertyValue != null) {
3683
+ const propertyValues = parsePropertyValues(Array.isArray(data.result.ochre.items.propertyValue) ? data.result.ochre.items.propertyValue : [data.result.ochre.items.propertyValue]);
3663
3684
  items.push(...propertyValues);
3664
3685
  }
3665
- if ("text" in data.result.ochre && data.result.ochre.text != null) {
3666
- const texts = parseTexts(Array.isArray(data.result.ochre.text) ? data.result.ochre.text : [data.result.ochre.text]);
3686
+ if ("text" in data.result.ochre.items && data.result.ochre.items.text != null) {
3687
+ const texts = parseTexts(Array.isArray(data.result.ochre.items.text) ? data.result.ochre.items.text : [data.result.ochre.items.text]);
3667
3688
  items.push(...texts);
3668
3689
  }
3669
- if ("set" in data.result.ochre && data.result.ochre.set != null) {
3670
- const sets = parseSets(Array.isArray(data.result.ochre.set) ? data.result.ochre.set : [data.result.ochre.set]);
3690
+ if ("set" in data.result.ochre.items && data.result.ochre.items.set != null) {
3691
+ const sets = parseSets(Array.isArray(data.result.ochre.items.set) ? data.result.ochre.items.set : [data.result.ochre.items.set]);
3671
3692
  items.push(...sets);
3672
3693
  }
3673
- if ("tree" in data.result.ochre && data.result.ochre.tree != null) {
3674
- const trees = parseTrees(Array.isArray(data.result.ochre.tree) ? data.result.ochre.tree : [data.result.ochre.tree]);
3694
+ if ("tree" in data.result.ochre.items && data.result.ochre.items.tree != null) {
3695
+ const trees = parseTrees(Array.isArray(data.result.ochre.items.tree) ? data.result.ochre.items.tree : [data.result.ochre.items.tree]);
3675
3696
  items.push(...trees);
3676
3697
  }
3677
3698
  return {
3699
+ totalCount: data.result.ochre.totalCount,
3700
+ page: data.result.ochre.page,
3701
+ pageSize: data.result.ochre.pageSize,
3678
3702
  items,
3679
3703
  error: null
3680
3704
  };
3681
3705
  } catch (error) {
3682
3706
  console.error(error);
3683
3707
  return {
3708
+ totalCount: null,
3709
+ page: null,
3710
+ pageSize: null,
3684
3711
  items: null,
3685
3712
  error: error instanceof Error ? error.message : "Failed to fetch items by property values"
3686
3713
  };
@@ -3693,58 +3720,52 @@ async function fetchItemsByPropertyValues(params, categoryParams, options) {
3693
3720
  * Schema for a single property value query item in the OCHRE API response
3694
3721
  */
3695
3722
  const propertyValueQueryItemSchema = z.object({
3696
- uuid: uuidSchema.optional().transform((val) => val ?? null),
3697
- count: z.number(),
3723
+ uuid: z.string().optional(),
3698
3724
  dataType: z.string(),
3699
3725
  identification: identificationSchema.optional(),
3700
- label: z.union([
3726
+ rawValue: z.union([
3701
3727
  z.string(),
3702
3728
  z.number(),
3703
3729
  z.boolean()
3704
- ]).optional().transform((val) => val?.toString() ?? null),
3705
- content: z.union([
3730
+ ]).optional(),
3731
+ value: z.union([
3706
3732
  z.string(),
3707
3733
  z.number(),
3708
3734
  z.boolean()
3709
- ]).optional().transform((val) => val ?? null)
3735
+ ]).optional()
3710
3736
  }).transform((val) => {
3711
- let value = val;
3737
+ const returnValue = {
3738
+ dataType: val.dataType,
3739
+ content: null,
3740
+ label: null
3741
+ };
3712
3742
  switch (val.dataType) {
3713
3743
  case "IDREF":
3744
+ returnValue.content = val.uuid != null ? val.uuid || null : null;
3745
+ returnValue.label = val.identification != null ? parseStringContent({ content: val.identification.label.content }) : null;
3746
+ break;
3714
3747
  case "string":
3715
3748
  case "date":
3716
3749
  case "dateTime":
3717
- value = {
3718
- ...val,
3719
- content: val.content?.toString() ?? null
3720
- };
3750
+ returnValue.content = val.rawValue?.toString() ?? null;
3751
+ returnValue.label = val.value?.toString() ?? null;
3721
3752
  break;
3722
3753
  case "integer":
3723
3754
  case "decimal":
3724
3755
  case "time":
3725
- value = {
3726
- ...val,
3727
- content: val.content !== null ? Number(val.content) : null
3728
- };
3756
+ returnValue.content = val.rawValue != null ? Number(val.rawValue) : null;
3757
+ returnValue.label = val.value?.toString() ?? null;
3729
3758
  break;
3730
3759
  case "boolean":
3731
- value = {
3732
- ...val,
3733
- content: val.content !== null ? Boolean(val.content) : null
3734
- };
3760
+ returnValue.content = val.rawValue != null ? Boolean(val.rawValue) : null;
3761
+ returnValue.label = val.value?.toString() ?? null;
3735
3762
  break;
3736
3763
  default:
3737
- value = val;
3764
+ returnValue.content = val.rawValue?.toString() ?? null;
3765
+ returnValue.label = val.value?.toString() ?? null;
3738
3766
  break;
3739
3767
  }
3740
- if ("identification" in value && value.identification != null) {
3741
- const { identification, ...rest } = value;
3742
- value = {
3743
- ...rest,
3744
- content: parseStringContent({ content: identification.label.content })
3745
- };
3746
- }
3747
- return value;
3768
+ return returnValue;
3748
3769
  });
3749
3770
  /**
3750
3771
  * Schema for the property values by property variables OCHRE API response
@@ -3766,44 +3787,15 @@ function buildXQuery(params, options) {
3766
3787
  let collectionScopeFilter = "";
3767
3788
  if (belongsToCollectionScopeUuids.length > 0) collectionScopeFilter = `[properties/property[label/@uuid="${BELONG_TO_COLLECTION_UUID}"][value[${belongsToCollectionScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")}]]]`;
3768
3789
  const propertyVariableFilters = propertyVariableUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
3769
- return `<ochre>{${`let $props := ${version === 2 ? "doc()" : "input()"}/ochre[@uuidBelongsTo="${projectScopeUuid}"]
3790
+ return `<ochre>{${`let $values := ${version === 2 ? "doc()" : "input()"}/ochre[@uuidBelongsTo="${projectScopeUuid}"]
3770
3791
  /*${collectionScopeFilter}
3771
3792
  /properties//property[label[${propertyVariableFilters}]]
3793
+ /value
3772
3794
 
3773
- let $values := $props/value
3774
-
3775
- let $uuid-values := $values[@uuid]
3776
- let $uuid-vals := distinct-values($uuid-values/@uuid)
3777
- let $uuid-dataType := string($uuid-values[1]/@dataType)
3778
- let $uuid-items :=
3779
- for $val in $uuid-vals
3780
- let $matching-prop := ($props[value/@uuid = $val])[1]
3781
- let $count := count($uuid-values[@uuid = $val])
3782
- let $identification := $matching-prop/ancestor::*[parent::ochre]/identification
3783
- let $label := $identification/label/content/string/text())
3784
- order by $count descending, $label ascending
3785
- return <item count="{$count}" uuid="{$val}" dataType="{$uuid-dataType}">{$identification}</item>
3786
-
3787
- let $raw-values := $values[@rawValue]
3788
- let $raw-vals := distinct-values($raw-values/@rawValue)
3789
- let $raw-dataType := string($raw-values[1]/@dataType)
3790
- let $raw-items :=
3791
- for $val in $raw-vals
3792
- let $count := count($raw-values[@rawValue = $val])
3793
- let $label := string($raw-values[@rawValue = $val][1])
3794
- order by $count descending, $label ascending
3795
- return <item count="{$count}" rawValue="{$val}" dataType="{$raw-dataType}" label="{$label}">{$val}</item>
3796
-
3797
- let $text-values := $values[not(@uuid) and not(@rawValue)]
3798
- let $text-vals := distinct-values(for $v in $text-values return string($v))
3799
- let $text-dataType := string($text-values[1]/@dataType)
3800
- let $text-items :=
3801
- for $val in $text-vals
3802
- let $count := count($text-values[string(.) = $val])
3803
- order by $count descending, $val ascending
3804
- return <item count="{$count}" dataType="{$text-dataType}">{$val}</item>
3805
-
3806
- return ($uuid-items, $raw-items, $text-items)`}}</ochre>`;
3795
+ for $v in $values
3796
+ return <item uuid="{$v/@uuid}" rawValue="{$v/@rawValue}" dataType="{$v/@dataType}" value="{string($v)}">{
3797
+ if (string($v/@uuid) != "") then $v/ancestor::*[parent::ochre]/identification else ()
3798
+ }</item>`}}</ochre>`;
3807
3799
  }
3808
3800
  /**
3809
3801
  * Fetches and parses property values by property variables from the OCHRE API
@@ -3832,8 +3824,22 @@ async function fetchPropertyValuesByPropertyVariables(params, options) {
3832
3824
  const data = await response.json();
3833
3825
  const parsedResultRaw = responseSchema.parse(data);
3834
3826
  if (Array.isArray(parsedResultRaw.result)) throw new TypeError("No items found");
3827
+ const parsedItems = Array.isArray(parsedResultRaw.result.ochre.item) ? parsedResultRaw.result.ochre.item : [parsedResultRaw.result.ochre.item];
3828
+ const groupedItems = [];
3829
+ for (const item of parsedItems) {
3830
+ const existingItem = groupedItems.find((i) => i.content === item.content);
3831
+ if (existingItem == null) groupedItems.push({
3832
+ count: 1,
3833
+ ...item
3834
+ });
3835
+ else existingItem.count++;
3836
+ }
3835
3837
  return {
3836
- items: (Array.isArray(parsedResultRaw.result.ochre.item) ? parsedResultRaw.result.ochre.item : [parsedResultRaw.result.ochre.item]).filter((item) => String(item.content).trim() !== ""),
3838
+ items: groupedItems.toSorted((a, b) => {
3839
+ if (a.count !== b.count) return b.count - a.count;
3840
+ if (a.label !== b.label) return a.label?.localeCompare(b.label ?? "") ?? 0;
3841
+ return a.content?.toString().localeCompare(b.content?.toString() ?? "") ?? 0;
3842
+ }),
3837
3843
  error: null
3838
3844
  };
3839
3845
  } catch (error) {
@@ -3986,4 +3992,4 @@ async function fetchWebsite(abbreviation, options) {
3986
3992
  }
3987
3993
 
3988
3994
  //#endregion
3989
- export { DEFAULT_API_VERSION, fetchByUuidMetadata, fetchGallery, fetchItem, fetchItemsByPropertyValues, fetchPropertyValuesByPropertyVariables, fetchWebsite, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByLabel, getPropertyByUuid, getPropertyValueByLabel, getPropertyValueByUuid, getPropertyValuesByLabel, getPropertyValuesByUuid, getUniqueProperties, getUniquePropertyLabels };
3995
+ export { DEFAULT_API_VERSION, DEFAULT_PAGE_SIZE, fetchByUuidMetadata, fetchGallery, fetchItem, fetchItemsByPropertyValues, fetchPropertyValuesByPropertyVariables, fetchWebsite, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByLabel, getPropertyByUuid, getPropertyValueByLabel, getPropertyValueByUuid, getPropertyValuesByLabel, getPropertyValuesByUuid, getUniqueProperties, getUniquePropertyLabels };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitalculture/ochre-sdk",
3
- "version": "0.18.4",
3
+ "version": "0.18.6",
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",