Contributing & Development Workflow
Prerequisites
- Node.js >= 20
- pnpm >= 8
Initial setup
pnpm install
pnpm buildpnpm build runs a full production build of all packages (via Turborepo). This is required once after cloning so that downstream packages can resolve each other.
Dev setup (after initial build)
When working on packages locally, switch them to stub mode instead of rebuilding after every change:
# Stub all packages at once (from monorepo root)
pnpm dev:packages
# Or stub a single package
pnpm --filter @mapomodule/store dev:prepareStub mode replaces dist/ with files that re-export directly from src/. This gives you:
- Instant type resolution in the IDE (no empty
.d.tsfiles) - No need to rebuild after every source change
After stubbing, regenerate the Nuxt app's auto-import types:
cd apps/example-e2e # or whichever app you're using
pnpm nuxt prepareNote: if you accidentally run
pnpm buildon a package during development, re-rundev:prepareon it and thennuxt prepareon the app. The production build now includes a dedicated declaration pass (tsc/vue-tscviatsconfig.build-types.json) and, for SFC packages, a cleanup step that removes zero-byte.vue.d.tsstubs.
Git Hooks (Husky)
Two hooks run automatically on every commit.
pre-commit — Prettier + focused tests
lint-staged runs two commands on the staged files:
prettier --write— formats all staged.ts,.tsx,.vue,.json,.mdfiles in place.vitest related --run— runs only the tests that cover the staged.ts/.tsx/.vuefiles.
vitest related inspects the import graph and executes only the subset of tests that directly or transitively import the changed files. If you modify src/deepMerge.ts, only deepMerge.test.ts runs — not the entire test suite.
commit-msg — commitlint
Every commit message is validated against the Conventional Commits spec. Invalid messages are rejected before the commit is recorded.
feat(core): add useMapoAuth composable ✔
fix(form): correct nested accessor path ✔
wip: stuff ✘Running Tests
# All packages (via Turborepo)
pnpm test
# Single package
pnpm --filter @mapomodule/utils test
# Watch mode (during development)
pnpm --filter @mapomodule/utils exec vitestType checking
# All packages (via Turborepo)
pnpm typecheck
# Single package
pnpm --filter @mapomodule/uikit typecheckPure-TypeScript packages (core, store, utils) type-check with tsc --noEmit. The packages that ship Vue SFCs (uikit, form) type-check with vue-tsc --noEmit, so .vue single-file components — including <script setup> and template bindings — are part of the gate. Run pnpm typecheck before pushing; the CI typecheck job runs the same thing.
Building
# All packages (respects dependency order)
pnpm build
# Single package
pnpm --filter @mapomodule/utils buildBuild pipeline details:
nuxt-module-build buildemits runtime artifacts indist/.tsconfig.build-types.jsonruns a declaration-only pass with stable mapping (src->dist).- TS-only packages use
tsc; SFC packages (form,uikit) usevue-tsc. - SFC packages run
node ../../../scripts/clean-empty-vue-dts.mjs distto remove empty.vue.d.ts/.d.vue.tsfiles that would degrade consumer typing.
CI Pipeline
The GitHub Actions pipeline mirrors local checks and runs in this order:
lint & typecheck → test → releaseThe release job only runs on push to main after both previous jobs pass.
TODO: in a future iteration, expand the pipeline test stage with a matrix covering multiple supported Node.js versions, Nuxt versions, and other relevant compatibility targets instead of a single runtime combination.
See Release Process for full details.