ochre-sdk 0.20.6 → 0.20.10

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
@@ -951,7 +951,7 @@ type WebElementComponent = {
951
951
  isResultsBarDisplayed: boolean;
952
952
  isMapDisplayed: boolean;
953
953
  isInputDisplayed: boolean;
954
- isLimitedToTitleQuery: boolean;
954
+ isLimitedToInputFilter: boolean;
955
955
  isLimitedToLeafPropertyValues: boolean;
956
956
  sidebarSort: "default" | "alphabetical";
957
957
  };
@@ -1238,6 +1238,7 @@ declare function fetchSetItems<U extends Array<DataCategory> = Array<DataCategor
1238
1238
  * @param params.setScopeUuids - An array of set scope UUIDs to filter by
1239
1239
  * @param params.belongsToCollectionScopeUuids - The collection scope UUIDs to filter by
1240
1240
  * @param params.propertyVariableUuids - The property variable UUIDs to query by
1241
+ * @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
1241
1242
  * @param params.isLimitedToLeafPropertyValues - Whether to limit the property values to leaf property values
1242
1243
  * @param options - Options for the fetch
1243
1244
  * @param options.fetch - The fetch function to use
@@ -1248,6 +1249,7 @@ declare function fetchSetPropertyValuesByPropertyVariables(params: {
1248
1249
  setScopeUuids: Array<string>;
1249
1250
  belongsToCollectionScopeUuids: Array<string>;
1250
1251
  propertyVariableUuids: Array<string>;
1252
+ queries?: Array<Query>;
1251
1253
  isLimitedToLeafPropertyValues?: boolean;
1252
1254
  }, options?: {
1253
1255
  fetch?: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response>;
package/dist/index.mjs CHANGED
@@ -760,81 +760,70 @@ const boundsSchema = z.string().transform((str, ctx) => {
760
760
  }
761
761
  }).pipe(z.tuple([z.tuple([z.number(), z.number()]), z.tuple([z.number(), z.number()])], { message: "Must contain exactly 2 coordinate pairs" }));
762
762
  /**
763
- * Schema for validating the parameters for the Set property values by property variables fetching function
763
+ * Shared schema for Set queries
764
764
  * @internal
765
765
  */
766
- const setPropertyValuesByPropertyVariablesParamsSchema = z.object({
767
- setScopeUuids: z.array(uuidSchema).min(1, "At least one set scope UUID is required"),
768
- belongsToCollectionScopeUuids: z.array(uuidSchema).default([]),
769
- propertyVariableUuids: z.array(uuidSchema).min(1, "At least one property variable UUID is required"),
770
- isLimitedToLeafPropertyValues: z.boolean().default(false)
771
- });
772
- const setItemsParamsSchema = z.object({
773
- setScopeUuids: z.array(uuidSchema).min(1, "At least one set scope UUID is required"),
774
- belongsToCollectionScopeUuids: z.array(uuidSchema).default([]),
775
- propertyVariableUuids: z.array(uuidSchema).default([]),
776
- queries: z.array(z.union([
777
- z.object({
778
- target: z.literal("propertyValue"),
779
- dataType: z.enum([
780
- "string",
781
- "integer",
782
- "decimal",
783
- "boolean",
784
- "time",
785
- "IDREF"
786
- ]),
787
- value: z.string(),
788
- matchMode: z.enum(["includes", "exact"]),
789
- isCaseSensitive: z.boolean(),
790
- language: z.string().default("eng"),
791
- operator: z.enum(["AND", "OR"]).optional(),
792
- isNegated: z.boolean().optional().default(false)
793
- }).strict(),
794
- z.object({
795
- target: z.literal("propertyValue"),
796
- dataType: z.enum(["date", "dateTime"]),
797
- value: z.string(),
798
- from: z.string(),
799
- to: z.string().optional(),
800
- matchMode: z.enum(["includes", "exact"]),
801
- isCaseSensitive: z.boolean(),
802
- language: z.string().default("eng"),
803
- operator: z.enum(["AND", "OR"]).optional(),
804
- isNegated: z.boolean().optional().default(false)
805
- }).strict(),
806
- z.object({
807
- target: z.literal("propertyValue"),
808
- dataType: z.enum(["date", "dateTime"]),
809
- value: z.string(),
810
- from: z.string().optional(),
811
- to: z.string(),
812
- matchMode: z.enum(["includes", "exact"]),
813
- isCaseSensitive: z.boolean(),
814
- language: z.string().default("eng"),
815
- operator: z.enum(["AND", "OR"]).optional(),
816
- isNegated: z.boolean().optional().default(false)
817
- }).strict(),
818
- z.object({
819
- target: z.enum([
820
- "title",
821
- "description",
822
- "image",
823
- "periods",
824
- "bibliography"
825
- ]),
826
- value: z.string(),
827
- matchMode: z.enum(["includes", "exact"]),
828
- isCaseSensitive: z.boolean(),
829
- language: z.string().default("eng"),
830
- operator: z.enum(["AND", "OR"]).optional(),
831
- isNegated: z.boolean().optional().default(false)
832
- }).strict()
833
- ])).default([]),
834
- page: z.number().min(1, "Page must be positive").default(1),
835
- pageSize: z.number().min(1, "Page size must be positive").default(DEFAULT_PAGE_SIZE)
836
- }).superRefine((value, ctx) => {
837
- for (const [index, query] of value.queries.entries()) {
766
+ const setQuerySchema = z.union([
767
+ z.object({
768
+ target: z.literal("propertyValue"),
769
+ dataType: z.enum([
770
+ "string",
771
+ "integer",
772
+ "decimal",
773
+ "boolean",
774
+ "time",
775
+ "IDREF"
776
+ ]),
777
+ value: z.string(),
778
+ matchMode: z.enum(["includes", "exact"]),
779
+ isCaseSensitive: z.boolean(),
780
+ language: z.string().default("eng"),
781
+ operator: z.enum(["AND", "OR"]).optional(),
782
+ isNegated: z.boolean().optional().default(false)
783
+ }).strict(),
784
+ z.object({
785
+ target: z.literal("propertyValue"),
786
+ dataType: z.enum(["date", "dateTime"]),
787
+ value: z.string(),
788
+ from: z.string(),
789
+ to: z.string().optional(),
790
+ matchMode: z.enum(["includes", "exact"]),
791
+ isCaseSensitive: z.boolean(),
792
+ language: z.string().default("eng"),
793
+ operator: z.enum(["AND", "OR"]).optional(),
794
+ isNegated: z.boolean().optional().default(false)
795
+ }).strict(),
796
+ z.object({
797
+ target: z.literal("propertyValue"),
798
+ dataType: z.enum(["date", "dateTime"]),
799
+ value: z.string(),
800
+ from: z.string().optional(),
801
+ to: z.string(),
802
+ matchMode: z.enum(["includes", "exact"]),
803
+ isCaseSensitive: z.boolean(),
804
+ language: z.string().default("eng"),
805
+ operator: z.enum(["AND", "OR"]).optional(),
806
+ isNegated: z.boolean().optional().default(false)
807
+ }).strict(),
808
+ z.object({
809
+ target: z.enum([
810
+ "title",
811
+ "description",
812
+ "image",
813
+ "periods",
814
+ "bibliography"
815
+ ]),
816
+ value: z.string(),
817
+ matchMode: z.enum(["includes", "exact"]),
818
+ isCaseSensitive: z.boolean(),
819
+ language: z.string().default("eng"),
820
+ operator: z.enum(["AND", "OR"]).optional(),
821
+ isNegated: z.boolean().optional().default(false)
822
+ }).strict()
823
+ ]);
824
+ const setQueriesSchema = z.array(setQuerySchema).default([]);
825
+ function validateSetQueriesOperators(queries, ctx) {
826
+ for (const [index, query] of queries.entries()) {
838
827
  if (index === 0 && query.operator != null) ctx.addIssue({
839
828
  code: "custom",
840
829
  path: [
@@ -854,6 +843,29 @@ const setItemsParamsSchema = z.object({
854
843
  message: "Query rules after the first must include an operator"
855
844
  });
856
845
  }
846
+ }
847
+ /**
848
+ * Schema for validating the parameters for the Set property values by property variables fetching function
849
+ * @internal
850
+ */
851
+ const setPropertyValuesByPropertyVariablesParamsSchema = z.object({
852
+ setScopeUuids: z.array(uuidSchema).min(1, "At least one set scope UUID is required"),
853
+ belongsToCollectionScopeUuids: z.array(uuidSchema).default([]),
854
+ propertyVariableUuids: z.array(uuidSchema).min(1, "At least one property variable UUID is required"),
855
+ queries: setQueriesSchema,
856
+ isLimitedToLeafPropertyValues: z.boolean().default(false)
857
+ }).superRefine((value, ctx) => {
858
+ validateSetQueriesOperators(value.queries, ctx);
859
+ });
860
+ const setItemsParamsSchema = z.object({
861
+ setScopeUuids: z.array(uuidSchema).min(1, "At least one set scope UUID is required"),
862
+ belongsToCollectionScopeUuids: z.array(uuidSchema).default([]),
863
+ propertyVariableUuids: z.array(uuidSchema).default([]),
864
+ queries: setQueriesSchema,
865
+ page: z.number().min(1, "Page must be positive").default(1),
866
+ pageSize: z.number().min(1, "Page size must be positive").default(DEFAULT_PAGE_SIZE)
867
+ }).superRefine((value, ctx) => {
868
+ validateSetQueriesOperators(value.queries, ctx);
857
869
  });
858
870
 
859
871
  //#endregion
@@ -2099,15 +2111,9 @@ async function fetchItem(uuid, category, itemCategories, options) {
2099
2111
  }
2100
2112
 
2101
2113
  //#endregion
2102
- //#region src/utils/fetchers/set/items.ts
2114
+ //#region src/utils/fetchers/set/query-helpers.ts
2103
2115
  /**
2104
2116
  * Build a string match predicate for an XQuery string
2105
- * @param params - The parameters for the predicate
2106
- * @param params.path - The path to the string
2107
- * @param params.value - The value to match
2108
- * @param params.matchMode - The match mode (includes or exact)
2109
- * @param params.isCaseSensitive - Whether to match case-sensitively
2110
- * @returns The string match predicate
2111
2117
  */
2112
2118
  function buildStringMatchPredicate(params) {
2113
2119
  const { path, value, matchMode, isCaseSensitive } = params;
@@ -2128,8 +2134,6 @@ function buildDateRangePredicate(params) {
2128
2134
  }
2129
2135
  /**
2130
2136
  * Build a property value predicate for an XQuery string
2131
- * @param query - The propertyValue query
2132
- * @returns The property value predicate
2133
2137
  */
2134
2138
  function buildPropertyValuePredicate(query) {
2135
2139
  if (query.dataType === "IDREF") return `.//properties//property[value[@uuid=${stringLiteral(query.value)}]]`;
@@ -2147,8 +2151,6 @@ function buildPropertyValuePredicate(query) {
2147
2151
  }
2148
2152
  /**
2149
2153
  * Build a query predicate for an XQuery string
2150
- * @param query - The query to build the predicate for
2151
- * @returns The query predicate
2152
2154
  */
2153
2155
  function buildQueryPredicate(query) {
2154
2156
  switch (query.target) {
@@ -2193,6 +2195,19 @@ function buildBooleanQueryClause(query) {
2193
2195
  return query.isNegated ? `not(${baseClause})` : baseClause;
2194
2196
  }
2195
2197
  /**
2198
+ * Build query filters for an XQuery string.
2199
+ */
2200
+ function buildQueryFilters(queries) {
2201
+ return queries.map((query, index) => {
2202
+ const clause = buildBooleanQueryClause(query);
2203
+ if (index === 0) return clause;
2204
+ return `${query.operator === "OR" ? "or" : "and"} ${clause}`;
2205
+ }).join(" ");
2206
+ }
2207
+
2208
+ //#endregion
2209
+ //#region src/utils/fetchers/set/items.ts
2210
+ /**
2196
2211
  * Build an XQuery string to fetch Set items from the OCHRE API
2197
2212
  * @param params - The parameters for the fetch
2198
2213
  * @param params.setScopeUuids - An array of Set scope UUIDs to filter by
@@ -2211,11 +2226,7 @@ function buildXQuery$1(params, options) {
2211
2226
  const startPosition = (page - 1) * pageSize + 1;
2212
2227
  const endPosition = page * pageSize;
2213
2228
  const setScopeFilter = `/set[(${setScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")})]/items/*`;
2214
- const queryFilters = queries.map((query, index) => {
2215
- const clause = buildBooleanQueryClause(query);
2216
- if (index === 0) return clause;
2217
- return `${query.operator === "OR" ? "or" : "and"} ${clause}`;
2218
- }).join(" ");
2229
+ const queryFilters = buildQueryFilters(queries);
2219
2230
  const filterPredicates = [];
2220
2231
  if (belongsToCollectionScopeUuids.length > 0) {
2221
2232
  const belongsToCollectionScopeValues = belongsToCollectionScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
@@ -2447,6 +2458,7 @@ const responseSchema = z.object({ result: z.union([z.object({ ochre: z.object({
2447
2458
  * @param params.setScopeUuids - An array of set scope UUIDs to filter by
2448
2459
  * @param params.belongsToCollectionScopeUuids - An array of collection scope UUIDs to filter by
2449
2460
  * @param params.propertyVariableUuids - An array of property variable UUIDs to fetch
2461
+ * @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
2450
2462
  * @param params.isLimitedToLeafPropertyValues - Whether to limit the property values to leaf property values
2451
2463
  * @param options - Options for the fetch
2452
2464
  * @param options.version - The version of the OCHRE API to use
@@ -2454,16 +2466,23 @@ const responseSchema = z.object({ result: z.union([z.object({ ochre: z.object({
2454
2466
  */
2455
2467
  function buildXQuery(params, options) {
2456
2468
  const version = options?.version ?? DEFAULT_API_VERSION;
2457
- const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, isLimitedToLeafPropertyValues } = params;
2458
- let setScopeFilter = "";
2459
- if (setScopeUuids.length > 0) setScopeFilter = `/set[(${setScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")})]/items`;
2460
- let collectionScopeFilter = "";
2461
- if (belongsToCollectionScopeUuids.length > 0) collectionScopeFilter = `//properties[property[label/@uuid="${BELONGS_TO_COLLECTION_UUID}" and value/(${belongsToCollectionScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")})]]`;
2469
+ const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, queries, isLimitedToLeafPropertyValues } = params;
2470
+ let setScopeFilter = "/set/items/*";
2471
+ if (setScopeUuids.length > 0) setScopeFilter = `/set[(${setScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ")})]/items/*`;
2462
2472
  const propertyVariableFilters = propertyVariableUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
2463
- return `<ochre>{${`let $matching-props := ${version === 2 ? "doc()" : "input()"}/ochre
2473
+ const queryFilters = buildQueryFilters(queries);
2474
+ const filterPredicates = [];
2475
+ if (belongsToCollectionScopeUuids.length > 0) {
2476
+ const belongsToCollectionScopeValues = belongsToCollectionScopeUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
2477
+ filterPredicates.push(`.//properties[property[label/@uuid="${BELONGS_TO_COLLECTION_UUID}" and value/(${belongsToCollectionScopeValues})]]`);
2478
+ }
2479
+ if (queryFilters.length > 0) filterPredicates.push(`(${queryFilters})`);
2480
+ const itemFilters = filterPredicates.length > 0 ? `[${filterPredicates.join(" and ")}]` : "";
2481
+ return `<ochre>{${`let $items := ${version === 2 ? "doc()" : "input()"}/ochre
2464
2482
  ${setScopeFilter}
2465
- ${collectionScopeFilter}
2466
- //property[label/(${propertyVariableFilters})]
2483
+ ${itemFilters}
2484
+
2485
+ let $matching-props := $items//property[label/(${propertyVariableFilters})]
2467
2486
 
2468
2487
  for $p in $matching-props
2469
2488
  for $v in $p/value${isLimitedToLeafPropertyValues ? "[not(@i)]" : ""}
@@ -2480,6 +2499,7 @@ function buildXQuery(params, options) {
2480
2499
  * @param params.setScopeUuids - An array of set scope UUIDs to filter by
2481
2500
  * @param params.belongsToCollectionScopeUuids - The collection scope UUIDs to filter by
2482
2501
  * @param params.propertyVariableUuids - The property variable UUIDs to query by
2502
+ * @param params.queries - Ordered queries to combine with AND/OR and optional NOT via negation
2483
2503
  * @param params.isLimitedToLeafPropertyValues - Whether to limit the property values to leaf property values
2484
2504
  * @param options - Options for the fetch
2485
2505
  * @param options.fetch - The fetch function to use
@@ -2489,11 +2509,12 @@ function buildXQuery(params, options) {
2489
2509
  async function fetchSetPropertyValuesByPropertyVariables(params, options) {
2490
2510
  try {
2491
2511
  const version = options?.version ?? DEFAULT_API_VERSION;
2492
- const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, isLimitedToLeafPropertyValues } = setPropertyValuesByPropertyVariablesParamsSchema.parse(params);
2512
+ const { setScopeUuids, belongsToCollectionScopeUuids, propertyVariableUuids, queries, isLimitedToLeafPropertyValues } = setPropertyValuesByPropertyVariablesParamsSchema.parse(params);
2493
2513
  const xquery = buildXQuery({
2494
2514
  setScopeUuids,
2495
2515
  belongsToCollectionScopeUuids,
2496
2516
  propertyVariableUuids,
2517
+ queries,
2497
2518
  isLimitedToLeafPropertyValues
2498
2519
  }, { version });
2499
2520
  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="*"`);
@@ -3027,8 +3048,8 @@ function parseWebElementProperties(componentProperty, elementResource) {
3027
3048
  isFilterMapDisplayed ??= false;
3028
3049
  let isFilterInputDisplayed = getPropertyValueByLabel(componentProperty.properties, "filter-input-displayed");
3029
3050
  isFilterInputDisplayed ??= false;
3030
- let isFilterLimitedToTitleQuery = getPropertyValueByLabel(componentProperty.properties, "filter-limit-to-title-query");
3031
- isFilterLimitedToTitleQuery ??= false;
3051
+ let isFilterLimitedToInputFilter = getPropertyValueByLabel(componentProperty.properties, "filter-limit-to-input-filter");
3052
+ isFilterLimitedToInputFilter ??= false;
3032
3053
  let isFilterLimitedToLeafPropertyValues = getPropertyValueByLabel(componentProperty.properties, "filter-limit-to-leaf-property-values");
3033
3054
  isFilterLimitedToLeafPropertyValues ??= false;
3034
3055
  let isSortDisplayed = getPropertyValueByLabel(componentProperty.properties, "sort-displayed");
@@ -3078,7 +3099,7 @@ function parseWebElementProperties(componentProperty, elementResource) {
3078
3099
  isResultsBarDisplayed: isFilterResultsBarDisplayed,
3079
3100
  isMapDisplayed: isFilterMapDisplayed,
3080
3101
  isInputDisplayed: isFilterInputDisplayed,
3081
- isLimitedToTitleQuery: isFilterLimitedToTitleQuery,
3102
+ isLimitedToInputFilter: isFilterLimitedToInputFilter,
3082
3103
  isLimitedToLeafPropertyValues: isFilterLimitedToLeafPropertyValues,
3083
3104
  sidebarSort: filterSidebarSort
3084
3105
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ochre-sdk",
3
- "version": "0.20.6",
3
+ "version": "0.20.10",
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",
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "devDependencies": {
49
49
  "@antfu/eslint-config": "^7.6.1",
50
- "@types/node": "^24.10.14",
50
+ "@types/node": "^24.10.15",
51
51
  "bumpp": "^10.4.1",
52
52
  "eslint": "^10.0.2",
53
53
  "prettier": "^3.8.1",