Skip to content

Commit 1346a99

Browse files
committed
docs(lint): cut the exclusive and unchanged claims about the walked rule-array carriers
filterBy and lookupFilters are not the only consumed rule-array carriers outside the walk (object-grid defaultFilters is another), so the article that said so goes from the lint changeset, the FILTER_KEYS docblock and the test header; relatedListFilter is no longer the one member off the filter spelling either. The empty-combinator and flow-token rules did change for values the lint receives (filterBy: {} and a flow node config.lookupFilters), so the clauses and the changeset bullet calling them unchanged are cut. Comments and changeset prose only; no code moves. Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 48dfbe5 commit 1346a99

3 files changed

Lines changed: 6 additions & 11 deletions

File tree

‎.changeset/19791-filter-walk-rule-array-carriers.md‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22
"@objectstack/lint": patch
33
---
44

5-
`filter-preset-comparand` now judges a list page's `interfaceConfig.filterBy` and a lookup field's `lookupFilters`, the two consumed filter carriers the shared filter walk never entered (#19791).
5+
`filter-preset-comparand` now judges a list page's `interfaceConfig.filterBy` and a lookup field's `lookupFilters`, consumed filter carriers the shared filter walk never entered (#19791).
66

77
Both carriers are rule arrays (`{ field, operator, value }`) whose values reach the engine's `where` verbatim, and neither schema carries a preset check. So `{ field: 'close_date', operator: 'gt', value: 'last_30_days' }` in either one parsed green and linted green, then the engine refused it at query time (`INVALID_FILTER` / 400). The same rule on a component `dataSource.filter` or a view `filter` was already refused. `filterBy` and `lookupFilters` join `FILTER_KEYS`, so `os lint`, `os validate` and the runtime publish gate (for `page` and `object` writes) now refuse it where it is written. Each finding carries its path (`pages[0].interfaceConfig.filterBy[0].value`, `objects[2].fields.account.lookupFilters[0].value`).
88

99
- **Which object a condition addresses.** The field-typed arm, which refuses a preset under equality or membership on a `date` / `datetime` field, binds `filterBy` to `interfaceConfig.source`. Without a `source` it falls back to the page's `object`. It binds `lookupFilters` to the field's `reference` and never to the object that owns the field, because the picker queries the referenced object. A `relatedListFilter` on the same field still binds to the owner.
1010
- **`filter-token-unknown` reaches the same two carriers.** An unresolvable placeholder such as `{current_user}` in `filterBy` or `lookupFilters` is now reported, as it already is in a view's `filter`. `{current_user_id}` and the date macros stay clean.
11-
- **Unchanged:** `filter-empty-combinator` / `filter-empty-node` judge Mongo-shape nodes only, and both carriers are arrays. `flow-filter-token-unknown` walks `flows`, and no flow schema declares either key.
1211
- **What you do:** in a `filterBy` or `lookupFilters` rule, replace a preset name with the `{date-macro}` window the message names (`{ operator: 'gte', value: '{30_days_ago}' }`) or with an ISO date.

‎packages/lint/src/filter-walk.ts‎

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,15 @@ type AnyRec = Record<string, unknown>;
5757
/**
5858
* Keys whose subtree is a filter. The one place a filter is authored.
5959
*
60-
* `relatedListFilter` (#8704) is the one member that does not spell the key
61-
* `filter`: it sits flat on a FIELD beside its `relatedList`/`relatedListTitle`/
60+
* `relatedListFilter` (#8704) sits flat on a FIELD beside its `relatedList`/`relatedListTitle`/
6261
* `relatedListColumns` family, so the family naming wins over the filter-key
6362
* convention. It carries a canonical Query-DSL `FilterCondition` (the schema
6463
* door already judges it at parse), and listing it here is what extends the
6564
* three walking rules — tokens, empty combinators, preset comparands — to the
6665
* new position instead of leaving a per-rule hole.
6766
*
68-
* `filterBy` and `lookupFilters` (#19791) are the two consumed RULE-ARRAY
69-
* carriers that do not spell the key `filter` either: a list page's always-on
67+
* `filterBy` and `lookupFilters` (#19791) are consumed RULE-ARRAY
68+
* carriers that do not spell the key `filter`: a list page's always-on
7069
* base filter (`interfaceConfig.filterBy`, `z.array(ViewFilterRuleSchema)`,
7170
* which the console spreads into the list query beside the view's own
7271
* `filter`) and a lookup field's picker filter (`lookupFilters`, lowered by the
@@ -76,10 +75,7 @@ type AnyRec = Record<string, unknown>;
7675
* and was refused only at query time. What the entry changes per walking rule,
7776
* measured: preset comparands and filter tokens now judge both carriers (the
7877
* engine resolves the same two placeholder vocabularies there and refuses the
79-
* same residue); empty combinators is unchanged, because both carriers are
80-
* arrays and that rule judges Mongo-shape nodes only; the flow token rule is
81-
* unchanged, because it walks `flows` alone and no flow schema declares
82-
* either key. The binding half — which object a condition on each carrier
78+
* same residue). The binding half — which object a condition on each carrier
8379
* addresses — is `validate-preset-comparands.ts`'s, not this walk's.
8480
*/
8581
export const FILTER_KEYS: ReadonlySet<string> = new Set([

‎packages/lint/src/validate-preset-comparands.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ describe('validatePresetComparands — arm 2, the FIELD-TYPED equality / members
673673
});
674674
});
675675

676-
// ── [#19791] The two consumed rule-array carriers the walk never entered ────
676+
// ── [#19791] consumed rule-array carriers the walk never entered ────
677677
//
678678
// A list page's `interfaceConfig.filterBy` and a lookup field's
679679
// `lookupFilters` both reach the engine's `where` verbatim, and neither schema

0 commit comments

Comments
 (0)