@baukit/data-contracts

中文文档
0.18.3发布于 2026/11/07MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 9230

运行时间中性数据合同,测量辅助器,以及可执行适配器兼容性测试.

中文使用文档
文档目录10 节
  1. 使用合同
  2. 资源预算计量
  3. 限制政策文件
  4. 导入信封
  5. 出口
  6. 已修改写入
  7. 持久草案
  8. 认证分区
  9. 证明适配器
  10. 描述文件擦除

@baukit/data-contracts

运行时间中性数据合同,测量辅助器,以及可执行适配器兼容性测试.

软件包定义了 JSON 密钥/值存储,ID顺序记录存储,并用有边框的密钥集 pagination,原子交易回调,以及chema元数据/迁移常规. 它刻意包含没有产品实体,也没有Expo SQLite,Dexie,或节点数据库适配器. 船上的储能适配器是 WebStorageKeyValueStore,因为Web存储不需要依赖.

使用合同

import type { StoredRecord, TransactionalStorageStore } from '@baukit/data-contracts';

interface Note extends StoredRecord {
  title: string;
}

type NoteDatabase = TransactionalStorageStore<Note>;

TransactionalStorageStore 使筑巢和生命周期行为明确. 内召回,呼叫 withTransaction 交易范围上下文 加入环境交易。 调用根库是独立的,必须 由适配器序列化. 之后 close() 解决, 所有操作拒绝 与 StorageError.code === "storage_closed". 使用配额失败 storage_quota_exceeded;呼叫者不需要解析提供者错误文本.

KeyValueStore.clearPrefix(prefix) 删除开头的每个密钥 prefix,例如所有 一个账户的草稿,当密钥看起来像 draft:<account>:<document>。匹配为 uTF-16 代码单位精确且区分大小写, 无字符为通配符, 且前缀为空 清理商店. clear() 整个店都空了.

WebStorageKeyValueStore 是一个 KeyValueStore 结束 sessionStorage 或者说 localStorage它存储 每个值作为 JSON 文本在您通过的名称空间下, 所以 clear() 财务报告和审定财务报表 clearPrefix() 永不删除 来源的其他密钥。 空名空间丢出 RangeError。存储失败拒绝 以满载的、 StorageError.code === "storage_quota_exceeded"。 。 。 .

import { WebStorageKeyValueStore } from '@baukit/data-contracts';

const drafts = new WebStorageKeyValueStore(sessionStorage, 'app:drafts:v1:');
await drafts.set('note:new', { title: '' });
await drafts.clearPrefix('note:');

年长者 StorageTransaction 财务报告和审定财务报表 Transaction 接口仍然可用 对于只执行原始表面的适配器.

资源预算计量

进口生产计量 /limits 子路径。 检查返回测量并允许 值,或抛出 LimitExceededError 和同样的田地。 产品选择每个允许的值和 将错误映射到他们自己的原因代码中.

import {
  checkCompactJsonUtf8Bytes,
  checkTrimmedUnicodeScalars,
} from '@baukit/data-contracts/limits';

checkTrimmedUnicodeScalars('  e\u0301  ', 2);
checkCompactJsonUtf8Bytes({ value: 'é' }, 14);

文本测量修饰 White_Space 两端有相机 它没有使案文正常化. 压缩 JSON 测量接受无效的,布尔的,有限度的数,只使用scalar的字符串,密集的数组, 和纯洁的物体。 普通对象可能使用可假设的自有字符串键. 不可承担财产是: 被忽略 。 符号密钥,访问器,自定义原型,循环引用,不支持的值, 非无限数量, 和无奖代孕投掷 ResourceMeasurementError。紧凑编码器 用途 JSON.stringify 属性命令,尽管属性命令不能改变所计量的字节数.

现有的产品帮助者可以一次迁移一次呼叫. 替换 codePointLength(value.trim()) 与 trimmedUnicodeScalarCount(value)替换一个 JSON.stringify 加号 TextEncoder 字节计数 与 compactJsonUtf8Bytes(value)。不同于原始 JSON.stringify,帮助者拒绝 JSON 的值 将省略或替换为 null。 。 。 .

checkRange(measured: number, minimum: number, maximum: number): LimitRange 包括检查 边框和返回 { measured, minimum, maximum }最低值或最高值 最大抛出量 LimitOutOfRangeError 和那些田园。 所有论据都必须是安全的 整数. 倒转边框 RangeError。零和等界限是有效的.

import { checkRange, enforceLimit } from '@baukit/data-contracts/limits';

enforceLimit('intervalSeconds', 'out_of_range', () => checkRange(3600, 3600, 2678400));

enforceLimit 地图 LimitOutOfRangeError 改为 LimitRangeError,一个子类 LimitError。 。 。 . 它携带 reason: 'out_of_range', (中文(简体) ), field, (中文(简体) ), measured, (中文(简体) ), minimum,以及 maximum继承 allowed 等于 maximum 对于已读取最大限制错误的呼叫者。 无效的参数 和倒置的界限 RangeError 和通过而不成为政策拒绝.

限制政策文件

parseLimitsPolicy(value, schema) 验证产品的限制政策文件,例如 limits.json 模板生成。 计划名称为支持的版本和每个版本的密钥 节。 解析器需要字符串 $comment准确的版本 准确的章节和钥匙集, 和正安全整数。 所列密钥 allowZero 作为 section.key 还接受零。 任何其他 形状抛出 LimitsPolicyError,其信息将失败的路径命名,但绝不是一个值。 通过 计划 as const 因此结果类型跟随声明的密钥。 添加范围路径到 rangeKeys 作为 section.key。这些条目完全包含 { minimum, maximum },具有非负安全性 整数界限和 minimum <= maximum。不能在 allowZero。 。 。 .

const schema = {
  version: 1,
  sections: { text: ['max_characters'], ranges: ['interval_seconds'] },
  rangeKeys: ['ranges.interval_seconds'],
} as const;
const policy = parseLimitsPolicy({
  $comment: 'Reviewed limits.',
  version: 1,
  text: { max_characters: 200 },
  ranges: { interval_seconds: { minimum: 3600, maximum: 2678400 } },
}, schema);
// policy.ranges.interval_seconds has minimum and maximum number properties.

enforceLimit(field, reason, check) 地图 LimitExceededError 输入 LimitError,包含 reason, (中文(简体) ), field, (中文(简体) ), measured,以及 allowed。它绘制失败范围 LimitRangeError 作为 说明。 其他错误通过.

import { checkTrimmedUnicodeScalars, enforceLimit, parseLimitsPolicy } from '@baukit/data-contracts/limits';

const schema = { version: 1, sections: { text: ['max_characters'] } } as const;
const policy = parseLimitsPolicy(limitsJson, schema);

enforceLimit('title', 'text_too_long', () =>
  checkTrimmedUnicodeScalars(title, policy.text.max_characters),
);

跨领域规则,例如一个限制不得超过另一个限制,在产品代码之后保留 剖析.

导入信封

这个 /import-envelope 子路径将导入安全与产品的文件格式区分开来. 产品 解码器返回安全上下文和可移动的已命名行对象. prepareImportEnvelope 检查 调用解码器前的源字节限制, 当超过行限制时停止, 拒绝 允许列表以外的字段,检查被允许的字段内的字符串,解码每行,以及 运行产品预览规划器。 计划员接收解码行,但没有交易适配器.

import {
  commitImportEnvelope,
  prepareImportEnvelope,
} from '@baukit/data-contracts/import-envelope';

const preview = await prepareImportEnvelope({
  source,
  limits: { maxSourceBytes: 2_097_152, maxRows: 5_000, maxStringBytes: 8_192 },
  decodeEnvelope: decodeProductExport,
  fieldAllowlist: { notes: ['id', 'title', 'body'] },
  decodeRow: decodePortableRow,
  plan: planImport,
});

await commitImportEnvelope({
  preview,
  transaction: repositories,
  write: writeImportPlan,
  afterCommit: () => requestSync(),
});

解码器仍然拥有格式和计划版本,需要的字段,重复的ID,墓碑 政策和实体解码。 策划者拥有冲突,出处,以及删除顺序. commitImportEnvelope 将完整的产品写到一个后面 withTransaction 电话 它引用 afterCommit 只有在那个电话决定之后 保留 afterCommit 因为它的失败是无能的 不退缩承诺的交易.

这个API是添加剂。 现有的导入代码可以通过包装其当前解码器和预览来迁移 首先计划者,然后将写入循环移动到 commitImportEnvelope。不需要文件 格式或数据库迁移.

出口

这个 /export 子路径是导入信封的对应 . encodeCsv 将行变为 RFC 4180 CSV 字符串:每个记录以 CRLF 结尾,当其中包含逗号时引用一个单元格,双键 引文, CR, 或 LF 。 一个空单元格的一行写为 "" 所以读者仍然看到一个领域. 帮助者没有运行时间依赖性;产品将字符串写入文件并共享.

import { csvNumeric, encodeCsv } from '@baukit/data-contracts/export';

const csv = encodeCsv(
  [
    ['note', 'amount', 'price'],
    ['=HYPERLINK("https://example.test")', -5, csvNumeric('1.50')],
  ],
  { byteOrderMark: true },
);

公式在默认情况下中和 。 文本单元格在第一个时会得到一个主原子 字符为 =, (中文(简体) ), +, (中文(简体) ), -, (中文(简体) ), @,标签,或CR,或何时 =, (中文(简体) ), +, (中文(简体) ), -,或 @ 跟踪主空格, 选项卡, CR, 或 LF。 只检查这些 ASCII 字符 。 气压会改变值 所以 文档中您自己的进口商必须读取它或者用 neutralizeFormulas: false。仅对从未打开的机器读取文件使用选择退出 电子表格.

文本看起来像负数,例如 '-5',是中和的。 传递真实数字为 有限制 number 或作为 csvNumeric(text) 格式化时,例如 '1.50'数字 单元格必须与 JSON 数字语法相匹配,并且不作修改. null 是一个空单元格. byteOrderMark: true 以 U+FEFF 为电子表格程序启动输出,该电子表格程序需要它来检测 UTF-8 (英语).

默认 null 财务报告和审定财务报表 '' 两者都写出一个空域,所以读者不能将它们区分开来. 两个选择 为您自己的进口商读取的文件保留它们:

  • quoteAllCells: true 引用每个文本和数字单元格。 虚无的细胞没有被引用,所以 '' 变成 "" 财务报告和审定财务报表 null 保持空闲。 一行只保留一个空格 ""。 。 。 .
  • nullMarker: '\\N' 写入未引用的无单元格标记并引用相同的文本单元格 内容,所以 "\N" 读回为文本。 标记必须非空而无双引号, 逗号、CR和LF; encodeCsv 丢出一个 RangeError 否则.
encodeCsv([[null, '\\N', '', 'x']], { nullMarker: '\\N' }); // \N,"\N",,x
encodeCsv([[null, '', -5]], { quoteAllCells: true }); // ,"","-5"

CsvEncodeError.code 实值 invalid_numeric_cell 非无限数字或外部数字单元格 jSON语法, invalid_unicode 和未受宠的代孕者在一起 unsupported_cell 对于任何其他运行时间值。 错误带有 rowIndex 财务报告和审定财务报表 columnIndex 永远不要牢房 数值. baukit_core::export::encode_csv 在 Rust 中通过相同的向量 (单位:千美元)fixtures/export-csv/csv-encoding-v1.json) (中文(简体) ).

ShareOutcome 产品将文件交给平台后发生的事情:

  • shared: 共享表或Web Share API接受文件. 一些本地共享表报告 即使用户没有选择目标就关闭了它们.
  • saved:文件被写到用户可以打开的地方,如浏览器下载.
  • cancelled:用户解除共享或保存UI,平台也这么说,例如用一个 网络共享 AbortError。 。 。 .
  • unavailable:运行时间没有共享或保存机制,所以没有尝试.
  • failed:尝试了一种机制,并报告了取消以外的错误.

SHARE_OUTCOMES 列出相同的数值。 软件包尚未执行 Expo 或浏览器.

已修改写入

这个 /revisioned-writes 子路径每次发送一个服务器文档的编辑, 每个选中 反对修改。 它没有反应依赖。 用钩子把它包起来 useSyncExternalStore页:1 抓取对象仅在状态变化时更改 .

import { createRevisionedWriteQueue } from '@baukit/data-contracts/revisioned-writes';

const queue = createRevisionedWriteQueue({
  initial: { scope: accountId, document: noteId, acknowledgedRevision: loaded.revision },
  write: async ({ scope, document, value, expectedRevision, afterUnknownOutcome, signal }) => {
    const response = await api.saveNote(scope, document, value, {
      ifMatch: expectedRevision,
      idempotencyKey: await keyFor(document, value, expectedRevision),
      signal,
    });
    if (response.status === 409) {
      return { kind: 'conflict', currentRevision: response.revision, conflict: response.body };
    }
    if (!response.ok) {
      return { kind: 'rejected', error: response.problem };
    }
    return { kind: 'accepted', revision: response.revision };
  },
  signal: pageLifetime.signal,
});

queue.enqueue(editedValue);
await queue.flush();

该快照将两个值分开. acknowledgedRevision 是服务器的最后一个版本 已经确认. unsent 是尚未写入的本地值。 写出它所花费的值 从 unsent 经确认的修订为 expectedRevision编辑时绘制的 飞去新鲜的 unsent 状态 dirty承认老年人 值从不标出保存的较新的值。 排队编辑与 coalesce(older, newer), (中文(简体) ), 默认保存新值。 写入补丁时传递自己的功能 页:1.

enqueue 从不发送。 在产品中跳出并呼叫 flush并行 flush 呼叫共享一个 排出,当队列被闲置或被暂停时,排出排出排出即可解决快照.

书面回调报告三种结果之一:

  • accepted 存储新修订并发送下一个未发送的值.
  • rejected 表示服务器在接受之前拒绝写入. 值会回到 unsent,与较新的编辑合并,状态是 failed。 。 。 . flush 或者说 retry 又发来了.
  • conflict 以服务器的修订和冲突有效载荷暂停队列 。 没有更多的发送 直到产品调用 reset 和它相信的修订。 为了保持本地价值, reset 改为 当前服务器修改和 enqueue 又是这个值.

从回信书中扔出,或者拒绝承诺,意味着结果不明. 服务器可能 已经应用了文字并丢失了回复。 队列移动到 unknown-outcome 并保留 准确价值和预期订正 uncertain,除了较新的编辑. flush 无所事事 那个状态. retry 发送相同的值和修订版 afterUnknownOutcome: true,所以请 产品可以重用其一能键。 否则读取服务器并拨打 reset。队列永远不会 将未知结果视为在服务器接受写入之前发生的故障.

reset(next) 是账户或文档切换器的生成栅栏。 它中止当前 通过 signal 回到了召回, 放弃了不在场和不确定的状态, 并忽略 旧世代的任何后期结果. cancel() 相同,并保留队列 cancelled 直到下一个 reset终止注入 signal 选项调用 cancel。 。 。 .

状态为 cancelled, (中文(简体) ), writing, (中文(简体) ), failed, (中文(简体) ), unknown-outcome, (中文(简体) ), conflict, (中文(简体) ), dirty,或 idle输入 优先级. error 拿着 rejected 错误或抛出值.

持久草案

这个 /durable-draft 子路径在任意 KeyValueStore所以它活下来了 重新装入或崩溃 。 它没有反应依赖.

import { createDurableDraft, type DraftCodec } from '@baukit/data-contracts/durable-draft';

const noteCodec: DraftCodec<NoteDraft> = {
  version: 2,
  encode: (value) => ({ body: value.body, baseRevision: value.baseRevision }),
  decode: (value, version) => decodeNoteDraft(value, version),
};

const draft = createDurableDraft({
  store,
  key: (scope: { accountId: string; noteId: string }) =>
    `note-draft:${scope.accountId}:${scope.noteId}`,
  codec: noteCodec,
});

await draft.open({ accountId, noteId }, { body: loaded.body, baseRevision: loaded.revision });
draft.update({ body: editedBody, baseRevision: loaded.revision });
await draft.save();

储存库 { version, value }。解码器拥有该值 : encode 返回 JSON,并 decode 接收未选中的 JSON 加上存储的版本并返回 decoded, (中文(简体) ), corrupt,或 unsupported-version中验证每个字段 decode从旧版本解码的值 算作升级,所以草稿打开了脏而下一个 save 重写. 帮助者返回 unsupported-version 不打电话 decode 当存储的版本在上方 codec.version, (中文(简体) ), 财务报告和审定财务报表 corrupt 当信封不整齐或 decode 掷出. 保留服务器基础修订版或 ETag 当产品需要后期冲突检查时,在值内.

一个公开的快照有两组状态. recovery 说什么 open 已找到 : none, (中文(简体) ), restored, (中文(简体) ), corrupt, (中文(简体) ), unsupported-version,或 unavailable 当读取失败时. persistence 说什么 存储正在进行中 : loading, (中文(简体) ), idle, (中文(简体) ), saving, (中文(简体) ), clearing,或 failed。 。 。 . dirty 当 价值与存储的数值不同 localRevision 计数本地更改。 一个恢复 草案也可能是肮脏的.

open 从不写或删除。 虽然复苏 corrupt 或者说 unsupported-version, (中文(简体) ), save 决定 blocked 因此,无法读取的数据保持不变。 打电话 clear({ reason: 'discarded' }) 改为 拿开.

clear 取出删除的理由 :

  • { reason: 'submitted', localRevision } 报告服务器在本地端确认值 修订。 快照显示 submission: 'confirmed' 并保持该值可见。 如果用户 修订后编辑了已储存的草案 clear 决定 newer-edits-kept。 。 。 .
  • { reason: 'discarded' } 删除草稿, 并将值返回给 open。 。 。 .

以 a 拒绝删除失败 DraftPersistenceError 并停留在快照中作为 persistence: 'failed'在呈文之后, submission 留下来 confirmed,所以产品可以分辨 "服务器有,但本地副本可能会回来",除了"没有发送". 读,写, 删除失败使用 DraftPersistenceError 与 code: 'draft_persistence_failed' 还有一个 operation。信息从不包含密钥或值.

open 一个新的瞄准镜 栅栏前一个。 尚未开始的旧范围的储存工作 跳过并解析 stale。已经开始的工作已经完成,但不会改变新的 示意图. 所有存储工作都按顺序进行,所以从A切换到B,然后回到A读取A的最后一个 写左. close() 不保存; 调用 save 打开 pagehide 或当应用程序移动到 背景情况.

move(scope) 将开放的草案交给另一个范围。 通常的情况是"新注"草稿 服务器创建刚刚成功 :

await draft.clear({ reason: 'submitted', localRevision });
await draft.move({ accountId, noteId: created.id });

当值是脏的或来自存储, move 首先在新密钥下写入, 替换 任何存储在那里。 然后删除每个案件中的旧密钥。 价值, localRevision,以及 submission 保持原样,然后保存到新键。 腐败或不支持的草案 决定 blocked。如果写入或删除失败, move 以 DraftPersistenceError, (中文(简体) ), 草案保留在旧范围,呼吁 move 再来一遍. move 不记得在哪里 草稿不见了 如果第二个编辑器仍然持有旧范围,产品会储存自己的指针 旧范围到新范围.

isScopeActive 当几个编辑可以拥有相同范围时, 例如两个标签时, 栏杆会写 与共享租赁。 帮助者在每次写入或删除前拨打 save, (中文(简体) ), clear,以及 move,对于移动的两个范围,当排队工作开始。 当它返回错误的操作 决定 stale 而存储是不被触及的。 读书不是被围住的.

const draft = createDurableDraft({
  store,
  key: noteDraftKey,
  codec: noteCodec,
  isScopeActive: (scope) => lease.holds(scope.accountId),
});

截图通过阅读 getSnapshot() 财务报告和审定财务报表 subscribe,哪个西装 useSyncExternalStore编辑 存储值本身总是同步读取,因为 KeyValueStore 是一个同步结束 有索引的DB和SQLite. 装入状态 persistence 实值 loading与 WebStorageKeyValueStore 维持一个小任务.

认证分区

deriveScopedStoreName(namespace, subject) 修剪有长度限制的条子 身份与 SHA-256 并返回不透明名称。 浏览器和节点运行时间 globalThis.crypto.subtle。反应土著必须安装符合标准 调用默认帮助器前的 Web Crypto 复方填充, 或注入一个 ScopedPersistenceDigest; 生成的世博会模板注入 expo-crypto。 。 。 .

保留 ScopedPersistenceRegistryStore 在域数据库之外(例如, 安全 Store 或 本地 Storage . resolveScopedStore 通过一个序列化访问 注册实例并验证所有版本元数据. 格式错误、 未知版本、 不一致、 或 文摘相匹配的元数据 PersistenceIdentityMismatchError 有代码 persistence_identity_mismatch 在域名商店打开之前. 商店名称可能只属于一个登记册条目, 包括跨名称空间.

ScopedPersistenceLifecycle 立刻藏起坚固的手柄,紧紧地关上 打开另一个主题, 重置产品提供的用户扫描内存,并发布 只有开口/移入/水分。 打电话 handleSessionExpired() (单位:千美元) 终端认证过期; 它关闭和块而不创建 主题切换。 为了证明理由 profile_erased电话 handleProfileErased() 带有配置的 erase 钩. 它关闭并删除最后一个选中分区, 删除其注册项, 结束时以理由被屏蔽 profile-erased编辑 cleanup 字段为 pending 当过渡被排队或运行时, complete 在消除后或当没有分区需要消除时 failed 如果关闭或关闭 擦除失败或无 erase 钩已配置 。 这个 error 是一个提示 除非清理失败, 当它持有清理错误时。 显示清理失败 仅在 cleanup === 'failed'。寿命周期保留分区 后边上下文 clear() 或者说 handleSessionExpired(),所以可以进行符号清除 在清除事件之前 清理失败保留了登记册条目。 选择 清除对象再次保留其清理结果和错误。 同时 选择不能重开已删除的配置文件; 新配置文件 ID 打开新文件 清除后分区. 清除后保留身份账户的产品必须按键分区 服务器配置文件ID,而不是身份提供者的主题.

产品可供应 resolveStore 在保存时选择自己的商店名称 共享的关闭/重置/被推出生命周期。 解析器验证了自己的 元数据与失败关闭 。 使用 recheckServerSubjectBeforeSyncAdoption 在服务器身份之前 收养或推出箱.

RecordStore.list 命令使用 JavaScript 字符串比较来升起不可移动字符串 ID。 页面大小限于 1..MAX_PAGE_SIZE,继续光标对呼叫者来说必须是不透明的。 适配器应该执行基于上一个返回的ID的密钥集光标,而不是数字偏移,所以在光标不能在后页移动之前插入.

证明适配器

维特帮手被隔离在一个只有测试的子路径中. Vitest是有意的不是同龄人依赖,因此它从未被安装在Jest或生产消费者中. 子路径没有 default 出口条件,所以杰斯特套房不能偶然解决. 在导入子路径之前, 在适配器项目的开发依赖性中安装 Vitest, 然后注册 :

import {
  describeImportEnvelopeContract,
  describeKeyValueContract,
  describeRecordStoreContract,
  describeSchemaMetadataContract,
  describeScopedPersistenceContract,
  describeTransactionContract,
  describeTransactionalStorageContract,
} from '@baukit/data-contracts/vitest';

const makeDatabase = () => new MyAdapter();

describeKeyValueContract(() => makeDatabase().keyValues);
describeRecordStoreContract(() => makeDatabase().records);
describeTransactionContract(makeDatabase);
describeTransactionalStorageContract(makeDatabase);
describeScopedPersistenceContract(makeNamedDatabaseAdapter);
describeSchemaMetadataContract(() => makeDatabase().schemaMetadata);
describeImportEnvelopeContract(importEnvelopeOptions);

每个工厂必须归还一个新鲜而空的商店. 记录套房提供 拥有 JSON 形状 { id, label, payload } 记录。 交易执行 必须显示回调范围视图, 并显示所有回调写入 一起使用,或者如果回调/拒绝,则不使用。 更强大的复合套房 还证明了回调结果、复合物和外加箱形原子学, 重新加入、配额正常化、密切行为和同时进行 交易系列化。 测距套房证明E-F-E记录和 收发箱隔离 打开前关闭 内存重置, 腐败的注册屏蔽 服务器主体检查 终端失效 内容 适配器厂必须重开相同同名的耐用数据. 这个 包含 InMemoryStore 曝光情况 keyValues, (中文(简体) ), records,以及 schemaMetadata 名字空间本身就在每个套房测试. 进口信封套件使用呼叫器提供的固定装置和一副新鲜的吊带. 它检查畸形 文件、无写预览、字段过滤、中途失败后回滚、光标或同步 承诺后状态变化.

持久性适配器和产品特有迁移逻辑属于产品或未来适配器包. 生产进入点没有运行时间依赖关系;只有 /vitest 子路径期望消费者的维特安装.

描述文件擦除

打电话 eraseProductProfile 仅在明确用户确认后。 编曲 eraseServerProfile 与 @baukit/api-runtime/erasure, (中文(简体) ), eraseLocalPartition 与 ScopedPersistenceLifecycle.eraseActivePartition(), (中文(简体) ), 财务报告和审定财务报表 signOut auth 客户端本地会话的清理.

已完成或待收到确认已承诺删除服务器配置文件 . 两者都管理本地分区的去除,然后签出. 尚未收到的收据报告a pending 因此 UI 可以解释登录账户删除仍然 结束。 当服务器运行时, 其操作 ID 可以无效 profile_erased 围栏 在不暴露行动身份的情况下确认犯罪.

一个明确的服务器故障或模糊的结果保留了本地数据和 届会。 重审一项含混不清的要求,即持续存在的一能钥匙. 服务器上钩前的故障仍然是安全的诊断警告. 局部失败 仍在尝试退出并报告两次失败;退出失败将保持不变 可见。 无论是清理失败, 都不应该触发新的服务器删除 .

版本与发布记录

@baukit/data-contracts 共发布 67 个版本,首次发布于 2026/08/26;过去 12 个月发布了 67 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.18.3latest2026/11/07今天
0.18.22026/11/061 天前
0.18.12026/11/062 天前
0.18.02026/11/052 天前
0.17.12026/11/034 天前
0.17.02026/11/025 天前

关于 @baukit/data-contracts 的常见问题

@baukit/data-contracts 是什么?

运行时间中性数据合同,测量辅助器,以及可执行适配器兼容性测试.

如何安装 @baukit/data-contracts?

在项目目录运行 npm install @baukit/data-contracts,或使用 pnpm add / yarn add / bun add。

@baukit/data-contracts 支持 TypeScript 吗?

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

@baukit/data-contracts 支持 ESM 还是 CommonJS?

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

@baukit/data-contracts 需要什么版本的 Node.js?

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

@baukit/data-contracts 可以商用吗?

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

@baukit/data-contracts 的下载量有多少?

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

@baukit/data-contracts 还在维护吗?

最新版本 0.18.3 发布于 2026/11/07(今天);至今共发布 67 个版本,其中过去 12 个月发布了 67 个;首次发布于 2026/08/26。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。