@lde/search-typesense 0.29.4 → 0.30.0

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.
@@ -317,7 +317,7 @@ function nestedFields(prefix, reference, nestedType, schema, defaultLocale, with
317
317
  type: boundaryArray ? 'string[]' : 'string',
318
318
  index: false,
319
319
  optional: true,
320
- }, ...nestedIdentityFields(prefix, field, schema));
320
+ }, ...nestedIdentityFields(prefix, field, schema, flattensToArray));
321
321
  continue;
322
322
  }
323
323
  if (deeper !== undefined) {
@@ -327,7 +327,7 @@ function nestedFields(prefix, reference, nestedType, schema, defaultLocale, with
327
327
  // an engine welds conditions on an entry's LEAF fields only. Its
328
328
  // identity companion is that leaf, so it sits beside the object rather
329
329
  // than inside it.
330
- ...nestedIdentityFields(prefix, field, schema));
330
+ ...nestedIdentityFields(prefix, field, schema, flattensToArray));
331
331
  continue;
332
332
  }
333
333
  children.push(...nestedLeafFields(prefix, field, defaultLocale, flattensToArray));
@@ -384,7 +384,7 @@ function identityCompanionFields(field, schema) {
384
384
  /** The identity companion of a nested field that stores an object: a flat leaf
385
385
  * beside it, holding the ids a filter welds on. Empty for a nested field that
386
386
  * declares no query Role, which needs none. */
387
- function nestedIdentityFields(prefix, field, schema) {
387
+ function nestedIdentityFields(prefix, field, schema, flattensToArray) {
388
388
  const names = physicalFields(field, schema);
389
389
  if (names.identity === undefined) {
390
390
  return [];
@@ -392,11 +392,23 @@ function nestedIdentityFields(prefix, field, schema) {
392
392
  return [
393
393
  {
394
394
  name: nestedFieldName(prefix, names.identity),
395
- // Always a list, whatever the enclosing reference's arity: the projection
396
- // writes it with `setArray`, and an indexed field's declared type is
397
- // checked against what is stored – a `string` here rejects every
398
- // document carrying such an edge, at import.
399
- type: 'string[]',
395
+ // Typed by what the PATH yields across the document, exactly as the `id`
396
+ // beside it is, and by the same two routes every other declaration here
397
+ // uses: an `object[]` ancestor multiplying the entries, or the field's
398
+ // own `array` making each entry hold a list. A weldable leaf is
399
+ // single-valued (ADR 26), so a companion that a weld names contributes
400
+ // one id per entry – but a multi-valued reference reached through a
401
+ // locally-nested Root Type is not weldable and still harvests a list.
402
+ // Getting either route wrong rejects the document at import: Typesense
403
+ // enforces the declared arity wherever nothing widens the path.
404
+ // `filterable` is the condition because it is what the projection writes
405
+ // a single id under, not because it decides the split: `tuplesOf` splits
406
+ // the identity field whatever Role earned it. A `facetable`-only
407
+ // companion is declared a list, which is what a facet reads and what the
408
+ // projection writes for it.
409
+ type: flattensToArray || field.array === true || field.filterable !== true
410
+ ? 'string[]'
411
+ : 'string',
400
412
  index: true,
401
413
  optional: true,
402
414
  },
@@ -458,6 +470,10 @@ function nestedLeafFields(prefix, field, defaultLocale, flattensToArray) {
458
470
  // `object[]` flattens it into one. `typesenseValueType` honours `array` only
459
471
  // for the string-shaped kinds, so a multi-valued nested `integer` would
460
472
  // otherwise be declared scalar and rejected at import.
473
+ //
474
+ // A weldable leaf of a Reference Type is single-valued (ADR 26), but that
475
+ // narrows nothing here: this same path declares the fields of the Root Type a
476
+ // `local` lookup nests, where `array` and `filterable` may legitimately meet.
461
477
  const storesAList = flattensToArray || field.array === true;
462
478
  fields.push({
463
479
  name: nestedFieldName(prefix, field.name),
@@ -498,8 +514,11 @@ function arrayValueType(type) {
498
514
  return 'float[]';
499
515
  case 'bool':
500
516
  return 'bool[]';
501
- // Already a list: a multi-valued declaration under a multi-valued ancestor
502
- // flattens no further.
517
+ // Already a list, and reachable even though a weldable leaf of a Reference
518
+ // Type is single-valued (ADR 26): this path also declares the fields of the
519
+ // Root Type a `local` lookup nests, and `searchSchema` constrains only
520
+ // Reference Types. A root keyword may be `array` and `filterable` at once –
521
+ // an ordinary facet – so flattening it must widen no further.
503
522
  case 'string[]':
504
523
  return 'string[]';
505
524
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lde/search-typesense",
3
- "version": "0.29.4",
3
+ "version": "0.30.0",
4
4
  "description": "Typesense implementation of the @lde/search SearchEngine port: collection-schema builder, query compiler, label-resolving result reconstruction, and blue/green index lifecycle. Engine-specific (Typesense) but domain-agnostic.",
5
5
  "repository": {
6
6
  "url": "git+https://github.com/ldelements/lde.git",
@@ -25,7 +25,7 @@
25
25
  "!**/*.tsbuildinfo"
26
26
  ],
27
27
  "dependencies": {
28
- "@lde/search": "^0.24.4",
28
+ "@lde/search": "^0.25.0",
29
29
  "@lde/text-normalization": "^0.1.2",
30
30
  "tslib": "^2.3.0",
31
31
  "typesense": "^3.0.6"