{"_id":"@cardano-mercury/core","_rev":"4-e2c6efcd4018bc4dac9b2e2810622406","name":"@cardano-mercury/core","dist-tags":{"latest":"0.2.3"},"versions":{"0.2.0":{"name":"@cardano-mercury/core","version":"0.2.0","license":"MIT","_id":"@cardano-mercury/core@0.2.0","maintainers":[{"name":"therealadamdean","email":"adam@crypto2099.io"}],"homepage":"https://github.com/cardano-mercury/mercury-core#readme","bugs":{"url":"https://github.com/cardano-mercury/mercury-core/issues"},"bin":{"mercury-core":"bin/mercury-core.js"},"dist":{"shasum":"3e567c2131de17c0928525eb5ba612a913777f2f","tarball":"https://registry.npmjs.org/@cardano-mercury/core/-/core-0.2.0.tgz","fileCount":23,"integrity":"sha512-I3UPP1eloKAtrdIMNrgu5minKhPkDXoKPLovPxB4134pg3mVP4URWgoHtzjq73VaPu7TtBX0ZXIvwRD1oOqY2w==","signatures":[{"sig":"MEQCIBxho5rxQWBIuKzf91J3Itkn3A1up6zDYin4PwU2opQRAiA8z5woBphZT28zx0rgylJ7jZCCHtwVIu/Ni9gow/kqtA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cardano-mercury%2fcore@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":86558},"type":"module","exports":{"./db":{"types":"./dist/db/index.d.ts","default":"./dist/db/index.js"},"./auth":{"types":"./dist/auth/index.d.ts","default":"./dist/auth/index.js"},"./money":{"types":"./dist/money.d.ts","default":"./dist/money.js"},"./cardano":{"types":"./dist/cardano/index.d.ts","default":"./dist/cardano/index.js"},"./db/migrate":{"types":"./dist/db/migrate.d.ts","default":"./dist/db/migrate.js"}},"gitHead":"c294920fe62fb562fa6db3fde508709be077bda5","scripts":{"dev":"tsc -p tsconfig.build.json --watch","lint":"eslint .","test":"vitest run","build":"tsc -p tsconfig.build.json","check":"tsc -p tsconfig.json --noEmit","format":"prettier --write .","db:migrate":"node bin/mercury-core.js migrate","test:watch":"vitest","db:generate":"drizzle-kit generate","format:check":"prettier --check .","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"therealadamdean","email":"adam@crypto2099.io"},"repository":{"url":"git+https://github.com/cardano-mercury/mercury-core.git","type":"git"},"_npmVersion":"10.9.8","description":"Shared database schema, authentication, and Cardano utilities for the Mercury apps.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"postgres":"^3.4.9"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.6.0","vitest":"^2.1.9","prettier":"^3.9.4","@eslint/js":"^10.0.1","typescript":"^5.6.0","@types/node":"^22","better-auth":"~1.6.23","drizzle-kit":"^0.31.10","drizzle-orm":"^0.45.2","@meshsdk/core":"^1.9.1","typescript-eslint":"^8.62.1","@vitest/coverage-v8":"^2.1.9","eslint-config-prettier":"^10.1.8"},"peerDependencies":{"better-auth":"~1.6.23","drizzle-orm":">=0.40","@meshsdk/core":"*"},"_npmOperationalInternal":{"tmp":"tmp/core_0.2.0_1783967299775_0.4191023071315758","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@cardano-mercury/core","version":"0.2.1","license":"MIT","_id":"@cardano-mercury/core@0.2.1","maintainers":[{"name":"therealadamdean","email":"adam@crypto2099.io"}],"homepage":"https://github.com/cardano-mercury/mercury-core#readme","bugs":{"url":"https://github.com/cardano-mercury/mercury-core/issues"},"bin":{"mercury-core":"bin/mercury-core.js"},"dist":{"shasum":"27ffbe020a09f292cdca433c9c46fd4ca32d22cf","tarball":"https://registry.npmjs.org/@cardano-mercury/core/-/core-0.2.1.tgz","fileCount":23,"integrity":"sha512-vKEj4p00SEvLNBFfs4M8dezy5hc4DvL655PfN2Zcwh1c57xugxLrcEh5I8VXIxQN0Qkf940rkoUW8ByKbo8NaQ==","signatures":[{"sig":"MEUCIH2AlcXCj42MBspRMkOMM1h2kkW9BeUWsIxVzEJRZ4ByAiEAvMT7fjRC6YJvZWzrjhzlFp8N+vpDafaaxav+seoHGQg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cardano-mercury%2fcore@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":86617},"type":"module","exports":{"./db":{"types":"./dist/db/index.d.ts","default":"./dist/db/index.js"},"./auth":{"types":"./dist/auth/index.d.ts","default":"./dist/auth/index.js"},"./money":{"types":"./dist/money.d.ts","default":"./dist/money.js"},"./cardano":{"types":"./dist/cardano/index.d.ts","default":"./dist/cardano/index.js"},"./db/migrate":{"types":"./dist/db/migrate.d.ts","default":"./dist/db/migrate.js"}},"gitHead":"beaa361e4341e0ba1ac693d675ad3e012b56f2ff","scripts":{"dev":"tsc -p tsconfig.build.json --watch","lint":"eslint .","test":"vitest run","build":"tsc -p tsconfig.build.json","check":"tsc -p tsconfig.json --noEmit","smoke":"bash scripts/smoke-pack.sh","format":"prettier --write .","db:migrate":"node bin/mercury-core.js migrate","test:watch":"vitest","db:generate":"drizzle-kit generate","format:check":"prettier --check .","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"therealadamdean","email":"adam@crypto2099.io"},"repository":{"url":"git+https://github.com/cardano-mercury/mercury-core.git","type":"git"},"_npmVersion":"10.9.8","description":"Shared database schema, authentication, and Cardano utilities for the Mercury apps.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"postgres":"^3.4.9"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.6.0","vitest":"^2.1.9","prettier":"^3.9.4","@eslint/js":"^10.0.1","typescript":"^5.6.0","@types/node":"^22","better-auth":"~1.6.23","drizzle-kit":"^0.31.10","drizzle-orm":"^0.45.2","@meshsdk/core":"^1.9.1","typescript-eslint":"^8.62.1","@vitest/coverage-v8":"^2.1.9","eslint-config-prettier":"^10.1.8"},"peerDependencies":{"better-auth":"~1.6.23","drizzle-orm":">=0.40","@meshsdk/core":"*"},"_npmOperationalInternal":{"tmp":"tmp/core_0.2.1_1783982878209_0.5870675961394043","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@cardano-mercury/core","version":"0.2.2","keywords":["cardano","mercury","better-auth","drizzle","blockfrost","postgres"],"author":{"name":"Cardano Mercury, Inc."},"license":"Apache-2.0","_id":"@cardano-mercury/core@0.2.2","maintainers":[{"name":"therealadamdean","email":"adam@crypto2099.io"}],"homepage":"https://github.com/cardano-mercury/mercury-core#readme","bugs":{"url":"https://github.com/cardano-mercury/mercury-core/issues"},"bin":{"mercury-core":"bin/mercury-core.js"},"dist":{"shasum":"5147e48320f55fffe756044d130a9f06261e0c9f","tarball":"https://registry.npmjs.org/@cardano-mercury/core/-/core-0.2.2.tgz","fileCount":23,"integrity":"sha512-Cg9n4qjQUdUI/qEKuVyl9OwaD1V4GLarXPAlA35jGILHrRKpZzBThCbEufhSChqVIiXUi5R91S8nrZ/CRizO3Q==","signatures":[{"sig":"MEQCIF4+EPEYQpy9YTITycfGiTOopYfRt3Bd1hgr59BtkNDWAiAaHxNBrTFM0KnEHN+SJA6YVZgVZF9ilDD1pV4nB8Fo9A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cardano-mercury%2fcore@0.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":91200},"type":"module","engines":{"node":">=22"},"exports":{"./db":{"types":"./dist/db/index.d.ts","default":"./dist/db/index.js"},"./auth":{"types":"./dist/auth/index.d.ts","default":"./dist/auth/index.js"},"./money":{"types":"./dist/money.d.ts","default":"./dist/money.js"},"./cardano":{"types":"./dist/cardano/index.d.ts","default":"./dist/cardano/index.js"},"./db/migrate":{"types":"./dist/db/migrate.d.ts","default":"./dist/db/migrate.js"}},"gitHead":"e1f519ceb7074dc754d7fe81aa562ba9e21e0c21","scripts":{"dev":"tsc -p tsconfig.build.json --watch","lint":"eslint .","test":"vitest run","build":"tsc -p tsconfig.build.json","check":"tsc -p tsconfig.json --noEmit","smoke":"bash scripts/smoke-pack.sh","format":"prettier --write .","changeset":"changeset","db:migrate":"node bin/mercury-core.js migrate","test:watch":"vitest","db:generate":"drizzle-kit generate","format:check":"prettier --check .","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build","changeset:version":"changeset version"},"_npmUser":{"name":"therealadamdean","email":"adam@crypto2099.io"},"repository":{"url":"git+https://github.com/cardano-mercury/mercury-core.git","type":"git"},"_npmVersion":"10.9.8","description":"Shared database schema, authentication, and Cardano utilities for the Mercury apps.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","dependencies":{"postgres":"^3.4.9"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.6.0","vitest":"^4.1.10","prettier":"^3.9.4","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^26","better-auth":"~1.6.23","drizzle-kit":"^0.31.10","drizzle-orm":"^0.45.2","@meshsdk/core":"^1.9.1","@changesets/cli":"^2.31.0","typescript-eslint":"^8.62.1","@vitest/coverage-v8":"^4.1.10","eslint-config-prettier":"^10.1.8"},"peerDependencies":{"better-auth":"~1.6.23","drizzle-orm":">=0.40","@meshsdk/core":"*"},"_npmOperationalInternal":{"tmp":"tmp/core_0.2.2_1784051680959_0.2117105670354249","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@cardano-mercury/core","version":"0.2.3","description":"Shared database schema, authentication, and Cardano utilities for the Mercury apps.","keywords":["cardano","mercury","better-auth","drizzle","blockfrost","postgres"],"license":"Apache-2.0","author":{"name":"Cardano Mercury, Inc."},"repository":{"type":"git","url":"git+https://github.com/cardano-mercury/mercury-core.git"},"homepage":"https://github.com/cardano-mercury/mercury-core#readme","bugs":{"url":"https://github.com/cardano-mercury/mercury-core/issues"},"engines":{"node":">=22"},"type":"module","sideEffects":false,"publishConfig":{"access":"public"},"bin":{"mercury-core":"bin/mercury-core.js"},"exports":{"./db":{"types":"./dist/db/index.d.ts","default":"./dist/db/index.js"},"./db/migrate":{"types":"./dist/db/migrate.d.ts","default":"./dist/db/migrate.js"},"./auth":{"types":"./dist/auth/index.d.ts","default":"./dist/auth/index.js"},"./cardano":{"types":"./dist/cardano/index.d.ts","default":"./dist/cardano/index.js"},"./money":{"types":"./dist/money.d.ts","default":"./dist/money.js"}},"scripts":{"prepublishOnly":"npm run build","build":"tsc -p tsconfig.build.json","smoke":"bash scripts/smoke-pack.sh","dev":"tsc -p tsconfig.build.json --watch","check":"tsc -p tsconfig.json --noEmit","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","lint":"eslint .","format":"prettier --write .","format:check":"prettier --check .","db:generate":"drizzle-kit generate","db:migrate":"node bin/mercury-core.js migrate","changeset":"changeset","changeset:version":"changeset version"},"peerDependencies":{"@meshsdk/core":"*","better-auth":"~1.6.23","drizzle-orm":">=0.40"},"dependencies":{"postgres":"^3.4.9"},"devDependencies":{"@changesets/cli":"^2.31.0","@eslint/js":"^10.0.1","@meshsdk/core":"^1.9.1","@types/node":"^26","@vitest/coverage-v8":"^4.1.10","better-auth":"~1.6.23","drizzle-kit":"^0.31.10","drizzle-orm":"^0.45.2","eslint":"^10.6.0","eslint-config-prettier":"^10.1.8","prettier":"^3.9.4","typescript":"^6.0.3","typescript-eslint":"^8.62.1","vitest":"^4.1.10"},"overrides":{"undici":"^6.27.0","ip-address":"^10.1.1","esbuild":"^0.25.0"},"_id":"@cardano-mercury/core@0.2.3","gitHead":"bdb0896340ee0caa6fb6f46fc07fc3ebb035b1fb","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-volyRQo7pTeg0eB+9RDlIFQDvGCqfiBrjL6RxY+t680hrxQeIm5R2VdlzJ5ALnrlb+1KEDwa5llzwiDf6FjApg==","shasum":"6e4f5decccab1e046495f4bc8a7b0d2317316628","tarball":"https://registry.npmjs.org/@cardano-mercury/core/-/core-0.2.3.tgz","fileCount":23,"unpackedSize":91293,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@cardano-mercury%2fcore@0.2.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC3CNnmqNpg1tySSs5ZCTPf+wLMZzCpEUD1qJCLudwZpQIgaHrc3K1mmIBHkfvwRpr4lcu+qmTTDDSkKDYezDPBL5s="}]},"_npmUser":{"name":"therealadamdean","email":"adam@crypto2099.io"},"directories":{},"maintainers":[{"name":"therealadamdean","email":"adam@crypto2099.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/core_0.2.3_1784134608619_0.8161448880564799"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-13T18:28:19.646Z","modified":"2026-07-15T16:56:49.221Z","0.2.0":"2026-07-13T18:28:19.914Z","0.2.1":"2026-07-13T22:47:58.328Z","0.2.2":"2026-07-14T17:54:41.113Z","0.2.3":"2026-07-15T16:56:48.781Z"},"bugs":{"url":"https://github.com/cardano-mercury/mercury-core/issues"},"author":{"name":"Cardano Mercury, Inc."},"license":"Apache-2.0","homepage":"https://github.com/cardano-mercury/mercury-core#readme","keywords":["cardano","mercury","better-auth","drizzle","blockfrost","postgres"],"repository":{"type":"git","url":"git+https://github.com/cardano-mercury/mercury-core.git"},"description":"Shared database schema, authentication, and Cardano utilities for the Mercury apps.","maintainers":[{"name":"therealadamdean","email":"adam@crypto2099.io"}],"readme":"# @cardano-mercury/core\n\nShared building blocks for the Mercury apps (financials, tokenomics): a common database schema,\nauthentication, and Cardano utilities. The apps depend on this package so they can share one\nPostgres database and a single account set, while keeping their own repos and app-specific code.\n\nIt is a framework-agnostic TypeScript package. It does not import any SvelteKit specifics\n(`$env`, `$app/*`); apps inject their own environment and framework glue.\n\n## Exports\n\n- `@cardano-mercury/core/db` — the shared Drizzle schema (Better Auth `user`/`session`/`account`/\n  `verification`/`two_factor`). Merge these into your app's drizzle client and foreign-key your own\n  tables to `user`. This package owns the migrations for these tables; apps generate migrations\n  only for their own.\n- `@cardano-mercury/core/auth` — `createAuth(options)`, a Better Auth factory with the shared\n  conventions (email/password with an 8 character minimum, two-factor, Postgres adapter, and for SSO\n  both cross-subdomain cookies and the matching `trustedOrigins`). Pass framework and app plugins\n  (e.g. SvelteKit's cookie plugin, magic link) via `options.plugins`; the returned instance's\n  `auth.api` picks up those plugins' endpoints with full types, no manual cast needed.\n- `@cardano-mercury/core/cardano` — a Blockfrost REST client (network and project id passed in),\n  plus `rewardAddressOf` / `makeOwnershipTest` for stake-key based wallet ownership. `makeOwnershipTest`\n  answers **membership** (\"is this address ours?\"), not **attribution** (\"whose bucket or account is\n  it?\") — one stake key routinely spans several payment addresses, so see its JSDoc before using it to\n  label anything.\n- `@cardano-mercury/core/money` — `formatAda` for lovelace.\n- `@cardano-mercury/core/db/migrate` — `runCoreMigrations(connectionString)`, the programmatic form\n  of the `mercury-core migrate` command below.\n\n## The shared auth migrations\n\nCore owns the five shared tables, so core also ships the SQL that creates them and a runner that\napplies it. Both apps foreign-key to `user`, so this has to run **before** either app migrates:\n\n```sh\nDATABASE_URL=postgres://... npx @cardano-mercury/core migrate\n```\n\nThe SQL is bundled in the published package, so this works from a container that installed core from\nthe registry, with no checkout of this repo. It is safe to run repeatedly (an applied migration is a\nno-op) and safe to run from several containers at once: the runner takes a Postgres advisory lock, so\na `docker compose up` that starts both apps together serialises rather than racing on `CREATE TABLE`.\nApps that would rather call it in-process can import `runCoreMigrations` from\n`@cardano-mercury/core/db/migrate` instead.\n\nThe ownership rule, stated once:\n\n- Core generates and applies migrations for `user`, `session`, `account`, `verification`, and\n  `two_factor`. Its journal is `__drizzle_migrations_core` in `public`.\n- Apps set `tablesFilter` to their own prefix, keep their own journal, and never generate, alter, or\n  drop the five shared tables. They re-export the schema from `@cardano-mercury/core/db` so they can\n  query and foreign-key to it.\n- Nobody runs `drizzle-kit push` against the shared database. It honours `tablesFilter` for tables\n  but not for sequences, and will offer to drop another app's migration-journal sequence.\n\n**Adopting a database that predates this.** If the shared tables already exist because an app created\nthem (or from a hand-run stopgap script), core refuses to touch them rather than failing halfway\nthrough a `CREATE TABLE`. Run it once with `--baseline` to adopt them as they are: core records its\nmigrations as applied without altering the tables, and later migrations then apply normally on top.\n\n```sh\nDATABASE_URL=postgres://... npx @cardano-mercury/core migrate --baseline\n```\n\n### Two ways a shared database bites, both silent\n\nThree writers on one Postgres is core's design, so these belong here rather than in an app. Both were\nfound the hard way, in production data.\n\n**`drizzle-kit push` will eat another app's migration history.** It applies `tablesFilter` to tables\nbut **not to sequences**, so from an app with `tablesFilter: ['financials_*']` correctly set, `push`\nstill proposes `DROP SEQUENCE \"public\".\"__drizzle_migrations_tokenomics_id_seq\"` — another app's\njournal. One invocation is enough. Do not add a `db:push` script; core does not have one, and neither\nshould an app. Generate and migrate only, so you are applying committed SQL and never diffing against\ntables you do not own.\n\n**Postgres truncates identifiers at 63 characters, and drizzle's derived names can exceed that.**\nDrizzle names a foreign key `{table}_{column}_{reftable}_{refcolumn}_fk`. Add a table prefix and it\noverflows:\n\n```\nfinancials_transaction_tag_transaction_id_financials_transaction_id_fk   (70 chars)\n```\n\nPostgres silently truncates that to 63 on creation. Drizzle then compares the 70-character name it\nexpects against the 63 in the database, concludes the constraint is missing, and offers to create it —\non every diff, forever. On a unique constraint it offers to **truncate the table** to add it. Nothing\nwarns you: Postgres emits a `NOTICE` and drizzle says nothing.\n\nName long constraints explicitly with `foreignKey({ ..., name })` and keep them under 63. Audit any\nshared database with:\n\n```sql\nselect conrelid::regclass, conname, length(conname)\nfrom pg_constraint\nwhere connamespace = 'public'::regnamespace and length(conname) >= 63\norder by length(conname) desc;\n```\n\nAnything at exactly 63 is almost certainly a truncated name that will never match again.\n\nCore's own tables are unprefixed, which is what keeps it clear: its longest derived identifier is\n`two_factor_user_id_user_id_fk` at 29 characters, 34 short of the cliff. The apps, with their\n`financials_` and `tokenomics_` prefixes, have far less room.\n\n## Using it from an app (SvelteKit)\n\n```ts\n// src/lib/server/auth.ts\nimport { createAuth } from '@cardano-mercury/core/auth';\nimport { sveltekitCookies } from 'better-auth/svelte-kit';\nimport { getRequestEvent } from '$app/server';\nimport { env } from '$env/dynamic/private';\nimport { db } from './db';\n\nexport const auth = createAuth({\n\tdb,\n\tsecret: env.BETTER_AUTH_SECRET,\n\tbaseURL: env.ORIGIN,\n\tissuer: 'Mercury Financials',\n\tcookieDomain: env.COOKIE_DOMAIN, // e.g. .cardano-mercury.com in production\n\tplugins: [sveltekitCookies(getRequestEvent)] // keep last\n});\n```\n\n`better-auth`, `drizzle-orm`, and `@meshsdk/core` are peer dependencies, so the app and core share\none instance of each.\n\n### An app needs the same _copy_ of `better-auth` as core, not just the same version\n\nInstall core from the registry, not as a `file:../mercury-core` link. The link is what breaks this,\nand the failure is worth understanding because the error message hides the cause completely.\n\nA `file:` link is a symlink, and TypeScript resolves through it to core's real path — so core's\n`.d.ts` picks up `better-auth` (and its `@better-auth/core` dependency) from **core's own**\n`node_modules`, while the app picks up **its** copy. Two directories, two type identities, even when\nboth are byte-identical at the same version. The instance `createAuth` returns then fails to satisfy\nconsumers such as `svelteKitHandler`, and TypeScript reports it as an inscrutable structural mismatch\nsomewhere deep in a plugin's `hooks.after.matcher`, never as \"you have two copies\". It is tempting to\npaper over it with a cast in the app's `hooks.server.ts`. Don't. Installing core from the registry\nhoists a single shared copy and the error disappears on its own.\n\nKeep versions aligned too: the peer range is pinned narrow (`~1.6.23`) so a mismatched app fails\nloudly at `npm install` instead of quietly generating a different auth schema against the shared\ndatabase. Moving `better-auth` means moving core and both apps together, in one go. But note that\nmatching versions alone is not sufficient — only a single copy makes the types agree.\n\n## Develop\n\n```sh\nnpm install\nnpm run build      # emit dist/ (ESM + types)\nnpm run dev        # tsc --watch\n```\n\nApps should depend on a published version (`\"@cardano-mercury/core\": \"^0.2.0\"`). A local\n`file:../mercury-core` link is convenient for iterating on core and an app together — run\n`npm run dev` here to rebuild on change — but it gives the app a second physical copy of\n`better-auth`, with the type consequences described above, so treat it as a temporary development\ntool rather than the normal way to consume core.\n\nReleases are cut by tagging: `.github/workflows/release.yml` fires on a `v*` tag, re-runs the full\ngate, checks the tag matches `package.json`, and publishes to npm with provenance.\n\n## Test\n\nVitest is the test runner; tests live next to the code they cover as `src/**/*.test.ts`.\n\n```sh\nnpm test           # run the suite once\nnpm run test:watch # re-run on change\nnpm run test:coverage  # enforce 100% line/branch/function coverage\nnpm run check      # strict tsc --noEmit; type-checks the source and the tests\n```\n\nBecause the apps depend on this shared library, every exported function carries happy-path,\nunhappy-path, and regression tests, and `test:coverage` fails under 100% on the logic-bearing\nmodules. The declarative pieces — the drizzle schema and the re-export barrels — are excluded from\nthe coverage threshold but still have shape regression tests (`src/db/schema.test.ts`). Test files\nare excluded from the published build via `tsconfig.build.json`, so `dist/` ships no test code.\n\n## Lint and format\n\nESLint (correctness/quality rules) and Prettier (formatting) round out the code-quality gate.\n\n```sh\nnpm run lint          # eslint, @typescript-eslint recommended rules\nnpm run format        # prettier --write; apply formatting\nnpm run format:check  # prettier --check; the CI-enforced check\n```\n\nPrettier owns all formatting (`eslint-config-prettier` disables any ESLint rule that would fight it),\nso its config in `.prettierrc.json` matches the SvelteKit convention the apps use: tabs, single\nquotes, no trailing commas, 100-column width.\n\nCI (`.github/workflows/ci.yml`) runs lint, format check, type-check, the coverage-gated tests, and\nthe build on every pull request and push to `main`; `main` is branch-protected so a PR can't merge\nuntil that check passes.\n","readmeFilename":"README.md"}