Skip to content

Commit c0b93ba

Browse files
xuyushun441-sysos-zhuangclaude
authored
fix(objectql): honor $searchFields override sent as a comma-string (ADR-0061) (#2159)
The $searchFields override (the view-level "narrow search to these fields" signal that list views send) arrives over the REST/OData path as a URL query param — i.e. a comma-separated STRING ("name,industry"), not an array. The engine only applied it when Array.isArray was true, so the override was a silent no-op: `search=tech&searchFields=name` still searched the default field set instead of just `name`. Coerce a string `requestedFields` to an array in resolveSearchFields (the single seam), and pass the raw value through from engine.find. Now `searchFields=name` narrows to the name field, `searchFields=industry` to industry (matched via option label→value), as intended. Verified end-to-end over HTTP: search "tech" with searchFields=name → only Initech (name match); with searchFields=industry → the 4 Technology accounts. Unit test added for the comma-string form. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent d5f6d29 commit c0b93ba

3 files changed

Lines changed: 19 additions & 5 deletions

File tree

packages/objectql/src/engine.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1916,7 +1916,7 @@ export class ObjectQL implements IDataEngine {
19161916
const _searchFilter = expandSearchToFilter(_searchRaw, {
19171917
fields: _findSchema.fields as any,
19181918
searchableFields: (_findSchema as any).searchableFields,
1919-
requestedFields: Array.isArray(_reqFields) ? _reqFields : undefined,
1919+
requestedFields: _reqFields,
19201920
displayField: (_findSchema as any).displayNameField,
19211921
});
19221922
if (_searchFilter) {

packages/objectql/src/search-filter.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ describe('resolveSearchFields', () => {
5555
expect(f).toEqual(['industry']);
5656
});
5757

58+
it('accepts a comma-separated requestedFields string (URL param form)', () => {
59+
const f = resolveSearchFields({
60+
fields: accountFields,
61+
searchableFields: ['name', 'industry', 'status'],
62+
requestedFields: 'industry, status',
63+
});
64+
expect(f).toEqual(['industry', 'status']);
65+
});
66+
5867
it('ignores an override that resolves to nothing allowed (falls back)', () => {
5968
const f = resolveSearchFields({
6069
fields: accountFields,

packages/objectql/src/search-filter.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ export interface ExpandSearchOptions {
3131
fields: Record<string, SearchFieldMeta>;
3232
/** Object-declared `searchableFields` (the canonical default set). */
3333
searchableFields?: string[];
34-
/** Validated `$searchFields` override — intersected with the allowed set. */
35-
requestedFields?: string[];
34+
/** Validated `$searchFields` override — intersected with the allowed set.
35+
* Accepts an array or a comma-separated string (the form a URL query param
36+
* arrives as). */
37+
requestedFields?: string | string[];
3638
/** Preferred display field, placed first in the auto-default. */
3739
displayField?: string;
3840
}
@@ -93,9 +95,12 @@ export function resolveSearchFields(opts: ExpandSearchOptions): string[] {
9395
const all = opts.fields || {};
9496
const declared = opts.searchableFields?.filter((f) => all[f]);
9597
const allowed = declared && declared.length > 0 ? declared : autoDefaultFields(all, opts.displayField);
96-
if (opts.requestedFields && opts.requestedFields.length > 0) {
98+
const requested = typeof opts.requestedFields === 'string'
99+
? opts.requestedFields.split(',').map((f) => f.trim()).filter(Boolean)
100+
: opts.requestedFields;
101+
if (requested && requested.length > 0) {
97102
const allowSet = new Set(allowed);
98-
const validated = opts.requestedFields.filter((f) => allowSet.has(f));
103+
const validated = requested.filter((f) => allowSet.has(f));
99104
if (validated.length > 0) return validated;
100105
}
101106
return allowed;

0 commit comments

Comments
 (0)