feat(codec): implement Candid schema parser and codegen renderer#186
feat(codec): implement Candid schema parser and codegen renderer#186b3hr4d wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 67226dcfaf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } else { | ||
| let fields_json: Vec<String> = fields.iter().map(|f| { | ||
| let label = match &*f.id { | ||
| candid_parser::candid::types::Label::Id(id) => id.to_string(), |
There was a problem hiding this comment.
Preserve explicit numeric Candid field IDs
When a DID uses explicit numeric labels in a non-tuple record/variant (e.g. record { 0 : nat; name : text }), this converts Label::Id(0) to the schema name "0". The renderer then emits a normal property "0": ...; @icp-sdk/core hashes that string label instead of treating it as field id 0 (numeric IDs are represented as _0_ in the JS IDL), so the generated codec is wire-incompatible for those records/variants. Preserve the label kind or encode numeric labels in the form the IDL builder expects.
Useful? React with 👍 / 👎.
| } else if (method.returns.length === 1) { | ||
| retCode = `, ${renderType(method.returns[0], " ")}` | ||
| } else { | ||
| retCode = `, c.tuple([${method.returns.map((r) => renderType(r, " ")).join(", ")}])` |
There was a problem hiding this comment.
Represent multi-value returns as separate returns
For methods with more than one return value, this emits a single c.tuple(...) return codec. CandidServiceCodec.toIDL() always wraps returnCodec.toIDL() in a one-element returns array, so a DID like m : () -> (nat, text) becomes [IDL.Tuple(IDL.Nat, IDL.Text)] instead of [IDL.Nat, IDL.Text]; actors generated from this codec will have the wrong Candid signature for real multi-return methods.
Useful? React with 👍 / 👎.
| if (visiting.has(name)) { | ||
| // Cycle detected: break cycle and return | ||
| return |
There was a problem hiding this comment.
Handle recursive type references lazily
When a schema contains a recursive type (for example type Node = record { next : opt Node }), breaking the DFS cycle here still lets rendering emit export const Node = c.record({ next: c.opt(Node) }). That reference is evaluated while Node is in its temporal dead zone, so importing the generated module throws before any codec can be used; cycles need a lazy/recursive codec representation or should be rejected instead of sorted eagerly.
Useful? React with 👍 / 👎.
This PR implements Slices 2 & 3 of the Candid Codec API:
Slice 3 (Parser Schema):
@ic-reactor/parser.Slice 2 (Codegen Renderer):
@ic-reactor/codegen.@ic-reactor/codschema builders and types.Playground Integration:
parseDidandgenerateCodecDeclarationsAPIs.