@ candid- core/ schema
一个 Zod 风格的运行时间 不错,驱动器 实心条子 合同模型:具有静态推论、结构验证、, a TypeScript-native Candid 二进制解码器, 以及一个装入器, 构造相同的 运行时从合同文件中发出的计划。 只有坎迪地层—— 呼叫弹匣( 运输、 身份、 演员) 属于您的层 在上面继续发展(下级) (中文(简体) ).
npm install --save-exact @candid-core/schema
这就是整个安装:没有运行时间依赖关系,也没有同行,主 处理包括(主要价值 页:1.
0.5.0,无
latest释放. 这个README描述为0.5.0. 升级 从0.4.0起,在运行时间没有任何变化,只有一条省略规则:schemaFromContract,并仅解码于 类型级别 :decode财务报告和审定财务报表decodeArgs从./codec现在输入其 因此,从解码值变为 键入其计划不描述停止编译。 移动两个软件包 组合:@candid-core/cli0.4.0对 与准确的这个释放. 从0.3.0升级到仅添加类型WithMode财务报告和审定财务报表ModeOf,该模块 cLI自0.3.0使用后生成. 从0.2.0升级是一次突破 变化:0.2.0也出口./actor, (中文(简体) ),./transport-icp, (中文(简体) ),./forms财务报告和审定财务报表./labels,宣布可选@icp-sdk/core端点,键入主机为{ toText(): string },以及 拒绝opt opt T, (中文(简体) ),opt null财务报告和审定财务报表opt reserved保留--save-exact数字 : 包是1.0前的,所以任何微小放出都可能打破下一个,以及@candid-core/cli和它完全一个释放.
@candid-core/schema0.3 打破 0.2 API(主值为条形文字,倒塌的选项为框式,每vec nat8是一个Uint8Array,生成的模块使用新的绑定布局,并可能省略声明,以及./actor, (中文(简体) ),./transport-icp, (中文(简体) ),./forms财务报告和审定财务报表./labels子路径已去; 没有兼容层 .每一变化都记录在 更改日志,哪些船舶 在焦油丸中:自0.4.0下起
0.5.0,自0.3.0下0.5.0财务报告和审定财务报表0.4.0,并且从0.2.0 这些,0.3.0财务报告和审定财务报表0.3.0-beta.1编辑 移徙说明 从0.4.0起, (中文(简体) ), 从0.3.0 财务报告和审定财务报表 从0.2.0 显示每个断开对您的代码意味着什么 编译器显示它.
import { c, principal, type Infer } from "@candid-core/schema";
import { validate } from "@candid-core/schema/validate";
import { encode, decode } from "@candid-core/schema/codec";
const Account = c.record({ owner: c.principal, balance: c.nat });
type Account = Infer<typeof Account>; // { owner: Principal; balance: bigint }
const value: Account = { owner: principal("aaaaa-aa"), balance: 5n };
validate(Account, value); // { ok: true } | { ok: false, issues }
const encoded = encode(Account, value); // { ok: true, bytes } | { ok: false, issues }
if (encoded.ok) {
decode(Account, encoded.bytes); // { ok: true, value: Account } | { ok: false, issues }
}
模块, 每个子路径导出 :
.- 计划核心:c建筑师,Schema<in out T>(故意 以无常者发誓,Infer,而且节点接口将行走者缩小到-+resolveSchema财务报告和审定财务报表serviceMethods读回一个,因为一个计划 名称为rec间接与服务的方法是一个表, 编辑Principal类型及其principal财务报告和审定财务报表isPrincipal函数../validate——有界限,已失效的结构验证;从未投出 任何值上(密钥未知的选项对象或不是 非负式安全整数抛出TypeError,在每个子路径中:选项是 使用稳定代码和$- 根深蒂固的道路——加isResultSchema财务报告和审定财务报表unwrapResult,计划指导读取variant { ok; err }公约 下级。 。 。 ../contract- 运行时从峡谷建造同样的计划 JSON合同文件——或单一文件ContractEnvelope携带 其散列强制字段名表../codec—— Candid 二进制线条格式, 有图案导向, 有 斯克的强制关系 在解码和明确的资源预算。 已验证 双向对照参考执行的向量。 编码 字节仅依赖于数值和 Candid 类型,绝不取决于是否 计划是生成、装入或手工建造的.
validate, (中文(简体) ), encode 财务报告和审定财务报表 decode 把他们的工作放在明显的堆栈上,而不是
JavaScript 调用堆栈, 因此配置的限制是他们唯一的界限 :
默认 maxDepth * 256人在工作中拒绝敌对的深度价值或信息
和这个极限成正比, 一个值得信赖的宿主 升起它可以走一个
10万级链接列表或ICRC-3无论引擎的堆栈大小值——
一个工人的小堆积包括——每通电话都有同样的答案.
这四个是整个导出地图: 没有别的了,一条深入 dist/
包含,可导入.
校长和 @icp-sdk/core
此软件包不依赖于 @icp-sdk/core ——非运行时间,不在其
声明,而不是作为对等者——因此,所有编译和运行时没有安装SDK,严格地说
类型脚本 skipLibCheck 不包含。 校长就是他的神话
文本,所以 SDK 值在您自己的边界上转换一次,与 principal()。 。 。 .
主要价值
c.principal 类型为 Principal从根导出 :
主文本作为品牌字符串——CRC-32校验和的小写基础32和
id 字节,破折叠组合为5个,例如 "ryjl3-tyaaa-aaaaa-aaaba-cai"。 。 。 .
这个 principal 服务参考文献 Principal
我也一样。 这是双向合同:
- 你得到的东西. 解码返回条形文字本身——平面
运行时的字符串 。 因此,解码答复仍然有效
JSON.stringify联合国 主要序列化作为其文本),structuredClone财务报告和审定财务报表postMessage, (中文(简体) ), 比较与===,并起到Map键或缓存键内。 没错 不是一个SDKPrincipal实例; 需要类转换的代码 sDK的车Principal.fromText(value)。 。 。 . - 尽能所施. 没错
Principal验证和编码 接受一个其文字是空洞而拒绝其他一切的字符串—— 非词性拼写,对象为toText()一个SDKPrincipal实例——与invalid_type,两个同意的案件。 做一个 与principal(),该文本或任何东西toText()数字 :
import { c, isPrincipal, principal, type Principal } from "@candid-core/schema";
import { encode } from "@candid-core/schema/codec";
declare const sdkPrincipal: { toText(): string }; // an @icp-sdk/core Principal, say
const owner: Principal = principal(sdkPrincipal); // once, at your boundary
const ledger = principal("ryjl3-tyaaa-aaaaa-aaaba-cai");
isPrincipal("aaaaa-aa"); // true: the management canister
isPrincipal("AAAAA-AA"); // false: not canonical
encode(c.record({ owner: c.principal }), { owner }); // { ok: true, bytes }
void ledger;
principal() 拒绝而不是修复。 文字必须已经是空洞的
– 小写,每五个字符后一个破折号,别的地方,匹配
校验和, 最后一个字符中的零补丁比特, 最多29字节的代号
- 或者它会扔出 TypeError;既不是一个字符串也不是一个
对象为 toText()。 。 。 . "aaaaa-aa" (管理罐)和
"2vxsx-fae" (匿名校长)是犬科; "AAAAA-AA" 财务报告和审定财务报表
"aaaaaaa" 没有. isPrincipal 是匹配的守护者, 相同的检查
validate 财务报告和审定财务报表 encode 应用。 该品牌只存在于类型系统中,所以
字符串不能代表主机, 没有该检查, 没有运行时间
费用.
这个名字和SDK的班级一致 输入两个别名的代码:
import type { Principal as CandidPrincipal } from "@candid-core/schema"。 。 。 .
从a .did 文件
两条路由编译 Candid 源码到文档 schemaFromContract
消耗,两者都产生生成的模块所携带的精确的计数.
没有Rust工具链, @candid-core/cli
运行与 Web Assembly 相同的编译器和生成器。 它写出生成的
模块和a ContractEnvelope 文档, ./generated/service.envelope.json, (中文(简体) ),
的字节与 compile --envelope 输出如下:
# The CLI release that pairs with this one: it peers exactly 0.5.0.
npx @candid-core/[email protected] gen ./service.did -o ./generated
有"一箱一箱"是两个命令 安装编译器, meant,哪个
发表于 candid-core 在它重新命名之前。 这是1.0前,所以针
版本此发行对 :
cargo install meant --version 0.1.0 --locked
meant compile ./service.did --envelope > ./service.json
compile --envelope 打印一个自定义文档: a ContractEnvelope
守住峡谷 contract 加一个 extensions 地图
org.candid-core.field-names/v1 条目带有字段名称表。 A 类
合同仓库权威字段标签 编号,而不是文本,所以名称
旅行副带 -- -- 和信封扩展部分在运河外直播
设计身份,所以携带他们 永远不会移动一个 contract_id。 。 。 .
schemaFromContract 消耗整个文档 :
import { readFileSync } from "node:fs";
import { schemaFromContract } from "@candid-core/schema/contract";
const built = schemaFromContract(JSON.parse(readFileSync("./service.json", "utf8")));
if (!built.ok) {
throw new Error(JSON.stringify(built.issues));
}
built.schemas.Account; // one Schema per declaration, in declaration order
built.actor; // the service schema, when the document has one
built.omitted; // what was left out, and why — the list the generator reports
二文件流也起作用:平原 compile (无) --envelope)指纹
{ ok, contract, source_info }名称 [container, id, name] 三进
source_info.field_labels - 其 label.kind 实值 "named" - 通过为
页:1 names 选项与赤色 contract数字 :
import { schemaFromContract, type FieldNameEntry } from "@candid-core/schema/contract";
declare const compiled: { contract: unknown };
declare const names: FieldNameEntry[];
schemaFromContract(compiled.contract, { names });
这两条路线都产生同样的计划 和明确的
names 选项总是胜过带信封的名字——信封的表格
然后就完全不咨询.
schemas 准确持有申报 生成的模块输出
同一文件。 无法代表生成模块的声明被忽略,
利用每一个宣言和行动者方法——通过巢穴
func 财务报告和审定财务报表 service 类型,直到包含的宣布,并列出
内 omitted 作为 { kind, name, reason, via? },按生成器顺序和
及其理由代码: reserved_field_name (一个真正命名为
_N_ id渲染,作为键会读回错误的线id,
ambiguous_variant_arm, (中文(简体) ), reserved_export_name (以名称命名的声明) actor
或者说 Actor, (中文(简体) ), invalid_declaration_name (名称不是)
标识符形状),以及 references_omitted,其 via 名称省略
引用声明。 演员从不省略;只输方法
列出。 无效的文档仍然失败, 与 issues。 。 。 .
位置和数字标签无名称并被跳过;这些字段
由生态系统的 _id_ 公约,恰好是生成者制造的
他们。 每个名字——信封携带或呼叫者提供相同——都是
hash-enforce:它必须是其id的 Candid 假象,所以一个表是
关闭失败, 而不是悄悄重命名一个字段 。 完全没有通过桌子
使每个领域成为 _id_,这也是什么
compile --no-source-info 离开你.
生成的模块导入此软件包为命名空间 $,各声明
名称下的宣布类型,并绑定其计划
$- 前缀的本地出口名称,所以没有Candid 名称 - c, (中文(简体) ),
Array, (中文(简体) ), delete - 与模块本身的绑定相撞,您导入
你写的名字( e)import { Tokens, actor, type Actor } from "./ledger"),以及
一个编译器也给它们取了名。 无法成为模块类型的名称
(单位:千美元)Array, (中文(简体) ), delete保留 $ 本地类型。 这个 .did医生
注释和参数名称在导出类型上成为 JSDoc, 有记录
属性和可变武器,以及 Actor和每个
vec nat8 是一个 Uint8Array,但是其元素类型被命名.
服务及菌类参考文献
A 类 service schema 描述一个罐子界面;它不叫一个.
serviceMethods 读取其方法表——名称、模式、参数和结果
schemas——和代码将每个调用时的论据和回音转换为 Candidd
字节,这是调用层从此软件包中需要的:
import { c, principal, serviceMethods } from "@candid-core/schema";
import { encodeArgs, decodeArgs } from "@candid-core/schema/codec";
const Account = c.record({ owner: c.principal, subaccount: c.opt(c.vec(c.nat8)) });
const Ledger = c.service({
balance_of: c.func([Account], [c.nat], "query"),
});
const method = serviceMethods(Ledger).get("balance_of");
if (method !== undefined) {
const request = encodeArgs(method.args, [
{ owner: principal("aaaaa-aa"), subaccount: null },
]);
// `request.bytes` is the argument a transport sends on the `method.mode`
// path; the reply's bytes decode with `decodeArgs(method.results, reply)`.
void request;
void decodeArgs;
}
请求字节是一个声音缓存或分解键:类型表是
从 Candid 类型结构所建, 所以一个调用编码到相同的字节
其计划是否来自生成的模块,来自 schemaFromContract, (中文(简体) ),
或从 c.* 和上面的一样,无论按键排列值
拼写其地.
运输、身份、证书核查、重复和援引
已解码的 func 引用是调用层的工作, 而不是这个软件包的: 一个 func
价值 保留惰性 { principal, method } 双人 仍在生成模块
导出输入的调用接口为类型 Actor 旁边 actor
服务计划,因为 c.rec 从 a 中删除方法结构
计划 类型 ——计程带值,而不是调用——所以调用层不能
把它从 typeof。 。 。 .
每种方法 Actor 也带有其模式: 它是调用签名
与 WithMode<mode>,以及 ModeOf 将模式读回,所以一个呼叫
层可以拒绝在编译时构建读取的更新.
import type { ModeOf, WithMode } from "@candid-core/schema";
type Actor = {
fee: (() => Promise<bigint>) & WithMode<"query">;
transfer: ((amount: bigint) => Promise<void>) & WithMode<"update">;
};
type FeeMode = ModeOf<Actor["fee"]>; // "query"
标记不会改变任何东西: 呼叫签名, keyof Actor 编辑
模块的导出是相同的,一个普通的async函数仍然执行
这个方法。 一个 Actor 用手书写,没有读作整体
MethodMode 结合,模式未知.
打开 OK/err 结果
variant { ok : T; err : E } 通用罐子结果公约,以及
寻常的解码方法就是 价值 页:1
ok编号 :err 密钥——在任何记录上误射的猜测,合法携带
那些字段名称, 一个不能输入错误的有效载荷。 是否得到答复
实值 结果,每一只手臂都携带着一个图谋:
import { c, type Infer } from "@candid-core/schema";
import { isResultSchema, unwrapResult } from "@candid-core/schema/validate";
const TransferError = c.variant({
bad_fee: c.record({ expected_fee: c.nat }),
too_old: c.null,
});
const TransferResult = c.variant({ ok: c.nat, err: TransferError });
isResultSchema(TransferResult); // true
isResultSchema(c.record({ ok: c.bool, err: c.opt(c.text) })); // false: a record is not a variant
declare const reply: unknown; // whatever the call decoded to
const outcome = unwrapResult(TransferResult, reply);
if (outcome.issues) {
// Not a value of this schema at all: the issues `validate` would report.
throw new Error(outcome.issues[0].message);
} else if (outcome.ok) {
const blockIndex: bigint = outcome.value;
void blockIndex;
} else {
const failure: Infer<typeof TransferError> = outcome.error;
void failure;
}
这两种拼法都得到承认,因为 双对数字 : ok编号 :err,这是莫托克的
Result.Result 生产,以及 Ok编号 :ErrRust的直截了当的衍生物
双臂和双臂 添加一个变体
第三个臂不是结果,因为将它映射到两个州会降低一个.
赤齿臂( C)variant { ok; err : text }打开 null单曲
candid 的值 null 它声明.
一个 err 臂是一个值,而不是一个例外:一个没有投出,一个
格式错误的值以 { ok: false, issues } 而不是作为一个
也一样 一个不是结果变体的计划 实值 程序员
错误和丢弃 TypeError。 。 。 .
支持矩阵
以被包装的柏油丸来测量——文物 npm pack 生产,
采取和消费作为一种依赖性 @arethetypeswrong/cli 财务报告和审定财务报表
直接编译,不从清单中推断.
| 类型脚本 | ≥ 5.0 |
moduleResolution | node16, (中文(简体) ), nodenext, (中文(简体) ), bundler |
| 模块格式 | 仅限无害环境管理 - 没有共同JS建造船只 |
| 来自无害环境管理的节点 | ≥ 16 (行使16.20、18.20、20.19、22.12、25.9) |
节点,来自普通JS require() | ≥ 20.19 ≥ 22.12,则 await import() |
| TypeScript, 来自普通JS 工程 | ≥ 5.8 与 "module": "nodenext" |
类型脚本 5.0 是一个硬地板,它是一个 剖析 下方错误,不是
类型错误 : c.tuple 以 const 类型参数 - 5.0
特性使tuple的元素类型不会扩大——所以4.9停止在
error TS1139: Type parameter declaration expected. 内 dist/schema.d.ts
在它输入前检查任何东西.
node10 分辨率完全无法看到此软件包. 没有高层
main 或者说 types 字段,仅一个 exports 映射, 所以每次导入失败
TS2307 — TypeScript 的自带信件指示您移动到 node16, (中文(简体) ), nodenext, (中文(简体) ),
或者说 bundler。 。 。 .
支持无害环境管理本身不足以作为节点. 建设目标ES2020
并且没有下层, 所以可选的连锁 和无效的连接到达
dist/ 逐字记录——它们出现在八个单元中的四个单元中 dist/ 船舶——以及
V8 8.0 语法,14前的节点可以解析. 上面楼层是
最古老的版本 这个软件包实际上运行 而不是最古老的
可能发挥作用:16.20.2 行使和通过每一个子路径,没有比这更古老的东西
被索赔.
从普通JS,两层独立. 跑步时, require() 联 合 国
一个ES模块是节点在20.19和22.12中添加的;低于所投的
ERR_REQUIRE_ESM时 await import("@candid-core/schema") 成功时间
每个版本测试。 在类型一级,a "type": "commonjs" 项目需求
类型脚本 5.8 财务报告和审定财务报表 "module": "nodenext" —— 说 "module": "node16" 被钉住
至节点16语义,仍拒绝使用 TS1479 每测试一个编译器,
最高包括7.0.
这是故意的 没有 engines 字段两个楼层都狭窄,即:
ES2020 无害环境管理能力节点,a require(esm)- 适合通用JS的 - 和
在安装元数据时执行会发出警告,或失败
engine-strict,对于消费者则不适用. 这里有记载
换句话说.
域形( 有意决定 )
类型描述现代域,而非代理-js运行时形状: opt T 实值
T | null - 除了内在类型的选择 null (单位:千美元)opt opt T, (中文(简体) ),
opt null, (中文(简体) ), opt reserved)为 { some: T } | null这样 None, (中文(简体) ), Some(None), (中文(简体) ),
财务报告和审定财务报表 Some(Some(x)) 保留三个不同的值——变体是:
{ tag, value } 受歧视的工会 vec nat8 (单位:千美元)blob)为 Uint8Array, (中文(简体) ),
nat编号 :int64位整数为 bigint校长是他们的教条
文字, 标记 Principal 绳子.
与代理人-js值形状的相容性是一个明显的非目标,记录在
计划的问题追踪器.
核查
每一份发行都开着一个包装的消费门 上面写着:,
在上传任何信息之前: 焦油球 npm pack 在犯罪时生产
被提取到一个干净的工程,在严格的类型Script下编译
skipLibCheck 关闭并执行——根和每一个子路径导出,一个真实的
编码/验证回程。 发布步骤然后从中构建并上传
同样的承诺。 此文件中的类型脚本
由同一扇门编成, 与被包装的文物相对, 所以这里有一个例子
无法从文件包中漂移。 解码器是额外的
对照参考执行方案本身的线线进行双向核查
向量计.
证明
生成的装订、合同模式和符合要求的大门都住在
实心 寄存器; 此软件包版本独立( 前 1. 0) .
变动情况 船在焦油和记录中
释放, 编译器板条箱版本它与(meant,作为
candid-core 在它重新命名之前).