{"_id":"@b4moss/crudian","_rev":"5-49b31df1920568046c23536b2aee6b0a","name":"@b4moss/crudian","dist-tags":{"latest":"0.9.0"},"versions":{"0.3.1":{"name":"@b4moss/crudian","version":"0.3.1","keywords":["crud","repository","sqlite","bun","drizzle","prisma","ddd"],"license":"MIT","_id":"@b4moss/crudian@0.3.1","maintainers":[{"name":"b4m-oss","email":"kohki.shikata@gmail.com"}],"homepage":"https://github.com/b4moss/crudian#readme","bugs":{"url":"https://github.com/b4moss/crudian/issues"},"dist":{"shasum":"630147cfacce0b75eaf4bab147ed29f88d8410ad","tarball":"https://registry.npmjs.org/@b4moss/crudian/-/crudian-0.3.1.tgz","fileCount":48,"integrity":"sha512-mMdT9kl5ZGP4z+CyKVXqywxTGhJJ3dZ9g2a2xYo4ix/QeQpQEw7T8COk55RMmqr0eY9++D8mto9gq6hWUmaFrg==","signatures":[{"sig":"MEQCICA1kNk3B6gxM4ojk3rvwXBjNHoKGJfemMCeeFyxkHFNAiAXeGAc2QJ72Bsr8ed6NwJsKT8hlqzFj2e9rlgu263WUg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":57991},"type":"module","engines":{"bun":">=1.0.0","node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./prisma":{"types":"./dist/prisma/index.d.ts","import":"./dist/prisma/index.js","default":"./dist/prisma/index.js"},"./drizzle":{"types":"./dist/drizzle/index.d.ts","import":"./dist/drizzle/index.js","default":"./dist/drizzle/index.js"},"./bun-sqlite":{"bun":"./dist/bun-sqlite/index.js","types":"./dist/bun-sqlite/index.d.ts","import":"./dist/bun-sqlite/node-stub.js","default":"./dist/bun-sqlite/node-stub.js"}},"gitHead":"1bb403ff3e37d0c6e4f86a2edab1c959af57113f","scripts":{"test":"bun run test:bun-sqlite && bun run test:drizzle && bun run test:prisma","build":"tsc -p tsconfig.json","test:prisma":"bun run prisma:generate && tsx --test src/prisma/crud.test.ts","test:drizzle":"tsx --test src/drizzle/crud.test.ts","prepublishOnly":"npm run build","prisma:generate":"prisma generate --schema prisma/schema.prisma","test:bun-sqlite":"bun test src/bun-sqlite"},"_npmUser":{"name":"b4m-oss","email":"kohki.shikata@gmail.com"},"repository":{"url":"git+https://github.com/b4moss/crudian.git","type":"git","directory":"packages/js"},"_npmVersion":"10.9.4","description":"CRUD abstraction for DDD repositories","directories":{},"_nodeVersion":"22.21.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.12","prisma":"^6.14.0","bun-types":"^1.2.0","typescript":"^5.8.0","drizzle-orm":"^0.44.4","@prisma/client":"^6.14.0","better-sqlite3":"^11.10.0","@types/better-sqlite3":"^7.6.13"},"peerDependencies":{"drizzle-orm":"^0.39.0 || ^0.40.0 || ^0.41.0 || ^0.44.0","@prisma/client":"^6.0.0","better-sqlite3":"^11.0.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true},"@prisma/client":{"optional":true},"better-sqlite3":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/crudian_0.3.1_1786625720965_0.8328257818489031","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@b4moss/crudian","version":"0.5.0","keywords":["crud","repository","sqlite","bun","drizzle","prisma","ddd"],"license":"MIT","_id":"@b4moss/crudian@0.5.0","maintainers":[{"name":"b4m-oss","email":"kohki.shikata@gmail.com"}],"homepage":"https://github.com/b4moss/crudian#readme","bugs":{"url":"https://github.com/b4moss/crudian/issues"},"dist":{"shasum":"805f0af260d4480c811a54ed6f5585b19c7173f0","tarball":"https://registry.npmjs.org/@b4moss/crudian/-/crudian-0.5.0.tgz","fileCount":48,"integrity":"sha512-UajTZGp0qnJcVv2hgfiPnOwqGTW95K0kwAMtUQA5YodZB6od/cGGgm2Moz2P4YAJ25/i//mV/CVEu/JqUi6X3g==","signatures":[{"sig":"MEUCIApVUVtIVxOCDMPe9jYZL0IJjCmyY+oxf1CpjzDBPi4gAiEA5Iwxpp9sN6x5I/CRO2ys6ZVaqRmF0ieCUzbuVoZPumo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@b4moss%2fcrudian@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":59988},"type":"module","engines":{"bun":">=1.0.0","node":">=24"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./prisma":{"types":"./dist/prisma/index.d.ts","import":"./dist/prisma/index.js","default":"./dist/prisma/index.js"},"./drizzle":{"types":"./dist/drizzle/index.d.ts","import":"./dist/drizzle/index.js","default":"./dist/drizzle/index.js"},"./bun-sqlite":{"bun":"./dist/bun-sqlite/index.js","types":"./dist/bun-sqlite/index.d.ts","import":"./dist/bun-sqlite/node-stub.js","default":"./dist/bun-sqlite/node-stub.js"}},"gitHead":"ebb11ebcb383ecc80b10052480aafc3a6e10c435","scripts":{"test":"bun run test:bun-sqlite && bun run test:drizzle && bun run test:prisma","build":"tsc -p tsconfig.json","test:prisma":"bun run prisma:generate && tsx --test src/prisma/crud.test.ts","test:drizzle":"tsx --test src/drizzle/crud.test.ts","prepublishOnly":"npm run build","prisma:generate":"prisma generate --schema prisma/schema.prisma","test:bun-sqlite":"bun test src/bun-sqlite"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b3b5770e-b5af-49e2-9424-ae079bcc2287"}},"repository":{"url":"git+https://github.com/b4moss/crudian.git","type":"git","directory":"packages/js"},"_npmVersion":"11.17.0","description":"CRUD abstraction for DDD repositories","directories":{},"_nodeVersion":"24.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.12","prisma":"^6.14.0","bun-types":"^1.2.0","typescript":"^5.8.0","drizzle-orm":"^0.44.4","@prisma/client":"^6.14.0","better-sqlite3":"^11.10.0","@types/better-sqlite3":"^7.6.13"},"peerDependencies":{"drizzle-orm":"^0.39.0 || ^0.40.0 || ^0.41.0 || ^0.44.0","@prisma/client":"^6.0.0","better-sqlite3":"^11.0.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true},"@prisma/client":{"optional":true},"better-sqlite3":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/crudian_0.5.0_1787644237338_0.28694610240966245","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@b4moss/crudian","version":"0.6.0","keywords":["crud","repository","sqlite","bun","drizzle","prisma","libsql","ddd"],"license":"MIT","_id":"@b4moss/crudian@0.6.0","maintainers":[{"name":"b4m-oss","email":"kohki.shikata@gmail.com"}],"homepage":"https://github.com/b4moss/crudian#readme","bugs":{"url":"https://github.com/b4moss/crudian/issues"},"dist":{"shasum":"48a2bce987a9c6ae3109ec16574784b6d104cd1c","tarball":"https://registry.npmjs.org/@b4moss/crudian/-/crudian-0.6.0.tgz","fileCount":54,"integrity":"sha512-AjQ0ifIGUbmwJVQn+jFKziQM6nt7G4vTrGvhry3Qir80V7QHJD/i3Ar4OST+Fu79I46enI02LGcH/0U3bBTyRQ==","signatures":[{"sig":"MEUCIQDFcTMYhSZG4o1OtRuwYfV4WQtqW1X6wwMy22oVcrbNnwIgYMiR0n8BGSAQDcp6q1QdE0hCPynEVTRJK1CVXzJhaUg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@b4moss%2fcrudian@0.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":73400},"type":"module","engines":{"bun":">=1.0.0","node":">=24"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./libsql":{"types":"./dist/libsql/index.d.ts","import":"./dist/libsql/index.js","default":"./dist/libsql/index.js"},"./prisma":{"types":"./dist/prisma/index.d.ts","import":"./dist/prisma/index.js","default":"./dist/prisma/index.js"},"./drizzle":{"types":"./dist/drizzle/index.d.ts","import":"./dist/drizzle/index.js","default":"./dist/drizzle/index.js"},"./bun-sqlite":{"bun":"./dist/bun-sqlite/index.js","types":"./dist/bun-sqlite/index.d.ts","import":"./dist/bun-sqlite/node-stub.js","default":"./dist/bun-sqlite/node-stub.js"}},"gitHead":"ac73367a1497f6fa95c272620d9f9e90a9569fac","scripts":{"test":"bun run test:bun-sqlite && bun run test:drizzle && bun run test:prisma && bun run test:libsql","build":"tsc -p tsconfig.json","test:libsql":"tsx --test src/libsql/crud.test.ts","test:prisma":"bun run prisma:generate && tsx --test src/prisma/crud.test.ts","test:drizzle":"tsx --test src/drizzle/crud.test.ts","prepublishOnly":"npm run build","prisma:generate":"prisma generate --schema prisma/schema.prisma","test:bun-sqlite":"bun test src/bun-sqlite"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b3b5770e-b5af-49e2-9424-ae079bcc2287"}},"repository":{"url":"git+https://github.com/b4moss/crudian.git","type":"git","directory":"packages/js"},"_npmVersion":"11.17.0","description":"CRUD abstraction for DDD repositories","directories":{},"_nodeVersion":"24.19.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.12","prisma":"^6.14.0","bun-types":"^1.2.0","typescript":"^5.8.0","drizzle-orm":"^0.44.4","@libsql/client":"^0.17.4","@prisma/client":"^6.14.0","better-sqlite3":"^13","@types/better-sqlite3":"^7.6.13"},"peerDependencies":{"drizzle-orm":"^0.39.0 || ^0.40.0 || ^0.41.0 || ^0.44.0","@libsql/client":"^0.14.0 || ^0.15.0 || ^0.17.0","@prisma/client":"^6.0.0","better-sqlite3":"^11.0.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true},"@libsql/client":{"optional":true},"@prisma/client":{"optional":true},"better-sqlite3":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/crudian_0.6.0_1787646507090_0.2093216974861034","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"@b4moss/crudian","version":"0.8.0","keywords":["crud","repository","sqlite","bun","drizzle","prisma","libsql","ddd"],"license":"MIT","_id":"@b4moss/crudian@0.8.0","maintainers":[{"name":"b4m-oss","email":"kohki.shikata@gmail.com"}],"homepage":"https://github.com/b4moss/crudian#readme","bugs":{"url":"https://github.com/b4moss/crudian/issues"},"dist":{"shasum":"1a4252c4fccda78fe6ee32f90ed7a173e6f02bfd","tarball":"https://registry.npmjs.org/@b4moss/crudian/-/crudian-0.8.0.tgz","fileCount":57,"integrity":"sha512-X7HVkOqxPiGuRXQl6qdpU7IaZJc1QQ4TLZrRbqj5Q/xw8cb7mh9voM63qyq9FR/Z5BvzDOVTWpYsXVo6OLk1cw==","signatures":[{"sig":"MEQCIGNHdCJnwxG1gZDXGZArUcsbwewP8djv4E4xtk0AyMdZAiA5CzwzlhdCDWFL0KQ6A6qN3iKix1vyglUTWDLpYTitOQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@b4moss%2fcrudian@0.8.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":83824},"type":"module","engines":{"bun":">=1.0.0","node":">=24"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./libsql":{"types":"./dist/libsql/index.d.ts","import":"./dist/libsql/index.js","default":"./dist/libsql/index.js"},"./prisma":{"types":"./dist/prisma/index.d.ts","import":"./dist/prisma/index.js","default":"./dist/prisma/index.js"},"./drizzle":{"types":"./dist/drizzle/index.d.ts","import":"./dist/drizzle/index.js","default":"./dist/drizzle/index.js"},"./bun-sqlite":{"bun":"./dist/bun-sqlite/index.js","types":"./dist/bun-sqlite/index.d.ts","import":"./dist/bun-sqlite/node-stub.js","default":"./dist/bun-sqlite/node-stub.js"}},"gitHead":"dc9cc555eab2db0506ac5b82cafd539755f1b5fd","scripts":{"test":"bun run test:bun-sqlite && bun run test:drizzle && bun run test:prisma && bun run test:libsql","build":"tsc -p tsconfig.json","test:libsql":"tsx --test src/libsql/crud.test.ts src/libsql/pk.test.ts","test:prisma":"bun run prisma:generate && tsx --test src/prisma/crud.test.ts src/prisma/pk.test.ts","test:drizzle":"tsx --test src/drizzle/crud.test.ts src/drizzle/pk.test.ts","prepublishOnly":"npm run build","prisma:generate":"prisma generate --schema prisma/schema.prisma","test:bun-sqlite":"bun test src/bun-sqlite"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b3b5770e-b5af-49e2-9424-ae079bcc2287"}},"repository":{"url":"git+https://github.com/b4moss/crudian.git","type":"git","directory":"packages/js"},"_npmVersion":"11.19.0","description":"CRUD abstraction for DDD repositories","directories":{},"_nodeVersion":"24.20.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.12","prisma":"^6.14.0","bun-types":"^1.2.0","typescript":"^5.8.0","drizzle-orm":"^0.45.2","@libsql/client":"^0.17.4","@prisma/client":"^6.14.0","better-sqlite3":"^13","@types/better-sqlite3":"^7.6.13"},"peerDependencies":{"drizzle-orm":"^0.39.0 || ^0.40.0 || ^0.41.0 || ^0.44.0","@libsql/client":"^0.14.0 || ^0.15.0 || ^0.17.0","@prisma/client":"^6.0.0","better-sqlite3":"^11.0.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true},"@libsql/client":{"optional":true},"@prisma/client":{"optional":true},"better-sqlite3":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/crudian_0.8.0_1788703120053_0.280458175896237","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"_id":"@b4moss/crudian@0.9.0","bugs":{"url":"https://github.com/b4moss/crudian/issues"},"dist":{"shasum":"b7729d1dedffdc2dab62504eb8ebab72115fe928","tarball":"https://registry.npmjs.org/@b4moss/crudian/-/crudian-0.9.0.tgz","fileCount":57,"integrity":"sha512-mAjcI2FNp2JjjG21k7sU3NfD+sFCJJuiXG+B9q/3ctjz2BqqOI/LYuY7JTJ8YxLTDvSRsQ7xYD1/y4qwuLLMhg==","signatures":[{"sig":"MEUCIE7NxCIRJflJGS0GQi+hdT9HqMEXayL1WsuY5uU/FQlhAiEAnkVVVr4UreltBScUMTKmM9n7+AIlfD5ADaHjkxquIik=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBWzKXiwX/XhNbnaBGTmVfekrQVD3a7iHG+bUcthJWoIAiAs+Sh7vcOIX6d4wYj95Js8RReIXK1iovX9ydcJW4kTog=="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@b4moss%2fcrudian@0.9.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":85495},"name":"@b4moss/crudian","type":"module","engines":{"bun":">=1.0.0","node":">=24"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./libsql":{"types":"./dist/libsql/index.d.ts","import":"./dist/libsql/index.js","default":"./dist/libsql/index.js"},"./prisma":{"types":"./dist/prisma/index.d.ts","import":"./dist/prisma/index.js","default":"./dist/prisma/index.js"},"./drizzle":{"types":"./dist/drizzle/index.d.ts","import":"./dist/drizzle/index.js","default":"./dist/drizzle/index.js"},"./bun-sqlite":{"bun":"./dist/bun-sqlite/index.js","types":"./dist/bun-sqlite/index.d.ts","import":"./dist/bun-sqlite/node-stub.js","default":"./dist/bun-sqlite/node-stub.js"}},"gitHead":"9fac102b089bd357e45b3ec42b410bfa167cbf7e","license":"MIT","scripts":{"test":"bun run test:bun-sqlite && bun run test:drizzle && bun run test:prisma && bun run test:libsql","build":"tsc -p tsconfig.json","test:libsql":"tsx --test src/libsql/crud.test.ts src/libsql/pk.test.ts","test:prisma":"bun run prisma:generate && tsx --test src/prisma/crud.test.ts src/prisma/pk.test.ts","test:drizzle":"tsx --test src/drizzle/crud.test.ts src/drizzle/pk.test.ts","prepublishOnly":"npm run build","prisma:generate":"prisma generate --schema prisma/schema.prisma","test:bun-sqlite":"bun test src/bun-sqlite"},"version":"0.9.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b3b5770e-b5af-49e2-9424-ae079bcc2287"}},"homepage":"https://github.com/b4moss/crudian#readme","keywords":["crud","repository","sqlite","bun","drizzle","prisma","libsql","ddd"],"repository":{"url":"git+https://github.com/b4moss/crudian.git","type":"git","directory":"packages/js"},"_npmVersion":"11.19.0","description":"CRUD abstraction for DDD repositories","directories":{},"maintainers":[{"name":"b4m-oss","email":"kohki.shikata@gmail.com"}],"_nodeVersion":"24.20.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.23.12","prisma":"^6.14.0","bun-types":"^1.2.0","typescript":"^5.8.0","drizzle-orm":"^0.45.2","@libsql/client":"^0.17.4","@prisma/client":"^6.14.0","better-sqlite3":"^13","@types/better-sqlite3":"^7.6.13"},"peerDependencies":{"drizzle-orm":"^0.39.0 || ^0.40.0 || ^0.41.0 || ^0.44.0","@libsql/client":"^0.14.0 || ^0.15.0 || ^0.17.0","@prisma/client":"^6.0.0","better-sqlite3":"^11.0.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true},"@libsql/client":{"optional":true},"@prisma/client":{"optional":true},"better-sqlite3":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/crudian_0.9.0_1789477862346_0.458665614366232"}}},"time":{"created":"2026-08-13T12:55:20.751Z","modified":"2026-09-15T13:11:02.802Z","0.3.1":"2026-08-13T12:55:21.097Z","0.5.0":"2026-08-25T07:50:37.480Z","0.6.0":"2026-08-25T08:28:27.217Z","0.8.0":"2026-09-06T13:58:40.232Z","0.9.0":"2026-09-15T13:11:02.427Z"},"bugs":{"url":"https://github.com/b4moss/crudian/issues"},"license":"MIT","homepage":"https://github.com/b4moss/crudian#readme","keywords":["crud","repository","sqlite","bun","drizzle","prisma","libsql","ddd"],"repository":{"url":"git+https://github.com/b4moss/crudian.git","type":"git","directory":"packages/js"},"description":"CRUD abstraction for DDD repositories","maintainers":[{"name":"b4m-oss","email":"kohki.shikata@gmail.com"}],"readme":"# @b4moss/crudian\n\nCRUD abstraction for DDD repositories.\n\nOne npm package, adapter subpaths. Shared contracts live at the package root; backends are imported from subpaths. Callers inject their own DB/client — crudian never opens connections or reads env secrets for you.\n\n**Versioning:** this npm package has its own SemVer (`package.json`). It is independent of the Go module (`packages/go/VERSION`). Shipping Go `0.7.0` does not require bumping this package.\n\n## Install\n\n```bash\nnpm install @b4moss/crudian\n```\n\nInstall only the peer deps for the adapter you use:\n\n| Subpath | Runtime | Sync / async | Peer dependencies |\n|---------|---------|--------------|-------------------|\n| `@b4moss/crudian/bun-sqlite` | Bun | sync | Bun (`bun:sqlite`) |\n| `@b4moss/crudian/drizzle` | Node.js 24+ | sync | `drizzle-orm`, `better-sqlite3` |\n| `@b4moss/crudian/prisma` | Node.js 24+ | async | `@prisma/client` |\n| `@b4moss/crudian/libsql` | Node.js 24+ / Bun | async | `@libsql/client` |\n\nNode must not import `@b4moss/crudian/bun-sqlite` (resolves to an explicit error stub).\n\n## Quick start (adapters)\n\n### Shared contracts\n\n```ts\nimport { where, CrudianError } from \"@b4moss/crudian\"\n```\n\n### Bun (`bun:sqlite`) — sync\n\n```ts\nimport { Database } from \"bun:sqlite\"\nimport { createCrud } from \"@b4moss/crudian/bun-sqlite\"\nimport { where } from \"@b4moss/crudian\"\n\nconst db = new Database(\":memory:\")\ndb.exec(`\n  CREATE TABLE items (\n    id INTEGER PRIMARY KEY AUTOINCREMENT,\n    name TEXT NOT NULL,\n    score INTEGER,\n    note TEXT\n  )\n`)\nconst crud = createCrud(db)\n// raw DB is also available as crud.db\n```\n\n### Drizzle (better-sqlite3) — sync\n\n```ts\nimport Database from \"better-sqlite3\"\nimport { drizzle } from \"drizzle-orm/better-sqlite3\"\nimport { createCrud } from \"@b4moss/crudian/drizzle\"\n\nconst sqlite = new Database(\":memory:\")\nsqlite.exec(`CREATE TABLE items (\n  id INTEGER PRIMARY KEY AUTOINCREMENT,\n  name TEXT NOT NULL,\n  score INTEGER,\n  note TEXT\n)`)\nconst db = drizzle(sqlite)\nconst crud = createCrud(db)\n```\n\n### Prisma (SQLite) — async\n\n```ts\nimport { PrismaClient } from \"@prisma/client\"\nimport { createCrud } from \"@b4moss/crudian/prisma\"\n\nconst client = new PrismaClient()\nconst crud = createCrud(client)\n\nawait crud.create(\"items\", { name: \"alpha\", score: 1 })\n```\n\n### libSQL (`@libsql/client`) — async\n\n```ts\nimport { createClient } from \"@libsql/client\"\nimport { createCrud } from \"@b4moss/crudian/libsql\"\n\nconst client = createClient({\n  url: process.env.LIBSQL_URL ?? \"file:local.db\",\n  authToken: process.env.LIBSQL_AUTH_TOKEN, // optional; set for remote hosts\n})\nconst crud = createCrud(client)\n\nawait crud.create(\"items\", { name: \"alpha\", score: 1 })\n```\n\nURL / auth token belong on the caller-created client (typically from `.env`).\n\n---\n\n## API reference (all methods)\n\nExamples below use the **sync** Bun adapter. For `prisma` / `libsql`, `await` every call (same shapes).\n\nAssume a table:\n\n```sql\nCREATE TABLE items (\n  id INTEGER PRIMARY KEY AUTOINCREMENT,\n  name TEXT NOT NULL,\n  score INTEGER,\n  note TEXT\n);\n```\n\n```ts\nimport { Database } from \"bun:sqlite\"\nimport { createCrud } from \"@b4moss/crudian/bun-sqlite\"\nimport { where } from \"@b4moss/crudian\"\n\nconst db = new Database(\":memory:\")\ndb.exec(/* schema above */)\nconst crud = createCrud(db)\n\ntype Item = { id: number; name: string; score: number | null; note: string | null }\n```\n\n### `create(table, cols)` → row\n\nInserts one row and returns it (including generated `id`).\n\n```ts\nconst row = crud.create<Item>(\"items\", { name: \"alpha\", score: 10, note: \"n\" })\n// { id: 1, name: \"alpha\", score: 10, note: \"n\" }\n```\n\n### `read(table, query?)` → row | `null`\n\nReads one row. Misses return `null` (does not throw).\n\n```ts\nconst found = crud.read<Item>(\"items\", {\n  columns: [\"id\", \"name\"],\n  where: where().eq(\"id\", row.id),\n})\n// { id: 1, name: \"alpha\" }\n\nconst missing = crud.read<Item>(\"items\", { where: where().eq(\"id\", 999) })\n// null\n```\n\n### `update(table, cols, query)` → row | `null`\n\nUpdates matching rows; returns the updated row. Zero matches → `null`. `where` is required.\n\n```ts\nconst updated = crud.update<Item>(\n  \"items\",\n  { score: 9 },\n  { where: where().eq(\"id\", row.id) },\n)\n// { id: 1, name: \"alpha\", score: 9, note: \"n\" }\n```\n\n### `delete(table, query)` → number\n\nDeletes matching rows; returns affected count. `where` is required.\n\n```ts\nconst deleted = crud.delete(\"items\", { where: where().eq(\"id\", row.id) })\n// 1\n```\n\n### `search(table, query?)` → `{ items, nextCursor, hasMore, total }`\n\nCanonical list API. Cursor pagination on `id` ascending. `total` is the full where-match count (ignores `limit` / `cursor`).\n\n`SearchQuery` fields:\n\n| Field | Meaning |\n|-------|---------|\n| `columns?` | Column list for `SELECT` (same idea as `read`). Omit → `*` |\n| `where?` | Condition builder / node |\n| `limit?` | Page size (default `20`) |\n| `cursor?` | Raw `id` cursor (keyset); rows with `id > cursor` |\n\n```ts\nfor (let i = 0; i < 5; i++) {\n  crud.create(\"items\", { name: `n${i}`, score: i })\n}\n\nconst page1 = crud.search<Item>(\"items\", { limit: 2 })\n// {\n//   items: [ { id: 1, ... }, { id: 2, ... } ],\n//   nextCursor: 2,\n//   hasMore: true,\n//   total: 5,\n// }\n\nconst page2 = crud.search<Item>(\"items\", {\n  limit: 2,\n  cursor: page1.nextCursor,\n})\n// items ids [3, 4], total still 5\n\nconst filtered = crud.search<Item>(\"items\", {\n  columns: [\"id\", \"name\"],\n  where: where().gte(\"score\", 3),\n  limit: 10,\n})\n// each item is { id, name } only\n```\n\n### `list(table, query?)` → same as `search`\n\nThin alias of `search` (same `SearchQuery`, including `columns`).\n\n```ts\nconst a = crud.list<Item>(\"items\", {\n  columns: [\"id\", \"name\"],\n  limit: 10,\n})\nconst b = crud.search<Item>(\"items\", {\n  columns: [\"id\", \"name\"],\n  limit: 10,\n})\n// a and b are deep-equal\n```\n\n### `count(table, query?)` → number\n\nWhere-match count only (`CountQuery` is `{ where? }`). No `limit` / `cursor` / `columns`.\n\n```ts\ncrud.count(\"items\") // 5\ncrud.count(\"items\", { where: where().eq(\"name\", \"n0\") }) // 1\n```\n\n### `exists(table, query?)` → boolean\n\nWhether any row matches (`CountQuery` shape). Does not return a count. Prefer this over `count(...) > 0` when you only need presence (e.g. email already registered).\n\n```ts\ncrud.exists(\"items\") // true if the table has any row\ncrud.exists(\"items\", { where: where().eq(\"name\", \"n0\") }) // true / false\n```\n\n### `upsert(table, cols)` → row\n\nConflict target is primary key `id`. Inserts or updates; returns the row. `id` is required in `cols`.\n\n```ts\nconst inserted = crud.upsert<Item>(\"items\", { id: 10, name: \"new\", score: 1 })\nconst again = crud.upsert<Item>(\"items\", { id: 10, name: \"upd\", score: 9 })\n// again.name === \"upd\"\n```\n\n### `duplicate(table, query)` → row | `null`\n\nCopies the first matching row (new `id`). Optional `overrides`. Zero matches → `null`. `where` is required.\n\n```ts\nconst source = crud.create<Item>(\"items\", { name: \"a\", score: 1, note: \"n\" })\nconst copy = crud.duplicate<Item>(\"items\", {\n  where: where().eq(\"id\", source.id),\n  overrides: { name: \"b\" },\n})\n// copy.id !== source.id, copy.name === \"b\"\n\nconst none = crud.duplicate<Item>(\"items\", { where: where().eq(\"id\", 999) })\n// null\n```\n\n### `bulkCreate(table, rows)` → number\n\nInserts many rows; returns inserted count. Empty array → `0`.\n\n```ts\nconst n = crud.bulkCreate(\"items\", [\n  { name: \"x\", score: 1 },\n  { name: \"y\", score: 2 },\n])\n// 2\n```\n\n### `bulkUpdate(table, cols, query)` → number\n\nUpdates many rows; returns affected count. `where` is required.\n\n```ts\nconst n = crud.bulkUpdate(\n  \"items\",\n  { score: 8 },\n  { where: where().eq(\"name\", \"x\") },\n)\n// 1\n```\n\n### `bulkDelete(table, query)` → number\n\nDeletes many rows; returns affected count. `where` is required.\n\n```ts\nconst n = crud.bulkDelete(\"items\", { where: where().eq(\"name\", \"y\") })\n// 1\n```\n\n### `bulkUpsert(table, rows)` → number\n\nUpserts many rows (each row needs `id`); returns processed count. Empty array → `0`.\n\n```ts\nconst n = crud.bulkUpsert(\"items\", [\n  { id: 100, name: \"z\", score: 1 },\n  { id: 10, name: \"z2\", score: 2 },\n])\n// 2\n```\n\n### `transaction(fn)` → `fn` return value\n\nRuns `fn` inside a transaction helper. Crudian does **not** auto-wrap each CRUD call; use this when you need atomic multi-step work. Success commits; throw rolls back.\n\n```ts\nconst result = crud.transaction(() => {\n  crud.create(\"items\", { name: \"a\", score: 1 })\n  crud.create(\"items\", { name: \"b\", score: 2 })\n  return \"ok\"\n})\n// result === \"ok\"; both rows visible afterward\n\ntry {\n  crud.transaction(() => {\n    crud.create(\"items\", { name: \"c\", score: 3 })\n    throw new Error(\"boom\")\n  })\n} catch {\n  // partial writes from that callback are rolled back\n}\n```\n\nAsync adapters:\n\n```ts\nawait crud.transaction(async () => {\n  await crud.create(\"items\", { name: \"a\", score: 1 })\n  await crud.create(\"items\", { name: \"b\", score: 2 })\n})\n```\n\n---\n\n## `where()` builder\n\n```ts\nimport { where } from \"@b4moss/crudian\"\n\nwhere().eq(\"name\", \"alpha\")\nwhere().ne(\"score\", 0)\nwhere().lt(\"score\", 10)\nwhere().lte(\"score\", 10)\nwhere().gt(\"score\", 0)\nwhere().gte(\"score\", 0)\nwhere().in(\"name\", [\"a\", \"b\"])\nwhere().like(\"name\", \"a%\")\nwhere().isNull(\"note\")\nwhere().isNotNull(\"note\")\n\nwhere()\n  .eq(\"name\", \"alpha\")\n  .and(where().gte(\"score\", 5))\n\nwhere()\n  .eq(\"name\", \"alpha\")\n  .or(where().eq(\"name\", \"beta\"))\n```\n\nNestable `and` / `or`. Empty `in([])` is rejected.\n\n---\n\n## Behavior notes\n\n| Topic | Behavior |\n|-------|----------|\n| Entry | `createCrud(db)` — inject a caller-owned client; exposed as `crud.db` |\n| Sync vs async | `bun-sqlite` / `drizzle` sync; `prisma` / `libsql` return `Promise`s |\n| `read` / `update` / `duplicate` miss | `null` |\n| `delete` / bulk miss | `0` |\n| Upsert conflict | primary key `id` |\n| Pagination | cursor on `id` ASC only (no offset) |\n| `columns` | optional on `read` / `search` / `list`; omit → `*` |\n| `search.total` / `count` | full where count; not page length |\n| `exists` | boolean presence; same input as `count`; use instead of `count > 0` when you only need yes/no |\n| Errors | minimal `CrudianError`; other errors propagate from the driver |\n| Identifiers | string required; no format validation |\n| Out of scope | relations, migrations, full-text search, ORM models |\n\n## License\n\nMIT © Bicycle for Mind LLC., Kohki SHIKATA\n","readmeFilename":"README.md"}