@ic-reactor/mcp 0.0.0-stage → 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.yml +108 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +77 -0
- package/.github/actions/setup-rust-wasm/action.yml +25 -0
- package/.github/dependabot.yml +107 -0
- package/.github/workflows/auth-latest.yml +67 -0
- package/.github/workflows/b3pay-site.yml +49 -0
- package/.github/workflows/ci.yml +430 -0
- package/.github/workflows/codeql.yml +41 -0
- package/.github/workflows/dependency-review.yml +68 -0
- package/.github/workflows/docs-check.yml +98 -0
- package/.github/workflows/docs.yml +265 -0
- package/.github/workflows/e2e.yml +90 -0
- package/.github/workflows/examples-published.yml +97 -0
- package/.github/workflows/release.yml +326 -0
- package/.husky/pre-commit +12 -0
- package/.prettierignore +109 -0
- package/.prettierrc +6 -0
- package/AGENTS.md +103 -0
- package/CHANGELOG.md +3268 -0
- package/CLAUDE.md +93 -0
- package/CNAME +1 -0
- package/CODE_OF_CONDUCT.md +7 -0
- package/CONTRIBUTING.md +433 -0
- package/LICENSE +21 -0
- package/README.md +2 -2
- package/SECURITY.md +74 -0
- package/b3pay-module.json +194 -0
- package/docs/.remarkrc.json +10 -0
- package/docs/README.md +64 -0
- package/docs/astro.config.mjs +205 -0
- package/docs/favicon.svg +15 -0
- package/docs/package.json +39 -0
- package/docs/public/favicon.svg +15 -0
- package/docs/public/ic-reactor-social-card.png +0 -0
- package/docs/scripts/b3pay-static.mjs +22 -0
- package/docs/scripts/check-example-docs.mjs +214 -0
- package/docs/scripts/check-links.mjs +212 -0
- package/docs/scripts/fix-dist-links.js +125 -0
- package/docs/scripts/fix-frontmatter.js +71 -0
- package/docs/scripts/remove-redundant-h1.cjs +48 -0
- package/docs/scripts/rewrite-typedoc-links.js +110 -0
- package/docs/scripts/split-index.js +69 -0
- package/docs/src/assets/ic-reactor-hero-dark.svg +23 -0
- package/docs/src/assets/ic-reactor-hero-light.svg +23 -0
- package/docs/src/assets/ic-reactor-lockup-dark.svg +15 -0
- package/docs/src/assets/ic-reactor-lockup-light.svg +15 -0
- package/docs/src/assets/ic-reactor-mark-dark.svg +14 -0
- package/docs/src/assets/ic-reactor-mark-light.svg +14 -0
- package/docs/src/assets/layers/candid-core-layer-icon-dark.svg +4 -0
- package/docs/src/assets/layers/candid-core-layer-icon-light.svg +4 -0
- package/docs/src/assets/layers/candid-profile-layer-icon-dark.svg +4 -0
- package/docs/src/assets/layers/candid-profile-layer-icon-light.svg +4 -0
- package/docs/src/assets/layers/ic-reactor-layer-icon-dark.svg +4 -0
- package/docs/src/assets/layers/ic-reactor-layer-icon-light.svg +4 -0
- package/docs/src/components/LibraryCards.astro +172 -0
- package/docs/src/components/LibraryIcon.astro +28 -0
- package/docs/src/components/SiteTitle.astro +241 -0
- package/docs/src/content/docs/404.mdx +19 -0
- package/docs/src/content/docs/build/agent-tools.mdx +593 -0
- package/docs/src/content/docs/build/icrc1-wallet.mdx +619 -0
- package/docs/src/content/docs/build/ssr-per-user.mdx +552 -0
- package/docs/src/content/docs/examples/canister-studio.mdx +95 -0
- package/docs/src/content/docs/examples/icrc-ledger.mdx +45 -0
- package/docs/src/content/docs/examples/index.mdx +38 -0
- package/docs/src/content/docs/examples/next-ssr.mdx +73 -0
- package/docs/src/content/docs/examples/node-agent-tool.mdx +80 -0
- package/docs/src/content/docs/examples/vite-wallet.mdx +71 -0
- package/docs/src/content/docs/guides/auth.mdx +1181 -0
- package/docs/src/content/docs/guides/client.mdx +551 -0
- package/docs/src/content/docs/guides/deploy.mdx +180 -0
- package/docs/src/content/docs/guides/errors.mdx +475 -0
- package/docs/src/content/docs/guides/getting-started.mdx +620 -0
- package/docs/src/content/docs/guides/reads.mdx +586 -0
- package/docs/src/content/docs/guides/ssr.mdx +529 -0
- package/docs/src/content/docs/guides/testing.mdx +401 -0
- package/docs/src/content/docs/guides/values.mdx +261 -0
- package/docs/src/content/docs/guides/vite-plugin.mdx +690 -0
- package/docs/src/content/docs/guides/writes.mdx +572 -0
- package/docs/src/content/docs/ic-reactor/index.mdx +167 -0
- package/docs/src/content/docs/index.mdx +65 -0
- package/docs/src/content/docs/migrating-from-3.mdx +535 -0
- package/docs/src/content/docs/packages/core.mdx +186 -0
- package/docs/src/content/docs/packages/mcp.mdx +163 -0
- package/docs/src/content/docs/packages/react.mdx +207 -0
- package/docs/src/content/docs/packages/vite-plugin.mdx +73 -0
- package/docs/src/content/docs/versioning.mdx +104 -0
- package/docs/src/content.config.ts +7 -0
- package/docs/src/styles/custom.css +189 -0
- package/docs/tsconfig.typedoc.json +26 -0
- package/docs/typedoc-entry.ts +17 -0
- package/docs/typedoc.json +37 -0
- package/e2e/Cargo.lock +646 -0
- package/e2e/Cargo.toml +3 -0
- package/e2e/README.md +101 -0
- package/e2e/frontends/build.mjs +94 -0
- package/e2e/frontends/index.html +10 -0
- package/e2e/global-setup.ts +65 -0
- package/e2e/icp.yaml +38 -0
- package/e2e/package.json +40 -0
- package/e2e/setup.ts +6 -0
- package/e2e/src/actor/Cargo.toml +14 -0
- package/e2e/src/actor/hello_actor.did +10 -0
- package/e2e/src/actor/src/lib.rs +73 -0
- package/e2e/src/calls.test.ts +132 -0
- package/e2e/src/declarations/hello_actor.envelope.json +175 -0
- package/e2e/src/declarations/hello_actor.ts +15 -0
- package/e2e/src/errors.test.ts +107 -0
- package/e2e/src/frontend-headers.test.ts +253 -0
- package/e2e/src/identity.test.ts +61 -0
- package/e2e/src/react.test.tsx +59 -0
- package/e2e/src/replica.ts +70 -0
- package/e2e/src/vite-env.test.ts +108 -0
- package/e2e/test.sh +47 -0
- package/e2e/tsconfig.json +20 -0
- package/e2e/tsconfig.typecheck.json +9 -0
- package/e2e/vitest.config.ts +22 -0
- package/eslint.config.mjs +100 -0
- package/evals/PREREGISTRATION.md +1346 -0
- package/evals/README.md +756 -0
- package/evals/conditions/thin/condition.json +8 -0
- package/evals/conditions/thin/docs/candid-core-cli.README.md +90 -0
- package/evals/conditions/thin/docs/candid-core-schema.README.md +339 -0
- package/evals/conditions/thin/package.json +25 -0
- package/evals/conditions/thin/starter/src/generated/icrc1.ts +57 -0
- package/evals/conditions/thin-guide/condition.json +10 -0
- package/evals/conditions/thin-guide/docs/llms.txt +292 -0
- package/evals/conditions/v3/condition.json +9 -0
- package/evals/conditions/v3/docs/ic-reactor-core.llms.txt +232 -0
- package/evals/conditions/v3/docs/ic-reactor-react.llms.txt +280 -0
- package/evals/conditions/v3/docs/llms-full.txt +1053 -0
- package/evals/conditions/v3/package.json +26 -0
- package/evals/conditions/v3/starter/src/declarations/icrc1.did.d.ts +95 -0
- package/evals/conditions/v3/starter/src/declarations/icrc1.did.js +140 -0
- package/evals/conditions/v4/PORTING.md +384 -0
- package/evals/conditions/v4/README.md +106 -0
- package/evals/conditions/v4/condition.json +5 -0
- package/evals/conditions/v4/docs/llms.txt +323 -0
- package/evals/conditions/v4/package.json +27 -0
- package/evals/conditions/v4/starter/src/generated/icrc1.ts +78 -0
- package/evals/conditions/v4-proto/condition.json +6 -0
- package/evals/conditions/v4-proto/docs/llms.txt +291 -0
- package/evals/conditions/v4-proto/lib/SHIM-NOTES.md +20 -0
- package/evals/conditions/v4-proto/lib/package.json +27 -0
- package/evals/conditions/v4-proto/lib/src/client.ts +471 -0
- package/evals/conditions/v4-proto/lib/src/errors.ts +214 -0
- package/evals/conditions/v4-proto/lib/src/index.ts +36 -0
- package/evals/conditions/v4-proto/lib/src/principal.ts +175 -0
- package/evals/conditions/v4-proto/lib/src/service.ts +69 -0
- package/evals/conditions/v4-proto/lib/src/types.ts +174 -0
- package/evals/conditions/v4-proto/lib/test/runtime.test.ts +170 -0
- package/evals/conditions/v4-proto/lib/test/tsconfig.json +10 -0
- package/evals/conditions/v4-proto/lib/test/types.test-d.ts +145 -0
- package/evals/conditions/v4-proto/lib/test/vitest.config.mjs +8 -0
- package/evals/conditions/v4-proto/lib/tsconfig.json +17 -0
- package/evals/conditions/v4-proto/package.json +26 -0
- package/evals/conditions/v4-proto/starter/src/generated/icrc1.service.ts +19 -0
- package/evals/conditions/v4-proto/starter/src/generated/icrc1.ts +57 -0
- package/evals/drive.mjs +1221 -0
- package/evals/gate.mjs +161 -0
- package/evals/harness/aggregate.mjs +534 -0
- package/evals/harness/aggregate.test.mjs +344 -0
- package/evals/harness/assemble.mjs +216 -0
- package/evals/harness/assemble.test.mjs +143 -0
- package/evals/harness/auth.mjs +91 -0
- package/evals/harness/check-docs.mjs +157 -0
- package/evals/harness/declarations/icrc1.did.d.ts +95 -0
- package/evals/harness/declarations/icrc1.did.js +140 -0
- package/evals/harness/drive-auth.test.mjs +584 -0
- package/evals/harness/drive.test.mjs +509 -0
- package/evals/harness/fake-auth.ts +67 -0
- package/evals/harness/fake-ledger.ts +178 -0
- package/evals/harness/gate-plan.mjs +104 -0
- package/evals/harness/gate-plan.test.mjs +243 -0
- package/evals/harness/icrc1.did +88 -0
- package/evals/harness/judge.mjs +63 -0
- package/evals/harness/judge.test.mjs +81 -0
- package/evals/harness/leak-scan.mjs +1373 -0
- package/evals/harness/leak-scan.test.mjs +1300 -0
- package/evals/harness/probes/amounts.ts +14 -0
- package/evals/harness/probes/node-tool.probe.ts +48 -0
- package/evals/harness/probes/probe.mjs +149 -0
- package/evals/harness/probes/react-wallet.probe.ts +96 -0
- package/evals/harness/public/support/auth.ts +38 -0
- package/evals/harness/public/support/fake-replica.d.ts +28 -0
- package/evals/harness/public/support/fake-replica.js +434 -0
- package/evals/harness/public/support/ledger.idl.d.ts +95 -0
- package/evals/harness/public/support/ledger.idl.js +140 -0
- package/evals/harness/public/support/world.ts +179 -0
- package/evals/harness/runs.mjs +139 -0
- package/evals/harness/sandbox.mjs +88 -0
- package/evals/harness/sandbox.test.mjs +134 -0
- package/evals/harness/ship.mjs +264 -0
- package/evals/harness/ship.test.mjs +552 -0
- package/evals/harness/world.ts +291 -0
- package/evals/package.json +26 -0
- package/evals/pnpm-lock.yaml +1537 -0
- package/evals/pnpm-workspace.yaml +12 -0
- package/evals/results/2026-09-30T14-22-05-924Z/pilot.json +384 -0
- package/evals/results/2026-09-30T14-22-05-924Z/pilot.rescanned.json +404 -0
- package/evals/results/2026-09-30T14-22-05-924Z/pilot.rescanned.rescored.json +404 -0
- package/evals/results/2026-09-30T14-22-05-924Z/plan.json +240 -0
- package/evals/results/2026-09-30T14-22-05-924Z/summary.json +1800 -0
- package/evals/results/2026-09-30T14-22-05-924Z/summary.rescanned.json +1843 -0
- package/evals/results/2026-09-30T14-22-05-924Z/summary.rescanned.rescored.json +2100 -0
- package/evals/results/2026-09-30T15-48-23-343Z/pilot.json +404 -0
- package/evals/results/2026-09-30T15-48-23-343Z/pilot.rescored.json +404 -0
- package/evals/results/2026-09-30T15-48-23-343Z/plan.json +242 -0
- package/evals/results/2026-09-30T15-48-23-343Z/summary.json +1843 -0
- package/evals/results/2026-09-30T15-48-23-343Z/summary.rescored.json +2195 -0
- package/evals/results/2026-10-03-beta1-gate/pilot.json +162 -0
- package/evals/results/2026-10-03-beta1-gate/plan.json +141 -0
- package/evals/results/2026-10-03-beta1-gate/summary.json +983 -0
- package/evals/results/2026-10-05-ga-gate/contaminated-run.json +55 -0
- package/evals/results/2026-10-05-ga-gate/pilot.json +162 -0
- package/evals/results/2026-10-05-ga-gate/plan.json +457 -0
- package/evals/results/2026-10-05-ga-gate/summary.json +1037 -0
- package/evals/results/2026-10-05-ga-gate/summary.rescanned.json +1037 -0
- package/evals/results/README.md +31 -0
- package/evals/runs-pilot.log +150 -0
- package/evals/runs-pilot2.log +150 -0
- package/evals/score.mjs +256 -0
- package/evals/setup.mjs +547 -0
- package/evals/tasks/node-tool/faulty/thin-accepts-exponent/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-accepts-exponent/src/index.ts +121 -0
- package/evals/tasks/node-tool/faulty/thin-anonymous-transfer/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-anonymous-transfer/src/index.ts +116 -0
- package/evals/tasks/node-tool/faulty/thin-every-reject-may-have-executed/meta.json +9 -0
- package/evals/tasks/node-tool/faulty/thin-every-reject-may-have-executed/src/index.ts +118 -0
- package/evals/tasks/node-tool/faulty/thin-fetches-root-key-off-local/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-fetches-root-key-off-local/src/index.ts +118 -0
- package/evals/tasks/node-tool/faulty/thin-ignores-root-key/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-ignores-root-key/src/index.ts +117 -0
- package/evals/tasks/node-tool/faulty/thin-misclassifies-reject-codes/meta.json +9 -0
- package/evals/tasks/node-tool/faulty/thin-misclassifies-reject-codes/src/index.ts +119 -0
- package/evals/tasks/node-tool/faulty/thin-no-nat64-cap/meta.json +9 -0
- package/evals/tasks/node-tool/faulty/thin-no-nat64-cap/src/index.ts +118 -0
- package/evals/tasks/node-tool/faulty/thin-number-amount/meta.json +10 -0
- package/evals/tasks/node-tool/faulty/thin-number-amount/src/index.ts +117 -0
- package/evals/tasks/node-tool/faulty/thin-truncates-fraction-digits/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-truncates-fraction-digits/src/index.ts +120 -0
- package/evals/tasks/node-tool/faulty/thin-unvalidated-recipient/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/thin-unvalidated-recipient/src/index.ts +118 -0
- package/evals/tasks/node-tool/faulty/v3-retry-call-errors/meta.json +11 -0
- package/evals/tasks/node-tool/faulty/v3-retry-call-errors/src/index.ts +149 -0
- package/evals/tasks/node-tool/faulty/v4-anonymous-identity-sent/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/v4-anonymous-identity-sent/src/index.ts +71 -0
- package/evals/tasks/node-tool/faulty/v4-never-may-have-executed/meta.json +9 -0
- package/evals/tasks/node-tool/faulty/v4-never-may-have-executed/src/index.ts +84 -0
- package/evals/tasks/node-tool/faulty/v4-proto-never-may-have-executed/meta.json +9 -0
- package/evals/tasks/node-tool/faulty/v4-proto-never-may-have-executed/src/index.ts +72 -0
- package/evals/tasks/node-tool/faulty/v4-proto-refuses-nat64-max/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/v4-proto-refuses-nat64-max/src/index.ts +72 -0
- package/evals/tasks/node-tool/faulty/v4-refuses-nat64-max/meta.json +5 -0
- package/evals/tasks/node-tool/faulty/v4-refuses-nat64-max/src/index.ts +84 -0
- package/evals/tasks/node-tool/hidden/node-tool.test.ts +312 -0
- package/evals/tasks/node-tool/prompt.md +55 -0
- package/evals/tasks/node-tool/prompt.minimal.md +30 -0
- package/evals/tasks/node-tool/solutions/thin/reference/src/index.ts +118 -0
- package/evals/tasks/node-tool/solutions/thin/reference-module-scope/src/index.ts +145 -0
- package/evals/tasks/node-tool/solutions/thin-guide/reference/src/index.ts +118 -0
- package/evals/tasks/node-tool/solutions/thin-guide/reference-module-scope/src/index.ts +145 -0
- package/evals/tasks/node-tool/solutions/v3/reference/src/index.ts +140 -0
- package/evals/tasks/node-tool/solutions/v3/reference-module-scope/src/index.ts +153 -0
- package/evals/tasks/node-tool/solutions/v4/reference/src/index.ts +84 -0
- package/evals/tasks/node-tool/solutions/v4/reference-module-scope/src/index.ts +105 -0
- package/evals/tasks/node-tool/solutions/v4-proto/reference/src/index.ts +72 -0
- package/evals/tasks/node-tool/solutions/v4-proto/reference-module-scope/src/index.ts +87 -0
- package/evals/tasks/node-tool/starter/src/contract.ts +31 -0
- package/evals/tasks/node-tool/starter/src/index.ts +7 -0
- package/evals/tasks/node-tool/starter/test/smoke.test.ts +22 -0
- package/evals/tasks/node-tool/starter/tsconfig.json +17 -0
- package/evals/tasks/node-tool/task.json +63 -0
- package/evals/tasks/react-wallet/faulty/thin-accepts-exponent/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-accepts-exponent/src/Wallet.tsx +216 -0
- package/evals/tasks/react-wallet/faulty/thin-anonymous-transfer/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-anonymous-transfer/src/Wallet.tsx +212 -0
- package/evals/tasks/react-wallet/faulty/thin-both-auth-buttons/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-both-auth-buttons/src/Wallet.tsx +210 -0
- package/evals/tasks/react-wallet/faulty/thin-constant-balance-key/meta.json +8 -0
- package/evals/tasks/react-wallet/faulty/thin-constant-balance-key/src/Wallet.tsx +213 -0
- package/evals/tasks/react-wallet/faulty/thin-no-nat64-cap/meta.json +9 -0
- package/evals/tasks/react-wallet/faulty/thin-no-nat64-cap/src/Wallet.tsx +213 -0
- package/evals/tasks/react-wallet/faulty/thin-number-balance/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-number-balance/src/Wallet.tsx +213 -0
- package/evals/tasks/react-wallet/faulty/thin-transfer-as-query/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-transfer-as-query/src/Wallet.tsx +254 -0
- package/evals/tasks/react-wallet/faulty/thin-truncates-fraction-digits/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-truncates-fraction-digits/src/Wallet.tsx +215 -0
- package/evals/tasks/react-wallet/faulty/thin-unguarded-balance-effect/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/thin-unguarded-balance-effect/src/Wallet.tsx +214 -0
- package/evals/tasks/react-wallet/faulty/v3-http-4xx-unknown/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v3-http-4xx-unknown/src/Wallet.tsx +224 -0
- package/evals/tasks/react-wallet/faulty/v3-mutation-retry-3/meta.json +12 -0
- package/evals/tasks/react-wallet/faulty/v3-mutation-retry-3/src/Wallet.tsx +225 -0
- package/evals/tasks/react-wallet/faulty/v3-unknown-as-error/meta.json +11 -0
- package/evals/tasks/react-wallet/faulty/v3-unknown-as-error/src/Wallet.tsx +182 -0
- package/evals/tasks/react-wallet/faulty/v4-every-reject-unknown/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-every-reject-unknown/src/Wallet.tsx +160 -0
- package/evals/tasks/react-wallet/faulty/v4-keep-previous-data/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-keep-previous-data/src/Wallet.tsx +166 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-every-reject-unknown/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-every-reject-unknown/src/Wallet.tsx +161 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-keep-previous-data/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-keep-previous-data/src/Wallet.tsx +163 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-retry-spread/meta.json +12 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-retry-spread/src/Wallet.tsx +162 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-status-not-idle/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-proto-status-not-idle/src/Wallet.tsx +163 -0
- package/evals/tasks/react-wallet/faulty/v4-retry-spread/meta.json +12 -0
- package/evals/tasks/react-wallet/faulty/v4-retry-spread/src/Wallet.tsx +163 -0
- package/evals/tasks/react-wallet/faulty/v4-status-not-idle/meta.json +5 -0
- package/evals/tasks/react-wallet/faulty/v4-status-not-idle/src/Wallet.tsx +162 -0
- package/evals/tasks/react-wallet/hidden/react-wallet.test.ts +536 -0
- package/evals/tasks/react-wallet/prompt.md +88 -0
- package/evals/tasks/react-wallet/prompt.minimal.md +51 -0
- package/evals/tasks/react-wallet/solutions/thin/reference/src/Wallet.tsx +213 -0
- package/evals/tasks/react-wallet/solutions/thin/reference-module-scope/src/Wallet.tsx +227 -0
- package/evals/tasks/react-wallet/solutions/thin-guide/reference/src/Wallet.tsx +213 -0
- package/evals/tasks/react-wallet/solutions/thin-guide/reference-module-scope/src/Wallet.tsx +227 -0
- package/evals/tasks/react-wallet/solutions/v3/reference/src/Wallet.tsx +224 -0
- package/evals/tasks/react-wallet/solutions/v3/reference-module-scope/src/Wallet.tsx +230 -0
- package/evals/tasks/react-wallet/solutions/v4/reference/src/Wallet.tsx +160 -0
- package/evals/tasks/react-wallet/solutions/v4/reference-module-scope/src/Wallet.tsx +178 -0
- package/evals/tasks/react-wallet/solutions/v4-proto/reference/src/Wallet.tsx +161 -0
- package/evals/tasks/react-wallet/solutions/v4-proto/reference-module-scope/src/Wallet.tsx +161 -0
- package/evals/tasks/react-wallet/starter/src/Wallet.tsx +12 -0
- package/evals/tasks/react-wallet/starter/src/auth.ts +16 -0
- package/evals/tasks/react-wallet/starter/src/config.ts +14 -0
- package/evals/tasks/react-wallet/starter/src/ii-auth.ts +43 -0
- package/evals/tasks/react-wallet/starter/src/main.tsx +15 -0
- package/evals/tasks/react-wallet/starter/test/smoke.test.ts +34 -0
- package/evals/tasks/react-wallet/starter/tsconfig.json +18 -0
- package/evals/tasks/react-wallet/task.json +84 -0
- package/examples/canister-studio/.stackblitzrc +4 -0
- package/examples/canister-studio/README.md +183 -0
- package/examples/canister-studio/did/ckbtc_minter.did +806 -0
- package/examples/canister-studio/did/icp_ledger.did +586 -0
- package/examples/canister-studio/did/icrc1.did +88 -0
- package/examples/canister-studio/package.json +45 -0
- package/examples/canister-studio/scripts/smoke.ts +188 -0
- package/examples/canister-studio/src/calls/CacheKeyPanel.tsx +104 -0
- package/examples/canister-studio/src/calls/ConfirmWrite.tsx +265 -0
- package/examples/canister-studio/src/calls/ErrorPanel.test.tsx +113 -0
- package/examples/canister-studio/src/calls/ErrorPanel.tsx +214 -0
- package/examples/canister-studio/src/calls/MethodRunner.test.tsx +354 -0
- package/examples/canister-studio/src/calls/MethodRunner.tsx +57 -0
- package/examples/canister-studio/src/calls/ReadRunner.tsx +244 -0
- package/examples/canister-studio/src/calls/ResendPanel.tsx +165 -0
- package/examples/canister-studio/src/calls/ShareLink.tsx +59 -0
- package/examples/canister-studio/src/calls/WriteRunner.test.tsx +678 -0
- package/examples/canister-studio/src/calls/WriteRunner.tsx +670 -0
- package/examples/canister-studio/src/calls/dedupe.ts +189 -0
- package/examples/canister-studio/src/calls/error-info.ts +168 -0
- package/examples/canister-studio/src/calls/history.test.ts +284 -0
- package/examples/canister-studio/src/calls/history.ts +287 -0
- package/examples/canister-studio/src/calls/kinds.ts +68 -0
- package/examples/canister-studio/src/calls/prepare.ts +32 -0
- package/examples/canister-studio/src/calls/query-options.ts +30 -0
- package/examples/canister-studio/src/calls/read.ts +47 -0
- package/examples/canister-studio/src/calls/readback.ts +100 -0
- package/examples/canister-studio/src/calls/record.ts +123 -0
- package/examples/canister-studio/src/calls/safe-calls.test.ts +299 -0
- package/examples/canister-studio/src/calls/share.ts +46 -0
- package/examples/canister-studio/src/calls/testing/doubles.tsx +108 -0
- package/examples/canister-studio/src/calls/testing/fixtures.ts +185 -0
- package/examples/canister-studio/src/calls/useCanisterHandle.ts +35 -0
- package/examples/canister-studio/src/canisters/ckbtc_minter.envelope.json +4228 -0
- package/examples/canister-studio/src/canisters/ckbtc_minter.ts +868 -0
- package/examples/canister-studio/src/canisters/icp_ledger.envelope.json +3454 -0
- package/examples/canister-studio/src/canisters/icp_ledger.ts +584 -0
- package/examples/canister-studio/src/canisters/icrc1.envelope.json +840 -0
- package/examples/canister-studio/src/canisters/icrc1.ts +78 -0
- package/examples/canister-studio/src/components/ActionButton.tsx +32 -0
- package/examples/canister-studio/src/components/AppHeader.tsx +83 -0
- package/examples/canister-studio/src/components/AppShell.tsx +29 -0
- package/examples/canister-studio/src/components/AuthButton.tsx +79 -0
- package/examples/canister-studio/src/components/Badge.tsx +79 -0
- package/examples/canister-studio/src/components/CanisterHeader.tsx +200 -0
- package/examples/canister-studio/src/components/CanisterJump.tsx +130 -0
- package/examples/canister-studio/src/components/Card.tsx +64 -0
- package/examples/canister-studio/src/components/Code.tsx +101 -0
- package/examples/canister-studio/src/components/CopyButton.tsx +126 -0
- package/examples/canister-studio/src/components/Disclosure.tsx +34 -0
- package/examples/canister-studio/src/components/EmptyState.tsx +34 -0
- package/examples/canister-studio/src/components/MethodList.test.tsx +137 -0
- package/examples/canister-studio/src/components/MethodList.tsx +244 -0
- package/examples/canister-studio/src/components/Notice.tsx +36 -0
- package/examples/canister-studio/src/components/ProvenanceBadge.tsx +44 -0
- package/examples/canister-studio/src/components/RouteError.tsx +42 -0
- package/examples/canister-studio/src/components/SectionBoundary.tsx +76 -0
- package/examples/canister-studio/src/components/Spinner.tsx +33 -0
- package/examples/canister-studio/src/components/Tabs.tsx +96 -0
- package/examples/canister-studio/src/components/canister/CanisterLoadFailure.test.tsx +56 -0
- package/examples/canister-studio/src/components/canister/CanisterLoadFailure.tsx +165 -0
- package/examples/canister-studio/src/components/canister/CanisterNotFound.tsx +59 -0
- package/examples/canister-studio/src/components/canister/CanisterPending.tsx +33 -0
- package/examples/canister-studio/src/components/canister/MethodOverview.tsx +93 -0
- package/examples/canister-studio/src/components/canister/MethodWorkspace.test.tsx +201 -0
- package/examples/canister-studio/src/components/canister/MethodWorkspace.tsx +187 -0
- package/examples/canister-studio/src/components/canister/shared-call.test.ts +186 -0
- package/examples/canister-studio/src/components/canister/shared-call.ts +133 -0
- package/examples/canister-studio/src/components/canister/shared-link-loader.test.ts +116 -0
- package/examples/canister-studio/src/components/canister/use-canister-page.ts +44 -0
- package/examples/canister-studio/src/components/canister/workspace-key.test.ts +27 -0
- package/examples/canister-studio/src/components/canister/workspace-key.ts +36 -0
- package/examples/canister-studio/src/components/canister-id-input.ts +69 -0
- package/examples/canister-studio/src/components/canister-names.ts +11 -0
- package/examples/canister-studio/src/components/download.ts +34 -0
- package/examples/canister-studio/src/components/fallbacks.tsx +33 -0
- package/examples/canister-studio/src/components/helpers.test.ts +107 -0
- package/examples/canister-studio/src/components/history/HistoryList.tsx +284 -0
- package/examples/canister-studio/src/components/home/FeaturedLedger.tsx +149 -0
- package/examples/canister-studio/src/components/home/OpenCanister.tsx +99 -0
- package/examples/canister-studio/src/components/home/featured.test.tsx +92 -0
- package/examples/canister-studio/src/components/home/featured.ts +64 -0
- package/examples/canister-studio/src/components/interface/CandidTab.tsx +38 -0
- package/examples/canister-studio/src/components/interface/CompatReport.tsx +92 -0
- package/examples/canister-studio/src/components/interface/CompatibilityTab.tsx +190 -0
- package/examples/canister-studio/src/components/interface/ProjectTab.tsx +196 -0
- package/examples/canister-studio/src/components/interface/TypeScriptTab.tsx +114 -0
- package/examples/canister-studio/src/components/interface/tools.test.tsx +169 -0
- package/examples/canister-studio/src/components/modes.ts +31 -0
- package/examples/canister-studio/src/components/playground/MethodPicker.tsx +67 -0
- package/examples/canister-studio/src/components/playground/PlaygroundForms.tsx +112 -0
- package/examples/canister-studio/src/components/playground/PlaygroundTools.tsx +219 -0
- package/examples/canister-studio/src/components/playground/sample.ts +43 -0
- package/examples/canister-studio/src/components/playground/target.test.tsx +86 -0
- package/examples/canister-studio/src/components/primitives.test.tsx +121 -0
- package/examples/canister-studio/src/components/provenance.ts +38 -0
- package/examples/canister-studio/src/components/route-render.test.tsx +71 -0
- package/examples/canister-studio/src/components/use-task.ts +56 -0
- package/examples/canister-studio/src/components/wallet/BalancePanel.tsx +110 -0
- package/examples/canister-studio/src/components/wallet/LedgerSummary.tsx +63 -0
- package/examples/canister-studio/src/components/wallet/MinterPanel.tsx +255 -0
- package/examples/canister-studio/src/components/wallet/SendPanel.test.tsx +297 -0
- package/examples/canister-studio/src/components/wallet/SendPanel.tsx +446 -0
- package/examples/canister-studio/src/components/wallet/ledgers.test.ts +36 -0
- package/examples/canister-studio/src/components/wallet/ledgers.ts +111 -0
- package/examples/canister-studio/src/forms/JsonPanel.tsx +157 -0
- package/examples/canister-studio/src/forms/MethodForm.test.tsx +369 -0
- package/examples/canister-studio/src/forms/MethodForm.tsx +368 -0
- package/examples/canister-studio/src/forms/TypedForm.tsx +55 -0
- package/examples/canister-studio/src/forms/context.ts +62 -0
- package/examples/canister-studio/src/forms/convert.ts +131 -0
- package/examples/canister-studio/src/forms/edge.test.ts +252 -0
- package/examples/canister-studio/src/forms/engine.test.ts +358 -0
- package/examples/canister-studio/src/forms/engine.ts +1492 -0
- package/examples/canister-studio/src/forms/fields/BytesField.tsx +210 -0
- package/examples/canister-studio/src/forms/fields/Field.tsx +106 -0
- package/examples/canister-studio/src/forms/fields/FieldShell.tsx +101 -0
- package/examples/canister-studio/src/forms/fields/Group.tsx +74 -0
- package/examples/canister-studio/src/forms/fields/ListField.tsx +256 -0
- package/examples/canister-studio/src/forms/fields/Segmented.tsx +78 -0
- package/examples/canister-studio/src/forms/fields/TimestampField.tsx +108 -0
- package/examples/canister-studio/src/forms/fields/UnitsField.tsx +119 -0
- package/examples/canister-studio/src/forms/fields/composites.tsx +389 -0
- package/examples/canister-studio/src/forms/fields/leaves.tsx +350 -0
- package/examples/canister-studio/src/forms/fields.test.tsx +396 -0
- package/examples/canister-studio/src/forms/helpers.test.ts +225 -0
- package/examples/canister-studio/src/forms/hints.ts +128 -0
- package/examples/canister-studio/src/forms/json.ts +119 -0
- package/examples/canister-studio/src/forms/parsing.test.ts +217 -0
- package/examples/canister-studio/src/forms/useMethodForm.ts +251 -0
- package/examples/canister-studio/src/interface/browser.test.ts +23 -0
- package/examples/canister-studio/src/interface/browser.ts +153 -0
- package/examples/canister-studio/src/interface/cache.ts +68 -0
- package/examples/canister-studio/src/interface/cli-cache.test.ts +155 -0
- package/examples/canister-studio/src/interface/cli-cache.ts +125 -0
- package/examples/canister-studio/src/interface/compile.server.test.ts +198 -0
- package/examples/canister-studio/src/interface/compile.server.ts +262 -0
- package/examples/canister-studio/src/interface/compile.test.ts +108 -0
- package/examples/canister-studio/src/interface/compile.ts +305 -0
- package/examples/canister-studio/src/interface/docs.test.ts +75 -0
- package/examples/canister-studio/src/interface/docs.ts +100 -0
- package/examples/canister-studio/src/interface/functions.test.ts +42 -0
- package/examples/canister-studio/src/interface/functions.ts +200 -0
- package/examples/canister-studio/src/interface/live-candid.server.ts +91 -0
- package/examples/canister-studio/src/interface/live-loader.test.ts +515 -0
- package/examples/canister-studio/src/interface/live-loader.ts +364 -0
- package/examples/canister-studio/src/interface/load.test.ts +328 -0
- package/examples/canister-studio/src/interface/load.ts +249 -0
- package/examples/canister-studio/src/interface/read-candid.test.ts +185 -0
- package/examples/canister-studio/src/interface/read-candid.ts +233 -0
- package/examples/canister-studio/src/interface/server-result.ts +42 -0
- package/examples/canister-studio/src/interface/typed.ts +68 -0
- package/examples/canister-studio/src/interface/types.ts +121 -0
- package/examples/canister-studio/src/lib/format.test.ts +107 -0
- package/examples/canister-studio/src/lib/format.ts +139 -0
- package/examples/canister-studio/src/lib/hex.test.ts +43 -0
- package/examples/canister-studio/src/lib/hex.ts +33 -0
- package/examples/canister-studio/src/lib/ids.test.ts +70 -0
- package/examples/canister-studio/src/lib/ids.ts +93 -0
- package/examples/canister-studio/src/lib/reactor.test.ts +55 -0
- package/examples/canister-studio/src/lib/reactor.ts +55 -0
- package/examples/canister-studio/src/lib/registry.test.ts +74 -0
- package/examples/canister-studio/src/lib/registry.ts +238 -0
- package/examples/canister-studio/src/lib/schema.ts +148 -0
- package/examples/canister-studio/src/routeTree.gen.ts +227 -0
- package/examples/canister-studio/src/router.test.ts +290 -0
- package/examples/canister-studio/src/router.tsx +127 -0
- package/examples/canister-studio/src/routes/__root.tsx +58 -0
- package/examples/canister-studio/src/routes/canister.$canisterId.index.tsx +172 -0
- package/examples/canister-studio/src/routes/canister.$canisterId.interface.tsx +98 -0
- package/examples/canister-studio/src/routes/canister.$canisterId.tsx +91 -0
- package/examples/canister-studio/src/routes/history.tsx +55 -0
- package/examples/canister-studio/src/routes/index.tsx +169 -0
- package/examples/canister-studio/src/routes/playground.tsx +286 -0
- package/examples/canister-studio/src/routes/safety.tsx +57 -0
- package/examples/canister-studio/src/routes/wallet.tsx +213 -0
- package/examples/canister-studio/src/safety/LabTransferForm.tsx +84 -0
- package/examples/canister-studio/src/safety/RequestLog.tsx +79 -0
- package/examples/canister-studio/src/safety/SafetyLab.test.tsx +89 -0
- package/examples/canister-studio/src/safety/SafetyLab.tsx +140 -0
- package/examples/canister-studio/src/safety/ScenarioCard.tsx +262 -0
- package/examples/canister-studio/src/safety/lab-run.ts +283 -0
- package/examples/canister-studio/src/safety/mock-ledger.test.ts +99 -0
- package/examples/canister-studio/src/safety/mock-ledger.ts +263 -0
- package/examples/canister-studio/src/safety/scenarios.test.ts +157 -0
- package/examples/canister-studio/src/safety/scenarios.ts +924 -0
- package/examples/canister-studio/src/styles.css +3453 -0
- package/examples/canister-studio/src/styles.test.ts +46 -0
- package/examples/canister-studio/src/values/CallPreview.test.tsx +86 -0
- package/examples/canister-studio/src/values/CallPreview.tsx +148 -0
- package/examples/canister-studio/src/values/ErrValueView.tsx +66 -0
- package/examples/canister-studio/src/values/Inspector.tsx +133 -0
- package/examples/canister-studio/src/values/ReplyView.test.tsx +341 -0
- package/examples/canister-studio/src/values/ReplyView.tsx +164 -0
- package/examples/canister-studio/src/values/candid-text.test.ts +516 -0
- package/examples/canister-studio/src/values/candid-text.ts +479 -0
- package/examples/canister-studio/src/values/hints.ts +58 -0
- package/examples/canister-studio/src/values/json.test.ts +66 -0
- package/examples/canister-studio/src/values/json.ts +31 -0
- package/examples/canister-studio/src/values/leaves.tsx +309 -0
- package/examples/canister-studio/src/values/schema.test.ts +123 -0
- package/examples/canister-studio/src/values/schema.ts +78 -0
- package/examples/canister-studio/src/values/test-router.tsx +21 -0
- package/examples/canister-studio/src/values/tree.tsx +670 -0
- package/examples/canister-studio/src/values/use-sha256.ts +29 -0
- package/examples/canister-studio/tsconfig.json +20 -0
- package/examples/canister-studio/vite.config.ts +50 -0
- package/examples/canister-studio/vitest.config.ts +20 -0
- package/examples/icrc-ledger/.stackblitzrc +4 -0
- package/examples/icrc-ledger/README.md +100 -0
- package/examples/icrc-ledger/ckbtc_minter.did +12 -0
- package/examples/icrc-ledger/icp_ledger.did +147 -0
- package/examples/icrc-ledger/icrc1.did +88 -0
- package/examples/icrc-ledger/index.html +13 -0
- package/examples/icrc-ledger/package.json +40 -0
- package/examples/icrc-ledger/scripts/smoke.ts +151 -0
- package/examples/icrc-ledger/src/App.tsx +71 -0
- package/examples/icrc-ledger/src/ErrorPanel.tsx +105 -0
- package/examples/icrc-ledger/src/MainnetTab.tsx +450 -0
- package/examples/icrc-ledger/src/SandboxTab.test.tsx +379 -0
- package/examples/icrc-ledger/src/SandboxTab.tsx +761 -0
- package/examples/icrc-ledger/src/blocks.test.ts +247 -0
- package/examples/icrc-ledger/src/blocks.ts +140 -0
- package/examples/icrc-ledger/src/canisters/ckbtc_minter.envelope.json +96 -0
- package/examples/icrc-ledger/src/canisters/ckbtc_minter.ts +16 -0
- package/examples/icrc-ledger/src/canisters/icp_ledger.envelope.json +690 -0
- package/examples/icrc-ledger/src/canisters/icp_ledger.ts +223 -0
- package/examples/icrc-ledger/src/canisters/icrc1.envelope.json +840 -0
- package/examples/icrc-ledger/src/canisters/icrc1.ts +78 -0
- package/examples/icrc-ledger/src/format.test.ts +41 -0
- package/examples/icrc-ledger/src/format.ts +68 -0
- package/examples/icrc-ledger/src/ledger.ts +15 -0
- package/examples/icrc-ledger/src/main.tsx +10 -0
- package/examples/icrc-ledger/src/minter.ts +16 -0
- package/examples/icrc-ledger/src/sandbox.test.ts +464 -0
- package/examples/icrc-ledger/src/sandbox.ts +281 -0
- package/examples/icrc-ledger/src/styles.css +391 -0
- package/examples/icrc-ledger/src/transfer-form.test.ts +62 -0
- package/examples/icrc-ledger/src/transfer-form.ts +97 -0
- package/examples/icrc-ledger/tsconfig.json +19 -0
- package/examples/icrc-ledger/vite.config.ts +44 -0
- package/examples/icrc-ledger/vitest.config.ts +12 -0
- package/examples/next-ssr/.stackblitzrc +4 -0
- package/examples/next-ssr/README.md +112 -0
- package/examples/next-ssr/icrc1.did +88 -0
- package/examples/next-ssr/next.config.ts +10 -0
- package/examples/next-ssr/package.json +41 -0
- package/examples/next-ssr/scripts/smoke.ts +169 -0
- package/examples/next-ssr/src/app/account/CertifiedBalances.tsx +58 -0
- package/examples/next-ssr/src/app/account/account.test.tsx +165 -0
- package/examples/next-ssr/src/app/account/page.tsx +82 -0
- package/examples/next-ssr/src/app/api/balance/[ledger]/[principal]/route.ts +10 -0
- package/examples/next-ssr/src/app/globals.css +278 -0
- package/examples/next-ssr/src/app/layout.tsx +34 -0
- package/examples/next-ssr/src/app/page.tsx +46 -0
- package/examples/next-ssr/src/app/providers.browser.test.tsx +127 -0
- package/examples/next-ssr/src/app/providers.test.tsx +73 -0
- package/examples/next-ssr/src/app/providers.tsx +60 -0
- package/examples/next-ssr/src/canisters/icrc1.envelope.json +840 -0
- package/examples/next-ssr/src/canisters/icrc1.ts +78 -0
- package/examples/next-ssr/src/components/BalanceTable.tsx +43 -0
- package/examples/next-ssr/src/components/LedgerCard.test.tsx +96 -0
- package/examples/next-ssr/src/components/LedgerCard.tsx +230 -0
- package/examples/next-ssr/src/components/LedgerError.tsx +32 -0
- package/examples/next-ssr/src/components/LedgerSections.tsx +22 -0
- package/examples/next-ssr/src/components/MyBalances.test.tsx +253 -0
- package/examples/next-ssr/src/components/MyBalances.tsx +129 -0
- package/examples/next-ssr/src/components/SessionBadge.tsx +18 -0
- package/examples/next-ssr/src/components/hydration.test.tsx +259 -0
- package/examples/next-ssr/src/components/server-data.ts +10 -0
- package/examples/next-ssr/src/format.ts +46 -0
- package/examples/next-ssr/src/ledgers.ts +38 -0
- package/examples/next-ssr/src/server/balance-route.test.ts +151 -0
- package/examples/next-ssr/src/server/balance-route.ts +157 -0
- package/examples/next-ssr/src/server/error-summary.test.ts +34 -0
- package/examples/next-ssr/src/server/error-summary.ts +37 -0
- package/examples/next-ssr/src/server/parse-owner.test.ts +39 -0
- package/examples/next-ssr/src/server/parse-owner.ts +34 -0
- package/examples/next-ssr/src/server/prefetch-ledgers.test.ts +137 -0
- package/examples/next-ssr/src/server/prefetch-ledgers.ts +70 -0
- package/examples/next-ssr/src/server/read-balances.test.ts +103 -0
- package/examples/next-ssr/src/server/read-balances.ts +78 -0
- package/examples/next-ssr/src/server/request-client.rsc.test.tsx +110 -0
- package/examples/next-ssr/src/server/request-client.ts +24 -0
- package/examples/next-ssr/src/testing/mock-ledgers.ts +115 -0
- package/examples/next-ssr/src/testing/react-server-dom-turbopack.d.ts +15 -0
- package/examples/next-ssr/src/testing/setup.ts +10 -0
- package/examples/next-ssr/tsconfig.json +31 -0
- package/examples/next-ssr/vitest.config.ts +59 -0
- package/examples/node-agent-tool/.stackblitzrc +4 -0
- package/examples/node-agent-tool/README.md +165 -0
- package/examples/node-agent-tool/icp.yaml +11 -0
- package/examples/node-agent-tool/icrc1.did +88 -0
- package/examples/node-agent-tool/package.json +32 -0
- package/examples/node-agent-tool/src/canisters/icrc1.envelope.json +840 -0
- package/examples/node-agent-tool/src/canisters/icrc1.ts +78 -0
- package/examples/node-agent-tool/src/cli.test.ts +64 -0
- package/examples/node-agent-tool/src/cli.ts +23 -0
- package/examples/node-agent-tool/src/command-line.ts +159 -0
- package/examples/node-agent-tool/src/commands/balance.ts +73 -0
- package/examples/node-agent-tool/src/commands/demo.test.ts +51 -0
- package/examples/node-agent-tool/src/commands/demo.ts +359 -0
- package/examples/node-agent-tool/src/commands/info.ts +69 -0
- package/examples/node-agent-tool/src/commands/reads.test.ts +133 -0
- package/examples/node-agent-tool/src/commands/resend.test.ts +363 -0
- package/examples/node-agent-tool/src/commands/transfer.test.ts +313 -0
- package/examples/node-agent-tool/src/commands/transfer.ts +415 -0
- package/examples/node-agent-tool/src/commands/watch.test.ts +159 -0
- package/examples/node-agent-tool/src/commands/watch.ts +135 -0
- package/examples/node-agent-tool/src/commands/whoami.ts +36 -0
- package/examples/node-agent-tool/src/context.ts +20 -0
- package/examples/node-agent-tool/src/dispatch.ts +70 -0
- package/examples/node-agent-tool/src/failure.test.ts +59 -0
- package/examples/node-agent-tool/src/failure.ts +176 -0
- package/examples/node-agent-tool/src/identity.test.ts +242 -0
- package/examples/node-agent-tool/src/identity.ts +228 -0
- package/examples/node-agent-tool/src/input.ts +110 -0
- package/examples/node-agent-tool/src/ledgers.test.ts +74 -0
- package/examples/node-agent-tool/src/ledgers.ts +62 -0
- package/examples/node-agent-tool/src/mock-ledger.ts +211 -0
- package/examples/node-agent-tool/src/network.test.ts +128 -0
- package/examples/node-agent-tool/src/network.ts +101 -0
- package/examples/node-agent-tool/src/output.test.ts +208 -0
- package/examples/node-agent-tool/src/output.ts +163 -0
- package/examples/node-agent-tool/src/run.ts +73 -0
- package/examples/node-agent-tool/src/test-kit.ts +167 -0
- package/examples/node-agent-tool/tsconfig.json +18 -0
- package/examples/node-agent-tool/vitest.config.ts +8 -0
- package/examples/vite-wallet/.stackblitzrc +4 -0
- package/examples/vite-wallet/Cargo.lock +646 -0
- package/examples/vite-wallet/Cargo.toml +5 -0
- package/examples/vite-wallet/README.md +107 -0
- package/examples/vite-wallet/backend/Cargo.toml +12 -0
- package/examples/vite-wallet/backend/backend.did +37 -0
- package/examples/vite-wallet/backend/src/lib.rs +133 -0
- package/examples/vite-wallet/icp.yaml +44 -0
- package/examples/vite-wallet/index.html +13 -0
- package/examples/vite-wallet/ledger.did +54 -0
- package/examples/vite-wallet/package.json +46 -0
- package/examples/vite-wallet/public/.ic-assets.json5 +26 -0
- package/examples/vite-wallet/scripts/faucet-args.test.ts +30 -0
- package/examples/vite-wallet/scripts/faucet-args.ts +41 -0
- package/examples/vite-wallet/scripts/faucet.ts +41 -0
- package/examples/vite-wallet/src/AddressBook.test.tsx +191 -0
- package/examples/vite-wallet/src/AddressBook.tsx +147 -0
- package/examples/vite-wallet/src/App.tsx +53 -0
- package/examples/vite-wallet/src/Balance.test.tsx +57 -0
- package/examples/vite-wallet/src/Balance.tsx +58 -0
- package/examples/vite-wallet/src/EnvironmentPanel.test.tsx +83 -0
- package/examples/vite-wallet/src/EnvironmentPanel.tsx +103 -0
- package/examples/vite-wallet/src/ErrorNote.tsx +70 -0
- package/examples/vite-wallet/src/Profile.test.tsx +145 -0
- package/examples/vite-wallet/src/Profile.tsx +92 -0
- package/examples/vite-wallet/src/SendIcp.test.tsx +231 -0
- package/examples/vite-wallet/src/SendIcp.tsx +244 -0
- package/examples/vite-wallet/src/SendToContact.test.tsx +113 -0
- package/examples/vite-wallet/src/SendToContact.tsx +102 -0
- package/examples/vite-wallet/src/SignIn.test.tsx +106 -0
- package/examples/vite-wallet/src/SignIn.tsx +120 -0
- package/examples/vite-wallet/src/Wallet.test.tsx +89 -0
- package/examples/vite-wallet/src/account-switch.test.tsx +108 -0
- package/examples/vite-wallet/src/auth/dev-accounts.test.ts +113 -0
- package/examples/vite-wallet/src/auth/dev-accounts.ts +216 -0
- package/examples/vite-wallet/src/auth/local-page.test.ts +28 -0
- package/examples/vite-wallet/src/auth/local-page.ts +20 -0
- package/examples/vite-wallet/src/auth/wallet-auth.test.ts +159 -0
- package/examples/vite-wallet/src/auth/wallet-auth.ts +131 -0
- package/examples/vite-wallet/src/canisters/backend.envelope.json +275 -0
- package/examples/vite-wallet/src/canisters/backend.ts +58 -0
- package/examples/vite-wallet/src/canisters/ledger.envelope.json +451 -0
- package/examples/vite-wallet/src/canisters/ledger.ts +56 -0
- package/examples/vite-wallet/src/client.ts +45 -0
- package/examples/vite-wallet/src/main.tsx +18 -0
- package/examples/vite-wallet/src/optimistic-contacts.ts +113 -0
- package/examples/vite-wallet/src/refusal.ts +17 -0
- package/examples/vite-wallet/src/styles.css +282 -0
- package/examples/vite-wallet/src/test/test-wallet.tsx +322 -0
- package/examples/vite-wallet/src/token.ts +50 -0
- package/examples/vite-wallet/src/transfer.test.ts +178 -0
- package/examples/vite-wallet/src/transfer.ts +110 -0
- package/examples/vite-wallet/src/use-canisters.ts +49 -0
- package/examples/vite-wallet/tsconfig.json +19 -0
- package/examples/vite-wallet/vite.config.ts +47 -0
- package/examples/vite-wallet/vitest.config.ts +17 -0
- package/package.json +9 -4
- package/packages/core/.size-limit.js +47 -0
- package/packages/core/LICENSE +21 -0
- package/packages/core/README.md +84 -0
- package/packages/core/llms.txt +610 -0
- package/packages/core/package.json +89 -0
- package/packages/core/src/call.ts +961 -0
- package/packages/core/src/canister.ts +259 -0
- package/packages/core/src/client.ts +2061 -0
- package/packages/core/src/errors.ts +1079 -0
- package/packages/core/src/hydration.ts +239 -0
- package/packages/core/src/index.ts +23 -0
- package/packages/core/src/keys.ts +108 -0
- package/packages/core/src/management.ts +138 -0
- package/packages/core/src/network.ts +1020 -0
- package/packages/core/src/options.ts +1000 -0
- package/packages/core/src/runtime.ts +50 -0
- package/packages/core/src/testing/fake-replica.ts +1166 -0
- package/packages/core/src/testing/index.ts +16 -0
- package/packages/core/src/testing/test-auth.ts +340 -0
- package/packages/core/src/testing/test-client.ts +559 -0
- package/packages/core/src/types.ts +541 -0
- package/packages/core/src/units.ts +299 -0
- package/packages/core/src/version.ts +4 -0
- package/packages/core/tests/canister-helpers.ts +187 -0
- package/packages/core/tests/canister-id.test.ts +158 -0
- package/packages/core/tests/canister-unwrap.test.ts +94 -0
- package/packages/core/tests/canister.test-d.ts +406 -0
- package/packages/core/tests/canister.test.ts +1921 -0
- package/packages/core/tests/client-account-change.test.ts +131 -0
- package/packages/core/tests/client-agents.test.ts +402 -0
- package/packages/core/tests/client-auth-network.test.ts +719 -0
- package/packages/core/tests/client-disposed.test.ts +403 -0
- package/packages/core/tests/client-helpers.ts +136 -0
- package/packages/core/tests/client-hydration.test.ts +166 -0
- package/packages/core/tests/client-pinned.test.ts +626 -0
- package/packages/core/tests/client-session.test.ts +348 -0
- package/packages/core/tests/client.test-d.ts +181 -0
- package/packages/core/tests/client.test.ts +1162 -0
- package/packages/core/tests/encode.test.ts +171 -0
- package/packages/core/tests/env-canister-id.test.ts +666 -0
- package/packages/core/tests/env-cookie-copies.test.ts +182 -0
- package/packages/core/tests/error-guard.test.ts +222 -0
- package/packages/core/tests/errors.test-d.ts +280 -0
- package/packages/core/tests/errors.test.ts +1359 -0
- package/packages/core/tests/fixtures/README.md +28 -0
- package/packages/core/tests/fixtures/accounts.did +21 -0
- package/packages/core/tests/fixtures/accounts.envelope.json +367 -0
- package/packages/core/tests/fixtures/accounts.ts +26 -0
- package/packages/core/tests/fixtures/archive.did +31 -0
- package/packages/core/tests/fixtures/archive.envelope.json +259 -0
- package/packages/core/tests/fixtures/archive.ts +55 -0
- package/packages/core/tests/fixtures/icrc1.did +88 -0
- package/packages/core/tests/fixtures/icrc1.envelope.json +840 -0
- package/packages/core/tests/fixtures/icrc1.ts +78 -0
- package/packages/core/tests/fixtures/management.did +724 -0
- package/packages/core/tests/fixtures/management.envelope.json +4455 -0
- package/packages/core/tests/fixtures/management.ts +486 -0
- package/packages/core/tests/fixtures/shapes.did +33 -0
- package/packages/core/tests/fixtures/shapes.envelope.json +440 -0
- package/packages/core/tests/fixtures/shapes.ts +56 -0
- package/packages/core/tests/fixtures/skippable.did +15 -0
- package/packages/core/tests/fixtures/skippable.envelope.json +182 -0
- package/packages/core/tests/fixtures/skippable.ts +33 -0
- package/packages/core/tests/func.test.ts +154 -0
- package/packages/core/tests/identity-attributes.test.ts +214 -0
- package/packages/core/tests/keys.test.ts +289 -0
- package/packages/core/tests/management.test.ts +206 -0
- package/packages/core/tests/network-helpers.ts +121 -0
- package/packages/core/tests/network.test-d.ts +78 -0
- package/packages/core/tests/network.test.ts +1051 -0
- package/packages/core/tests/options.test.ts +1594 -0
- package/packages/core/tests/redirect-sign-in.test.ts +393 -0
- package/packages/core/tests/resend.test-d.ts +81 -0
- package/packages/core/tests/resend.test.ts +723 -0
- package/packages/core/tests/skip.test-d.ts +125 -0
- package/packages/core/tests/testing-entry.test.ts +73 -0
- package/packages/core/tests/testing-fake-replica.test.ts +1242 -0
- package/packages/core/tests/testing-test-auth.test-d.ts +84 -0
- package/packages/core/tests/testing-test-auth.test.ts +483 -0
- package/packages/core/tests/testing-test-client.test-d.ts +184 -0
- package/packages/core/tests/testing-test-client.test.ts +1272 -0
- package/packages/core/tests/time-realm.test.ts +63 -0
- package/packages/core/tests/time.test.ts +238 -0
- package/packages/core/tests/traps/README.md +39 -0
- package/packages/core/tests/traps/anonymous-write.test.ts +145 -0
- package/packages/core/tests/traps/classification-table.test.ts +256 -0
- package/packages/core/tests/traps/err-arm.test.ts +144 -0
- package/packages/core/tests/traps/fetch-spy.ts +39 -0
- package/packages/core/tests/traps/invalidation-after-write.test.ts +178 -0
- package/packages/core/tests/traps/ledger.ts +248 -0
- package/packages/core/tests/traps/root-key-off-local.test.ts +130 -0
- package/packages/core/tests/traps/stale-data-across-users.test.ts +173 -0
- package/packages/core/tests/traps/unresolved-name.test.ts +155 -0
- package/packages/core/tests/traps/update-as-query.test.ts +244 -0
- package/packages/core/tests/traps/update-not-resent.test.ts +126 -0
- package/packages/core/tests/traps/update-resent-when-never-delivered.test.ts +159 -0
- package/packages/core/tests/traps.test-d.ts +476 -0
- package/packages/core/tests/units.test-d.ts +118 -0
- package/packages/core/tests/units.test.ts +634 -0
- package/packages/core/tsconfig.json +19 -0
- package/packages/core/tsconfig.typecheck.json +16 -0
- package/packages/core/vitest.config.ts +13 -0
- package/packages/mcp/LICENSE +21 -0
- package/packages/mcp/README.md +189 -0
- package/packages/mcp/package.json +62 -0
- package/packages/mcp/src/candid/candid-text.test.ts +455 -0
- package/packages/mcp/src/candid/candid-text.ts +501 -0
- package/packages/mcp/src/candid/contract.test.ts +398 -0
- package/packages/mcp/src/candid/formats.ts +155 -0
- package/packages/mcp/src/candid/hex.ts +29 -0
- package/packages/mcp/src/candid/json-schema.test.ts +758 -0
- package/packages/mcp/src/candid/json-schema.ts +454 -0
- package/packages/mcp/src/candid/json.test.ts +1207 -0
- package/packages/mcp/src/candid/json.ts +1053 -0
- package/packages/mcp/src/candid/schema-walk.ts +189 -0
- package/packages/mcp/src/candid/type-text.test.ts +179 -0
- package/packages/mcp/src/candid/type-text.ts +238 -0
- package/packages/mcp/src/cli.ts +134 -0
- package/packages/mcp/src/identity.ts +188 -0
- package/packages/mcp/src/interface/cache.test.ts +48 -0
- package/packages/mcp/src/interface/cache.ts +68 -0
- package/packages/mcp/src/interface/cli-cache.test.ts +150 -0
- package/packages/mcp/src/interface/cli-cache.ts +122 -0
- package/packages/mcp/src/interface/compile-worker.test.ts +246 -0
- package/packages/mcp/src/interface/compile-worker.ts +290 -0
- package/packages/mcp/src/interface/compile.test.ts +155 -0
- package/packages/mcp/src/interface/compile.ts +281 -0
- package/packages/mcp/src/interface/docs.test.ts +105 -0
- package/packages/mcp/src/interface/docs.ts +86 -0
- package/packages/mcp/src/interface/fixtures/icrc1.did +88 -0
- package/packages/mcp/src/interface/hex.ts +8 -0
- package/packages/mcp/src/interface/ids.test.ts +71 -0
- package/packages/mcp/src/interface/ids.ts +87 -0
- package/packages/mcp/src/interface/loader.test.ts +804 -0
- package/packages/mcp/src/interface/loader.ts +519 -0
- package/packages/mcp/src/interface/read-candid.test.ts +300 -0
- package/packages/mcp/src/interface/read-candid.ts +259 -0
- package/packages/mcp/src/interface/types.ts +113 -0
- package/packages/mcp/src/network.ts +122 -0
- package/packages/mcp/src/options.ts +149 -0
- package/packages/mcp/src/server/approval.ts +159 -0
- package/packages/mcp/src/server/naming.ts +43 -0
- package/packages/mcp/src/server/results.ts +102 -0
- package/packages/mcp/src/server/server.ts +797 -0
- package/packages/mcp/src/server/tools.ts +116 -0
- package/packages/mcp/src/usage.ts +40 -0
- package/packages/mcp/tests/approval.test.ts +60 -0
- package/packages/mcp/tests/identity.test.ts +234 -0
- package/packages/mcp/tests/naming.test.ts +62 -0
- package/packages/mcp/tests/options.test.ts +140 -0
- package/packages/mcp/tests/server.test.ts +997 -0
- package/packages/mcp/tsconfig.json +19 -0
- package/packages/mcp/tsconfig.typecheck.json +10 -0
- package/packages/mcp/vitest.config.ts +10 -0
- package/packages/react/LICENSE +21 -0
- package/packages/react/README.md +328 -0
- package/packages/react/llms.txt +95 -0
- package/packages/react/package.json +95 -0
- package/packages/react/src/index.tsx +678 -0
- package/packages/react/tests/abandoned-render.test.tsx +816 -0
- package/packages/react/tests/auth.test.tsx +315 -0
- package/packages/react/tests/caller-keys.test.tsx +2334 -0
- package/packages/react/tests/client-time.test.ts +40 -0
- package/packages/react/tests/entry.test.ts +52 -0
- package/packages/react/tests/helpers.tsx +291 -0
- package/packages/react/tests/hydration.test.tsx +262 -0
- package/packages/react/tests/ownership.test.tsx +260 -0
- package/packages/react/tests/provider.server.test.tsx +169 -0
- package/packages/react/tests/query-client.test.tsx +107 -0
- package/packages/react/tests/strict-mode.test.tsx +288 -0
- package/packages/react/tests/suspense.test-d.tsx +357 -0
- package/packages/react/tests/two-query-cores.test.tsx +135 -0
- package/packages/react/tests/types.test-d.tsx +63 -0
- package/packages/react/tsconfig.json +23 -0
- package/packages/react/tsconfig.test.json +8 -0
- package/packages/react/tsconfig.typecheck.json +16 -0
- package/packages/react/vitest.config.ts +39 -0
- package/packages/vite-plugin/LICENSE +21 -0
- package/packages/vite-plugin/README.md +532 -0
- package/packages/vite-plugin/package.json +76 -0
- package/packages/vite-plugin/src/describe-value.test.ts +43 -0
- package/packages/vite-plugin/src/describe-value.ts +167 -0
- package/packages/vite-plugin/src/dev-environment.test.ts +747 -0
- package/packages/vite-plugin/src/dev-environment.ts +510 -0
- package/packages/vite-plugin/src/env.ts +431 -0
- package/packages/vite-plugin/src/fetch.ts +348 -0
- package/packages/vite-plugin/src/file-identity.ts +106 -0
- package/packages/vite-plugin/src/generate.ts +691 -0
- package/packages/vite-plugin/src/index.test.ts +1243 -0
- package/packages/vite-plugin/src/index.ts +2565 -0
- package/packages/vite-plugin/src/interface.ts +339 -0
- package/packages/vite-plugin/src/local-host.ts +34 -0
- package/packages/vite-plugin/src/options.ts +641 -0
- package/packages/vite-plugin/src/principal-text.test.ts +87 -0
- package/packages/vite-plugin/src/principal-text.ts +98 -0
- package/packages/vite-plugin/tests/close.test.ts +141 -0
- package/packages/vite-plugin/tests/environment-mode.test.ts +136 -0
- package/packages/vite-plugin/tests/fake-ic.ts +214 -0
- package/packages/vite-plugin/tests/fetch-sdk.test.ts +27 -0
- package/packages/vite-plugin/tests/fetch.test.ts +1196 -0
- package/packages/vite-plugin/tests/fixtures/fake-cli/bin.js +90 -0
- package/packages/vite-plugin/tests/fixtures/fake-cli/package.json +8 -0
- package/packages/vite-plugin/tests/fixtures/icrc1.did +88 -0
- package/packages/vite-plugin/tests/generation.test.ts +1036 -0
- package/packages/vite-plugin/tests/icp-command.test.ts +194 -0
- package/packages/vite-plugin/tests/icp-timeout.test.ts +83 -0
- package/packages/vite-plugin/tests/no-process-exit.test.ts +83 -0
- package/packages/vite-plugin/tests/on-generated.test.ts +323 -0
- package/packages/vite-plugin/tests/output-collision.test.ts +329 -0
- package/packages/vite-plugin/tests/package.test.ts +62 -0
- package/packages/vite-plugin/tests/project.test.ts +2993 -0
- package/packages/vite-plugin/tests/support.ts +339 -0
- package/packages/vite-plugin/tests/timeout.test.ts +107 -0
- package/packages/vite-plugin/tsconfig.json +23 -0
- package/packages/vite-plugin/tsconfig.typecheck.json +16 -0
- package/packages/vite-plugin/vitest.config.ts +9 -0
- package/pnpm-workspace.yaml +23 -0
- package/scripts/ai-context-files.js +72 -0
- package/scripts/assemble-docs-site.mjs +485 -0
- package/scripts/assemble-docs-site.test.mjs +568 -0
- package/scripts/build-examples.js +58 -0
- package/scripts/check-ai-context.js +963 -0
- package/scripts/check-ai-context.test.mjs +811 -0
- package/scripts/check-exports.mjs +767 -0
- package/scripts/check-exports.test.mjs +1136 -0
- package/scripts/check-snippets/ambient.d.ts +428 -0
- package/scripts/check-snippets/app/generated/backend.did +7 -0
- package/scripts/check-snippets/app/generated/backend.ts +15 -0
- package/scripts/check-snippets/app/generated/icrc1.did +88 -0
- package/scripts/check-snippets/app/generated/icrc1.ts +78 -0
- package/scripts/check-snippets/app/globals.ts +26 -0
- package/scripts/check-snippets/docs/guides/App.tsx +21 -0
- package/scripts/check-snippets/docs/guides/app/providers.tsx +23 -0
- package/scripts/check-snippets/docs/guides/auth-client.ts +47 -0
- package/scripts/check-snippets/docs/guides/canisters/backend.ts +3 -0
- package/scripts/check-snippets/docs/guides/canisters/icrc1.ts +3 -0
- package/scripts/check-snippets/docs/guides/components/LedgerCard.tsx +26 -0
- package/scripts/check-snippets/docs/guides/components/shell.tsx +11 -0
- package/scripts/check-snippets/docs/guides/components/sign-in-page.tsx +29 -0
- package/scripts/check-snippets/docs/guides/components/slow-section.tsx +5 -0
- package/scripts/check-snippets/docs/guides/generated/accounts.ts +95 -0
- package/scripts/check-snippets/docs/guides/generated/ckbtc_minter.ts +40 -0
- package/scripts/check-snippets/docs/guides/generated/icp_ledger.ts +267 -0
- package/scripts/check-snippets/docs/guides/ledger.ts +10 -0
- package/scripts/check-snippets/docs/guides/server/request-client.ts +8 -0
- package/scripts/check-snippets.mjs +993 -0
- package/scripts/check-snippets.test.mjs +338 -0
- package/scripts/check-stack.mjs +501 -0
- package/scripts/check-stack.test.mjs +800 -0
- package/scripts/clean-node-modules.js +67 -0
- package/scripts/example-projects.js +58 -0
- package/scripts/export-budget.mjs +145 -0
- package/scripts/faults.json +6749 -0
- package/scripts/lib/fault-workspace.mjs +210 -0
- package/scripts/lib/io.mjs +29 -0
- package/scripts/lib/io.test.mjs +38 -0
- package/scripts/lib/markdown-fences.mjs +56 -0
- package/scripts/lib/markdown-fences.test.mjs +84 -0
- package/scripts/lib/package-exports.mjs +54 -0
- package/scripts/lib/package-exports.test.mjs +66 -0
- package/scripts/lib/release-pr-steps.mjs +47 -0
- package/scripts/release-tag.mjs +95 -0
- package/scripts/release-tag.test.mjs +278 -0
- package/scripts/release-workflow.test.mjs +98 -0
- package/scripts/release.js +167 -0
- package/scripts/release.test.mjs +347 -0
- package/scripts/removed-v3-names.js +125 -0
- package/scripts/size-app/.size-limit.js +90 -0
- package/scripts/size-app/core.js +3 -0
- package/scripts/size-app/package.json +24 -0
- package/scripts/size-app/react.js +4 -0
- package/scripts/size-app.test.mjs +73 -0
- package/scripts/sync-ai-context-versions.js +102 -0
- package/scripts/sync-example-versions.js +151 -0
- package/scripts/test-examples-published.mjs +1585 -0
- package/scripts/test-examples-published.test.mjs +1586 -0
- package/scripts/traps/any-method-vars-not-a-list.json +5 -0
- package/scripts/traps/canister-method-unknown.json +5 -0
- package/scripts/traps/client-says-who-calls-once.json +5 -0
- package/scripts/traps/client-says-who-calls.json +5 -0
- package/scripts/traps/err-only-on-canister-err.json +14 -0
- package/scripts/traps/format-units-refuses-missing-value.json +5 -0
- package/scripts/traps/format-units-refuses-number.json +5 -0
- package/scripts/traps/format-units-unknown-option.json +5 -0
- package/scripts/traps/guard-err-is-the-methods.json +5 -0
- package/scripts/traps/guard-false-keeps-every-kind.json +5 -0
- package/scripts/traps/internals-not-exported.json +9 -0
- package/scripts/traps/network-refuses-unknown-name.json +5 -0
- package/scripts/traps/never-err-has-no-type.json +5 -0
- package/scripts/traps/options-method-unknown.json +5 -0
- package/scripts/traps/options-vars-wrong-type.json +5 -0
- package/scripts/traps/parse-units-refuses-number.json +5 -0
- package/scripts/traps/parse-units-unknown-option.json +5 -0
- package/scripts/traps/principal-is-not-plain-text.json +14 -0
- package/scripts/traps/query-options-refuses-oneway.json +5 -0
- package/scripts/traps/query-options-refuses-update.json +5 -0
- package/scripts/traps/refuse-next-unknown-option.json +5 -0
- package/scripts/traps/resend-key-reads-the-methods-arg.json +5 -0
- package/scripts/traps/resend-states-its-dedupe-key.json +5 -0
- package/scripts/traps/suspense-refuses-argument-skip.json +5 -0
- package/scripts/traps/suspense-refuses-skippable-read.json +5 -0
- package/scripts/traps/suspense-refuses-vars-skip-fits.json +5 -0
- package/scripts/traps/test-handler-method-unknown.json +5 -0
- package/scripts/traps/test-handler-nat-is-bigint.json +5 -0
- package/scripts/traps/test-handler-takes-the-domain-value.json +5 -0
- package/scripts/traps/vars-of-two-arguments-are-the-tuple.json +5 -0
- package/scripts/typecheck-examples.js +122 -0
- package/scripts/verify-faults.mjs +375 -0
- package/scripts/verify-faults.test.mjs +402 -0
- package/scripts/verify-package-artifacts.mjs +590 -0
- package/scripts/verify-peer-floors.js +399 -0
- package/scripts/verify-peer-floors.test.mjs +422 -0
- package/scripts/verify-test-fails-rules.mjs +104 -0
- package/scripts/verify-test-fails-rules.test.mjs +215 -0
- package/scripts/verify-test-fails.js +371 -0
- package/scripts/verify-traps.mjs +505 -0
- package/scripts/verify-traps.test.mjs +521 -0
- package/scripts/verify-typescript-floor.js +239 -0
- package/skill-packages/ic-reactor/SKILL.md +103 -0
- package/stack.json +8 -0
- package/tsconfig.base.json +23 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,691 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generation: `meant gen` in a child process.
|
|
3
|
+
*
|
|
4
|
+
* Meant's generator is WebAssembly. Running it in the dev server's own
|
|
5
|
+
* process would let one trap, one runaway loop or one memory blow-up on a bad
|
|
6
|
+
* `.did` take the dev server down with it. A child process takes only itself
|
|
7
|
+
* down: the plugin reads what it printed (or why it did not print) and reports
|
|
8
|
+
* that for the canister it was generating.
|
|
9
|
+
*
|
|
10
|
+
* This module imports nothing from Vite and nothing from the CLI. It resolves
|
|
11
|
+
* the CLI's bin script from the app's own `node_modules` and runs it with the
|
|
12
|
+
* running Node binary, never through a shell.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { spawn } from "node:child_process"
|
|
16
|
+
import fs from "node:fs"
|
|
17
|
+
import { createRequire } from "node:module"
|
|
18
|
+
import path from "node:path"
|
|
19
|
+
import { describeError, describePath } from "./describe-value.js"
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The `@meantjs/cli` release this plugin is built against. The package
|
|
23
|
+
* declares it as an exact peer, and a test keeps the two equal: the app has to
|
|
24
|
+
* install the generator that pairs with the `@meantjs/schema` runtime its
|
|
25
|
+
* generated modules import.
|
|
26
|
+
*/
|
|
27
|
+
export const MEANT_CLI_VERSION = "0.5.1"
|
|
28
|
+
|
|
29
|
+
/** The `schemaVersion` of the `--json` document this module understands. */
|
|
30
|
+
const REPORT_SCHEMA_VERSION = 1
|
|
31
|
+
|
|
32
|
+
/** How long one generator process may run before it is killed. */
|
|
33
|
+
export const GENERATE_TIMEOUT_MS = 60_000
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The most stderr lines of one process passed on to the logger. The generator
|
|
37
|
+
* prints nothing there when all is well, so more than this is a runaway
|
|
38
|
+
* process, which would flood the terminal for as long as its timeout.
|
|
39
|
+
*/
|
|
40
|
+
const MAX_STREAMED_LINES = 200
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The most characters kept of one stderr line. A longer line is logged cut at
|
|
44
|
+
* this length, with a note, and the rest of it is dropped as it arrives. It
|
|
45
|
+
* bounds the line being assembled, which the cap on the whole stream does not:
|
|
46
|
+
* a process that writes without a newline would otherwise grow that line
|
|
47
|
+
* until it exited or was killed at the timeout.
|
|
48
|
+
*/
|
|
49
|
+
const MAX_LINE_CHARS = 4096
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The most output kept from one stream of the generator. A report is a few
|
|
53
|
+
* lines per canister; the cap only stops a runaway process from filling memory
|
|
54
|
+
* before the timeout kills it.
|
|
55
|
+
*/
|
|
56
|
+
const MAX_OUTPUT_BYTES = 4 * 1024 * 1024
|
|
57
|
+
|
|
58
|
+
/** What the generator left out of a module, as it reports it. */
|
|
59
|
+
export interface Omission {
|
|
60
|
+
kind: string
|
|
61
|
+
name: string
|
|
62
|
+
reason: string
|
|
63
|
+
via?: string
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** A canister to generate, with absolute paths. */
|
|
67
|
+
export interface GenerateCanister {
|
|
68
|
+
/** The canister's name in the plugin options, for messages. */
|
|
69
|
+
name: string
|
|
70
|
+
didFile: string
|
|
71
|
+
outDir: string
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* What happened to one `.did` written into one output directory: a module, or
|
|
76
|
+
* the reason there is none. It is the fate of every canister that names that
|
|
77
|
+
* pair, which is why it lists names. Canisters with one interface (an ICP
|
|
78
|
+
* ledger and a ckBTC ledger on `icrc1.did`) are one generation and one module.
|
|
79
|
+
*/
|
|
80
|
+
export interface Outcome {
|
|
81
|
+
/** The canisters this applies to, by their names in the plugin options. */
|
|
82
|
+
names: string[]
|
|
83
|
+
/** The module the generator wrote or checked, when it said. */
|
|
84
|
+
module?: string
|
|
85
|
+
/** `written` when a file was created or changed, `unchanged` otherwise. */
|
|
86
|
+
status: "written" | "unchanged" | "failed"
|
|
87
|
+
omitted: Omission[]
|
|
88
|
+
/** Why the generation failed, in words fit for an error message. */
|
|
89
|
+
failure?: string
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface GenerateResult {
|
|
93
|
+
outcomes: Outcome[]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The absolute path of the `meant` bin script installed for the app
|
|
98
|
+
* rooted at `root`.
|
|
99
|
+
*
|
|
100
|
+
* Resolved from the app and not from the plugin: the CLI that pairs with the
|
|
101
|
+
* app's `@meantjs/schema` is the one the app installed, wherever the
|
|
102
|
+
* package manager put the plugin. Throws an `Error` that says what to install.
|
|
103
|
+
*/
|
|
104
|
+
export function resolveCliBin(root: string): string {
|
|
105
|
+
const requireFromApp = createRequire(path.join(root, "package.json"))
|
|
106
|
+
let manifestPath: string
|
|
107
|
+
try {
|
|
108
|
+
manifestPath = requireFromApp.resolve("@meantjs/cli/package.json")
|
|
109
|
+
} catch {
|
|
110
|
+
throw new Error(
|
|
111
|
+
`cannot find @meantjs/cli from ${root}. Install the generator that pairs with ` +
|
|
112
|
+
`this plugin next to @meantjs/schema: npm install --save-dev --save-exact ` +
|
|
113
|
+
`@meantjs/cli@${MEANT_CLI_VERSION}`
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8")) as {
|
|
117
|
+
bin?: string | Record<string, string>
|
|
118
|
+
}
|
|
119
|
+
const bin =
|
|
120
|
+
typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.meant
|
|
121
|
+
if (!bin) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`${manifestPath} declares no \`meant\` bin, so it is not the generator this plugin runs`
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
return path.resolve(path.dirname(manifestPath), bin)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface ProcessResult {
|
|
130
|
+
stdout: string
|
|
131
|
+
stderr: string
|
|
132
|
+
code: number | null
|
|
133
|
+
signal: NodeJS.Signals | null
|
|
134
|
+
/** Set when the process never ran to its end: it did not start, or was killed at the timeout or by the caller. */
|
|
135
|
+
problem?: string
|
|
136
|
+
/** Whether Node could not start the process at all, so another try would fail the same way. */
|
|
137
|
+
unstartable?: boolean
|
|
138
|
+
/** Whether the caller stopped the process, so nothing is left to try. */
|
|
139
|
+
stopped?: boolean
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const keep = (text: string, chunk: string, limit: number) =>
|
|
143
|
+
text.length >= limit ? text : text + chunk
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Run `node <bin> ...args` in `cwd` and settle with what it did. Never
|
|
147
|
+
* rejects. Aborting `signal` kills the process, and a signal that is already
|
|
148
|
+
* aborted starts none.
|
|
149
|
+
*
|
|
150
|
+
* @param maxOutputBytes - The most kept of each stream. A report larger than
|
|
151
|
+
* this is cut, so it no longer parses.
|
|
152
|
+
*/
|
|
153
|
+
export function runProcess(
|
|
154
|
+
bin: string,
|
|
155
|
+
args: string[],
|
|
156
|
+
cwd: string,
|
|
157
|
+
timeoutMs: number,
|
|
158
|
+
signal?: AbortSignal,
|
|
159
|
+
onStderrLine?: (line: string) => void,
|
|
160
|
+
maxOutputBytes = MAX_OUTPUT_BYTES
|
|
161
|
+
): Promise<ProcessResult> {
|
|
162
|
+
return new Promise((resolve) => {
|
|
163
|
+
let stdout = ""
|
|
164
|
+
let stderr = ""
|
|
165
|
+
let timedOut = false
|
|
166
|
+
let settled = false
|
|
167
|
+
|
|
168
|
+
const stopped: Omit<ProcessResult, "stdout" | "stderr"> = {
|
|
169
|
+
code: null,
|
|
170
|
+
signal: null,
|
|
171
|
+
problem: "was stopped",
|
|
172
|
+
stopped: true,
|
|
173
|
+
}
|
|
174
|
+
if (signal?.aborted) {
|
|
175
|
+
resolve({ stdout, stderr, ...stopped })
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// A line is passed on when it is complete, not when its first bytes
|
|
180
|
+
// arrive, and what follows the last newline is passed on at the end. The
|
|
181
|
+
// line being assembled keeps at most MAX_LINE_CHARS characters: `cut` says
|
|
182
|
+
// that it had more.
|
|
183
|
+
let unfinished = ""
|
|
184
|
+
let cut = false
|
|
185
|
+
let passed = 0
|
|
186
|
+
const pass = (text: string) => {
|
|
187
|
+
if (!text.trim() || passed > MAX_STREAMED_LINES) return
|
|
188
|
+
passed++
|
|
189
|
+
onStderrLine?.(
|
|
190
|
+
passed > MAX_STREAMED_LINES
|
|
191
|
+
? `more than ${MAX_STREAMED_LINES} lines on stderr: the rest is not logged`
|
|
192
|
+
: text.trimEnd()
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
const passUnfinished = () => {
|
|
196
|
+
pass(
|
|
197
|
+
cut
|
|
198
|
+
? `${unfinished} [line cut at ${MAX_LINE_CHARS} characters]`
|
|
199
|
+
: unfinished
|
|
200
|
+
)
|
|
201
|
+
unfinished = ""
|
|
202
|
+
cut = false
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const settle = (result: Omit<ProcessResult, "stdout" | "stderr">) => {
|
|
206
|
+
if (settled) return
|
|
207
|
+
settled = true
|
|
208
|
+
passUnfinished()
|
|
209
|
+
clearTimeout(timer)
|
|
210
|
+
signal?.removeEventListener("abort", stop)
|
|
211
|
+
resolve({ stdout, stderr, ...result })
|
|
212
|
+
}
|
|
213
|
+
const stop = () => {
|
|
214
|
+
// Nothing of a run that was stopped is passed on, not even a last line.
|
|
215
|
+
unfinished = ""
|
|
216
|
+
cut = false
|
|
217
|
+
child.kill("SIGKILL")
|
|
218
|
+
settle(stopped)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// No shell, and stdin closed: the CLI never reads it, and a child that
|
|
222
|
+
// inherited the dev server's terminal could not be told apart from it.
|
|
223
|
+
const child = spawn(process.execPath, [bin, ...args], {
|
|
224
|
+
cwd,
|
|
225
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
226
|
+
windowsHide: true,
|
|
227
|
+
})
|
|
228
|
+
const timer = setTimeout(() => {
|
|
229
|
+
timedOut = true
|
|
230
|
+
child.kill("SIGKILL")
|
|
231
|
+
}, timeoutMs)
|
|
232
|
+
signal?.addEventListener("abort", stop, { once: true })
|
|
233
|
+
|
|
234
|
+
child.stdout.setEncoding("utf-8")
|
|
235
|
+
child.stderr.setEncoding("utf-8")
|
|
236
|
+
child.stdout.on(
|
|
237
|
+
"data",
|
|
238
|
+
(chunk: string) => (stdout = keep(stdout, chunk, maxOutputBytes))
|
|
239
|
+
)
|
|
240
|
+
child.stderr.on("data", (chunk: string) => {
|
|
241
|
+
stderr = keep(stderr, chunk, maxOutputBytes)
|
|
242
|
+
// Past the last line that is logged there is nothing left to assemble.
|
|
243
|
+
if (settled || !onStderrLine || passed > MAX_STREAMED_LINES) return
|
|
244
|
+
const pieces = chunk.split(/\r?\n/)
|
|
245
|
+
pieces.forEach((piece, index) => {
|
|
246
|
+
const room = MAX_LINE_CHARS - unfinished.length
|
|
247
|
+
if (piece.length > room) cut = true
|
|
248
|
+
unfinished += piece.slice(0, room)
|
|
249
|
+
if (index < pieces.length - 1) passUnfinished()
|
|
250
|
+
})
|
|
251
|
+
})
|
|
252
|
+
child.on("error", (error) =>
|
|
253
|
+
settle({
|
|
254
|
+
code: null,
|
|
255
|
+
signal: null,
|
|
256
|
+
problem: `could not start: ${error.message}`,
|
|
257
|
+
unstartable: true,
|
|
258
|
+
})
|
|
259
|
+
)
|
|
260
|
+
child.on("close", (code, signal) =>
|
|
261
|
+
settle({
|
|
262
|
+
code,
|
|
263
|
+
signal,
|
|
264
|
+
problem: timedOut
|
|
265
|
+
? `did not finish within ${timeoutMs / 1000}s and was killed`
|
|
266
|
+
: undefined,
|
|
267
|
+
})
|
|
268
|
+
)
|
|
269
|
+
})
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** How a process that produced no usable report ended, with its stderr. */
|
|
273
|
+
export function describeProcess(run: ProcessResult, reason?: string): string {
|
|
274
|
+
const ending =
|
|
275
|
+
run.problem ??
|
|
276
|
+
(run.signal
|
|
277
|
+
? `was killed by ${run.signal}`
|
|
278
|
+
: `exited with code ${run.code}`)
|
|
279
|
+
const lines = [`\`meant\` ${ending}`]
|
|
280
|
+
if (reason) lines.push(reason)
|
|
281
|
+
const stderr = run.stderr.trim()
|
|
282
|
+
if (stderr) lines.push(stderr)
|
|
283
|
+
return lines.join("\n")
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
interface ReportEntry {
|
|
287
|
+
status: string
|
|
288
|
+
module?: string
|
|
289
|
+
omitted: Omission[]
|
|
290
|
+
diagnostics: unknown[]
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* The entries of a `--json` document, in command-line order: `undefined` when
|
|
295
|
+
* stdout is not JSON at all, and an `Error` for a document this module does
|
|
296
|
+
* not know how to read.
|
|
297
|
+
*/
|
|
298
|
+
function parseReport(stdout: string, count: number): ReportEntry[] | undefined {
|
|
299
|
+
let report: unknown
|
|
300
|
+
try {
|
|
301
|
+
report = JSON.parse(stdout)
|
|
302
|
+
} catch {
|
|
303
|
+
return undefined
|
|
304
|
+
}
|
|
305
|
+
const { schemaVersion, entries } = (report ?? {}) as Record<string, unknown>
|
|
306
|
+
if (schemaVersion !== REPORT_SCHEMA_VERSION) {
|
|
307
|
+
throw new Error(
|
|
308
|
+
`its report has schemaVersion ${String(schemaVersion)}, and this plugin reads ${REPORT_SCHEMA_VERSION}; ` +
|
|
309
|
+
`install @meantjs/cli@${MEANT_CLI_VERSION}`
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
if (!Array.isArray(entries) || entries.length !== count) {
|
|
313
|
+
throw new Error(`its report does not have one entry per .did (${count})`)
|
|
314
|
+
}
|
|
315
|
+
return entries.map((entry): ReportEntry => {
|
|
316
|
+
const { status, module, omitted, diagnostics } = entry as Record<
|
|
317
|
+
string,
|
|
318
|
+
unknown
|
|
319
|
+
>
|
|
320
|
+
return {
|
|
321
|
+
status: String(status),
|
|
322
|
+
module: typeof module === "string" ? module : undefined,
|
|
323
|
+
omitted: Array.isArray(omitted) ? (omitted as Omission[]) : [],
|
|
324
|
+
diagnostics: Array.isArray(diagnostics) ? diagnostics : [],
|
|
325
|
+
}
|
|
326
|
+
})
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/** One line (plus its notes) for a compiler diagnostic. */
|
|
330
|
+
export function formatDiagnostic(diagnostic: unknown): string {
|
|
331
|
+
const { code, message, notes } = (diagnostic ?? {}) as {
|
|
332
|
+
code?: unknown
|
|
333
|
+
message?: unknown
|
|
334
|
+
notes?: unknown
|
|
335
|
+
}
|
|
336
|
+
if (typeof message !== "string") return JSON.stringify(diagnostic)
|
|
337
|
+
const lead = typeof code === "string" ? `${code}: ${message}` : message
|
|
338
|
+
const extra = Array.isArray(notes) ? notes.map((note) => ` ${note}`) : []
|
|
339
|
+
return [lead, ...extra].join("\n")
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** What every generator process of one `generate` call shares. */
|
|
343
|
+
interface Context {
|
|
344
|
+
cli: string
|
|
345
|
+
root: string
|
|
346
|
+
timeoutMs: number
|
|
347
|
+
signal?: AbortSignal
|
|
348
|
+
/**
|
|
349
|
+
* Called with each line a generator process writes to stderr, as it writes
|
|
350
|
+
* it, and the `.did` files that process is generating. The generator prints
|
|
351
|
+
* nothing there with `--json` when all is well, so a line is worth showing.
|
|
352
|
+
* What a process that failed wrote is also part of its failure message.
|
|
353
|
+
*/
|
|
354
|
+
onStderr?: (line: string, didFiles: string[]) => void
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/** One `.did` to write into one output directory, for each canister that names the pair. */
|
|
358
|
+
interface Unit {
|
|
359
|
+
names: string[]
|
|
360
|
+
didFile: string
|
|
361
|
+
outDir: string
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* One generator process for `units`, which all write into `outDir`. The report
|
|
366
|
+
* names each unit's fate. A process that ends without a usable report (it
|
|
367
|
+
* crashed, or was killed at the timeout) fails every unit it was given, unless
|
|
368
|
+
* there is more than one: it could have been any of them, so each is run alone
|
|
369
|
+
* to find out, side by side. A unit that is the cause fails alone, and the
|
|
370
|
+
* others are generated. A hang costs one more wait for that unit, and no more.
|
|
371
|
+
*/
|
|
372
|
+
async function runGroup(
|
|
373
|
+
context: Context,
|
|
374
|
+
outDir: string,
|
|
375
|
+
units: Unit[]
|
|
376
|
+
): Promise<GenerateResult> {
|
|
377
|
+
const run = await runProcess(
|
|
378
|
+
context.cli,
|
|
379
|
+
["gen", ...units.map((unit) => unit.didFile), "-o", outDir, "--json"],
|
|
380
|
+
context.root,
|
|
381
|
+
context.timeoutMs,
|
|
382
|
+
context.signal,
|
|
383
|
+
(line) =>
|
|
384
|
+
context.onStderr?.(
|
|
385
|
+
line,
|
|
386
|
+
units.map((unit) => unit.didFile)
|
|
387
|
+
)
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
let entries: ReportEntry[] | undefined
|
|
391
|
+
let reason: string | undefined
|
|
392
|
+
if (!run.problem) {
|
|
393
|
+
try {
|
|
394
|
+
entries = parseReport(run.stdout, units.length)
|
|
395
|
+
// A process that crashed says so by its exit and its stderr.
|
|
396
|
+
if (!entries && run.code === 0) reason = "it printed no report"
|
|
397
|
+
} catch (error) {
|
|
398
|
+
reason = describeError(error)
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (!entries) {
|
|
403
|
+
if (units.length > 1 && !run.unstartable && !run.stopped) {
|
|
404
|
+
const results = await Promise.all(
|
|
405
|
+
units.map((unit) => runGroup(context, outDir, [unit]))
|
|
406
|
+
)
|
|
407
|
+
return { outcomes: results.flatMap((result) => result.outcomes) }
|
|
408
|
+
}
|
|
409
|
+
const failure = describeProcess(run, reason)
|
|
410
|
+
return {
|
|
411
|
+
outcomes: units.map(({ names }) => ({
|
|
412
|
+
names,
|
|
413
|
+
status: "failed",
|
|
414
|
+
omitted: [],
|
|
415
|
+
failure,
|
|
416
|
+
})),
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return {
|
|
421
|
+
outcomes: units.map((unit, index): Outcome => {
|
|
422
|
+
const entry = entries[index]
|
|
423
|
+
if (entry.status === "failed") {
|
|
424
|
+
return {
|
|
425
|
+
names: unit.names,
|
|
426
|
+
status: "failed",
|
|
427
|
+
omitted: [],
|
|
428
|
+
failure:
|
|
429
|
+
entry.diagnostics.map(formatDiagnostic).join("\n") ||
|
|
430
|
+
"`meant` reported the entry as failed",
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return {
|
|
434
|
+
names: unit.names,
|
|
435
|
+
module: entry.module,
|
|
436
|
+
status: entry.status === "unchanged" ? "unchanged" : "written",
|
|
437
|
+
omitted: entry.omitted,
|
|
438
|
+
}
|
|
439
|
+
}),
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/** `"a"`, or `"a", "b"`: canister names as messages quote them. */
|
|
444
|
+
export function quoteNames(names: string[]): string {
|
|
445
|
+
return names.map((name) => `"${name}"`).join(", ")
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Whether the filesystem that holds `dir` takes `A.ts` and `a.ts` for one
|
|
450
|
+
* file, `undefined` when that cannot be told.
|
|
451
|
+
*
|
|
452
|
+
* It looks a name up in a spelling with its case swapped and asks whether that
|
|
453
|
+
* finds the same entry. The name is one inside `dir`, or inside the nearest
|
|
454
|
+
* directory above it that exists (`dir` may be made by the generator), or that
|
|
455
|
+
* directory's own, so that the lookup is made where the modules will be. Only
|
|
456
|
+
* ASCII letters are swapped: other scripts fold by rules a probe cannot know.
|
|
457
|
+
*/
|
|
458
|
+
export function foldsCase(dir: string): boolean | undefined {
|
|
459
|
+
const swapCase = (name: string) =>
|
|
460
|
+
name.replace(/[a-z]/gi, (letter) =>
|
|
461
|
+
letter === letter.toLowerCase()
|
|
462
|
+
? letter.toUpperCase()
|
|
463
|
+
: letter.toLowerCase()
|
|
464
|
+
)
|
|
465
|
+
const probe = (entry: string): boolean | undefined => {
|
|
466
|
+
const swapped = path.join(
|
|
467
|
+
path.dirname(entry),
|
|
468
|
+
swapCase(path.basename(entry))
|
|
469
|
+
)
|
|
470
|
+
if (swapped === entry) return undefined
|
|
471
|
+
try {
|
|
472
|
+
const found = fs.lstatSync(entry, { bigint: true })
|
|
473
|
+
// A filesystem that reports no file index cannot say that two names
|
|
474
|
+
// are one file.
|
|
475
|
+
if (found.ino === 0n) return undefined
|
|
476
|
+
try {
|
|
477
|
+
const other = fs.lstatSync(swapped, { bigint: true })
|
|
478
|
+
return other.dev === found.dev && other.ino === found.ino
|
|
479
|
+
} catch (error) {
|
|
480
|
+
return (error as NodeJS.ErrnoException).code === "ENOENT"
|
|
481
|
+
? false
|
|
482
|
+
: undefined
|
|
483
|
+
}
|
|
484
|
+
} catch {
|
|
485
|
+
return undefined
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
for (let at = dir; ; at = path.dirname(at)) {
|
|
490
|
+
let names: string[] = []
|
|
491
|
+
try {
|
|
492
|
+
names = fs.readdirSync(at)
|
|
493
|
+
} catch {
|
|
494
|
+
// Not made yet, or not a directory.
|
|
495
|
+
}
|
|
496
|
+
const named = names.find((name) => swapCase(name) !== name)
|
|
497
|
+
const verdict =
|
|
498
|
+
(named === undefined ? undefined : probe(path.join(at, named))) ??
|
|
499
|
+
probe(at)
|
|
500
|
+
if (verdict !== undefined) return verdict
|
|
501
|
+
if (path.dirname(at) === at) return undefined
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Each pair of `.did` and `outDir` of `canisters` once, as one generation,
|
|
507
|
+
* and the generations refused, each with the one before it that writes its
|
|
508
|
+
* module (`owner`). The CLI names a module after its `.did` (`outputsOf`), so
|
|
509
|
+
* `a/ledger.did` and `b/ledger.did` in one `outDir` write one `ledger.ts`:
|
|
510
|
+
* the first in the order of `canisters` keeps it. Whether `A.did` and `a.did`
|
|
511
|
+
* collide depends on the filesystem of the `outDir`, which `folds` is asked
|
|
512
|
+
* once for each: they do where it ignores case (macOS and Windows by default)
|
|
513
|
+
* and write two modules where it does not, or where it cannot be told.
|
|
514
|
+
*/
|
|
515
|
+
function planGenerations(
|
|
516
|
+
canisters: GenerateCanister[],
|
|
517
|
+
folds: (outDir: string) => boolean | undefined
|
|
518
|
+
): { units: Unit[]; refused: Map<Unit, Unit> } {
|
|
519
|
+
// Each pair of .did and outDir once, and the module each would write.
|
|
520
|
+
const units = new Map<string, Unit>()
|
|
521
|
+
const claimed = new Map<string, Unit>()
|
|
522
|
+
const refused = new Map<Unit, Unit>()
|
|
523
|
+
|
|
524
|
+
// The probe runs once for each outDir.
|
|
525
|
+
const folding = new Map<string, boolean>()
|
|
526
|
+
const targetOf = (unit: Unit): string => {
|
|
527
|
+
let folded = folding.get(unit.outDir)
|
|
528
|
+
if (folded === undefined) {
|
|
529
|
+
folded = folds(unit.outDir) ?? false
|
|
530
|
+
folding.set(unit.outDir, folded)
|
|
531
|
+
}
|
|
532
|
+
return folded ? moduleOf(unit).toLowerCase() : moduleOf(unit)
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
for (const canister of canisters) {
|
|
536
|
+
const key = JSON.stringify([canister.didFile, canister.outDir])
|
|
537
|
+
const same = units.get(key)
|
|
538
|
+
if (same) {
|
|
539
|
+
same.names.push(canister.name)
|
|
540
|
+
continue
|
|
541
|
+
}
|
|
542
|
+
const unit: Unit = {
|
|
543
|
+
names: [canister.name],
|
|
544
|
+
didFile: canister.didFile,
|
|
545
|
+
outDir: canister.outDir,
|
|
546
|
+
}
|
|
547
|
+
units.set(key, unit)
|
|
548
|
+
const target = targetOf(unit)
|
|
549
|
+
const owner = claimed.get(target)
|
|
550
|
+
if (owner) refused.set(unit, owner)
|
|
551
|
+
else claimed.set(target, unit)
|
|
552
|
+
}
|
|
553
|
+
return { units: [...units.values()], refused }
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/** Why `unit` is not generated: it would write the module `owner` writes. */
|
|
557
|
+
function collisionFailure(unit: Unit, owner: Unit, root: string): string {
|
|
558
|
+
return (
|
|
559
|
+
`would write ${describePath(path.relative(root, moduleOf(unit)))}, which ${quoteNames(owner.names)} already writes` +
|
|
560
|
+
(moduleOf(unit) === moduleOf(owner)
|
|
561
|
+
? ". "
|
|
562
|
+
: ` as ${describePath(path.relative(root, moduleOf(owner)))}: the filesystem does not tell the two names apart. `) +
|
|
563
|
+
`The generator names a module after its .did file: rename one file or give one canister its own outDir`
|
|
564
|
+
)
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* The canisters of `canisters` that cannot be generated because one before
|
|
569
|
+
* them writes their module, by name, each with why: the canisters `generate`
|
|
570
|
+
* would refuse if it were given them all. The plugin asks it of every
|
|
571
|
+
* canister it generates before a run does anything, so that such a canister
|
|
572
|
+
* is refused before anything is fetched, run or written for it, whichever
|
|
573
|
+
* canisters the run then generates. Never throws.
|
|
574
|
+
*
|
|
575
|
+
* @param folds - Whether the filesystem of an `outDir` ignores case: by
|
|
576
|
+
* default, the `foldsCase` probe.
|
|
577
|
+
*/
|
|
578
|
+
export function moduleCollisions(
|
|
579
|
+
canisters: GenerateCanister[],
|
|
580
|
+
root: string,
|
|
581
|
+
folds: (outDir: string) => boolean | undefined = foldsCase
|
|
582
|
+
): Map<string, string> {
|
|
583
|
+
const failures = new Map<string, string>()
|
|
584
|
+
for (const [unit, owner] of planGenerations(canisters, folds).refused) {
|
|
585
|
+
const failure = collisionFailure(unit, owner, root)
|
|
586
|
+
for (const name of unit.names) failures.set(name, failure)
|
|
587
|
+
}
|
|
588
|
+
return failures
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Generate `canisters` with the CLI at `cli`: one process for each output
|
|
593
|
+
* directory, run side by side. Never rejects. Aborting `signal` kills the
|
|
594
|
+
* processes that are running, and their canisters fail as stopped.
|
|
595
|
+
*
|
|
596
|
+
* Canisters that name the same `.did` and the same `outDir` are one
|
|
597
|
+
* generation: the CLI gets the file once, and its outcome belongs to each of
|
|
598
|
+
* them. That is the case of many canisters with one interface (two ICRC-1
|
|
599
|
+
* ledgers on `icrc1.did`), which share one module.
|
|
600
|
+
*
|
|
601
|
+
* Different `.did` files that would write the same module (the CLI names an
|
|
602
|
+
* output after its `.did`, so `a/ledger.did` and `b/ledger.did` in one
|
|
603
|
+
* `outDir` collide) are refused here, naming both. The CLI would otherwise
|
|
604
|
+
* refuse the whole run with a usage error. Whether `A.did` and `a.did` collide
|
|
605
|
+
* depends on the filesystem of the `outDir`: they do where it ignores case
|
|
606
|
+
* (macOS and Windows by default) and write two modules where it does not. The
|
|
607
|
+
* plugin refuses such a canister before its run does anything for it (see
|
|
608
|
+
* `moduleCollisions`), so for the plugin this is the check of last resort.
|
|
609
|
+
*/
|
|
610
|
+
export async function generate(
|
|
611
|
+
request: Context & {
|
|
612
|
+
canisters: GenerateCanister[]
|
|
613
|
+
/**
|
|
614
|
+
* Whether the filesystem that holds an `outDir` ignores case, `undefined`
|
|
615
|
+
* when unknown, which is taken as a filesystem that does not. For tests,
|
|
616
|
+
* which cannot rely on the filesystem of the machine they run on.
|
|
617
|
+
*/
|
|
618
|
+
foldsCase?: (outDir: string) => boolean | undefined
|
|
619
|
+
}
|
|
620
|
+
): Promise<GenerateResult> {
|
|
621
|
+
const { root } = request
|
|
622
|
+
const { units, refused } = planGenerations(
|
|
623
|
+
request.canisters,
|
|
624
|
+
request.foldsCase ?? foldsCase
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
const outcomes: Outcome[] = [...refused].map(([unit, owner]) => ({
|
|
628
|
+
names: unit.names,
|
|
629
|
+
status: "failed",
|
|
630
|
+
omitted: [],
|
|
631
|
+
failure: collisionFailure(unit, owner, root),
|
|
632
|
+
}))
|
|
633
|
+
|
|
634
|
+
const groups = new Map<string, Unit[]>()
|
|
635
|
+
for (const unit of units) {
|
|
636
|
+
if (refused.has(unit)) continue
|
|
637
|
+
groups.set(unit.outDir, [...(groups.get(unit.outDir) ?? []), unit])
|
|
638
|
+
}
|
|
639
|
+
const results = await Promise.all(
|
|
640
|
+
[...groups].map(([outDir, members]) => runGroup(request, outDir, members))
|
|
641
|
+
)
|
|
642
|
+
return {
|
|
643
|
+
outcomes: [...outcomes, ...results.flatMap((result) => result.outcomes)],
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/** The files `meant gen` writes for one `.did`, as it names them. */
|
|
648
|
+
export interface Outputs {
|
|
649
|
+
/** The `.did`'s file name without a final `.did`: `ledger` for `a/ledger.did`. */
|
|
650
|
+
stem: string
|
|
651
|
+
/** `<stem>.ts` in the output directory: the generated module. */
|
|
652
|
+
module: string
|
|
653
|
+
/** `<stem>.envelope.json` beside it: the contract envelope. */
|
|
654
|
+
envelope: string
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* The files `meant gen` writes for the `.did` at `didFile` into
|
|
659
|
+
* `outDir`, named as the CLI names them: after the file's name with a final
|
|
660
|
+
* `.did` cut off, exactly, and nothing else cut. `a/ledger.did` writes
|
|
661
|
+
* `ledger.ts` and `ledger.envelope.json`, `ledger.v2.did` writes
|
|
662
|
+
* `ledger.v2.ts`, and a file named `.did` writes `.ts`. A name that does not
|
|
663
|
+
* end in `.did` (`api.candid`, `api.DID`) keeps its whole name
|
|
664
|
+
* (`api.candid.ts`), and the CLI reads no such file: it fails its entry
|
|
665
|
+
* (`did_source_not_found`) and writes nothing.
|
|
666
|
+
*
|
|
667
|
+
* The plugin's one rule for these names: the modules canisters would write
|
|
668
|
+
* (`moduleCollisions`, `generate`) and the files a run puts back when it takes
|
|
669
|
+
* nothing of a `.did` written while the generator read it are both named by
|
|
670
|
+
* it. The rule is the CLI's own (its `stemOf`), and a test compares it with
|
|
671
|
+
* the paths the CLI reports.
|
|
672
|
+
*/
|
|
673
|
+
export function outputsOf({
|
|
674
|
+
didFile,
|
|
675
|
+
outDir,
|
|
676
|
+
}: {
|
|
677
|
+
didFile: string
|
|
678
|
+
outDir: string
|
|
679
|
+
}): Outputs {
|
|
680
|
+
const stem = path.basename(didFile).replace(/\.did$/, "")
|
|
681
|
+
return {
|
|
682
|
+
stem,
|
|
683
|
+
module: path.join(outDir, `${stem}.ts`),
|
|
684
|
+
envelope: path.join(outDir, `${stem}.envelope.json`),
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/** The module the CLI writes for `unit` (see `outputsOf`). */
|
|
689
|
+
function moduleOf(unit: Unit): string {
|
|
690
|
+
return outputsOf(unit).module
|
|
691
|
+
}
|