ochre-sdk 0.22.19 → 0.22.20

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 (2) hide show
  1. package/dist/index.mjs +277 -96
  2. package/package.json +4 -4
package/dist/index.mjs CHANGED
@@ -2511,6 +2511,16 @@ function buildPropertyStringQueryExpression(params) {
2511
2511
  value,
2512
2512
  matchMode,
2513
2513
  isCaseSensitive
2514
+ }),
2515
+ rawValueQueryExpression: buildValueRawValueInnerQuery({
2516
+ value,
2517
+ matchMode,
2518
+ isCaseSensitive
2519
+ }),
2520
+ bareValueQueryExpression: buildValueDirectTextInnerQuery({
2521
+ value,
2522
+ matchMode,
2523
+ isCaseSensitive
2514
2524
  })
2515
2525
  });
2516
2526
  }
@@ -3030,6 +3040,47 @@ function buildOrderedItemsClause(sort) {
3030
3040
  })}
3031
3041
  return $item`;
3032
3042
  }
3043
+ function isExactStringPropertyQuery(query) {
3044
+ return "target" in query && query.target === "property" && query.dataType === "string" && query.value != null && query.matchMode === "exact" && query.isNegated !== true;
3045
+ }
3046
+ function getCtsQueriesWithoutExactStringPropertyQueries(queries) {
3047
+ if (queries == null) return null;
3048
+ if ("target" in queries) return isExactStringPropertyQuery(queries) ? null : queries;
3049
+ if ("or" in queries) return queries;
3050
+ const filteredChildren = [];
3051
+ for (const childQuery of queries.and) {
3052
+ const filteredChildQuery = getCtsQueriesWithoutExactStringPropertyQueries(childQuery);
3053
+ if (filteredChildQuery != null) filteredChildren.push(filteredChildQuery);
3054
+ }
3055
+ if (filteredChildren.length === 0) return null;
3056
+ return filteredChildren.length === 1 ? filteredChildren[0] ?? null : { and: filteredChildren };
3057
+ }
3058
+ function buildExactStringPropertyPredicate(query) {
3059
+ const propertyPredicates = [];
3060
+ const value = stringLiteral(query.value);
3061
+ if (query.propertyVariable != null) propertyPredicates.push(`label/@uuid = ${stringLiteral(query.propertyVariable)}`);
3062
+ propertyPredicates.push(`value[
3063
+ not(@inherited = "true")
3064
+ and (
3065
+ content[@xml:lang = ${stringLiteral(query.language)}]/string = ${value}
3066
+ or @rawValue = ${value}
3067
+ or (not(content) and text() = ${value})
3068
+ )
3069
+ ]`);
3070
+ return `.//properties/property[${propertyPredicates.join(" and ")}]`;
3071
+ }
3072
+ function buildExactStringPropertyXPathFilterExpression(queries) {
3073
+ if (queries == null) return null;
3074
+ if ("target" in queries) return isExactStringPropertyQuery(queries) ? buildExactStringPropertyPredicate(queries) : null;
3075
+ if ("or" in queries) return null;
3076
+ const childExpressions = [];
3077
+ for (const childQuery of queries.and) {
3078
+ const childExpression = buildExactStringPropertyXPathFilterExpression(childQuery);
3079
+ if (childExpression != null) childExpressions.push(childExpression);
3080
+ }
3081
+ if (childExpressions.length === 0) return null;
3082
+ return childExpressions.join(" and ");
3083
+ }
3033
3084
  /**
3034
3085
  * Build an XQuery string to fetch Set items from the OCHRE API
3035
3086
  * @param params - The parameters for the fetch
@@ -3047,7 +3098,9 @@ function buildXQuery$1(params) {
3047
3098
  const startPosition = (page - 1) * pageSize + 1;
3048
3099
  const setScopeDeclaration = `declare variable $setScopeUuids := (${setScopeUuids.map((uuid) => stringLiteral(uuid)).join(", ")});`;
3049
3100
  const baseItemsExpression = "doc()/ochre/set[@uuid = $setScopeUuids]/items/*";
3050
- const compiledQueryPlan = buildQueryPlan({ queries });
3101
+ const ctsQueries = getCtsQueriesWithoutExactStringPropertyQueries(queries);
3102
+ const exactStringPropertyXPathFilterExpression = buildExactStringPropertyXPathFilterExpression(queries);
3103
+ const compiledQueryPlan = buildQueryPlan({ queries: ctsQueries });
3051
3104
  const itemsQueryExpressions = [];
3052
3105
  const belongsToCollectionQueryExpression = buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids, BELONGS_TO_COLLECTION_UUID);
3053
3106
  if (compiledQueryPlan.queryExpression != null) itemsQueryExpressions.push(compiledQueryPlan.queryExpression);
@@ -3056,8 +3109,11 @@ function buildXQuery$1(params) {
3056
3109
  const orderedItemsClause = buildOrderedItemsClause(sort);
3057
3110
  const xqueryDeclarations = ["xquery version \"1.0-ml\";", setScopeDeclaration];
3058
3111
  if (compiledQueryPlan.prolog !== "") xqueryDeclarations.push(compiledQueryPlan.prolog);
3059
- const itemsClause = itemsQueryExpression == null ? `let $items := ${baseItemsExpression}` : `let $query := ${itemsQueryExpression}
3060
- let $items := cts:search(${baseItemsExpression}, $query)`;
3112
+ const searchedItemsClause = itemsQueryExpression == null ? `let $searchedItems := ${baseItemsExpression}` : `let $query := ${itemsQueryExpression}
3113
+ let $searchedItems := cts:search(${baseItemsExpression}, $query)`;
3114
+ const itemsClause = exactStringPropertyXPathFilterExpression == null ? `${searchedItemsClause}
3115
+ let $items := $searchedItems` : `${searchedItemsClause}
3116
+ let $items := $searchedItems[${exactStringPropertyXPathFilterExpression}]`;
3061
3117
  return `${xqueryDeclarations.join("\n\n")}
3062
3118
 
3063
3119
  <ochre>{
@@ -3190,67 +3246,27 @@ function parsePropertyValueBooleanContent(rawValue) {
3190
3246
  if (typeof rawValue === "boolean") return rawValue;
3191
3247
  return rawValue.toString().toLocaleLowerCase("en-US") === "true";
3192
3248
  }
3193
- function getPropertyValueGroupKey(value) {
3194
- const contentKey = value.content == null ? "null" : `${typeof value.content}:${value.content.toLocaleString("en-US")}`;
3195
- return `${value.dataType}|${contentKey}`;
3196
- }
3197
- function aggregatePropertyValues(values) {
3198
- const groupedPropertyValuesMap = /* @__PURE__ */ new Map();
3199
- for (const value of values) {
3200
- const key = getPropertyValueGroupKey(value);
3201
- const existing = groupedPropertyValuesMap.get(key);
3202
- if (existing == null) {
3203
- groupedPropertyValuesMap.set(key, {
3204
- dataType: value.dataType,
3205
- content: value.content,
3206
- label: value.label,
3207
- itemUuids: new Set([value.itemUuid])
3208
- });
3209
- continue;
3210
- }
3211
- existing.itemUuids.add(value.itemUuid);
3212
- if (existing.label == null && value.label != null) existing.label = value.label;
3213
- }
3214
- const groupedPropertyValues = [];
3215
- for (const group of groupedPropertyValuesMap.values()) {
3216
- if (group.content == null) continue;
3217
- groupedPropertyValues.push({
3218
- count: group.itemUuids.size,
3219
- dataType: group.dataType,
3220
- content: group.content,
3221
- label: group.label
3222
- });
3223
- }
3224
- return groupedPropertyValues.toSorted((a, b) => {
3249
+ function sortPropertyValues(values) {
3250
+ return values.toSorted((a, b) => {
3225
3251
  if (a.count !== b.count) return b.count - a.count;
3226
3252
  if (a.label !== b.label) return a.label?.localeCompare(b.label ?? "") ?? 0;
3227
3253
  return a.content?.toString().localeCompare(b.content?.toString() ?? "") ?? 0;
3228
3254
  });
3229
3255
  }
3230
- function aggregateAttributeValues(values) {
3231
- const groupedAttributeValuesMap = /* @__PURE__ */ new Map();
3232
- for (const value of values) {
3233
- if (value.content == null || value.content === "") continue;
3234
- const existing = groupedAttributeValuesMap.get(value.content);
3235
- if (existing == null) {
3236
- groupedAttributeValuesMap.set(value.content, {
3237
- content: value.content,
3238
- itemUuids: new Set([value.itemUuid])
3239
- });
3240
- continue;
3241
- }
3242
- existing.itemUuids.add(value.itemUuid);
3243
- }
3244
- const groupedAttributeValues = [];
3245
- for (const group of groupedAttributeValuesMap.values()) groupedAttributeValues.push({
3246
- count: group.itemUuids.size,
3247
- content: group.content
3248
- });
3249
- return groupedAttributeValues.toSorted((a, b) => {
3256
+ function getPropertyValueKey(value) {
3257
+ return `${value.dataType}|${typeof value.content}:${value.content.toLocaleString("en-US")}`;
3258
+ }
3259
+ function sortAttributeValues(values) {
3260
+ return values.toSorted((a, b) => {
3250
3261
  if (a.count !== b.count) return b.count - a.count;
3251
3262
  return a.content.localeCompare(b.content);
3252
3263
  });
3253
3264
  }
3265
+ const countSchema = z.union([z.number(), z.string()]).optional().transform((val) => {
3266
+ if (val == null || val === "") return 1;
3267
+ const count = Number(val);
3268
+ return Number.isFinite(count) ? count : 1;
3269
+ });
3254
3270
  function getPropertyVariableUuidsFromQueries(queries) {
3255
3271
  const propertyVariableUuids = /* @__PURE__ */ new Set();
3256
3272
  if (queries == null) return [];
@@ -3287,8 +3303,10 @@ function getItemFilterQueriesFromPropertyValueQueries(queries) {
3287
3303
  */
3288
3304
  const propertyValueQueryItemSchema = z.object({
3289
3305
  uuid: z.string(),
3306
+ scope: z.enum(["global", "variable"]).default("global"),
3290
3307
  variableUuid: z.string().optional(),
3291
- itemUuid: z.string().optional(),
3308
+ count: countSchema,
3309
+ globalCount: countSchema.nullish(),
3292
3310
  dataType: z.string(),
3293
3311
  rawValue: fakeStringSchema.optional(),
3294
3312
  content: z.union([
@@ -3298,8 +3316,10 @@ const propertyValueQueryItemSchema = z.object({
3298
3316
  ]).optional()
3299
3317
  }).transform((val) => {
3300
3318
  const returnValue = {
3319
+ scope: val.scope,
3301
3320
  variableUuid: val.variableUuid != null && val.variableUuid !== "" ? val.variableUuid : null,
3302
- itemUuid: val.itemUuid != null && val.itemUuid !== "" ? val.itemUuid : null,
3321
+ count: val.count,
3322
+ globalCount: val.globalCount ?? null,
3303
3323
  dataType: val.dataType,
3304
3324
  content: null,
3305
3325
  label: null
@@ -3331,11 +3351,11 @@ const propertyValueQueryItemSchema = z.object({
3331
3351
  });
3332
3352
  const attributeValueQueryItemSchema = z.object({
3333
3353
  attributeType: z.enum(["bibliographies", "periods"]),
3334
- itemUuid: z.string().optional(),
3354
+ count: countSchema,
3335
3355
  content: z.string().optional()
3336
3356
  }).transform((val) => ({
3337
3357
  attributeType: val.attributeType,
3338
- itemUuid: val.itemUuid != null && val.itemUuid !== "" ? val.itemUuid : null,
3358
+ count: val.count,
3339
3359
  content: val.content != null && val.content !== "" ? val.content : null
3340
3360
  }));
3341
3361
  /**
@@ -3360,9 +3380,8 @@ const responseSchema = z.object({ result: z.union([z.object({ ochre: z.object({
3360
3380
  */
3361
3381
  function buildXQuery(params) {
3362
3382
  const { setScopeUuids, belongsToCollectionScopeUuids, queries, propertyVariableUuids, attributes, isLimitedToLeafPropertyValues } = params;
3363
- const setScopeValues = setScopeUuids.map((uuid) => stringLiteral(uuid));
3364
- const setScopeDeclaration = setScopeValues.length > 0 ? `declare variable $setScopeUuids := (${setScopeValues.join(", ")});` : "";
3365
- const baseItemsExpression = setScopeValues.length > 0 ? "doc()/ochre/set[@uuid = $setScopeUuids]/items/*" : "doc()/ochre/set/items/*";
3383
+ const setScopeDeclaration = `declare variable $setScopeUuids := (${setScopeUuids.map((uuid) => stringLiteral(uuid)).join(", ")});`;
3384
+ const baseItemsExpression = "doc()/ochre/set[@uuid = $setScopeUuids]/items/*";
3366
3385
  const compiledQueryPlan = buildQueryPlan({ queries: getItemFilterQueriesFromPropertyValueQueries(queries) });
3367
3386
  const itemsQueryExpressions = [];
3368
3387
  const belongsToCollectionQueryExpression = buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids, BELONGS_TO_COLLECTION_UUID);
@@ -3372,39 +3391,186 @@ function buildXQuery(params) {
3372
3391
  const valueFilter = isLimitedToLeafPropertyValues ? "[not(@i)]" : "";
3373
3392
  const queryBlocks = [];
3374
3393
  const returnedSequences = [];
3375
- const xqueryDeclarations = ["xquery version \"1.0-ml\";"];
3376
- if (setScopeDeclaration !== "") xqueryDeclarations.push(setScopeDeclaration);
3394
+ const xqueryDeclarations = [
3395
+ "xquery version \"1.0-ml\";",
3396
+ "declare namespace map = \"http://marklogic.com/xdmp/map\";",
3397
+ setScopeDeclaration,
3398
+ `declare function local:increment-count($counts, $key) {
3399
+ let $current := map:get($counts, $key)
3400
+ return map:put(
3401
+ $counts,
3402
+ $key,
3403
+ if (empty($current)) then 1 else xs:integer($current) + 1
3404
+ )
3405
+ };
3406
+
3407
+ declare function local:value-display($v) {
3408
+ if ($v/content)
3409
+ then string-join($v/content[@xml:lang="eng"]//text(), "")
3410
+ else string($v)
3411
+ };
3412
+
3413
+ declare function local:value-content($data-type, $raw-value, $value-uuid, $display) {
3414
+ if ($data-type = "IDREF") then $value-uuid
3415
+ else if ($data-type = ("integer", "decimal", "time")) then
3416
+ if ($raw-value castable as xs:double)
3417
+ then string(xs:double($raw-value))
3418
+ else ""
3419
+ else if ($data-type = "boolean") then
3420
+ if ($raw-value = "") then ""
3421
+ else if (lower-case($raw-value) = "true") then "true"
3422
+ else "false"
3423
+ else if ($raw-value != "") then $raw-value
3424
+ else if ($display != "" and $display != "<unassigned>") then $display
3425
+ else ""
3426
+ };
3427
+
3428
+ declare function local:value-kind($data-type) {
3429
+ if ($data-type = ("integer", "decimal", "time")) then "number"
3430
+ else if ($data-type = "boolean") then "boolean"
3431
+ else "string"
3432
+ };
3433
+
3434
+ declare function local:property-output-raw-value($data-type, $raw-value, $content) {
3435
+ if ($data-type = ("integer", "decimal", "time", "boolean")) then $content
3436
+ else $raw-value
3437
+ };
3438
+
3439
+ declare function local:put-property-detail(
3440
+ $details,
3441
+ $key,
3442
+ $scope,
3443
+ $variable-uuid,
3444
+ $value-uuid,
3445
+ $raw-value,
3446
+ $data-type,
3447
+ $display
3448
+ ) {
3449
+ let $existing := map:get($details, $key)
3450
+ return
3451
+ if (
3452
+ empty($existing)
3453
+ or (string-length(string($existing)) = 0 and string-length($display) gt 0)
3454
+ ) then
3455
+ map:put(
3456
+ $details,
3457
+ $key,
3458
+ <propertyValue scope="{$scope}" variableUuid="{$variable-uuid}" uuid="{$value-uuid}" rawValue="{$raw-value}" dataType="{$data-type}">{$display}</propertyValue>
3459
+ )
3460
+ else ()
3461
+ };
3462
+
3463
+ declare function local:add-property-facet(
3464
+ $counts,
3465
+ $details,
3466
+ $seen,
3467
+ $key,
3468
+ $scope,
3469
+ $variable-uuid,
3470
+ $value-uuid,
3471
+ $raw-value,
3472
+ $data-type,
3473
+ $display
3474
+ ) {
3475
+ if (exists(map:get($seen, $key))) then ()
3476
+ else (
3477
+ map:put($seen, $key, true()),
3478
+ local:increment-count($counts, $key),
3479
+ local:put-property-detail($details, $key, $scope, $variable-uuid, $value-uuid, $raw-value, $data-type, $display)
3480
+ )
3481
+ };
3482
+
3483
+ declare function local:add-attribute-facet($counts, $seen, $key) {
3484
+ if (exists(map:get($seen, $key))) then ()
3485
+ else (
3486
+ map:put($seen, $key, true()),
3487
+ local:increment-count($counts, $key)
3488
+ )
3489
+ };`
3490
+ ];
3377
3491
  if (compiledQueryPlan.prolog !== "") xqueryDeclarations.push(compiledQueryPlan.prolog);
3378
3492
  if (propertyVariableUuids.length > 0) {
3379
- const propertyVariableFilters = propertyVariableUuids.map((uuid) => `@uuid="${uuid}"`).join(" or ");
3380
- queryBlocks.push(`let $matching-props := $items//property[label[${propertyVariableFilters}]]
3493
+ const propertyVariableValues = propertyVariableUuids.map((uuid) => stringLiteral(uuid));
3494
+ xqueryDeclarations.push(`declare variable $facetLabelUuids := (${propertyVariableValues.join(", ")});`);
3495
+ queryBlocks.push(`let $global-property-counts := map:map()
3496
+ let $variable-property-counts := map:map()
3497
+ let $variable-property-details := map:map()
3498
+ let $variable-property-global-keys := map:map()
3499
+ let $_property-aggregation := xdmp:eager(
3500
+ for $item in $items
3501
+ let $global-seen := map:map()
3502
+ let $variable-seen := map:map()
3503
+ return
3504
+ for $p in $item/properties/property[label/@uuid = $facetLabelUuids]
3505
+ let $variable-uuid := string($p/label/@uuid)
3506
+ for $v in $p/value${valueFilter}
3507
+ let $value-uuid := string($v/@uuid)
3508
+ let $raw-value := string($v/@rawValue)
3509
+ let $data-type := string($v/@dataType)
3510
+ let $display := local:value-display($v)
3511
+ let $content := local:value-content($data-type, $raw-value, $value-uuid, $display)
3512
+ let $value-kind := local:value-kind($data-type)
3513
+ let $output-raw-value := local:property-output-raw-value($data-type, $raw-value, $content)
3514
+ let $global-key := string-join(($data-type, $value-kind, $content), "||")
3515
+ let $variable-key := string-join(($variable-uuid, $data-type, $value-kind, $content), "||")
3516
+ where $content != ""
3517
+ return (
3518
+ local:add-attribute-facet($global-property-counts, $global-seen, $global-key),
3519
+ local:add-property-facet($variable-property-counts, $variable-property-details, $variable-seen, $variable-key, "variable", $variable-uuid, $value-uuid, $output-raw-value, $data-type, $display),
3520
+ map:put($variable-property-global-keys, $variable-key, $global-key)
3521
+ )
3522
+ )
3381
3523
 
3382
3524
  let $property-values :=
3383
- for $p in $matching-props
3384
- for $v in $p/value${valueFilter}
3385
- let $item-uuid := $v/ancestor::*[parent::items]/@uuid
3386
- let $variable-uuid := $p/label/@uuid
3387
- return <propertyValue uuid="{$v/@uuid}" rawValue="{$v/@rawValue}" dataType="{$v/@dataType}" itemUuid="{$item-uuid}" variableUuid="{$variable-uuid}">{
3388
- if ($v/content) then string-join($v/content[@xml:lang="eng"]//text(), "") else $v/text()
3389
- }</propertyValue>`);
3525
+ (
3526
+ $_property-aggregation,
3527
+ for $key in map:keys($variable-property-counts)
3528
+ let $detail := map:get($variable-property-details, $key)
3529
+ let $global-key := map:get($variable-property-global-keys, $key)
3530
+ return <propertyValue scope="variable" variableUuid="{string($detail/@variableUuid)}" uuid="{string($detail/@uuid)}" rawValue="{string($detail/@rawValue)}" dataType="{string($detail/@dataType)}" count="{map:get($variable-property-counts, $key)}" globalCount="{map:get($global-property-counts, $global-key)}">{
3531
+ string($detail)
3532
+ }</propertyValue>
3533
+ )`);
3390
3534
  returnedSequences.push("$property-values");
3391
3535
  }
3392
3536
  if (attributes.bibliographies) {
3393
- queryBlocks.push(`let $bibliography-values :=
3537
+ queryBlocks.push(`let $bibliography-counts := map:map()
3538
+ let $_bibliography-aggregation := xdmp:eager(
3394
3539
  for $item in $items
3395
- for $bibliography in $item/bibliographies/bibliography
3540
+ let $seen := map:map()
3541
+ return
3542
+ for $bibliography in $item/bibliographies/bibliography
3396
3543
  let $label := string-join($bibliography/identification/label/content[@xml:lang="eng"]//text(), "")
3397
3544
  where string-length($label) gt 0
3398
- return <attributeValue attributeType="bibliographies" itemUuid="{$item/@uuid}" content="{$label}" />`);
3545
+ return local:add-attribute-facet($bibliography-counts, $seen, $label)
3546
+ )
3547
+
3548
+ let $bibliography-values :=
3549
+ (
3550
+ $_bibliography-aggregation,
3551
+ for $label in map:keys($bibliography-counts)
3552
+ return <attributeValue attributeType="bibliographies" count="{map:get($bibliography-counts, $label)}" content="{$label}" />
3553
+ )`);
3399
3554
  returnedSequences.push("$bibliography-values");
3400
3555
  }
3401
3556
  if (attributes.periods) {
3402
- queryBlocks.push(`let $period-values :=
3557
+ queryBlocks.push(`let $period-counts := map:map()
3558
+ let $_period-aggregation := xdmp:eager(
3403
3559
  for $item in $items
3404
- for $period in $item/periods/period
3560
+ let $seen := map:map()
3561
+ return
3562
+ for $period in $item/periods/period
3405
3563
  let $label := string-join($period/identification/label/content[@xml:lang="eng"]//text(), "")
3406
3564
  where string-length($label) gt 0
3407
- return <attributeValue attributeType="periods" itemUuid="{$item/@uuid}" content="{$label}" />`);
3565
+ return local:add-attribute-facet($period-counts, $seen, $label)
3566
+ )
3567
+
3568
+ let $period-values :=
3569
+ (
3570
+ $_period-aggregation,
3571
+ for $label in map:keys($period-counts)
3572
+ return <attributeValue attributeType="periods" count="{map:get($period-counts, $label)}" content="{$label}" />
3573
+ )`);
3408
3574
  returnedSequences.push("$period-values");
3409
3575
  }
3410
3576
  const itemsClause = itemsQueryExpression == null ? `let $items := ${baseItemsExpression}` : `let $query := ${itemsQueryExpression}
@@ -3470,35 +3636,50 @@ async function fetchSetPropertyValues(params, options) {
3470
3636
  if (parsedResultRaw.result.ochre.propertyValue != null) parsedPropertyValues.push(...Array.isArray(parsedResultRaw.result.ochre.propertyValue) ? parsedResultRaw.result.ochre.propertyValue : [parsedResultRaw.result.ochre.propertyValue]);
3471
3637
  if (parsedResultRaw.result.ochre.attributeValue != null) parsedAttributeValues.push(...Array.isArray(parsedResultRaw.result.ochre.attributeValue) ? parsedResultRaw.result.ochre.attributeValue : [parsedResultRaw.result.ochre.attributeValue]);
3472
3638
  }
3473
- const propertyValuesByPropertyVariableUuidRaw = {};
3474
- const flattenedPropertyValues = [];
3639
+ const propertyValuesByPropertyVariableUuid = {};
3640
+ const flattenedPropertyValuesByKey = /* @__PURE__ */ new Map();
3475
3641
  for (const propertyValue of parsedPropertyValues) {
3476
- const aggregatePropertyValueItem = {
3477
- itemUuid: propertyValue.itemUuid,
3642
+ if (propertyValue.content == null) continue;
3643
+ const propertyValueItem = {
3644
+ count: propertyValue.count,
3478
3645
  dataType: propertyValue.dataType,
3479
3646
  content: propertyValue.content,
3480
3647
  label: propertyValue.label
3481
3648
  };
3482
- flattenedPropertyValues.push(aggregatePropertyValueItem);
3483
- if (propertyValue.variableUuid == null) continue;
3484
- (propertyValuesByPropertyVariableUuidRaw[propertyValue.variableUuid] ??= []).push(aggregatePropertyValueItem);
3485
- }
3486
- const propertyValuesByPropertyVariableUuid = {};
3487
- for (const [propertyVariableUuid, values] of Object.entries(propertyValuesByPropertyVariableUuidRaw)) {
3488
- const aggregatedValues = aggregatePropertyValues(values);
3489
- if (aggregatedValues.length > 0) propertyValuesByPropertyVariableUuid[propertyVariableUuid] = aggregatedValues;
3649
+ const globalPropertyValueItem = {
3650
+ count: propertyValue.globalCount ?? propertyValue.count,
3651
+ dataType: propertyValue.dataType,
3652
+ content: propertyValue.content,
3653
+ label: propertyValue.label
3654
+ };
3655
+ const globalPropertyValueKey = getPropertyValueKey({
3656
+ dataType: globalPropertyValueItem.dataType,
3657
+ content: propertyValue.content
3658
+ });
3659
+ const existingGlobalPropertyValue = flattenedPropertyValuesByKey.get(globalPropertyValueKey);
3660
+ if (existingGlobalPropertyValue == null) flattenedPropertyValuesByKey.set(globalPropertyValueKey, globalPropertyValueItem);
3661
+ else if (existingGlobalPropertyValue.label == null && globalPropertyValueItem.label != null) existingGlobalPropertyValue.label = globalPropertyValueItem.label;
3662
+ if (propertyValue.scope === "global") continue;
3663
+ if (propertyValue.variableUuid != null) (propertyValuesByPropertyVariableUuid[propertyValue.variableUuid] ??= []).push(propertyValueItem);
3490
3664
  }
3491
- const attributeValuesByTypeRaw = {
3665
+ for (const [propertyVariableUuid, values] of Object.entries(propertyValuesByPropertyVariableUuid)) propertyValuesByPropertyVariableUuid[propertyVariableUuid] = sortPropertyValues(values);
3666
+ const attributeValuesByType = {
3492
3667
  bibliographies: [],
3493
3668
  periods: []
3494
3669
  };
3495
- for (const attributeValue of parsedAttributeValues) attributeValuesByTypeRaw[attributeValue.attributeType].push(attributeValue);
3670
+ for (const attributeValue of parsedAttributeValues) {
3671
+ if (attributeValue.content == null || attributeValue.content === "") continue;
3672
+ attributeValuesByType[attributeValue.attributeType].push({
3673
+ count: attributeValue.count,
3674
+ content: attributeValue.content
3675
+ });
3676
+ }
3496
3677
  return {
3497
- propertyValues: aggregatePropertyValues(flattenedPropertyValues),
3678
+ propertyValues: sortPropertyValues([...flattenedPropertyValuesByKey.values()]),
3498
3679
  propertyValuesByPropertyVariableUuid,
3499
3680
  attributeValues: {
3500
- bibliographies: attributes.bibliographies ? aggregateAttributeValues(attributeValuesByTypeRaw.bibliographies) : null,
3501
- periods: attributes.periods ? aggregateAttributeValues(attributeValuesByTypeRaw.periods) : null
3681
+ bibliographies: attributes.bibliographies ? sortAttributeValues(attributeValuesByType.bibliographies) : null,
3682
+ periods: attributes.periods ? sortAttributeValues(attributeValuesByType.periods) : null
3502
3683
  },
3503
3684
  error: null
3504
3685
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ochre-sdk",
3
- "version": "0.22.19",
3
+ "version": "0.22.20",
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",
@@ -46,7 +46,7 @@
46
46
  "@date-fns/utc": "^2.1.1",
47
47
  "date-fns": "^4.1.0",
48
48
  "fast-equals": "^6.0.0",
49
- "zod": "^4.3.6"
49
+ "zod": "^4.4.1"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@antfu/eslint-config": "^8.2.0",
@@ -54,9 +54,9 @@
54
54
  "bumpp": "^11.0.1",
55
55
  "eslint": "^10.2.1",
56
56
  "prettier": "^3.8.3",
57
- "tsdown": "^0.21.9",
57
+ "tsdown": "^0.21.10",
58
58
  "typescript": "^6.0.3",
59
- "vitest": "^4.1.4"
59
+ "vitest": "^4.1.5"
60
60
  },
61
61
  "scripts": {
62
62
  "dev": "tsdown src/index.ts --watch",