# `Query`

> Contract 2.0.0 · package sha256 `a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e` · generated from `configurator-runtime.d.ts` by `services/onsite-scripter/scripts/build-contract-docs.mjs`; edit the source, not this file.

Type · `import type { Query } from '@holostep-configurators/runtime-client/contract';` · stable · since 2.0.0 · section 6. Queries, rules and parts

All fields are ANDed; an array of queries matches any of them. Every field is authored or fixed
at creation: no rule
and no Frame write can change it, so a rule never changes its own members. (Only [`Collection.set`](Collection.set.md)
changes an item's [`name`](Part.name.md), [`tags`](Part.tags.md) or [`meta`](Part.meta.md); membership is re-evaluated at that commit.)
- Primitives: a glTF node whose mesh has several primitives loads as a group part (the
  node: its name, id and pose) with one mesh part per primitive under it, in primitive order,
  as the 1.x loader builds it: a primitive part's [`name`](Part.name.md) is the glTF mesh's authored name, its
  [`id`](Part.id.md) the cleaned mesh name, numbered when taken (spec section 6.9, ID1), and its [`slot`](Part.slot.md) its
  primitive's material. A rule on the node's name reaches them through the group (R8); [`slot`](Part.slot.md),
  or the group's [`children`](Part.children.md), picks some of them.
- Groups: a [`name`](Part.name.md) glob also matches group parts, and a rule on a
  group cascades to every mesh below (spec section 6.10, R8); `kind: 'mesh'` keeps it to meshes,
  as a 1.4 RegExp tested over meshes only did.
- Counting: `{ collection }` matches that collection's root group part too, and `{ node }` its
  model's root and groups, so [`find({ collection: 'shelves' }).count`](Parts.count.md) is one more than the
  shelves. Count items with `kind: 'mesh'` (or a tag they carry):
  [`find({ collection: 'shelves', kind: 'mesh' }).count`](Parts.count.md).
A [`Part`](Part.md) matches that one part. A rule holds it, and [`state()`](Writer.state.md), the feed and patches read it
back, as its address (spec section 6.9, ID1), so they stay JSON: `{ node, id }`,
`{ collection, key, id }`, or for a model's, a collection's or an item's root part
`{ node, root: true }`, `{ collection, root: true }` or `{ collection, key, root: true }`. A query that matches nothing records 'target-unmatched'
([`Report.matched`](ReportFields.matched.md)).

Inherited from [`Part`](Part.md): [`id`](Part.id.md), [`name`](Part.name.md), [`kind`](Part.kind.md), [`source`](Part.source.md), [`node`](Part.node.md), [`collection`](Part.collection.md), [`key`](Part.key.md), [`role`](Part.role.md), [`tags`](Part.tags.md), [`slot`](Part.slot.md), [`meta`](Part.meta.md), [`parent`](Part.parent.md), [`children`](Part.children.md), [`exists`](Part.exists.md), [`visible`](Part.visible.md), [`pose`](Part.pose.md), [`worldPose`](Part.worldPose.md), [`restPose`](Part.restPose.md), [`material`](Part.material.md).

Inherited from [`PartActions`](PartActions.md): [`set`](PartActions.set.md), [`bounds`](PartActions.bounds.md), [`find`](PartActions.find.md), [`follow`](PartActions.follow.md).

## Declaration

```ts
export type Query = {
  node?: string;
  collection?: string;
  key?: string;
  id?: string;
  name?: string;
  slot?: string;
  kind?: 'group' | 'mesh' | 'joint' | 'light' | 'lines' | 'label';
  tag?: string;
  role?: Role;
  meta?: Readonly<Record<string, JsonPrimitive>>;
  root?: boolean;
} | Part | readonly Query[];
```

## Example

Imports: values (`has`, `validate`, the `Holo*Error` classes, the pure helpers) from `@holostep-configurators/runtime-client`, types from `@holostep-configurators/runtime-client/contract`, `/math` and `/testing` names from those entries; `boot` from the runtime module the root's `loadRuntimeAtFloor` resolves to. A type your page defines is your app's: declare it there, never import it from the package.

Compiled under the contract's strict settings (`examples/declaration/06-Query.ts`):

```ts
import type { Session } from '@holostep-configurators/runtime-client/contract';
declare const session: Session;
declare const signal: AbortSignal;
// Hide the 'matte black' primitive of one named node in one placed unit. When the slot is
// unique in the model, `{ node: unitId, slot: 'matte black' }` is enough.
declare const unitId: string;
const body = session.find({ node: unitId, name: 'Corpus.012', kind: 'group' }).first();
for (const p of body?.children ?? []) {
  if (p.slot === 'matte black') await p.set({ visible: false });
}
// A node's or a collection's query also matches its root group part: count meshes, not parts.
export const meshCount = (q: { node: string } | { collection: string }): number =>
  session.find({ ...q, kind: 'mesh' }).count;
```

## Generic-API test (spec 3.1)

| Rule | Result |
| --- | --- |
| 1. Neutral name | pass: `Query` names no product |
| 2. A precedent | pass: [DOM Document.querySelectorAll](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll) (row `K58`) |
| 3. Two apps, or labs | pass: 28 apps (ledger: app-bcb7ef21da, app-f3598fad77, app-f9a32142f1, app-fc07850558, app-fc306ec3dc, app-fd09090420; fleet cross-check: app-04c2774145, app-0c773a4ee3, app-37356bf09f, app-378d190f1b, app-4762caacdc, app-4f16d2f6da, app-4fd23bc869, app-510d750508 and 20 more) |
| 4. The cheaper fix first | decided per need in Appendix B: rows `K58` at tier stable (a member only where no rule, data, asset or app code serves the need) |
