# @classytic/repo-core 中文文档

规范地址：https://npmcn.com/package/%40classytic/repo-core/

版本：0\.38\.0
npm 元数据更新时间：2026-11-03T16:17:17.503Z
中文译文更新时间：2026-11-09T23:57:44.022Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40classytic/repo-core
原文对照：https://npmcn.com/package/%40classytic/repo-core/?lang=original
项目主页：https://github.com/classytic/repo-core#readme
源码仓库：https://github.com/classytic/repo-core

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

- 包体积（解压后）：1 MB，242 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22
- 运行依赖：0 个
- peer 依赖：fast-check ^4\.10\.2
- 首次发布：2026-04-19T21:37:34.749Z
- 最新版本发布：2026-11-03T16:17:17.341Z
- 近 30 天下载量：3555（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：43（近 12 个月 43 个）

## 中文简介

驱动-不可知寄存器原始:钩子,滤镜IR,操作,发卡,缓存合同. 蒙戈基特、斯克利特基特、克基特和棱镜基金会。 从设计上看——这里没有插件船;每个套件都有自己的.

## 安装

```sh
npm install @classytic/repo-core
```

也可以使用：`pnpm add @classytic/repo-core`、`yarn add @classytic/repo-core`、`bun add @classytic/repo-core`

## README

# @ 经典/ repo- core

[![Sponsor](https://img.shields.io/github/sponsors/classytic?style=flat-square&label=Sponsor&logo=GitHub&color=EA4AAA)](https://github.com/sponsors/classytic)

**驱动-不可知寄存器原始.** 钩子 过滤 IR、 操作注册、 页码、 URL 查询解析、 缓存合同—— 共享基础 `@classytic/mongokit`, (中文(简体) ), `@classytic/sqlitekit`,以及未来 `@classytic/pgkit` 编号 : `@classytic/prismakit`。 。 。 .

复古核心为 **工具包作者的基础设施.** 终端用户安装一个工具包(mongokit / sqlitekit),并从该命名空间导入完整的API. Repo-core是每个套件运行时间所基于的——你通常不会直接在应用代码中导入.

## 设计原则

-   **仅限无害环境管理.** `.mjs` + 键 `.d.mts` 输出。节点22+.
-   **无根桶.** 每个公共地表都是它的子路径 `exports`。直接从符号所在位置导入;未使用的模块从不输入您解析图.
-   **零运行时间依赖关系.** 没有驱动器导入到任何地方 `src/`。 。 。 .
-   **树能被建筑所震动.** `unbundle: true` 在tsdown——1:1 src-dist,没有共享块.
-   **这里没有插件 .** 每个套件都拥有自己的插件执行功能,这样它们就可以使用驱动本地特性(mongoose的内置时间戳, SQLite 触发器, Postgres) `now()`普里斯玛 `@default`) (中文(简体) ). Repo-core提供原始人包作曲: `CacheAdapter`, (中文(简体) ), `stableStringify`, (中文(简体) ), `buildTenantScope`, (中文(简体) ), `HOOK_PRIORITY`,钩状引擎,过滤器IR.

## 子路径

```ts
// Hook engine + priority constants + canonical event names. HOOK_EVENTS turns
// raw strings into compile-checked constants so typos fail at build time.
import { HOOK_EVENTS, HOOK_PRIORITY, HookEngine } from '@classytic/repo-core/hooks';

// Abstract repository base + MinimalRepo / StandardRepo contracts + plugin types.
import { RepositoryBase, type MinimalRepo, type Plugin } from '@classytic/repo-core/repository';

// Driver-agnostic filter AST — combinators (eq/and/or/in/like/between/...) + walk/match + scope helpers.
import { and, eq, gte, in_, like, buildTenantScope, matchFilter } from '@classytic/repo-core/filter';

// URL → ParsedQuery grammar. Backend frameworks (Express/Arc/Fastify) parse req.query here.
import { parseUrl } from '@classytic/repo-core/query-parser';

// Pagination primitives — cursor codec, keyset helpers, offset math, the canonical
// result types (`OffsetPaginationResult`, `KeysetPaginationResult`,
// `AggregatePaginationResult`, `PaginationResult`) and the wire helper
// `toCanonicalList()`. Single source of truth — primitives' duplicate dropped,
// mongokit/sqlitekit re-export from here.
import { encodeCursor, decodeCursor, validateKeysetSort, toCanonicalList } from '@classytic/repo-core/pagination';
import type { OffsetPaginationResult, KeysetPaginationResult, AggregatePaginationResult, PaginationResult } from '@classytic/repo-core/pagination';

// Tenant config — the canonical `TenantConfig`, `TenantStrategy`, `TenantFieldType`,
// `resolveTenantConfig`, `DEFAULT_TENANT_CONFIG`, `ResolvedTenantConfig`. Kits'
// `MultiTenantOptions extends Pick<TenantConfig, ...>`.
import { resolveTenantConfig, DEFAULT_TENANT_CONFIG } from '@classytic/repo-core/tenant';
import type { TenantConfig, ResolvedTenantConfig } from '@classytic/repo-core/tenant';

// Cache plumbing — the CacheAdapter interface every kit's cachePlugin writes against.
import { type CacheAdapter, stableStringify, createMemoryCacheAdapter } from '@classytic/repo-core/cache';

// Error contracts — `HttpError` throwable + `ErrorContract` wire shape +
// `ErrorDetail` + `ErrorCode` + `ERROR_CODES` + `toErrorContract()` +
// `statusToErrorCode()`. Single source of truth — primitives' errors module dropped,
// mongokit's local `HttpError` dropped, `ArcError implements HttpError`.
import { toErrorContract, statusToErrorCode, ERROR_CODES, createError, conservativeMongoIsDuplicateKey } from '@classytic/repo-core/errors';
import type { HttpError, ErrorContract, ErrorDetail, ErrorCode } from '@classytic/repo-core/errors';

// Error kinds: one coarse class per wire code (validation, unauthorized, forbidden,
// not_found, conflict, precondition_failed, rate_limited, unavailable, internal).
// `errorKind(code, status?)` reads the table first, then falls back to the status.
import { errorKind, ERROR_KIND_BY_CODE, type ErrorKind } from '@classytic/repo-core/errors';

// Change feed: the ChangeLogStore contract a sync engine or a replaying SSE stream
// reads, plus the in-memory reference store. See "Change feed for realtime replay".
import { MemoryChangeLogStore, CursorExpiredError, isCursorExpiredError } from '@classytic/repo-core/sync';
import type { ChangeLogStore, ChangeEntry, ChangesSinceOptions, ChangesPage } from '@classytic/repo-core/sync';

// Schema generator interface — kits ship `SchemaGenerator<TModel>` + the
// compile-time conformance assertion; arc adapters are typed against it.
import type { SchemaGenerator, SchemaGeneratorContext } from '@classytic/repo-core/schema';
import { isSchemaGenerator } from '@classytic/repo-core/schema';

// Operation registry (for arc-level policy dispatch + doc generation).
import { CORE_OP_REGISTRY, describe } from '@classytic/repo-core/operations';

// Repository hook context type (for plugin authors).
import type { RepositoryContext } from '@classytic/repo-core/context';

// Capabilities + resilience (0.6.0) — runtime feature detection, the unified
// retry/abort primitives, and the change-feed contract types.
import { withRetry, throwIfAborted } from '@classytic/repo-core/repository';
import type { RepoCapabilities, RetryPolicy, ChangeEvent, WatchOptions } from '@classytic/repo-core/repository';

// Domain events (0.6.0) — pass `events: { transport }` at construction and every
// mutating op publishes `<resource>.<verb>` through any arc-compatible transport.
import type { RepositoryEventPublisher, DomainEvent } from '@classytic/repo-core/events';

// Standard Schema validation (0.6.0) — `schema` / `updateSchema` construction
// options accept any Zod / Valibot / ArkType / Effect schema.
import { validateStandardSchema, type StandardSchemaV1 } from '@classytic/repo-core/schema';
```

**没有 `.` / 根条目.** 从确切的子路径导入——这就是保持树摇的诚实的合同.

## 示例:工具包的仓库扩展 `RepositoryBase`

```ts
import { RepositoryBase } from '@classytic/repo-core/repository';
import { compileFilter } from './my-kit-compiler.js';

export class MyKitRepository<T> extends RepositoryBase {
  // Kit-specific CRUD methods. Each routes through `_buildContext` → plugins
  // → native driver call → `_emitAfter` so every plugin (timestamp, cache,
  // multi-tenant, audit) composes identically across kits.
  async getAll(params: {...}) {
    const context = await this._buildContext('getAll', params);
    const cached = this._cachedValue(context);
    if (cached) return cached;
    const where = compileFilter(context.filters);
    const result = await this.driver.query(where);
    await this._emitAfter('getAll', context, result);
    return result;
  }
}
```

## 示例: URL – 解析查询 – 任何工具包

每个工具包的URL语法都是一样的. 前端释放出一个 URL; 交换后端 DB 不改变单个查询字符串.

```ts
import { parseUrl } from '@classytic/repo-core/query-parser';

app.get('/users', async (req, res) => {
  const parsed = parseUrl(req.query, {
    allowedFilterFields: ['email', 'role', 'active', 'createdAt'],
    fieldTypes: { active: 'boolean', createdAt: 'date' },
    maxLimit: 200,
  });
  // Works identically against any kit's repository:
  //   const page = await sqliteUserRepo.getAll(parsed);
  //   const page = await mongoUserRepo.getAll(parsed);
  res.json(await userRepo.getAll(parsed));
});
```

URL 语法 :

| 網址 | 已生产过滤器IR |
| --- | --- |
| `?status=active` | `eq('status', 'active')` |
| `?age[gte]=18&age[lt]=65` | `and(gte('age', 18), lt('age', 65))` |
| `?role[in]=admin,editor` | `in_('role', ['admin', 'editor'])` |
| `?name[contains]=john` | `like('name', '%john%')` |
| `?price[between]=10,100` | `and(gte(...), lte(...))` |
| `?deletedAt[exists]=false` | `isNull('deletedAt')` |
| `?sort=-createdAt,name` | `{ createdAt: -1, name: 1 }` 联 合 国 `.sort`(中文(简体) ) |
| `?select=name,email,-password` | `{ name: 1, email: 1, password: 0 }` |
| `?page=2&limit=50` | 解析查询上的页形字段 |
| `?after=eyJ2Ij...` | 不透明的密钥集光标 |

## 方便插件的事件名称

```ts
import { HOOK_EVENTS, HOOK_PRIORITY } from '@classytic/repo-core/hooks';

// Cross-kit plugin — works identically on mongokit, sqlitekit, pgkit, prismakit.
export function stampOrgId(orgId: string): Plugin {
  return {
    name: 'stamp-org-id',
    apply(repo) {
      repo.on(HOOK_EVENTS.BEFORE_CREATE, (ctx) => {
        if (!ctx.data?.organizationId) ctx.data = { ...ctx.data, organizationId: orgId };
      }, { priority: HOOK_PRIORITY.POLICY });
    },
  };
}
```

泰波斯喜欢 `'before:craete'` 成为编译错误。 订阅给定的套件不会放出的事件是无声的不放出(这是钩子引擎如何工作的),所以插件可以安全地为完整的标准集接线收听器.

## 能力——特征检测,而非运行时出乎意料

每个工具箱声明 `readonly capabilities: RepoCapabilities` (必须 `StandardRepo` 从0.6.0起。 手提式主机分支在启动时一次:

```ts
if (!repo.capabilities.arrayOperators) {
  // SQL kit without JSON array rewrites — model tags as a join table
}
if (repo.capabilities.aggregateOps?.percentile) {
  dashboard.enableLatencyPercentiles();
}
```

那套套间 `ConformanceFeatures` 是同一类别名—— 一个工具箱在运行时宣布的 恰恰是交叉设备组的验证.

## 配置驱动验证+事件(0.6.0)

`RepositoryBaseOptions` 遵循媒体 kit 的配置驱动激活: 通过 插槽和特性点亮; 省去它和接线是惰性的.

```ts
import { z } from 'zod';

const repo = createRepository(UserModel, {
  // Any Standard Schema validator — Zod, Valibot, ArkType, Effect.
  schema: z.object({ name: z.string().min(1), email: z.string().email() }),
  updateSchema: z.object({ name: z.string().min(1) }).partial(),

  // Any arc / primitives-compatible EventTransport. Every mutating op then
  // publishes `user.created` / `user.updated` / `user.deleted` / ...
  events: { transport: redisTransport, source: 'commerce' },
});
```

验证运行于 `HOOK_PRIORITY.VALIDATION` (150) — 政策插件之后 (有租户印出字段),缓存前. 事件出版从未 操作失败; 向 `error:events` 钩.

> **警告 - 弧形主机 :** 这些是相同的事件名称 `@classytic/arc`是因为 `eventStrategy: 'auto'` 发射 连接回波级桥和弧 用于一个资源双publishes的自动事件无声( arc 双publish) dev-warn 无法看到 repo 层). 每个资源选择一层.

## 更改实时重播的种子

`@classytic/repo-core/sync` 出口 `ChangeLogStore` 合同:仅是附件、承诺命令的文档更改种子。 同步引擎拉动它;服务器发送事件流可以重放它,所以重新连接的客户端 `Last-Event-ID` (条目: `cursor`)在光标后获得每个更改,因为每个文档的最新状态如果种子是压缩的. `MemoryChangeLogStore` 是参考商店 mongokit 的 `createChangeLogStore` 是一个持久的。 证明一个商店 `runChangeLogStoreConformance` 从 `@classytic/repo-core/testing`。 。 。 .

每家店都遵守四条规则 如果有五条规则

1.  咒语很不透明,每个店都按顺序订购 绝不允许检查站经过后来实施的入境.
2.  `append(entry, { session })` 加入呼叫者的交易, 因此种子条目会以商务写入 .
3.  删除为墓碑(`op: 'delete'`,没有 `doc`),永无间隙.
4.  `since(cursor)` 不包含 `cursor` (单位:千美元)`''` 表示从开始)并按光标顺序返回条目; 页时 `hasMore`,呼应返回 `cursor`。 。 。 .
5.  执行可选的商店 `prune(before)` 保存每个文档的最新状态并返回新视野;光标比它老 `CursorExpiredError`。 。 。 .

```ts
import { isCursorExpiredError, type ChangeLogStore, type ChangesSinceOptions } from '@classytic/repo-core/sync';

// MemoryChangeLogStore and mongokit only: 16-digit cursors, or '' for "from the beginning".
const CURSOR = /^(\d{16})?$/;

type Read = Pick<ChangesSinceOptions, 'tenantId' | 'scopes' | 'sharedScopes'>;

// One pass: every entry after `from`, in cursor order. Call it on connect with Last-Event-ID,
// then on every wake-up (a timer, or a "feed changed" ping) with the cursor it returned.
// The feed is the only source of events, so the hand-off from replay to live has no gap.
async function pump(store: ChangeLogStore, from: string, read: Read, send: (e: unknown) => void) {
  // A malformed cursor, or one ahead of the head (a restored DB, a restarted memory store, a
  // forged id), resyncs: echoing it back would replay nothing until the sequence caught up.
  if (!CURSOR.test(from) || from > (await store.latestCursor())) return { resync: true } as const;
  let cursor = from;
  try {
    for (;;) {
      const page = await store.since(cursor, { ...read, limit: 500 });
      for (const entry of page.changes) send(entry); // SSE `id:` = entry.cursor
      cursor = page.cursor;
      if (!page.hasMore) return { cursor } as const;
    }
  } catch (err) {
    if (isCursorExpiredError(err)) return { resync: true } as const;
    throw err; // a failure, not a resync: see "Errors" below
  }
}
```

-   **谁能读出什么.** 构建 `read` 在服务器上,从不从请求。 租户读取 `tenantId` 从认证范围和 **未关闭** 当没有的时候: `since` 与 `tenantId: undefined` 返回两个商店中每个租户的条目,所以一个没有被选中的组织的用户会流出每个人的数据. `scopes` 财务报告和审定财务报表 `sharedScopes` 缩放`sharedScopes` 增加其他租户在这些范围中的条目,所以它们来自服务器配置或服务器侧允许列表. 平台阅读器( 否) `tenantId`)是一个单独的,有明确入门的分支,如提升或平台范围.
-   **Resync. (原始内容存档于2018-10-12).** 带着头 `latestCursor(read)` **在此之前** 客户端重新装入其快照并将其作为新的 `id:`; 继续从中可以重复快照已有的条目,这是安全的(下个点)。 抓取头部 在快照丢失的条目之间. `CursorExpiredError` (与 `isCursorExpiredError`,该匹配 `name`,因此它能幸存两个再录核拷贝在一个图中),而上面的检查失败的光标就是再录信号.
-   **至少从头开始.** 通过再连接和再同步,客户端可以两次看到一个条目. 应用条目 `(scope, docId, version)` 忽视谁 `version` 并不比持有的要新.
-   **现场直播.** 如果中枢从feed以外的地方推动直播事件(arc事件,一个酒吧/子消息),它们不会携带feed光标和SSE `id:` 无法保持一致。 民意调查 `since` 作为活源(上),或订阅活的种子条目,先缓冲,再播放,再放下缓冲条目 `cursor` 实值 `<=` 最后一个重播.
-   **错误.** 任何其他 `since` 错误是失败: 在服务器上登录原因, 发送固定的 `{ code, message }` (例如 `internal_error` 并关闭。 永远不要回声错误 : `CursorExpiredError` 而mongokit的光标错误嵌入了客户端的生光标,驱动程序错误可以命名收藏,索引和查询形状.
-   **固定宽光标.** `MemoryChangeLogStore` 和mongokit薄荷 16位零加序号,所以 `CURSOR` 而简单的字符串比较对他们是有用的。 其他商店可能不会:将光标视为不透明,除非您知道该商店. 比起未过滤器 `latestCursor()`: 一个被过滤后的头可以坐在光标后面 a `sharedScopes` 读者合法持有.
-   **不要在记忆和梦幻中磨蹭.** `MemoryChangeLogStore` 没有 `prune`,所以它从来没有扔 `CursorExpiredError`;用于测试和dev,而不是证明再同步路径. 它的序列随过程以零重新开始. Mongokit的店铺契约 `compactSuperseded` (没有地平线)并且也没有抛出它,所以读者也应该封住它回放多远.
-   **最新状态,不是每个过渡.** 之后 `prune` (或梦幻怪兽) `compactSuperseded`) 重放输出每个文档的最新条目。 需要每一个过渡的读者决不能缩小这一范围.

## 输入结果额外

```ts
import type { OffsetPaginationResult } from '@classytic/repo-core/pagination';

// Kit adds a typed surface-level extra without breaking cross-kit substitutability.
type MongokitPage<T> = OffsetPaginationResult<T, { warning?: string }>;

function render(page: MongokitPage<User>) {
  if (page.warning) showBanner(page.warning);
  return page.docs.map(userRow);
}
```

默认 `TExtra` 实值 `Record<string, never>` —— 说 `OffsetPaginationResult<User>` 前后行为相同; 通用可随意忽略.

## 状态

**v. 6.0 — 标准化发布.** 需求 `RepoCapabilities` 特性 检测( 与 `ConformanceFeatures`),标准Schema验证 插槽、域活性排放(`/events`, (中文(简体) ), `watch()` 换食合同, 统一 `RetryPolicy` + 键 `signal` 取消,和 `recordToFilter` 从每个孩子的拷贝中晋升.

由下列人士组成:

-   `@classytic/mongokit` 3.16 — `Repository extends RepositoryBase`; 声明 `MONGOKIT_CAPABILITIES`; 执行 `watch()` 通过更改流; 钩子引擎, 插件顺序验证器, `HOOK_PRIORITY`,页码+ `HttpError` 键入所有源代码。 蒙哥克特自己来的 `QueryParser` 保持独立.
-   `@classytic/sqlitekit` ≥0.6 - `SqliteRepository extends RepositoryBase`; 声明 `SQLITEKIT_CAPABILITIES`; Filter IR 编译为 Drizzle / 原始 SQL 本土; `recordToFilter` 从这里消耗.
-   `@classytic/arc` 2.12 - 适配器对准 `SchemaGenerator<TModel>`· ; `ArcError implements HttpError`; 页形接线信封(`method` 歧视者) `toCanonicalList()` 与 `reply.sendList()`。 。 。 .

见 [INFRA.md (英语)](https://npmcn.com/package/%40classytic/repo-core/INFRA.md) 用于建筑原则、子路径图、建造/工具决定和pgkit/棱镜路线图.

见 [文件/数据寿命周期.md](https://npmcn.com/package/%40classytic/repo-core/docs/data-lifecycle.md) 10亿册——保留/TTL, `archiveByFilter` 冷藏取出, `cursor()` 流线扫描、房客清洗、分配钥匙警卫和每后端的硬化/分块/后置游戏本(工具包拥有的与数据库拥有的).

## 许可证

麻省理工学院——见 [自由主义](https://npmcn.com/package/%40classytic/repo-core/LICENSE)。 。 。 .

## 商标

密码是麻省理工学院许可的. **"classytic","arc",并标志为: 经典专卖局长** 并且现在 **没有** 根据麻省理工学院颁发的许可证——见 [贸易商](https://npmcn.com/package/%40classytic/repo-core/TRADEMARK.md)。 。 。 . 叉子必须更名;许可证覆盖了代码,而不是品牌.

## 常见问题

### @classytic/repo-core 是什么？

驱动-不可知寄存器原始:钩子,滤镜IR,操作,发卡,缓存合同\. 蒙戈基特、斯克利特基特、克基特和棱镜基金会。 从设计上看——这里没有插件船;每个套件都有自己的\.

### 如何安装 @classytic/repo-core？

在项目目录运行 npm install @classytic/repo-core，或使用 pnpm add / yarn add / bun add。

### @classytic/repo-core 支持 TypeScript 吗？

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

### @classytic/repo-core 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @classytic/repo-core 需要什么版本的 Node\.js？

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

### @classytic/repo-core 可以商用吗？

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

### @classytic/repo-core 的下载量有多少？

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

### @classytic/repo-core 还在维护吗？

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

