Skip to content

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

icp-cli-quickjs-plugin

An icp-cli sync plugin that runs a JavaScript script against the canister being synced. It exposes to the script roughly the same capabilities a native sync plugin has — calling the target canister, reading its metadata, setting its environment variables, the sync inputs, and read-only filesystem access — plus Candid, principal, and encoding helpers convenient for canister work.

Scripts run on QuickJS via rquickjs; it is a small ES2020-class engine without Node or Web APIs, so no require/import, no fetch, no timers — just the language plus the host functions the plugin provides.

API.md documents the scripting API in full.

Building

The plugin is a WebAssembly component targeting wasm32-wasip2:

rustup target add wasm32-wasip2
cargo build --target wasm32-wasip2 --release

The component is emitted at target/wasm32-wasip2/release/icp_js_plugin.wasm.

The crate also builds for the host, so cargo check and cargo test run without a WebAssembly runtime.

Using it

Declare the plugin as a sync step, with the entry script under the script key (or inline in a script field). Any other files declared are read by the host and handed to the script by path; directories under dirs: are preopened read-only.

sync:
  steps:
    - plugin: ./icp_js_plugin.wasm
      canisters: [ledger]
      files:
        script: sync.js
        config: config.json

A script runs to completion for a clean sync; throwing fails the step with the thrown message.

Examples

Push a list of authorized principals from a JSON file to a sibling canister:

// { "authorized": ["aaaaa-aa", "ryjl3-tyaaa-aaaaa-aaaba-cai"] }
const config = JSON.parse(files["config.json"]);

// `set_authorized : (vec principal) -> ()`. The strings out of the file are
// wrapped in `Principal.from(..)`, which both validates them and tells the encoder
// they are principals rather than text.
const authorized = config.authorized.map((p) => Principal.from(p));
callUpdate("example", "set_authorized", candid`(${authorized})`);

Or the same call written against the canister's own interface, which turns the strings into principals itself:

const config = JSON.parse(files["config.json"]);
callTyped("example", "set_authorized", config.authorized);

What a script gets

Each of these is covered in API.md:

Sync inputs canisterId, identity, environment, proxy, files, dirs, fields, canisterIds and friends, as globals.
Canister calls callQuery / callUpdate / canisterCall, against the synced canister or any canister the step declared.
Coerced calls callTyped / canisterCallTyped and CandidInterface, which encode and decode against the callee's own .did.
Candid The candid template tag, CandidArgs, candidEncode / candidDecode, the number types, and the exact-encoding classes for variants, optionals, tuples and references.
Metadata sections canisterMetadata, reading a canister's custom sections.
Environment variables canisterSetenv, setting one runtime variable on a canister.
Principals The Principal class of icp-js-core.
Helpers sha256, encodeUtf8 / decodeUtf8, and randomBytes.
Filesystem Read-only reads, predicates and joinPath over the declared dirs:.
Output print / eprint and the console methods.

License

This project is licensed under the Apache-2.0 license.

Contribution

This project does not accept external contributions. Pull requests from individuals outside the organization will be automatically closed.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages