Merge main into next#39
Merged
Merged
Conversation
* docs: import planning docs from miden-client (web SDK ones) Per @SantiagoPittella's review on miden-client #1992: 5 of the 13 stray planning .md files at the miden-client repo root are web-SDK- relevant — they belong here, not in the Rust client repo. Importing under docs/planning/ with an index README that calls out their snapshot-not-maintained status. AGENTS.md Api.Rework.Impl.md REACT_SDK_PLAN.md SimplifiedAPI.md SimplifiedAPI.sdk.review.md The miden-client side (#1992 commit e20e6261a) deletes all 13 stray docs; the other 8 are either already-tracked issues, stale, or non- client concerns and don't need to be ported. * docs: keep only AGENTS.md from imported planning docs * ci: replace paths-ignore with intra-job filter so docs-only PRs aren't blocked by required checks that never run
* chore: add .nvmrc + lefthook + lint-staged for local dev hygiene * chore: fix lefthook config — drop broken per-file tsc, use pnpm exec, guard prepare
* chore(web-client): swap chai expect for @playwright/test expect * chore(web-client): swap puppeteer Page type for @playwright/test * chore(web-client): drop mocha/chai/puppeteer/esm/ts-node devDeps + .mocharc.json The legacy mocha-based Playwright wiring has been fully replaced by @playwright/test (assertions) and vitest (unit tests). Remove the dead test infrastructure: - crates/web-client/.mocharc.json (deleted) - crates/web-client/tsconfig.json: drop the "ts-node" block - crates/web-client/package.json devDependencies removed: - mocha - chai - puppeteer - esm - ts-node - pnpm-lock.yaml regenerated Verified: pnpm --filter @miden-sdk/miden-sdk run test:unit passes (295 tests across 13 files).
* chore(deps): bump miden-client to 0.14.5
Bumps the workspace miden-client dependency on `main` from 0.14.0 (locked
at 0.14.4) to 0.14.5, the latest 0.14.x patch on crates.io. No API
changes required on the web-sdk side — same minor line, just patch-level
updates from upstream miden-client.
The `next` branch separately tracks miden-client `next` (0.15.0
unreleased) and is unaffected by this bump.
* docs: clarify lazy entry — SSR / controlled WASM init, not 'most users skip crypto'
The previous README framing of `@miden-sdk/miden-sdk/lazy` as for 'apps
where most users never touch crypto' is misleading. The actual point of
the lazy entry is to allow usage in environments that hang on top-level
await (Next.js / SSR, Capacitor WKWebView) or where the caller wants to
explicitly control when the WASM-init cost is paid.
Also adds the missing `await MidenClient.ready()` contract: until you
call it, every wasm-bindgen type imported from the lazy entry is just a
stub that throws on construction. Async SDK methods await internally
and are exempt.
* docs: add React-side lazy guidance — gate UI on isReady from useMiden()
Apps using @miden-sdk/react with the lazy entry don't call
MidenClient.ready() directly; MidenProvider does it for them and
exposes the readiness state through useMiden() as { isReady,
isInitializing, error }. Adds the contract + a minimal example,
plus pointers to the loadingComponent / errorComponent provider
props for the zero-glue case.
* chore(ci): add publint + arethetypeswrong gates for published packages
Adds publint and @arethetypeswrong/cli as root devDeps and wires three
new scripts:
- check:publint - runs publint per published workspace package
- check:attw - runs attw --pack . per published workspace package
- check:publish - builds web-client, react-sdk, vite-plugin then runs
both gates
Filters target the three publishable packages by name
(@miden-sdk/miden-sdk, @miden-sdk/react, @miden-sdk/vite-plugin), which
skips the private web_store workspace member that has no exports map
worth checking.
A new workflow (.github/workflows/check-publish.yml) runs check:publish
on PRs and pushes to main/next. It mirrors the WASM build setup from
test.yml's build-web-client-dist-folder job (Rust toolchain, sccache,
binaryen, Swatinem/rust-cache) and uses MIDEN_FAST_BUILD on the WASM
build since publint/attw inspect package shape and types, not the
optimization level of the WASM blob.
Mode: STRICT. Per the task rule (document only if both tools find > ~3
issues per package; otherwise leave strict), only @miden-sdk/miden-sdk
clearly clears that bar - the other two packages have <= 1 attw issue
and 1 publint warning each, so a doc-and-tolerate path would be
overkill. The CI gate will be red on first PR; the author should decide
whether to fix the underlying export map issues or merge red.
Local results today (built with MIDEN_FAST_BUILD=true):
publint (exit 0 - warnings/suggestions only):
- @miden-sdk/miden-sdk: 1 suggestion (pkg.browser refactor)
- @miden-sdk/react: 1 warning + 2 suggestions
(types ambiguous under "import" condition;
missing "type" field; repository.url shape)
- @miden-sdk/vite-plugin: 1 warning + 2 suggestions (same shape as react)
attw (exit 1 - real failures):
- @miden-sdk/miden-sdk: CJSResolvesToESM, InternalResolutionError
across multiple matrix cells, NoResolution
on the /lazy subpath under node10
- @miden-sdk/react: FalseCJS (masquerading-as-CJS) under node16
from-ESM for both . and /lazy; NoResolution
on /lazy under node10
- @miden-sdk/vite-plugin: FalseCJS under node16 from-ESM
Per task scope, no source or build-config changes were made to address
these - the gate ships first, the fixes are followup work.
* chore(miden-sdk): fix exports map for attw + publint compliance
- Split the `exports` conditions into explicit `import` blocks with
`types` listed first, eliminating the ambiguous-types warning publint
reported. Drop the implicit `default` fallthrough that caused
attw to flag CJSResolvesToESM under the node16-cjs profile.
- Add an `.attw.json` selecting the `esm-only` profile. The package is
`"type": "module"` and ships only ESM artifacts (rollup output +
WASM glue); `require()` consumers must already use a dynamic import.
The `esm-only` profile communicates this intent to attw and makes
the node10 / node16-cjs columns informational only.
- Add a post-build step (`scripts/post-build.js`) that:
1. Rewrites extensionless relative specifiers in the published
`dist/*.d.ts` files (e.g. `from "./api-types"` ->
`from "./api-types.js"`). Without explicit extensions, Node16
type resolution flags an `InternalResolutionError` on every
relative import inside `dist/index.d.ts` and `dist/api-types.d.ts`.
2. Emits a `lazy/package.json` shim at the package root pointing at
`dist/index.{js,d.ts}` so node10 resolution (which doesn't read
`exports`) can still locate `@miden-sdk/miden-sdk/lazy`.
- Add `lazy` to the `files` array so the shim ships in the tarball.
- Expose `./package.json` from `exports` to keep tooling that reads
the manifest at runtime working under strict resolution.
Public import paths (`@miden-sdk/miden-sdk` and
`@miden-sdk/miden-sdk/lazy`) are unchanged. Verified that the
existing vitest unit suite (295 tests) still passes against the new
build output.
* chore(react-sdk): fix exports map for attw + publint compliance
- Split each `exports` subpath into explicit `import` / `require`
conditions with `types` listed first. publint flagged the previous
shape because `types: "./dist/index.d.ts"` resolved as CJS under the
`import` condition (FalseCJS / ambiguous-types). The new shape uses
the `.d.mts` declaration tsup already emits for the ESM build, so
TypeScript sees an `.mts` declaration when resolving via `import`
and a `.d.ts` declaration when resolving via `require`.
- Add `"type": "commonjs"` to silence publint's package-type-detection
suggestion (tsup emits `.js` as CJS and `.mjs` as ESM, matching).
- Add a `lazy/package.json` shim at the package root that points at
`dist/lazy.{js,mjs,d.ts}`. node10 resolution doesn't read the
`exports` map, so `@miden-sdk/react/lazy` previously failed to
resolve under that column; the shim is the standard fix.
- Expose `./package.json` from `exports` and add `lazy` to the `files`
array so the shim ships in the tarball.
Public import paths (`@miden-sdk/react` and `@miden-sdk/react/lazy`)
are unchanged. Verified that the existing vitest unit suite (719
tests) still passes.
* chore(vite-plugin): fix exports map for attw + publint compliance
- Split the `exports["."]` block into explicit `import` / `require`
conditions with `types` listed first. publint flagged the previous
shape because `types: "./dist/index.d.ts"` was interpreted as CJS
when resolving via the `import` condition (FalseCJS / ambiguous
types under `import`). The new shape uses the `.d.mts` declaration
tsup already emits for the ESM build, so TypeScript sees an
`.mts` declaration when resolving via `import` and a `.d.ts`
declaration when resolving via `require`.
- Add `"type": "commonjs"` to silence publint's package-type-detection
suggestion (tsup emits `.js` as CJS and `.mjs` as ESM, matching).
Public import path (`@miden-sdk/vite-plugin`) is unchanged. Verified
the existing vitest suite (27 tests) still passes.
* chore(react-sdk): drop CJS output, ship ESM-only
* chore(web-client): deduplicate lazy/package.json shim
* chore(ci): prettier-format post-build.js
* chore(react-sdk): rename CJS configs to .cjs after ESM-only flip
Switching @miden-sdk/react to "type": "module" makes .js files ESM by
default, which breaks two CJS-syntax files:
- packages/react-sdk/eslint.config.js (uses module.exports + require())
- packages/react-sdk/test/serve-tests.js (uses require())
Renamed both to .cjs. Updated playwright.config.ts:34 to reference the
new filename. ESLint auto-discovers either extension; no other consumer
references the renamed paths.
* chore: add vitest workspace + root test script * chore(vitest): migrate from defineWorkspace to defineConfig projects (vitest 3 modern shape) * chore(ci): exclude root vitest.config.ts from eslint typed-linting
* chore: add knip for unused-exports/deps detection
Lands knip 6.7.0 plus a baseline knip.jsonc config covering the four
TS-bearing workspaces (`packages/react-sdk`, `packages/vite-plugin`,
`crates/web-client`, `crates/idxdb-store/src`) and a root scripts entry.
Mode: warning-only. The script is `knip --no-exit-code` so CI does not
go red on day-one findings; promoting to strict mode is a follow-up
once the baseline backlog is cleared.
Baseline findings (pnpm run check:knip, exit 0 in --no-exit-code):
Unused files 4 (3 are .d.ts ambient declarations in
crates/web-client/js/types/, plus
packages/react-sdk/src/__tests__/utils/test-utils.tsx)
Unused dependencies 3 (root prettier; web-client @rollup/plugin-typescript, dexie)
Unused devDeps 5 (root and idxdb-store @typescript-eslint/eslint-plugin;
web-client http-server + mocha;
react-sdk http-server)
Unlisted dependency 1 (web-client test references @aspect-build/aspect-rsdoctor)
Unlisted binary 1 (vite in .github/workflows/wallet-pages.yml)
Unresolved imports 4 (web-client tests import ./eager.js / ./index.js
relative paths — likely dist-time URLs)
Unused exports 23 (all in packages/react-sdk test mocks)
Unused exported types 9 (react-sdk SignerContext + types/index.ts re-exports)
Duplicate exports 3 (playwright.global.setup.ts; react-jsx-runtime.js;
vite-plugin index.ts midenVitePlugin|default)
Per-workspace tally:
root 1 dep, 1 devDep
packages/react-sdk 1 file, 1 devDep, 23 exports, 9 types, 1 dup-export
packages/vite-plugin 1 dup-export
crates/web-client 3 files, 2 deps, 2 devDeps, 1 unlisted dep,
1 unlisted bin, 4 unresolved imports, 1 dup-export
crates/idxdb-store/src 1 devDep
No CI workflow added in this commit — that lands separately once the
baseline is cleaned up. No source code modified.
* chore(web-client): drop dead @aspect-build import in sync_lock test
The 'waiters are rejected when sync times out' test destructured
acquireSyncLock/releaseSyncLock/releaseSyncLockWithError from a stale
@aspect-build/aspect-rsdoctor path that has nothing to do with this
codebase, then immediately fell back to nulls and never used the
bindings. The only thing actually exercised below is client.syncState(),
so the destructuring + bogus import was pure dead code.
Flagged by knip as the sole 'unlisted dependency' import in
crates/web-client; removing the dead block both fixes the finding and
makes the test honest about what it's checking.
* chore: drop unused devDeps + deps flagged by knip
Removes packages that no source file, build config, lint config, test, or
script references. Verified each by grepping the repo for imports / CLI
invocations / config references before deletion.
- root: @typescript-eslint/eslint-plugin (root eslint.config.js wires
parser only; no plugin-rules block, so the plugin pkg sits idle)
- crates/idxdb-store/src: @typescript-eslint/eslint-plugin (its
eslint.config.mjs uses 'typescript-eslint' meta-package, not the
legacy plugin)
- packages/react-sdk: http-server (no script or workflow runs it)
- crates/web-client: http-server, mocha (rollup + playwright + vitest
pipeline does not invoke either; no .mocharc, no http-server script)
- crates/web-client deps: @rollup/plugin-typescript (rollup.config.js
uses node-resolve + commonjs + wasm-tool only — no TS plugin), dexie
(only the idxdb-store crate uses dexie, and it lists its own copy)
Lockfile regenerated via pnpm install --no-frozen-lockfile.
* chore: drop unused files + dead exports flagged by knip
react-sdk:
- Delete src/__tests__/utils/test-utils.tsx — exports renderWithProvider,
renderHookWithProvider, etc., none of which any test imports. The repo
uses renderHook/render directly from @testing-library/react.
- Strip 'export' off internal mock helpers and types in __tests__/mocks/
(createMockOutputNote, createMockTransactionRecord, MockNoteFilter and
~17 other Mock* constants, MockWebClientType, createMockSignCallback,
createMockAccountStorageMode). They were never imported across module
boundaries; making them module-private is correct.
- Delete the createMockSdkModule factory along with the Mock* class /
enum constants that only existed to populate it. No test in the repo
ever called the factory, so it pulled an entire wing of dead code.
- Remove unreachable type re-exports: GetKeyCallback / InsertKeyCallback
/ NoteId / NoteVisibility / StorageMode were re-exported through
src/types/index.ts but src/index.ts never re-exported them, so they
were not part of the package's public surface. The underlying types
stay locally-typed where they're actually used.
- Make ClientWithTransactions in src/utils/transactions.ts module-private
(the noteFilters.ts copy is the one consumers use).
web-client:
- Delete crates/web-client/.mocharc.json (only consumer was mocha, which
was removed in the previous commit) and the matching ts-node /
esm devDeps + the now-orphan ts-node block in tsconfig.json.
Public API of @miden-sdk/react is unchanged: every type still exported
through src/index.ts continues to be exported. Only types that were
never reachable through the package entry have been demoted.
* chore(knip): allowlist public-API exports + ambient .d.ts files
After deleting actual dead code, the remaining findings are all cases
where knip can't statically see the consumer:
- crates/web-client/js/types/{index,api-types,docs-entry}.d.ts: shipped
as the package's published types via 'cpr js/types dist' in the build
script, so they ARE the consumer of themselves at publish time.
Registered as entry points with a comment naming the post-build copy
step.
- ./eager.js, ./index.js: dynamic imports inside page.evaluate()
callbacks, executed in the browser against http://localhost:8080
(i.e. the dist/ output served by the test http server). Resolved at
test runtime, not relative to the Playwright test file. Allowlisted
via ignoreUnresolved with a comment.
- ./crates/miden_client_web: wasm-bindgen module emitted into dist/ by
the rollup rust plugin; the .d.ts files reference it but it doesn't
exist until after build. Same allowlist with a comment.
- prettier: invoked from the repo Makefile via 'pnpm exec prettier .';
knip doesn't scan Makefile rules. Allowlisted in ignoreDependencies.
- vite: invoked from .github/workflows/wallet-pages.yml via 'pnpm exec
vite build' inside the wallet example workspace, which has its own
package.json + lockfile not visible to this monorepo's graph.
Allowlisted in ignoreBinaries.
- Three intentional dual-export sites (vite plugin named+default, the
Playwright test fixture's named+default 'test', and the React JSX
runtime shim's jsx/jsxs/jsxDEV aliases): rules.duplicates set to
'off' globally with a comment enumerating each case so a future
change knows when to revisit it.
Also dropped the redundant entry patterns and the empty docs/** ignore
patterns that knip flagged as configuration hints.
After this, 'pnpm exec knip' exits 0 with zero findings; the 3 remaining
'configuration hints' are about react-sdk's package.json exports
pointing at not-yet-built dist/lazy.* files, which is correct and
doesn't affect the exit code.
* chore(knip): flip check:knip to strict mode
All baseline findings have been triaged in the preceding commits, so the
warning-only flag is no longer needed. Knip now fails CI on any new
unused export / dep / file / unresolved import.
* chore(ci): wire knip into lint workflow
* chore(ci): restore dexie + prettier-format knip files
Knip's static scan flagged dexie as unused, but it's bundled into the
web-client test page at runtime via rollup — page.evaluate blocks load
the bundle from localhost:8080 which transitively imports dexie. The
removal broke 22 integration tests with "Failed to resolve module
specifier 'dexie'". Re-added dexie@^4.0.1 to crates/web-client deps
and registered it in knip's top-level ignoreDependencies with a comment.
Also runs prettier --write on knip.jsonc and two react-sdk source
files that were missed in the earlier cleanup pass.
* chore(knip): allowlist publint/attw + .cjs serve-tests rename
Removes overlapping formatting rules (semi, comma-dangle, eol-last, space-before-blocks, keyword-spacing, no-multiple-empty-lines) from the root eslint.config.js so Prettier 3.x is the single source of truth for style. Logic rules (camelcase, @typescript-eslint/no-unused-vars) are preserved. Adds eslint-config-prettier as the last entry in both flat configs (eslint.config.js and packages/react-sdk/eslint.config.js) to disable any remaining stylistic rules pulled in transitively from rule presets, preventing eslint and prettier from fighting. Extends .prettierignore to mirror the eslint configs' ignore list (dist, target, node_modules, generated .d.ts, docs, idxdb-store codegen) so prettier --check stays scoped to source we actually own. The existing .prettierrc.json (trailingComma: es5) is left as-is. Verified: pnpm --filter @miden-sdk/react run lint shows 0 errors (same 5 pre-existing warnings as main); prettier --check on packages/react-sdk and packages/vite-plugin source passes with no reformatting needed.
…#35) The pre-split miden-client release workflow shipped all three packages on a tagged release; the web-sdk port dropped react-sdk and vite-plugin publishing while keeping web-client. End users `npm install @miden-sdk/react` were therefore stuck on the `next` dist-tag (set by publish-web-client-next.yml) instead of getting the latest tagged release. This restores parity with pre-split behaviour: - New scripts/check-react-sdk-version-release.sh and scripts/check-vite-plugin-version-release.sh — same pattern as the existing check-web-client-version-release.sh (compare package.json version against the tagged commit's parent, set should_publish flag). - publish-web-client-release.yml now runs each package's version-bump check and conditionally builds + publishes that package. The three publishes are independent, so a release that bumps only one package republishes only that one. - The web-client build runs whenever EITHER web-client OR react-sdk needs to ship, since react-sdk's build consumes the WASM dist.
Match the secret name to the cargo env var (and to miden-node's convention) so the publish-crates workflow picks up the org-managed secret without an indirection.
…ale AGENTS (#38) - Add a top-level CLAUDE.md aimed at AI agents (and humans skimming for build/lint/test/release conventions). Captures pnpm-only rule, the Makefile-driven workflows, runExclusive, the eager/lazy entry contract, the npm-registry-driven publish gate, and cross-repo coordination notes. The README already links to it (line 337). - Refresh packages/react-sdk/CLAUDE.md against the current source: * useNotes returns notes/consumableNotes (not input/consumable) * useAccounts returns accounts/wallets/faucets (no 'all') * Mutation hooks expose action-named callbacks (send, mint, ...) and a 'result' field — not generic { mutate, data } * useSend / useMultiSend take assetId / recipients (not faucetId / outputs) * SendResult has txId (not transactionId) * SignerAccountConfig uses publicKeyCommitment + accountType * Hook reference table reorganized into query/mutation buckets and includes the previously-undocumented hooks (useNoteStream, useSyncControl, useTransactionHistory, useImportNote / Export*, etc.) - Remove docs/planning/AGENTS.md — 7 lines of miden-client leftover that referenced 'yarn prettier' (the repo migrated to pnpm). All the still-useful content is now in the top-level CLAUDE.md.
Forward-port main's hotfix-stream commits onto next: - #14 docs: import 5 web-SDK-relevant planning docs from miden-client - #15 publint + attw gates and fix exports maps (lazy entry on main) - #16 react-sdk eslint+typescript-eslint dep alignment - #17 knip in strict mode - #18 drop mocha/chai/puppeteer/esm/ts-node devDeps from web-client - #19 .nvmrc + lefthook + lint-staged - #20 drop stylistic eslint rules; let prettier own formatting - #21 vitest workspace + root test script - #34 (NOT applied) bump miden-client to 0.14.5 — would regress next's git+branch=next dep that tracks miden-client 0.15.x in development - #35 publish react-sdk + vite-plugin alongside web-client (already on next via #36) - #37 rename CRATES_IO_TOKEN secret to CARGO_REGISTRY_TOKEN (already on next via #36) - #38 add top-level CLAUDE.md + refresh react-sdk usage guide Conflict resolutions (all in favor of next where main and next have diverged architecturally): - Cargo.toml — kept next's miden-client = git+branch=next pin (rejected main's 0.14.5 crates.io regression) - Cargo.lock — kept next's lock (matches next's Cargo.toml) - .github/workflows/publish-web-client-release.yml — kept next's multi-job napi-augmented variant; main's single-job version was a strict subset - .github/workflows/test.yml — kept next's drop of test-web-client-unit job (the JS API drift from miden-client next made those vitest specs no longer match; covered by Playwright + the Node.js test job) - crates/web-client/package.json — kept next's structure (browser+node exports without the eager/lazy split; napi-aware files list) - packages/react-sdk/package.json — kept next's structure (no /lazy subpath export) - packages/react-sdk/tsup.config.ts — kept next's deletion (next's build script invokes tsup with CLI args, not via config file) - crates/web-client/test/tags.test.ts — kept next's modernized test harness (run + client/sdk/helpers fixture; main still uses page fixture) Net-additive files brought in from main (auto-merged, harmless on next but currently unwired into next's exports): - crates/web-client/lazy/package.json (subpath stub for the eager/lazy split — not reachable via next's exports map) - packages/react-sdk/lazy/package.json (same) - crates/web-client/scripts/post-build.js (called by main's build script; next's build script does not invoke it yet) These three orphan files are tracked here so a follow-up PR can decide whether to wire next's package.jsons up to use the eager/lazy split, or to delete the orphan files.
Follow-up on the merge: bring main's eager/lazy entry-point split to next without dropping next's napi-rs Node.js binding. Conflicts in the original merge of #39 left the lazy/ subpath stub and post-build.js orphaned (auto-merged from main but not reachable through next's exports map). This commit wires them up by: - Recreating crates/web-client/js/eager.js. Same wrapper as main: at module top level, await getWasmOrThrow() then re-export * from ./index.js. (The file existed on main; PR #13's import of miden-client next overwrote next's tree wholesale and the eager wrapper was lost.) - Adding ./js/eager.js to rollup.config.js's input list so the build emits dist/eager.js alongside dist/index.js. - Rewriting crates/web-client/package.json's exports map to combine next's napi node entry with main's eager/lazy split: ".": node → ./js/node-index.js (napi binding for Node.js) import.default → ./dist/eager.js (browser default, TLA) "./lazy": import.default → ./dist/index.js (browser SSR/Capacitor) - Wiring node ./scripts/post-build.js into the build chain (was auto-merged from main but not invoked) so dist's .d.ts files get the relative-import extension fixups attw / publint require. - Dropping packages/react-sdk/lazy/package.json. The orphan stub was auto-merged from main but next's react-sdk doesn't expose a /lazy subpath in its package.json yet — adopting that requires also flipping the react-sdk source to import from `@miden-sdk/miden-sdk/lazy` and reintroducing the tsup config with the eager-rewrite hook. Out of scope here; tracked as a separate follow-up. Smoke-tested locally: `pnpm --filter @miden-sdk/miden-sdk run build` emits dist/eager.js (4.4KB wrapper) and dist/index.js (108KB lazy bundle) in 2m30s; post-build rewrites 3 .d.ts files.
Three CI gates that landed via the merge from main now run cleanly on next.
knip (unused-deps/exports):
- crates/web-client/package.json: remove chai, esm, http-server, mocha,
puppeteer, ts-node, @rollup/plugin-typescript (web-client doesn't run
vitest itself; tests are Playwright-only).
- packages/react-sdk/package.json: bump @typescript-eslint/* to ^8 and
eslint to ^9 (matches root); drop http-server.
- crates/idxdb-store/src/package.json: drop @vitest/coverage-v8 (root
vitest workspace owns coverage).
- knip.jsonc: refresh crates/web-client entry patterns for next's
layout (add storageView.js, js/node/**; drop safe-arrays.js and
js/__tests__/ that don't exist on next). Drop ./eager.js from
ignoreUnresolved (the file now exists). js/node-index.js is auto-
detected via the package.json 'node' exports condition; remove the
redundant entry.
- napi-compat.js: drop the export keyword on internal-only helpers
(wrapClass, patchSdkPrototypes, makeArrayPolyfills) — they're used
inside the file but not imported by any consumer.
- test/node-adapter.ts: drop export on sdk + MockWasmWebClient (used
internally by setupNodeGlobals + WasmWebClient wrappers, not by any
test).
- test/test-setup.ts: drop export on createNodeMockClient + createNode
SdkWrapper (used internally by the test fixture factories).
- test/test-helpers.ts: delete integrationMint + integrationConsume
(intended as test helpers but no callers — ressurect from git history
if a future test needs them).
- packages/react-sdk/src/store/MidenStore.ts: delete useClient,
useIsReady, useInitError, useConfig selectors — never imported (the
test that name-checked 'useClient'/'useIsReady' actually exercises
state via getState(), not the hook).
publint + attw:
- crates/web-client/package.json: split the 'node' exports condition
into a {types, default} pair pointing at dist/index.d.ts so attw +
publint stop flagging the napi entry as type-less.
- packages/react-sdk/package.json: split exports into separate import
+ require conditions, each with its own types entry, so node16-from-
ESM resolution stops 'masquerading as CJS' (attw 🎭).
pnpm-lock.yaml: regenerated against the cleaned package.jsons.
Knip flagged @vitest/coverage-v8 as unused because vitest loads it dynamically at runtime when --coverage is passed; knip's static scan can't see the dependency. Removing it broke 'idxdb-store unit tests' on CI with ERR_MODULE_NOT_FOUND. Add it back, mark it as ignoreDependencies in knip's per-workspace config for crates/idxdb-store/src.
…over @vitest/coverage-v8)
Cleaner replacement for the previous knip ignoreDependencies workaround.
The previous fix re-added @vitest/coverage-v8 to package.json and
manually told knip to ignore it. That worked but was the wrong layer:
knip's vitest plugin reads vitest.config.ts and discovers any provider
referenced under coverage.provider as a real dep. Main's idxdb-store
config has `coverage: { provider: 'v8', ... }`; next's was stripped
to bare environment+setupFiles when PR #13 imported miden-client next,
so knip lost sight of the dep entirely.
Restore the coverage block — provider, reporters, include/exclude —
which gives knip its static reference and also produces a real
coverage report on every CI run. Keep the threshold field empty for
now: next has napi additions (notes.ts, settings.ts, sync.ts,
transactions.ts, etc.) at ~0% coverage that main's 95/95/95/95 gate
would reject. Backfilling those tests is tracked separately; once
covered we ratchet next up to match main.
… gate Bring next's idxdb-store/ts/ test coverage in line with main's: - 7 test files were missing entirely on next (auth.test.ts, export.test.ts, import.test.ts, settings.test.ts, sync.test.ts, transactions.test.ts, utils.test.ts) — port verbatim from main; the underlying source files are byte-identical between branches. - 4 test files (accounts, chainData, notes, schema) were thinner on next than main — overwrite with main's versions. - chainData.test.ts: patch the 3 pruneIrrelevantBlocks call sites for next's expanded signature (dbId + blocksToUntrack[] + nodeIdsToRemove[] vs main's single dbId arg). Add two new tests for the napi-only pruning paths (untrack-then-prune, MMR-node deletion). - Restore the 95/95/95/95 thresholds in vitest.config.ts that PR #13 inadvertently dropped when it imported miden-client next into web-sdk next. Result: 298 tests pass, coverage 99.88%/97.63%/100%/99.88% (lines/branches/funcs/stmts) — clears the 95% gate on every metric.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Forward-port `main`'s hotfix-stream commits onto `next`. `main` has accumulated 12 commits since the two branches diverged; this PR brings them across (modulo two that don't apply on next), and wires up the eager/lazy entry-point split on next while preserving its napi-rs Node.js binding.
What lands on next from main
Hybrid eager/lazy + napi (commit `bcf093b1`)
The merge originally left main's eager/lazy split orphaned on next — the `lazy/package.json` stubs and `post-build.js` came across, but next's `package.json` exports kept its napi-only shape and the `js/eager.js` wrapper that main has was missing entirely (PR #13's bulk import of miden-client `next` overwrote next's tree before main introduced eager.js).
This PR now wires the split up properly:
```jsonc
".": {
"node": "./js/node-index.js", // napi: Node.js gets the native binding
"import": { "types": "./dist/index.d.ts",
"default": "./dist/eager.js" } // browser default: TLA-eager
},
"./lazy": {
"import": { "types": "./dist/index.d.ts",
"default": "./dist/index.js" } // SSR / Capacitor / lazy init
},
"./package.json": "./package.json"
```
Smoke-tested locally: `pnpm --filter @miden-sdk/miden-sdk run build` emits `dist/eager.js` (4.4KB) and `dist/index.js` (108KB) in ~2m30s; post-build rewrites 3 `.d.ts` files.
Conflict resolutions
All in favor of `next` where the two branches diverged architecturally:
Follow-ups
Test plan