@byline/client 4.17.0 → 4.18.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.
@@ -9,7 +9,7 @@ import { applyAfterRead, assertActorCanPerform, buildSearchDocument, cancelDocum
9
9
  import { getReadSecurityDomain, resolveReadRequestContext, resolveReadSecurityFilters, } from './read-context.js';
10
10
  import { expectedDocumentId } from './read-internals.js';
11
11
  import { shapeDocument, shapePopulatedInPlace } from './response.js';
12
- import { assertSearchQueryLength, finalizeSearchHits } from './search.js';
12
+ import { assertSearchFieldScope, assertSearchQueryLength, finalizeSearchHits } from './search.js';
13
13
  function toScheduleInfo(schedule) {
14
14
  const { executionToken: _executionToken, executionExpiresAt: _executionExpiresAt, ...info } = schedule;
15
15
  return info;
@@ -148,8 +148,10 @@ export class CollectionHandle {
148
148
  'see `@byline/search-postgres` → `postgresSearch()` for the built-in driver.',
149
149
  });
150
150
  }
151
+ assertSearchFieldScope(provider, options.fieldScope);
151
152
  const results = await provider.search({
152
153
  query: options.query,
154
+ fieldScope: options.fieldScope,
153
155
  matching: options.matching,
154
156
  collectionPath: this.definition.path,
155
157
  locale: options.locale ?? this.client.defaultLocale,
package/dist/search.d.ts CHANGED
@@ -17,9 +17,11 @@
17
17
  * into shaped `ClientDocument`s in the same query.
18
18
  */
19
19
  import type { RequestContext } from '@byline/auth';
20
- import type { ReadContext, ReadMode, SearchHit } from '@byline/core';
20
+ import type { ReadContext, ReadMode, SearchHit, SearchProvider } from '@byline/core';
21
21
  import type { BylineClient } from './client.js';
22
22
  import type { ClientSearchResults, HydratedSearchHit, ZoneSearchOptions } from './types.js';
23
+ /** Validate the optional logical body-field scope before calling a provider. */
24
+ export declare function assertSearchFieldScope(provider: SearchProvider, fieldScope: string[] | undefined): void;
23
25
  export interface FinalizeSearchHitsParams {
24
26
  client: BylineClient<any>;
25
27
  requestContext: RequestContext;
package/dist/search.js CHANGED
@@ -7,6 +7,20 @@
7
7
  */
8
8
  import { assertActorCanPerform, createReadContext, ERR_VALIDATION, getCollectionAdminConfig, MAX_SEARCH_QUERY_LENGTH, resolveSearchZones, } from '@byline/core';
9
9
  import { resolveReadRequestContext, resolveReadSecurityFilters } from './read-context.js';
10
+ /** Validate the optional logical body-field scope before calling a provider. */
11
+ export function assertSearchFieldScope(provider, fieldScope) {
12
+ if (fieldScope == null)
13
+ return;
14
+ if (fieldScope.length === 0 ||
15
+ fieldScope.some((field) => typeof field !== 'string' || field.trim().length === 0)) {
16
+ throw ERR_VALIDATION({ message: 'Search fieldScope must contain one or more field names.' });
17
+ }
18
+ if (!provider.capabilities.fullText.fieldScope) {
19
+ throw ERR_VALIDATION({
20
+ message: 'The registered search provider does not support field-scoped full-text queries.',
21
+ });
22
+ }
23
+ }
10
24
  /**
11
25
  * Authorise (and optionally hydrate) provider hits, per collection:
12
26
  *
@@ -163,6 +177,7 @@ export async function zoneSearch(client, options) {
163
177
  if (readable.size === 0) {
164
178
  throw firstAbilityError;
165
179
  }
180
+ assertSearchFieldScope(provider, options.fieldScope);
166
181
  let aggregateRestricted = readable.size !== members.length;
167
182
  if (!options._bypassBeforeRead) {
168
183
  for (const member of members) {
@@ -176,6 +191,7 @@ export async function zoneSearch(client, options) {
176
191
  }
177
192
  const results = await provider.search({
178
193
  query: options.query,
194
+ fieldScope: options.fieldScope,
179
195
  matching: options.matching,
180
196
  zone: options.zone,
181
197
  locale: options.locale ?? client.defaultLocale,
package/dist/types.d.ts CHANGED
@@ -183,6 +183,8 @@ interface StatusControls {
183
183
  export interface CollectionSearchOptions extends BeforeReadControls {
184
184
  /** Free-text query string. */
185
185
  query: string;
186
+ /** Restrict full-text matching to named fields from the collection's `search.body`. */
187
+ fieldScope?: string[];
186
188
  /** Provider-neutral term and phrase matching semantics. */
187
189
  matching?: SearchMatching;
188
190
  /** Restrict to a single content locale (defaults to the client default). */
@@ -217,6 +219,8 @@ export interface CollectionSearchOptions extends BeforeReadControls {
217
219
  export interface ZoneSearchOptions extends BeforeReadControls {
218
220
  /** Free-text query string. */
219
221
  query: string;
222
+ /** Restrict full-text matching to body-field names shared by participating collections. */
223
+ fieldScope?: string[];
220
224
  /** Provider-neutral term and phrase matching semantics. */
221
225
  matching?: SearchMatching;
222
226
  /** The zone (named cross-collection scope) to search. */
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@byline/client",
3
3
  "private": false,
4
4
  "license": "MPL-2.0",
5
- "version": "4.17.0",
5
+ "version": "4.18.0",
6
6
  "engines": {
7
7
  "node": ">=20.9.0"
8
8
  },
@@ -44,8 +44,8 @@
44
44
  ],
45
45
  "dependencies": {
46
46
  "uuid": "^14.0.2",
47
- "@byline/auth": "4.17.0",
48
- "@byline/core": "4.17.0"
47
+ "@byline/auth": "4.18.0",
48
+ "@byline/core": "4.18.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@biomejs/biome": "2.5.10",
@@ -57,8 +57,8 @@
57
57
  "tsc-alias": "^1.9.2",
58
58
  "typescript": "^7.0.2",
59
59
  "vitest": "^4.1.11",
60
- "@byline/search-postgres": "4.17.0",
61
- "@byline/db-postgres": "4.17.0"
60
+ "@byline/search-postgres": "4.18.0",
61
+ "@byline/db-postgres": "4.18.0"
62
62
  },
63
63
  "publishConfig": {
64
64
  "access": "public",