How to land changes in this monorepo.
- Node 22 LTS or newer for development. The
.nvmrcpins22(resolves to the latest 22.x onnvm/fnm/volta) so contributors test the published floor by default. CI runs[22, 24]. The published packages declareengines.node: >=22.0.0. See "Node version management" in AGENTS.md for the three-knob model. - pnpm 11.x. Corepack will install the exact version pinned in the root
package.json#packageManagerfield — you don't need to install pnpm globally.
git clone git@github.com:inflowpayai/inflow-node.git
cd inflow-node
corepack enable
pnpm install --frozen-lockfileThe first install will take a few minutes. Subsequent commands hit turbo's cache and are usually instant.
pnpm typecheck # tsc --noEmit against tsconfig.json + tsconfig.test.json per package (turbo'd)
pnpm lint # eslint src test --max-warnings 0 (turbo'd; covers both src/ and test/)
pnpm build # tsup, dual ESM + CJS + .d.ts (turbo'd)
pnpm test # turbo runs each package's vitest run --coverage; thresholds enforced per-package
pnpm format # prettier write — also reflows TSDoc bodies to printWidth via prettier-plugin-jsdoc (direct — not turbo'd)
pnpm typedoc # generate API reference into docs/api/ (gitignored)The first four run via Turborepo. Cache hits are reported on the right-hand side of each line; touch a file in one
package and only that package plus its dependents rebuild. format runs prettier directly across the whole tree.
Pre-release / publish troubleshooting scripts:
pnpm check-exports # validates each package's `exports` map resolves on disk after build
pnpm verify-publish # `pnpm pack --dry-run` per package; asserts dist/, README.md, LICENSE in each tarball
pnpm check-publish # builds, then runs the two above — use before tagging a releaseThese run automatically in .github/workflows/ci.yml (between Build and Test) and inside pnpm release, so the normal
flow doesn't need them. See publishing.md for the full release pipeline.
To run a single package's tests:
pnpm --filter @inflowpayai/x402-seller testTo watch a single package:
pnpm --filter @inflowpayai/x402-seller test:watchA single long-lived main branch. Feature work happens on short-lived branches off main:
git switch -c feat/x402-buyer-better-retry
# … hack …
git push -u origin feat/x402-buyer-better-retry
gh pr create --base mainPRs that touch packages/** need a Changeset entry. CI fails the PR without one.
pnpm changeset
# select packages, pick patch/minor/major, write the summary
git add .changeset/*.md && git commit -m "chore: add changeset"
git pushSee publishing.md for the full release flow.
Conventional Commits. Pick one of feat, fix, chore, docs, refactor, test, perf, build, ci. Scope by
package:
feat(x402-seller): add inflowAccepts permit2 emission
fix(x402-buyer): poll loop respects retries: 0
docs(monorepo): clarify branch model
refactor(x402-seller): collapse capability table into facilitator client
The release-PR generation step uses Conventional Commits to produce the CHANGELOG.md entries.
- Strict TypeScript:
strict,noUncheckedIndexedAccess,exactOptionalPropertyTypes. Noany, no!assertions, noas unknown ascasts except at documented type boundaries (seepackages/x402-buyer/src/inflow-client.tsfor the canonical pattern — the foundationx402Clientdoesn't accept InFlow's widenednetwork: string). - Comments describe what the code does or why it exists right now. No references to phases, milestones, server-side internals, or "future work."
- Use the typed accessor helpers (
@inflowpayai/x402/extensions,@inflowpayai/x402/extras) rather than direct bracket access on open-endedextra/extensionsmaps. - Lint emoji-free unless the request explicitly calls for them.
- Vitest. Per-package
vitest.config.ts. MSW for HTTP mocking (Node mode).fast-checkfor property tests where a unit invariant fits. - Coverage threshold ≥90% lines / functions / statements, ≥85% branches — enforced.
pnpm testfails the build below the floor. - Defensive guards that can't be reached from external inputs should be marked
/* v8 ignore start/stop */rather than hand-crafted tests that exist purely to satisfy coverage.
When adding one, follow the same template as the existing three (x402, x402-seller, x402-buyer):
packages/<name>/{src,test/unit}package.jsonwith"version": "1.0.0",peerDependencies,publishConfig.access: public,publishConfig.provenance: truetsconfig.jsonextendingtsconfig.base.jsontsup.config.ts+vitest.config.tsREADME.md
Then pnpm install to update the lockfile.
Use GitHub Issues. For security-sensitive findings, see SECURITY.md.
- publishing.md — release flow, npm provenance, first publish.
- tooling.md — pnpm, Turborepo, Changesets, Vitest, tsup reference.