@lde/search-typesense 0.29.0 → 0.29.1

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.
@@ -145,7 +145,11 @@ function typesenseFields(searchType, field, defaultLocale, defaultSortingField,
145
145
  const nested = nestedTypeOf(searchType, field, schema);
146
146
  if (nested !== undefined) {
147
147
  return [
148
- ...nestedFields(field.name, field, nested, schema, defaultLocale),
148
+ ...nestedFields(field.name, field, nested, schema, defaultLocale, false,
149
+ // The declaring type is already on the path, exactly as the frame and
150
+ // the extraction seed theirs, so a lookup back to it is cut at the
151
+ // same depth here as it is there.
152
+ new Set([searchType.name])),
149
153
  ...identityCompanionFields(field, schema),
150
154
  ];
151
155
  }
@@ -287,10 +291,30 @@ function nestedFields(prefix, reference, nestedType, schema, defaultLocale, with
287
291
  }
288
292
  const deeper = nestedTypeOfNestedField(field, schema);
289
293
  if (deeper !== undefined && walked.has(deeper.name)) {
290
- // The cycle stops here, and so does the frame – nothing will ever be
291
- // stored under this field, so nothing is declared for it. Falling
292
- // through would declare it as a LEAF, whose scalar type is not what a
293
- // nested object would be stored as.
294
+ // The cycle stops here, and so does the frame – but a value is still
295
+ // stored: the extraction falls back to the target's key hop, and the
296
+ // projection writes the referent as an `{id}` object beside its identity
297
+ // leaf. So the BOUNDARY is declared and only the descent stops. Falling
298
+ // through instead would declare the field as a LEAF, whose scalar type
299
+ // is not what a nested object is stored as.
300
+ const boundary = nestedFieldName(prefix, field.name);
301
+ const boundaryArray = flattensToArray || field.array === true;
302
+ children.push({
303
+ name: boundary,
304
+ type: boundaryArray ? 'object[]' : 'object',
305
+ // Nothing under it is indexed – the key is a stored value, and the
306
+ // leaf a filter welds on sits beside the object, not inside it.
307
+ index: false,
308
+ optional: true,
309
+ }, {
310
+ // Always a Root Type, so always identified: `searchSchema` rejects
311
+ // inline cycles, so the only way to arrive at a type already on the
312
+ // path is a `local` lookup, whose target declares a class.
313
+ name: nestedFieldName(boundary, 'id'),
314
+ type: boundaryArray ? 'string[]' : 'string',
315
+ index: false,
316
+ optional: true,
317
+ }, ...nestedIdentityFields(prefix, field, schema));
294
318
  continue;
295
319
  }
296
320
  if (deeper !== undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"query-compiler.d.ts","sourceRoot":"","sources":["../src/query-compiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAEzE,OAAO,EAGL,KAAK,MAAM,EACX,KAAK,QAAQ,EAEb,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,UAAU,EAIhB,MAAM,aAAa,CAAC;AAmBrB;mDACmD;AACnD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CACvB,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,SAAS,MAAM,EAAE,KACpB,UAAU,GAAG,SAAS,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,UAAU,EACtB,OAAO,GAAE,wBAA6B,GACrC,YAAY,CAAC,MAAM,CAAC,CAkCtB;AAwfD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD"}
1
+ {"version":3,"file":"query-compiler.d.ts","sourceRoot":"","sources":["../src/query-compiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAEzE,OAAO,EAGL,KAAK,MAAM,EACX,KAAK,QAAQ,EAEb,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,UAAU,EAIhB,MAAM,aAAa,CAAC;AAmBrB;mDACmD;AACnD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CACvB,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,SAAS,MAAM,EAAE,KACpB,UAAU,GAAG,SAAS,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAC/B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,UAAU,EACtB,OAAO,GAAE,wBAA6B,GACrC,YAAY,CAAC,MAAM,CAAC,CAkCtB;AA4fD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD"}
@@ -99,12 +99,11 @@ function queryFields(searchType, locale, schema) {
99
99
  * contribute its own companions. A set shared across the walk would let the
100
100
  * first field claim the type and leave the second's companions indexed but
101
101
  * unqueried. What it does guard is a type reached from ITSELF, which a
102
- * {@link ReferenceStrategy.local local} lookup can do.
102
+ * {@link ReferenceStrategy.local local} lookup can do – cut at the same
103
+ * boundary the collection's own walk cuts at, so no field is declared indexed
104
+ * that this walk does not ask for.
103
105
  */
104
106
  function collectSearchable(searchType, locale, schema, prefix, onPath, names, weights) {
105
- if (onPath.has(searchType.name)) {
106
- return;
107
- }
108
107
  const walked = new Set(onPath).add(searchType.name);
109
108
  for (const field of searchableFields(searchType)) {
110
109
  const search = physicalFields(field).search;
@@ -139,7 +138,12 @@ function collectSearchable(searchType, locale, schema, prefix, onPath, names, we
139
138
  continue;
140
139
  }
141
140
  const nested = nestedReferenceType(schema, field) ?? localLookupTypeOf(field, schema);
142
- if (nested !== undefined) {
141
+ // Cut on the CHILD, not on entry, and against the set this level was
142
+ // reached with – the same boundary the collection's own walk cuts at
143
+ // (`nestedFields`). Returning on entry instead skipped the companions of
144
+ // the level the collection HAD declared, leaving them indexed and absent
145
+ // from `query_by` wherever a type reached itself.
146
+ if (nested !== undefined && !onPath.has(nested.name)) {
143
147
  collectSearchable(nested, locale, schema, qualify(prefix, field.name), walked, names, weights);
144
148
  }
145
149
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lde/search-typesense",
3
- "version": "0.29.0",
3
+ "version": "0.29.1",
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.0",
28
+ "@lde/search": "^0.24.1",
29
29
  "@lde/text-normalization": "^0.1.2",
30
30
  "tslib": "^2.3.0",
31
31
  "typesense": "^3.0.6"