docs(namespace): the d.ts JSDoc wave — the sealed field-addressing law on the full find + aggregation surface, present-tense, with the refusal semantics and migration note inline (comment-only; verified zero code lines changed)
This commit is contained in:
parent
5502abcdd8
commit
fcb24ab627
1 changed files with 106 additions and 17 deletions
|
|
@ -498,6 +498,43 @@ export interface UpdateRelationParams<T = any> {
|
||||||
* - **Graph:** `connected` for relationship traversal (via GraphAdjacencyIndex)
|
* - **Graph:** `connected` for relationship traversal (via GraphAdjacencyIndex)
|
||||||
*
|
*
|
||||||
* See also: [Query Operators](../../docs/QUERY_OPERATORS.md) for all `where` operators.
|
* See also: [Query Operators](../../docs/QUERY_OPERATORS.md) for all `where` operators.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* **Field-addressing law.** Governs every query-surface field name — `where`
|
||||||
|
* and `orderBy` on this interface, plus `AggregateSource.where` and
|
||||||
|
* `AggregateDefinition.groupBy` in the aggregation engine:
|
||||||
|
*
|
||||||
|
* 1. A bare name (e.g. `'level'`, `'rank'`, `'score'`) always means the
|
||||||
|
* caller's own metadata field — it reads `entity.metadata.<name>`. There
|
||||||
|
* is no fallback to an engine-internal field of the same name and no
|
||||||
|
* priority resolution between the two; metadata wins unconditionally.
|
||||||
|
* 2. `system.<field>` reaches an engine scalar, explicitly, and only for
|
||||||
|
* these ten: `id`, `type`, `subtype`, `createdAt`, `updatedAt`,
|
||||||
|
* `confidence`, `weight`, `visibility`, `service`, `createdBy`.
|
||||||
|
* 3. `vector`, `connections`, `level` (the engine-internal node field — a
|
||||||
|
* different thing from a user metadata field also named `level`),
|
||||||
|
* `data`, and `_rev` are invisible plumbing: neither spelling can
|
||||||
|
* address them from a query surface.
|
||||||
|
* 4. `metadata.<field>` is the explicit spelling of the bare form and means
|
||||||
|
* exactly the same thing as rule 1.
|
||||||
|
* 5. A name that matches none of the above — most often a bare name that
|
||||||
|
* collides with one of the ten system-scalar names in rule 2 — REFUSES
|
||||||
|
* with a typed {@link UnresolvableFieldError} naming both candidates,
|
||||||
|
* e.g. `no metadata field 'createdAt' — did you mean system.createdAt or
|
||||||
|
* metadata.createdAt?`. The same loud-refusal principle covers whole
|
||||||
|
* options: the previously accepted-and-silently-ignored `cursor`,
|
||||||
|
* `includeRelations`, and `writeOnly` now throw
|
||||||
|
* {@link UnsupportedFindOptionError} instead of doing nothing.
|
||||||
|
* 6. **Ordering contract** (identical on the pure-JS engine and the native
|
||||||
|
* accelerator): rows missing or `null` on the `orderBy` field sort LAST
|
||||||
|
* in BOTH `asc` and `desc` order and are never dropped from the result;
|
||||||
|
* ties break by `id` ascending.
|
||||||
|
*
|
||||||
|
* Migration note: a call site written against the old rule — e.g.
|
||||||
|
* `orderBy: 'createdAt'` or `where: { visibility: 'internal' }` meaning the
|
||||||
|
* engine scalar — now refuses instead of silently reading the wrong field.
|
||||||
|
* The thrown error names the exact fix (`system.createdAt`). A loud
|
||||||
|
* refusal with the fix in hand beats a silent behavior flip.
|
||||||
*/
|
*/
|
||||||
export interface FindParams<T = any> {
|
export interface FindParams<T = any> {
|
||||||
// Vector Intelligence
|
// Vector Intelligence
|
||||||
|
|
@ -516,7 +553,18 @@ export interface FindParams<T = any> {
|
||||||
* `{ exists: true }`, `{ missing: true }`) use `where: { subtype: { …operators… } }`.
|
* `{ exists: true }`, `{ missing: true }`) use `where: { subtype: { …operators… } }`.
|
||||||
*/
|
*/
|
||||||
subtype?: string | string[]
|
subtype?: string | string[]
|
||||||
/** Metadata filters using BFO operators (e.g., `{ year: { greaterThan: 2020 } }`) */
|
/**
|
||||||
|
* Metadata filters using BFO operators (e.g., `{ year: { greaterThan: 2020 } }`).
|
||||||
|
* Field names follow the field-addressing law — see the `@remarks` on
|
||||||
|
* {@link FindParams}: a bare key is always the caller's metadata field;
|
||||||
|
* an engine scalar needs the explicit `system.<field>` form.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* await brain.find({ where: { level: { greaterThan: 5 } } }) // metadata.level
|
||||||
|
* await brain.find({ where: { 'system.visibility': 'internal' } }) // engine scalar
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
where?: Partial<T>
|
where?: Partial<T>
|
||||||
|
|
||||||
// Visibility
|
// Visibility
|
||||||
|
|
@ -548,29 +596,49 @@ export interface FindParams<T = any> {
|
||||||
// Control options
|
// Control options
|
||||||
limit?: number // Max results (default: 10)
|
limit?: number // Max results (default: 10)
|
||||||
offset?: number // Skip N results
|
offset?: number // Skip N results
|
||||||
|
/**
|
||||||
|
* @deprecated Not implemented. Passing `cursor` throws
|
||||||
|
* {@link UnsupportedFindOptionError} — it used to be accepted and
|
||||||
|
* silently ignored, which masked that no cursor pagination ever ran. Use
|
||||||
|
* `offset` / `limit` until cursor pagination ships.
|
||||||
|
*/
|
||||||
cursor?: string // Cursor-based pagination
|
cursor?: string // Cursor-based pagination
|
||||||
|
|
||||||
// Sorting
|
// Sorting
|
||||||
/**
|
/**
|
||||||
* Field to sort by. User metadata fields sort by their stored values —
|
* Field to sort by. Follows the field-addressing law (see the `@remarks`
|
||||||
* including natural names like `level`, `rank`, or `score` (an engine-internal
|
* on {@link FindParams}): a bare name (`'level'`, `'rank'`, `'score'`, …)
|
||||||
* field can never shadow your metadata; fixed 2026-08 after a production
|
* always sorts by that metadata field; the ten engine scalars sort only
|
||||||
* report). System timestamps (`createdAt`, `updatedAt`) sort by entity age.
|
* via the explicit `system.<field>` form (e.g. `'system.createdAt'`); a
|
||||||
|
* name that resolves to neither throws {@link UnresolvableFieldError}
|
||||||
|
* naming the fix.
|
||||||
*
|
*
|
||||||
* Ordering contract (identical on the pure-JS engine and the native
|
* Ordering contract (identical on the pure-JS engine and the native
|
||||||
* accelerator): entities missing the field sort LAST in both directions —
|
* accelerator): rows missing or `null` on this field sort LAST in BOTH
|
||||||
* they are never dropped from the result; ties break deterministically.
|
* `asc` and `desc` order and are never dropped from the result; ties
|
||||||
|
* break by `id` ascending.
|
||||||
*
|
*
|
||||||
* NOTE — the field-addressing law is changing (announced 2026-08): bare
|
* @example
|
||||||
* names will mean user metadata ALWAYS, and system fields will be reached
|
* ```typescript
|
||||||
* explicitly as `system.<field>` (e.g. `system.createdAt`), with typed
|
* await brain.find({ orderBy: 'level', order: 'desc' }) // metadata.level
|
||||||
* refusals for unresolvable names. Until that release, bare `createdAt`
|
* await brain.find({ orderBy: 'system.createdAt', order: 'desc' }) // engine scalar
|
||||||
* and friends keep resolving to the system fields as documented above.
|
* ```
|
||||||
*/
|
*/
|
||||||
orderBy?: string
|
orderBy?: string
|
||||||
|
/**
|
||||||
|
* Sort direction: `'asc'` (default) or `'desc'`. Per the ordering
|
||||||
|
* contract on `orderBy`, rows missing/`null` on the sorted field sort
|
||||||
|
* LAST in both directions — `order` never moves them to the front.
|
||||||
|
*/
|
||||||
order?: 'asc' | 'desc' // Sort direction: 'asc' (default) or 'desc'
|
order?: 'asc' | 'desc' // Sort direction: 'asc' (default) or 'desc'
|
||||||
|
|
||||||
// Advanced options
|
// Advanced options
|
||||||
|
/**
|
||||||
|
* @deprecated Not implemented. Passing `includeRelations` throws
|
||||||
|
* {@link UnsupportedFindOptionError} — it used to be accepted and
|
||||||
|
* silently ignored, so no relationships were ever attached. Fetch
|
||||||
|
* relationships separately via `brain.related()`.
|
||||||
|
*/
|
||||||
includeRelations?: boolean // Include entity relationships
|
includeRelations?: boolean // Include entity relationships
|
||||||
excludeVFS?: boolean // Exclude VFS entities from results (default: false - VFS included)
|
excludeVFS?: boolean // Exclude VFS entities from results (default: false - VFS included)
|
||||||
service?: string // Multi-tenancy filter
|
service?: string // Multi-tenancy filter
|
||||||
|
|
@ -603,6 +671,11 @@ export interface FindParams<T = any> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Performance options
|
// Performance options
|
||||||
|
/**
|
||||||
|
* @deprecated Not implemented. Passing `writeOnly` throws
|
||||||
|
* {@link UnsupportedFindOptionError} — it used to be accepted and
|
||||||
|
* silently ignored, so validation was never actually skipped.
|
||||||
|
*/
|
||||||
writeOnly?: boolean // Skip validation for high-speed ingestion
|
writeOnly?: boolean // Skip validation for high-speed ingestion
|
||||||
|
|
||||||
// Aggregation
|
// Aggregation
|
||||||
|
|
@ -1352,7 +1425,10 @@ export type GroupByDimension =
|
||||||
export interface AggregateSource {
|
export interface AggregateSource {
|
||||||
/** Filter by entity type(s) */
|
/** Filter by entity type(s) */
|
||||||
type?: NounType | NounType[]
|
type?: NounType | NounType[]
|
||||||
/** Metadata filter (same syntax as find({ where })) */
|
/**
|
||||||
|
* Metadata filter — same syntax and field-addressing law as find()'s
|
||||||
|
* `where` (see the `@remarks` on {@link FindParams}).
|
||||||
|
*/
|
||||||
where?: Record<string, unknown>
|
where?: Record<string, unknown>
|
||||||
/** Multi-tenancy service filter */
|
/** Multi-tenancy service filter */
|
||||||
service?: string
|
service?: string
|
||||||
|
|
@ -1366,7 +1442,11 @@ export interface AggregateDefinition {
|
||||||
name: string
|
name: string
|
||||||
/** Which entities contribute to this aggregate */
|
/** Which entities contribute to this aggregate */
|
||||||
source: AggregateSource
|
source: AggregateSource
|
||||||
/** Dimensions to group by */
|
/**
|
||||||
|
* Dimensions to group by — field names follow the same field-addressing
|
||||||
|
* law as find()'s `where` / `orderBy` (see the `@remarks` on
|
||||||
|
* {@link FindParams}).
|
||||||
|
*/
|
||||||
groupBy: GroupByDimension[]
|
groupBy: GroupByDimension[]
|
||||||
/** Named metrics to compute */
|
/** Named metrics to compute */
|
||||||
metrics: Record<string, AggregateMetricDef>
|
metrics: Record<string, AggregateMetricDef>
|
||||||
|
|
@ -1425,16 +1505,25 @@ export interface AggregateGroupState {
|
||||||
export interface AggregateQueryParams {
|
export interface AggregateQueryParams {
|
||||||
/** Name of the aggregate to query */
|
/** Name of the aggregate to query */
|
||||||
name: string
|
name: string
|
||||||
/** Filter aggregate groups by their key values */
|
/**
|
||||||
|
* Filter aggregate groups by their key values — same field-addressing
|
||||||
|
* law as find() (see the `@remarks` on {@link FindParams}).
|
||||||
|
*/
|
||||||
where?: Record<string, unknown>
|
where?: Record<string, unknown>
|
||||||
/**
|
/**
|
||||||
* Filter groups by their computed METRIC values (SQL HAVING). Same BFO operators as
|
* Filter groups by their computed METRIC values (SQL HAVING). Same BFO operators as
|
||||||
* `where`, but applied to the derived metric results plus `count`, e.g.
|
* `where`, but applied to the derived metric results plus `count`, e.g.
|
||||||
* `{ revenue: { greaterThan: 1000 } }`. Evaluated per group (O(groups), independent of
|
* `{ revenue: { greaterThan: 1000 } }`. Evaluated per group (O(groups), independent of
|
||||||
* entity count), before sort/pagination.
|
* entity count), before sort/pagination. Metric names and `count` are looked up
|
||||||
|
* directly, not field-addressed; a group-KEY field used here follows the same
|
||||||
|
* field-addressing law as find() (see the `@remarks` on {@link FindParams}).
|
||||||
*/
|
*/
|
||||||
having?: Record<string, unknown>
|
having?: Record<string, unknown>
|
||||||
/** Sort by metric name or group key field */
|
/**
|
||||||
|
* Sort by metric name (a key from `metrics`, looked up directly) or by a
|
||||||
|
* group key field — a group key field follows the same field-addressing
|
||||||
|
* law as find()'s `orderBy` (see the `@remarks` on {@link FindParams}).
|
||||||
|
*/
|
||||||
orderBy?: string
|
orderBy?: string
|
||||||
/** Sort direction */
|
/** Sort direction */
|
||||||
order?: 'asc' | 'desc'
|
order?: 'asc' | 'desc'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue