# @ai-matrx/records 中文文档

规范地址：https://npmcn.com/package/%40ai-matrx/records/

版本：0\.99\.153
npm 元数据更新时间：2026-10-30T12:15:36.491Z
中文译文更新时间：2026-11-05T18:08:26.856Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40ai-matrx/records
原文对照：https://npmcn.com/package/%40ai-matrx/records/?lang=original
项目主页：https://github.com/AI-Matrix-Engine/aidream/tree/main/apps/shared/records#readme
源码仓库：https://github.com/AI-Matrix-Engine/aidream

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：34.4 MB，305 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=20
- 运行依赖：3 个
- peer 依赖：react \>=18\.0\.0，@tanstack/react-query \>=5\.100\.0
- 首次发布：2026-09-19T07:24:14.802Z
- 最新版本发布：2026-10-30T12:15:36.318Z
- 近 30 天下载量：105515（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：422（近 12 个月 422 个）

## 中文简介

AI Matrx唱片店的无头客户端: Table / Field / Rule / Record / relations / Home 类型,从商店本身读取的已关闭的词汇和拒绝代码,打入商店门上的打字器和没有其他的,合并-field Dec

## 安装

```sh
npm install @ai-matrx/records
```

也可以使用：`pnpm add @ai-matrx/records`、`yarn add @ai-matrx/records`、`bun add @ai-matrx/records`

## README

# @ai- matrx/ 记录

AI Matrx唱片店的无头客户端: Table / Field / Rule / 记录 / 关系 / 家庭类型、 关闭词汇和拒绝代码 从商店ISTELF, 打出的电话 在商店的门,没有别的, 合并字段声明,一个只预测什么 商店本身的触发器 拒绝, 和一个结果封 从来没有扔.

包件装有"根"、"无头" `/core` 和反应绑定 `/react`。 。 。 . `@ai-matrx/records-ui` 做它; 没有别的谈话 商店.

**这个套装的规矩是:** 客户镜像商店的合同 永远不要重新执行 商店执行的规则。 商店拒绝的地方,这个 软件包表面显示商店本身的句子——从不翻译.

```ts
import {
  type Table, type Field, type StoredRecord, // the shapes
  type ValueEnvelope,                        // ver · src · actor · on_behalf_of · at · absent · alternates · dated
  PARITY_FIELD_TYPES,                        // the 13 field types, read from custom.parity_field_types()
  ACTOR_VOCABULARY,                          // exactly: user, agent, system
  ABSENCE_REASONS,                           // exactly: never asked, none, refused, conflicting
  STORE_DOORS, STORE_REFUSAL_CODES,          // GENERATED from pg_proc on the live store
} from "@ai-matrx/records";
```

## 快速启动——我们自己的系统内的记录库

公司需要从自己的屏幕上列出、创建、编辑、归档和观看所有记录,或 剧本,没有我们的。 一个包;每个段仅在导入时加载.

```sh
npm install @ai-matrx/records @supabase/supabase-js
```

```ts
import { createClient } from "@supabase/supabase-js";
import { createRecords, sessionAuth } from "@ai-matrx/records/setup";
import { ensureTable } from "@ai-matrx/records/core";

// 1. Sign in. The database address is https://db.matrxserver.com; the publishable key is on your
//    AI Matrx account page. Any supabase-js sign-in works (password, magic link, SSO, server cookies).
const supabase = createClient("https://db.matrxserver.com", PUBLISHABLE_KEY);
await supabase.auth.signInWithPassword({ email, password });

// 2. One call. You choose the organization new records are saved in; reads span all of yours.
const matrx = await createRecords({ auth: sessionAuth(supabase), organizationId: (orgs) => orgs[0] ?? null });

// 3. A table (found by its slug, or made the first time), then records.
const table = await ensureTable(matrx.records, { name: "Service callbacks", slug: "service_callbacks",
  fields: [{ key: "caller", label: "Caller", type: "text" }, { key: "phone", label: "Phone", type: "phone" }] });
if (!table.ok) throw new Error(table.error.message);
const tableId = table.data;                 // the table id

const created = await matrx.records.recordWrite({ table_id: tableId, data: { caller: "Marcus Delgado", phone: "+14155550178" } });
const page    = await matrx.records.list({ table_id: tableId, limit: 50 });                  // { rows, total }
const record_id = created.ok ? created.data : "";
const read    = await matrx.records.recordRead({ record_id, withVersion: true });          // .data.document, .data.version
const expectedVersion = read.ok ? (read.data.version ?? undefined) : undefined;
const edited  = await matrx.records.recordUpdate({ record_id, patch: { phone: "+14155550199" }, expectedVersion }); // answers the new version
// Always send expectedVersion: a colleague's newer edit is then refused (`stale_write`, field by field), never overwritten.
const archived = await matrx.records.recordDelete({ record_id });                            // soft: recordRestore brings it back

// 4. Live: other people's changes to this table (this setup's own writes are not echoed back).
const stop = matrx.watch(tableId, { records: (ids) => console.log("changed", ids) });

// 5. Search across every table you can see; platform records (contacts…) through matrx.entities.
const hits = await matrx.search({ search: "Delgado" });

stop(); matrx.close(); // a script closes the live socket before it exits
```

每一个呼叫回答 `{ ok: true, data } | { ok: false, error }` - 商店自己的句子,从来没有 掷出. 反应主机添加 `@ai-matrx/records/react` 或者说 `@ai-matrx/records/data/react` 同样的钩子 客户端; `@ai-matrx/records-ui` 是我们可选的一组屏幕。 组织 API 密钥插入 `auth` 作为第二种模式(计划);今天 `auth` 是一个签名的会话.

| 节次 | 什麽 |
| --- | --- |
| `records/setup` | `createRecords`, (中文(简体) ), `sessionAuth` - 上面的电话 |
| `records/core` | 每个门上输入的客户端(表格、记录、版本、视图、表格、总数) |
| `records/realtime` | 用户端口设置 |
| `records/search` | `searchRecords`, (中文(简体) ), `listStoreRecordCandidates` |
| `records/forms` | 表格文档,嵌入,读取一个公共地址, `typedAnswersFor` |
| `records/versions` | 版本规则 : `useRecordVersions`,版本携带的写出门, `askOnce`, (中文(简体) ), `refusal` |
| `records/entity`, (中文(简体) ), `records/entity/react` | 平台记录(联系人、项目、任务) |
| `records/data`, (中文(简体) ), `records/data/react` | 一个数据端口和自定义表格和实体上的 TanStack 钩子 |
| `records/react` | 提供者 + 钩子在客户端之上 |

## /core-门上的打字客户端

```ts
import { createClient } from "@supabase/supabase-js";
import { createRecordsClient, ensureTable, supabaseDataSource } from "@ai-matrx/records/core";

const supabase = createClient(url, publishableKey);  // the client that carries this person's session
const records = createRecordsClient({
  dataSource: supabaseDataSource(supabase),  // binds the store's schema for you
  actor: { actor: "user" },                  // who is acting: "user", "agent" or "system"
  organizationId: orgId,                     // where writes go; the store is keyed (organization_id, id)
  onError: (e) => report(e),                 // OPTIONAL — the default screams to console
});
// Reads of tables and records span `organizationIds` when you pass them (every organization the
// person belongs to); typed tables read every one of them by default, without being told.
// (This block is compiled with the package: src/__tests__/readme-quick-start-compiles.tsx.)

// A page's own small table: found by its slug, or made the first time (one transaction).
const log = await ensureTable(records, { name: "Front desk callback log", slug: "front_desk_callback_log",
  fields: [{ key: "caller_phone", label: "Phone", type: "phone", unique: true }, { key: "reason", label: "Reason", type: "long_text" }] });
const one = await records.tableFind({ slug: "front_desk_callback_log" });          // the Table, or null
const id  = await records.recordUpsert({ table_id, key: "caller_phone", data: { caller_phone, reason } }); // write-or-update
// With expectedVersion it is an EDIT: no live record of that key → stale_write, never a new record.

const written = await records.recordWrite({ table_id, data: { title: "Acme", owner: personId } });
const rows    = await records.list({ table_id, limit: 50 });
const read    = await records.recordRead({ record_id, withComputed: true });
const moved   = await records.recordUpdate({ record_id, patch: { title: "Acme Inc" }, expectedVersion: 3 });

if (!moved.ok && moved.error.code === "stale_write") {
  // The store's own words, plus the conflict field by field.
  moved.error.message;  // "Someone else changed this record while you were working on it. …"
  staleWriteDetail(moved.error); // { expected_version, current_version, contested_fields }
}
```

### `ensureTable` 永远不要改变一栏,它说每个栏是如何不同的

已经存在的表格将每个列都完全保留在存储中(重排是转换一个人) (决定)。 要求的规格不同

```ts
const log = await ensureTable(records, spec);
// { ok: true, data: tableId, homeId, created: false,
//   drift: [{ field: "caller_phone", aspect: "type",  stored: "text",   declared: "phone" },
//           { field: "patient_name", aspect: "label", stored: "Patient", declared: "Patient full name" }] }
```

`drift` 实值 `FieldDrift[]` —— 说 `{ field, aspect, stored, declared }`, (中文(简体) ), `aspect` 一个 `type` (比例类型, 其他行为, `format`, (中文(简体) ), `label`, (中文(简体) ), `multi`, (中文(简体) ), `required`, (中文(简体) ), `unique`,或 `spec` (该栏的规格可以 不读取; `declared` 是商店的句子。 没错 `[]` 当出生和无异时 `null` 只能从一个老店里拿来比较 申报的一面是商店存储的规格 这样 `long_text` 永远不是假的 `type` 漂来漂去。 这个形状是合同的放行时间漂移 检查读取( n)`parseFieldDrift` 键入原始答案).

### 应用程序保存的表格

```ts
const outputs = await ensureTable(records, {
  name: "Exercise flashcard outputs", slug: "agent_output_exercise_flashcard",
  platformOwned: true, keptFor: "agent_output", kind: "exercise_flashcard",
  homeId: sharedOutputsHome,                         // a NEW table goes in this Home; none is made
  fields: [{ key: "body_region", label: "Body region", type: "select", optionsTableId }],
});
```

`keptFor` 是地址的一部分: 带有它的光谱只找到一个为该词保留的表格, 而光谱 没有它就永远找不到一个应用的桌子——一个人的桌子和一个应用的一发子弹的桌子是不同的 图表. `platformOwned`, (中文(简体) ), `keptFor`, (中文(简体) ), `kind`, (中文(简体) ), `draftsFor` 财务报告和审定财务报表 `draftsStamp` 存储在桌子上 生产. `homeId` 必须是这个组织的活家 打电话者可能改变,或什么都不做. `optionsTableId` 重新使用现有的选择列表; `declaration` 过任何其他 `custom.field_declare` 键.

### 当两个桌子共用一发子弹时, `tableFind` 财务报告和审定财务报表 `ensureTable` 可能有所不同

鼻涕并不是独一无二的(较老的组织持有一些重复. `tableFind` 回答最年长的 子弹的表 **呼叫者可能会看到**。 。 。 . `ensureTable` 取最古老的弹子表 **总计** 如果打电话者可能不知道, 拒绝用读取门本身的话 比做第二个桌子。 对于一个最古老的复制品, `tableFind` 返回更新表格时 `ensureTable` 拒绝;双方总是同意,当打电话者能看到最年长的.

这里什么也没有, 这里什么也没有发明一个答案。 店里的门 尚未答复 `door_absent`,命名门和欠车道 这.. `fieldPropose`, (中文(简体) ), `tablePropose` 财务报告和审定财务报表 `mergeFieldResolve` 今天拒绝,而不是返回一个空列表,它会读作“有” 没什么".

## 三道作一桌(每分一分下,同作一铺)

每一道都在同一地段结束: 一个普通的记录存储表,有商店自己的门 决定访问、历史和档案。 选一个和你站的地方匹配的.

**1\. 从代码——声明,它存在于先用上,行被打出.** 无编码源 : `RowOf` 编号 : `InsertOf` 来自于声明,所以一个错误的选择,缺少必要的一栏或拼写错误 列失败 `tsc`。 。 。 .

```ts
import { defineTypedTable, f } from "@ai-matrx/records/typed-table";
import { useTypedTable } from "@ai-matrx/records/react";

export const vendorContacts = defineTypedTable({
  name: "Vendor contacts", slug: "vendor_contacts", scope: "organization", kept_for: "purchasing", key: "vendor",
  fields: {
    vendor: f.text({ required: true, unique: true }),
    contact_name: f.text(),
    category: f.select(["Medical supplies", "Lab services", "Facilities", "IT"] as const),
    monthly_spend: f.currency("USD"),
  },
});
// in a component under <RecordsProvider>: the table is made in the active organization on mount
const { rows, upsert } = useTypedTable(vendorContacts);
await upsert({ vendor: "Quest Diagnostics", category: "Lab services", monthly_spend: 1850 });
```

**2\. 从结构化的JSON——REST v1或AI Matrx MCP中 `tables` 工具** (单位:千美元)`POST /api/v1/tables` 与 `X-Organization-Id`; 磁共振 `tables {action:"create_table", organization_id, name, columns}`:

```json
{ "name": "Vendor contacts", "columns": [
  { "name": "Vendor", "type": "text", "required": true, "unique": true },
  { "name": "Category", "type": "choice", "choices": ["Medical supplies", "Lab services"] },
  { "name": "Monthly spend", "type": "currency" } ] }
```

**3\. 来自SQL - `POST /api/v1/sql` 或 MCP 程序 `sql` 工具**,一次一个声明,写成 邮政: `CREATE TABLE vendor_contacts (vendor text not null unique, category text check (category in ('Medical supplies','Lab services')), monthly_spend numeric)`,则 `INSERT …`, (中文(简体) ), `SELECT … WHERE … ORDER BY … LIMIT`, (中文(简体) ), `UPDATE … WHERE`, (中文(简体) ), `DELETE … WHERE` (档案), `ALTER TABLE … ADD COLUMN`子集和每次拒绝:援助性梦 `aidream/services/table_api/FEATURE.md`。 。 。 .

**已经存在的表格** (在应用软件中制作,或由2或3方式制作)得到一个打入的定义,其中 `pnpm tables:types <table id | slug> [--organization <id>] --out features/x/vendor-contacts.ts`, (中文(简体) ), 发射 `columns` 地图加 `…Row` 编号 : `…Insert` 类型从活商店.

## /typed-table- 月台保留自己的特性的表格

需要自己一个小表的特征,在代码中宣布一次;每个组织得到其 第一次使用的自有副本,行类型来自声明.

**十分钟的路程**

```ts
// features/decisions/decision-picks.typed-table.ts — imports only @ai-matrx/records/typed-table
import { defineTypedTable, f } from "@ai-matrx/records/typed-table";

export const decisionPicks = defineTypedTable({
  name: "UI decision picks", slug: "ui_decision_picks", kept_for: "decisions",
  scope: "person", owner: "lane:PLATFORM-APP-DATA",       // owner is optional
  key: "decision_id",                                       // must be a unique field
  fields: {
    decision_id: f.text({ label: "Decision", unique: true, required: true }),
    choice: f.select(["a", "b", "neither"] as const, { label: "Choice" }),
    decided_at: f.datetime({ label: "Decided" }),
  },
});

// in a component under <RecordsProvider>
const { rows, upsert, remove, loading, error, status } = useTypedTable(decisionPicks);
await upsert({ decision_id: "header-density", choice: "a" });   // choice: "maybe" does not compile
```

-   `rows` 为: `RowOf<typeof decisionPicks>[]` 个人所属的每个组织 客户端 `organizationIds` 当主机通过它们, 否则商店自己的列表(`iam.my_orgs()`(三); 呼叫者什么也没有通过. `{ organizationId }` 缩到一(也是写作的地方). 没有它,写给活跃的组织(客户端 `organizationId`) (中文(简体) ).
-   `total` 是商店的数 这个人可能看到的行; `truncated` 当 `rows` 10 000起停止(`APP_ROWS_CEILING`)——读诵从来不默不作声.
-   `status` 实值 `"ok"`, (中文(简体) ), `"drifted"` (所储存的列与代码不同——报告,从未) 应用; 已存储的一列代码不再声明为漂移 `extra`, (中文(简体) ), `"archived"` (商店) 拒绝再来一次: `error` 说,命名桌子 `upsert` 同样的回答 句子——从已归档的表格中恢复)或 `null` 不明或拒绝. `error` 这是 商店本身的句子; 在没有12号车道门的商店里 `door_absent`。 。 。 .
-   每个打入的表格都是由它的 sulter 和 `kept_for`: 一个人自己的同一颗子弹的桌子是 不同的桌子,从来不回答。 一个组织的每张打字台都住在一个家庭, "平面表格".
-   **密码取决于它:** `ensureTypedTable` 标记每个副本 `code_depends: true` (单位:千美元) `app_table.declared_in` 从定义的 `declared_in`) (中文(简体) ). 商店拒绝归档, 重命名( slug 或 `kept_for`),移动或解开标记,穿过每个门 `archiveTypedTableDeliberately(client, { tableId, typedSlug, reason })` - 一个人打出子弹, 拒绝代理.
-   无头: `ensureTypedTable(client, def, { organizationId })`, (中文(简体) ), `checkTypedTable(client, def)` (单位:千美元)`status`, (中文(简体) ), `drift`, (中文(简体) ), `rowCount`, (中文(简体) ), `listAppRows`, (中文(简体) ), `upsertAppRow`, (中文(简体) ), `removeAppRow` (商店的软 页:1 该商店拒绝在密钥下一个从未声明过的定义(23514名名名下)的值.
-   **毕业** (合同:共同文件) `projects/data-doctrine-adoption/v6/CONTRACT-PLATFORM-APP-DATA-GRADUATION.md`: 定义添加 `graduatedTo: { token: "<schema>.<table>", map: { <field>: <column> | "custom_fields" | "association" } }` 一旦其标准实体表存在(通过 `platform.create_entity_table`) (中文(简体) ). 每个申报 字段必须映射(与 `"association"`; 光谱散列不移动. `pnpm tables:graduate <module> <export> [--target clone|production] [--dry-run]` 复制每组活的和存档的行 组织的复制件(id, organization, 作者, 时间戳, 版本,存档状态, `shown_to`, (中文(简体) ), `visibility` 保存;未申报的密钥 `custom_fields`; 存储簿记+ `legacy_id` → `metadata`· ; 关系值 `platform.associations`),每个组织进行一次交易, `ON CONFLICT (id) DO NOTHING`,拒绝任何数 异议,然后档案 每一个现场副本通过 `custom.table_archive_deliberately` ("毕业为". 默认目标:克隆人. 纯洁 导出部件 : `graduationProblems`, (中文(简体) ), `graduatedRow`。 。 。 .
-   构建器 : `text longText email phone url number integer decimal currency(unit) percent checkbox date datetime select multiSelect relation(otherDef) member attachment entityReference(kinds)` 财务报告和审定财务报表 仅读 `formula autonumber createdTime modifiedTime` (缺席) `InsertOf`) (中文(简体) ).

**大门** (Arman 2026-10-02号裁决,逐字记录 `systems/data/custom-data/DECISIONS.md`,"当平台可能将自己的数据保存在商店":

-   **允许 :** 实验,特征 很少人使用,未经证实的收养,短期中途停留,小数据 包括其行属于组织的平台功能(预订,录取名单).
-   **禁止 :** 大部分或所有的人使用 (tags), 一个明显的长期特征,数据 几乎不会改变形状, 或很多数据.
-   **大小, 不是时间 :** 没有记录理由或审查日期;表格为50 000行 \* 包括所有组织,并每增加10 000人`checkTypedTable`是因为 `rowCount` 输入 检查;确认步骤尚未建立).

**范围,老实说:** `organization` 排队由排队组织成员看到,每排 成员可以添加行(复制时与编辑级成员共享). `person` 排起"只有我":他们是 **隐藏在别人的名单上** - 商店的上游清单 丢掉它们,所以另一个成员读到的只有她自己的一行——但是它们是 **未锁定**(单位:千美元) 有排行ID的成员仍然可以打开. 店面锁是店面的机密级别, 独立且需要所有者按表批准; 绝不放任何必须属于私人的东西 在一个 `person` 页:1. `global` 在平台组织中是一份,仅由服务器代码编写; `ensureTypedTable` 拒绝,除非该组织被明确命名.

## 镜子——商店要说的话,半秒前说

```ts
import { predictWriteRefusals } from "@ai-matrx/records/core";

const problems = predictWriteRefusals({ fields, document, recordType });
// [{ field_key: "amount", sqlstate: "23514", predicted_by: "custom.validate_values",
//    message: "Amount has to be at least 1" }]
```

这不是验证——商店验证,在写出门内,不能 绕行。 镜子上只写着店里要说的话,在店里 准确的句子,上面写着什么是看不见的(选择成员, 关系目标,任何需要查询的内容)。 沉默的意思是"问店".

## /反应-绑住一次,然后钩子

```tsx
import {
  RecordsProvider, useTables, useFields, useRecords, useRecord, useRecordMutation,
} from "@ai-matrx/records/react";

<RecordsProvider config={{ dataSource: supabaseDataSource(supabase), actor: { actor: "user" }, organizationId: orgId }}>
  {children}
</RecordsProvider>;
// A config without `actor` is refused by name ("RecordsProvider needs config.actor …").

const { tables } = useTables();
const { fields } = useFields(table_id);
const { rows, total, live, liveOffReason } = useRecords({ table_id, pageSize: 50 });
const { write, update, remove, conflict } = useRecordMutation();
```

`live` 绝不是妄言的;当实时不受约束的时候, `liveOffReason` 说 为什么在句子中屏幕可以显示.

## /实体——平台记录(联系人,项目,任务)通过同一端口

通过相同的平台记录(联系人,项目,任务.) `DataPort` 小程序读取自定义 与表齐. 一个在商店实体门上打字的瘦客户端和一个主机 `DataPort` 实体 化名, 和符号第一反应钩 在记录的一个数据引擎上(`@ai-matrx/records/data/react`) (中文(简体) ).

**读与写.** `create` 保存到活动组织中的主机名( 无拒绝 ) `organization_required`, (中文(简体) ), `update` 发送所看见的版本(与 商店的句子, `archive` 编号 : `restore` 移动一行到垃圾堆和后面. **名单是实时的** 当主机经过时 `realtime: createEntityRealtime({ manager })` (和 `organization`: 其他人的改变是 `rows:<alias>` 命名标识的事件.

```ts
import { createEntityDataPort } from "@ai-matrx/records/entity";
import { DataPortProvider, hostEvents, useDataRows } from "@ai-matrx/records/data/react";

const port = createEntityDataPort({
  dataSource: supabase, // the signed-in person's supabase-js client
  aliases: { contacts: { kind: "entity", token: "party", organizationId } },
});

// in React:
// <DataPortProvider port={port} events={hostEvents(port)} portKey="applet-1" queryClient={qc}>
//   const { rows, hasMore, loadMore, error } = useDataRows("contacts", { org: organizationId, sort: [{ column: "display_name" }] });
```

在 React app中,请命名类型,让引擎来做剩下的:

```tsx
import { EntityDataProvider, useEntityList, useEntityWrite } from "@ai-matrx/records/entity/react";

// once, high: <EntityDataProvider dataSource={supabase} activeOrganizationId={activeOrg}>…
const contacts = useEntityList("party", { where: [{ column: "last_name", op: "eq", value: "Ellis" }] });
const write = useEntityWrite("party");
await write.update(contacts.rows[0]._id, { first_name: "Ada" }); // drawn at once, rolled back on refusal
```

### 条目

| 条目 | 什麽 |
| --- | --- |
| `@ai-matrx/records/entity` | `createEntityClient({ dataSource })` → `list`, (中文(简体) ), `get`, (中文(简体) ), `columns`, (中文(简体) ), `insert`, (中文(简体) ), `update`, (中文(简体) ), `archive`, (中文(简体) ), `unarchive`· ; `toWire`· ; `mapEntityError`· ; `createEntityDataPort({ client | dataSource, aliases, activeOrganizationId })` → `HostDataPort` + 键 `describe`· ; `createEntityRealtime` |
| `@ai-matrx/records/entity/react` | `EntityDataProvider`, (中文(简体) ), `useEntityList`, (中文(简体) ), `useEntityColumns`, (中文(简体) ), `useEntityType`, (中文(简体) ), `useEntityRow`, (中文(简体) ), `useEntityWrite` |

### 值得了解的行为

-   车道默认为该型号自有起降道,由商店决定; 2; `org` 是一个过滤器,从不锁.
-   Page 是密钥集: 光标是商店的 `next_after`。 。 。 .
-   商店尚未提供的过滤器或排序器被名字与商店的句子拒绝,从未在浏览器中被模仿.
-   自定义字段读取自 `row._custom` 过滤为 `_custom.<key>`; 个人可能无法读取的字段到达 `null`。 。 。 .
-   商店的倒数封顶上停放的总数报告为: `null` (未知),绝不是错误的号码.

当地力学: `src/entity/FEATURE.md`。前称软件包 `@ai-matrx/entity-data` (折旧;相同的API,更名进口: `/core` 财务报告和审定财务报表 `/port` → `records/entity`, (中文(简体) ), `/react` → `records/entity/react`) (中文(简体) ).

## 钻倒——宣布的定义

服务器演练( A)`platform.drill_describe` 编号 : `platform.drill_ask`)回答一个标准表格 登记册,或 **已声明定义**(单位:千美元) `*.drill.ts` 文件( 编号`declareDrillDefinition({...})`, (中文(简体) ), 形状在 `scripts/drill-definitions/ai_usage.drill.ts`汇编成每个定义的一个函数, `platform.drill_def__<key>()`维度可能携带 `level` (爆发,显示,属性, 记录);UI方面是 `useDrill` 内 `@ai-matrx/records-ui` 和表格在 `@ai-matrx/design-system` (它的README § drill - down).

| 命令( 在本包中) | 对 |
| --- | --- |
| `pnpm drill:sync --write --lane <LANE>` | 写一个活动文件( + 反向) , 用于每个活体不同的声明 |
| `pnpm drill:sync --write --lane <LANE> --only <key,key>` | 同样的,只有你的定义, 从来不是同行的半干 |
| `pnpm drill:sync --check` | 人口普查:每一份声明都健全,与其活体相当(另1个除外) |
| `pnpm drill:sync --check --only <key,key>` | 定义的普查 |
| `... --target clone` | 读取夜间拷贝而不是制作 |

`--only` 命名一个密钥, 没有宣布文件失败, 所以一个打字从不作为“ 无所事事 ” .

## 生成的一半

`src/store.generated.ts` 作者为 `pnpm records:generate` 从现场 商店自己的目录——来自商店词汇功能的词汇表, 字段类型 `custom.parity_field_types()`门从 `pg_proc`, (中文(简体) ), 来自内核行的内核id,来自 `platform.entity_types`。 。 。 . `pnpm check:store-registry` 此软件包和存储时退出非零 不同的是,另一道门是怎样加成红色支票的 而不是一个惊喜.

## 那个套房

`pnpm test` 跑向现场排练分支。 每个案子都是一个 总是在 `rollback`里面的套房打开 产品开关,只满足自己的一半需求,并设置 `request.jwt.claims` 参加运动的测试`test@test.com`)——所以每个 电话通过真正的门,真正的触发器和真正的守卫,作为一个 真实身份,然后分支是同字节(最后一个测试) 从新的连接中重新读取并证明它). 红色一半是相同的 电话没有这种状态, 由商店的信息短信断言.

## 图标

| 命令 | 它会做什么 |
| --- | --- |
| `pnpm records:generate` | 重写 `src/store.generated.ts` 从现场商店 |
| `pnpm check:store-registry` | 当软件包和商店有分歧时失败 |
| `pnpm test` | 真正的门套房 |
| `pnpm build` | {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你来干什么 `dist` (sm + cjs + d.ts),然后是客户端边界印章 |
| `pnpm check:package` | · 出口协议 |

## 常见问题

### @ai-matrx/records 是什么？

AI Matrx唱片店的无头客户端: Table / Field / Rule / Record / relations / Home 类型,从商店本身读取的已关闭的词汇和拒绝代码,打入商店门上的打字器和没有其他的,合并-field Dec

### 如何安装 @ai-matrx/records？

在项目目录运行 npm install @ai-matrx/records，或使用 pnpm add / yarn add / bun add。

### @ai-matrx/records 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @ai-matrx/records 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @ai-matrx/records 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=20。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @ai-matrx/records 可以商用吗？

@ai-matrx/records 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @ai-matrx/records 的下载量有多少？

根据 npm 官方下载统计，@ai-matrx/records 在 2026/10/05 – 2026/11/03 这 30 天内被下载 105,515 次，日均约 3,517 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @ai-matrx/records 还在维护吗？

最新版本 0\.99\.153 发布于 2026/10/30（6 天前）；至今共发布 422 个版本，其中过去 12 个月发布了 422 个；首次发布于 2026/09/19。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

