{"_id":"@didactika/prisma-autoread","_rev":"7-d3f56f174f5ff7d3e8ba1eed24817c7b","name":"@didactika/prisma-autoread","dist-tags":{"latest":"1.2.0"},"versions":{"0.1.0":{"name":"@didactika/prisma-autoread","version":"0.1.0","keywords":["prisma","express","rest","filter","pagination","middleware","autoread"],"author":{"name":"Didactika","email":"info@didactika.org"},"license":"MIT","_id":"@didactika/prisma-autoread@0.1.0","maintainers":[{"name":"e2rd0","email":"me@e2rd0.com"}],"contributors":[{"name":"Eduardo Estrada","email":"me@e2rd0.com"}],"homepage":"https://github.com/didactika/prisma-autoread#readme","bugs":{"url":"https://github.com/didactika/prisma-autoread/issues"},"dist":{"shasum":"c330cf50263c238291caac8b554db7db3f2ec9e5","tarball":"https://registry.npmjs.org/@didactika/prisma-autoread/-/prisma-autoread-0.1.0.tgz","fileCount":6,"integrity":"sha512-vVuGikVXF5jBapBE1NmvwyIfgI6MPiM7VXkaTU5AynG1/405pkv1MHqPaiM3y7OFN4bmEb5C2fu5AJue71Sbow==","signatures":[{"sig":"MEYCIQDN59GiI8MGZ7dMSAtzOBf8ISvoh3M+reRRsbsu0PVsAAIhAPyrNEh7cqKjpAe/Az7dlqLh76PL858ygRnys8s30tjM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":150138},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"3706ba499c13b0fab805e1b076ef64d1cbe028e5","scripts":{"test":"jest","build":"tsup","test:e2e":"prisma generate && prisma db push --force-reset && jest --testPathPattern=tests/e2e","test:unit":"jest --testPathPattern=tests/unit","test:coverage":"jest --coverage","prepublishOnly":"npm run test && npm run build","test:integration":"jest --testPathPattern=tests/integration"},"_npmUser":{"name":"e2rd0","email":"me@e2rd0.com"},"repository":{"url":"git+https://github.com/didactika/prisma-autoread.git","type":"git"},"_npmVersion":"11.9.0","description":"Auto-generate Express GET list endpoints from your Prisma schema — type-aware filtering, pagination, search, and relation includes from the query string, zero boilerplate.","directories":{},"_nodeVersion":"24.14.0","dependencies":{"halson":"^3.1.0","http-response-client":"^1.1.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","tsup":"^8.5.1","prisma":"^6.0.0","express":"^4.21.2","ts-jest":"^29.0.0","supertest":"^7.0.0","typescript":"^5.0.0","@types/jest":"^29.0.0","@types/node":"^20.0.0","@prisma/client":"^6.0.0","@types/express":"^5.0.0","@types/supertest":"^6.0.0"},"peerDependencies":{"express":">=4.0.0","@prisma/client":">=6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/prisma-autoread_0.1.0_1781253009455_0.9503620556647028","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@didactika/prisma-autoread","version":"1.0.0","keywords":["prisma","express","rest","filter","search","pagination","cursor","rsql","odata","jsonapi","hal","aggregate","query-method","middleware","autoread"],"author":{"name":"Didactika","email":"info@didactika.org"},"license":"MIT","_id":"@didactika/prisma-autoread@1.0.0","maintainers":[{"name":"e2rd0","email":"me@e2rd0.com"},{"name":"hector21","email":"hectorlazaroarrechea@gmail.com"}],"contributors":[{"name":"Eduardo Estrada","email":"me@e2rd0.com"},{"name":"Hector Arrechea","email":"hectorlazaroarrechea@gmail.com"}],"homepage":"https://github.com/didactika/prisma-autoread#readme","bugs":{"url":"https://github.com/didactika/prisma-autoread/issues"},"dist":{"shasum":"e1d2118575327916bc1f5e949123e2ed493492f7","tarball":"https://registry.npmjs.org/@didactika/prisma-autoread/-/prisma-autoread-1.0.0.tgz","fileCount":7,"integrity":"sha512-SPpEyVTNLcoGyxwNj2l5Dv4QaOri415M4ApYmm7Gf0mdVlu8QlT02jzkwmjexsrtlDLJ1gU0jSJTzObH37SJTA==","signatures":[{"sig":"MEYCIQDEDbbQRMgzKvS1oRP3TdFQEJvUpu+cMRnzfF3/pGIGCQIhANp6W8a1wNRzbmuIS3Ero9dz64Eeb1wv/narWhrYFvF2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@didactika%2fprisma-autoread@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":532554},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"3779c4c1a5c72a4b7d2428706467f72efdc91943","scripts":{"test":"jest","build":"tsup","test:e2e":"prisma generate && prisma db push --force-reset && jest --testPathPattern=tests/e2e","test:unit":"jest --testPathPattern=tests/unit","test:coverage":"jest --coverage","prepublishOnly":"npm run test:unit && npm run test:integration && npm run build","test:integration":"jest --testPathPattern=tests/integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:18ebdf66-9c77-4c1d-b9e3-0733248fd05f"}},"repository":{"url":"git+https://github.com/didactika/prisma-autoread.git","type":"git"},"_npmVersion":"11.18.0","description":"Auto-generate Express search endpoints from your Prisma schema — GET/QUERY/POST, Prisma-native filtering, RSQL & OData, aggregations, cursor pagination and HAL/JSON:API/CSV output, zero boilerplate.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"halson":"^3.1.0","http-response-client":"^1.1.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","tsup":"^8.5.1","prisma":"^6.0.0","express":"^4.21.2","ts-jest":"^29.0.0","supertest":"^7.0.0","typescript":"^5.0.0","@types/jest":"^29.0.0","@types/node":"^20.0.0","@prisma/client":"^6.0.0","@types/express":"^5.0.0","@types/supertest":"^6.0.0"},"peerDependencies":{"express":">=4.0.0","@prisma/client":">=5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/prisma-autoread_1.0.0_1784803067832_0.605849767263555","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@didactika/prisma-autoread","version":"1.1.0","keywords":["prisma","express","rest","filter","search","pagination","cursor","rsql","odata","jsonapi","hal","aggregate","query-method","middleware","autoread"],"author":{"name":"Didactika","email":"info@didactika.org"},"license":"MIT","_id":"@didactika/prisma-autoread@1.1.0","maintainers":[{"name":"e2rd0","email":"me@e2rd0.com"},{"name":"hector21","email":"hectorlazaroarrechea@gmail.com"}],"contributors":[{"name":"Eduardo Estrada","email":"me@e2rd0.com"},{"name":"Hector Arrechea","email":"hectorlazaroarrechea@gmail.com"}],"homepage":"https://github.com/didactika/prisma-autoread#readme","bugs":{"url":"https://github.com/didactika/prisma-autoread/issues"},"dist":{"shasum":"abe7272c559f37fadea0e88377e780de185d4cd8","tarball":"https://registry.npmjs.org/@didactika/prisma-autoread/-/prisma-autoread-1.1.0.tgz","fileCount":7,"integrity":"sha512-nd2faZUn8JutOKd0WyfeZ7TEf4ZVcOWHRJqSav8y9Gdz821HjdHGDglCBtFf20r4F+qvLurMLGRUUE/Ukm9K9Q==","signatures":[{"sig":"MEQCIBzeyFJyhgLddi+iNznB/qxobA8GkHgT8P5BOWAewM25AiBy48KHkInej+HH6uTJjGN5bKwtstSagmV4HWKe3ZL9ZA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@didactika%2fprisma-autoread@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":593472},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"53607569a50f0f01fe781b7f778de3661db97756","scripts":{"test":"jest","build":"tsup","test:e2e":"prisma generate && prisma db push --force-reset && jest --testPathPattern=tests/e2e","test:unit":"jest --testPathPattern=tests/unit","test:coverage":"jest --coverage","prepublishOnly":"npm run test:unit && npm run test:integration && npm run build","test:integration":"jest --testPathPattern=tests/integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:18ebdf66-9c77-4c1d-b9e3-0733248fd05f"}},"repository":{"url":"git+https://github.com/didactika/prisma-autoread.git","type":"git"},"_npmVersion":"11.18.0","description":"Auto-generate Express search endpoints from your Prisma schema — GET/QUERY/POST, Prisma-native filtering, RSQL & OData, aggregations, cursor pagination and HAL/JSON:API/CSV output, zero boilerplate.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"halson":"^3.1.0","http-response-client":"^1.1.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","tsup":"^8.5.1","prisma":"^6.0.0","express":"^4.21.2","ts-jest":"^29.0.0","supertest":"^7.0.0","typescript":"^5.0.0","@types/jest":"^29.0.0","@types/node":"^20.0.0","@prisma/client":"^6.0.0","@types/express":"^5.0.0","@types/supertest":"^6.0.0"},"peerDependencies":{"express":">=4.0.0","@prisma/client":">=5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/prisma-autoread_1.1.0_1785329745424_0.00017774442071094576","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@didactika/prisma-autoread","version":"1.1.1","keywords":["prisma","express","rest","filter","search","pagination","cursor","rsql","odata","jsonapi","hal","aggregate","query-method","middleware","autoread"],"author":{"name":"Didactika","email":"info@didactika.org"},"license":"MIT","_id":"@didactika/prisma-autoread@1.1.1","maintainers":[{"name":"e2rd0","email":"me@e2rd0.com"},{"name":"hector21","email":"hectorlazaroarrechea@gmail.com"}],"contributors":[{"name":"Eduardo Estrada","email":"me@e2rd0.com"},{"name":"Hector Arrechea","email":"hectorlazaroarrechea@gmail.com"}],"homepage":"https://github.com/didactika/prisma-autoread#readme","bugs":{"url":"https://github.com/didactika/prisma-autoread/issues"},"dist":{"shasum":"8551b1d3f3e4a288c0ee0c58499977f6a91da64f","tarball":"https://registry.npmjs.org/@didactika/prisma-autoread/-/prisma-autoread-1.1.1.tgz","fileCount":7,"integrity":"sha512-fMcMQJF+T1gLFcnJp5k+oZTtaTz8v/0HMAs90aK0tYCr2fmYcCgXLHhqtt4nSGPXfr6AqukQ3/Y5d4+F3elS6A==","signatures":[{"sig":"MEUCIQCP6kQvprZq5269hZ9XUYnJd/GwYWKPuu8Rcj9YHch1CgIgKDeMqMvPXlVSsaMst2Tvoy65IbEUo4dIhoJ9693EARg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@didactika%2fprisma-autoread@1.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":603546},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"f8cc1888959f6485aa820f1d772f2ca01b56eb75","scripts":{"test":"jest","build":"tsup","test:e2e":"prisma generate && prisma db push --force-reset && jest --testPathPattern=tests/e2e","test:unit":"jest --testPathPattern=tests/unit","test:coverage":"jest --coverage","prepublishOnly":"npm run test:unit && npm run test:integration && npm run build","test:integration":"jest --testPathPattern=tests/integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:18ebdf66-9c77-4c1d-b9e3-0733248fd05f"}},"repository":{"url":"git+https://github.com/didactika/prisma-autoread.git","type":"git"},"_npmVersion":"11.18.0","description":"Auto-generate Express search endpoints from your Prisma schema — GET/QUERY/POST, Prisma-native filtering, RSQL & OData, aggregations, cursor pagination and HAL/JSON:API/CSV output, zero boilerplate.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"halson":"^3.1.0","http-response-client":"^1.1.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","tsup":"^8.5.1","prisma":"^6.0.0","express":"^4.21.2","ts-jest":"^29.0.0","supertest":"^7.0.0","typescript":"^5.0.0","@types/jest":"^29.0.0","@types/node":"^20.0.0","@prisma/client":"^6.0.0","@types/express":"^5.0.0","@types/supertest":"^6.0.0"},"peerDependencies":{"express":">=4.0.0","@prisma/client":">=5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/prisma-autoread_1.1.1_1785330977856_0.01167763801691879","host":"s3://npm-registry-packages-npm-production"}},"1.1.2":{"name":"@didactika/prisma-autoread","version":"1.1.2","keywords":["prisma","express","rest","filter","search","pagination","cursor","rsql","odata","jsonapi","hal","aggregate","query-method","middleware","autoread"],"author":{"name":"Didactika","email":"info@didactika.org"},"license":"MIT","_id":"@didactika/prisma-autoread@1.1.2","maintainers":[{"name":"e2rd0","email":"me@e2rd0.com"},{"name":"hector21","email":"hectorlazaroarrechea@gmail.com"}],"contributors":[{"name":"Eduardo Estrada","email":"me@e2rd0.com"},{"name":"Hector Arrechea","email":"hectorlazaroarrechea@gmail.com"}],"homepage":"https://github.com/didactika/prisma-autoread#readme","bugs":{"url":"https://github.com/didactika/prisma-autoread/issues"},"dist":{"shasum":"6d23340d93d3e018111ea96242c57e264a8f7426","tarball":"https://registry.npmjs.org/@didactika/prisma-autoread/-/prisma-autoread-1.1.2.tgz","fileCount":7,"integrity":"sha512-az/N6LHW4mJ9ym9MJxdKSB98jYcxmSiG8ExzxACcoNOBf17O0ud4vPIvLHGq4hGVNVbSswS2xBAOwX7ttIBdqA==","signatures":[{"sig":"MEQCIBRC056pPC0r3re3QNjiGVcwnrtYG+4XPwozmcXImWWzAiBgTDkJFVkoY/EaUcPsHDoANw8Jw86tCTeXj9tpBPZa4A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@didactika%2fprisma-autoread@1.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":607315},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"6a9f43339d38508d81e7dceed71772d512916539","scripts":{"test":"jest","build":"tsup","test:e2e":"prisma generate && prisma db push --force-reset && jest --testPathPattern=tests/e2e","test:unit":"jest --testPathPattern=tests/unit","test:coverage":"jest --coverage","prepublishOnly":"npm run test:unit && npm run test:integration && npm run build","test:integration":"jest --testPathPattern=tests/integration"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:18ebdf66-9c77-4c1d-b9e3-0733248fd05f"}},"repository":{"url":"git+https://github.com/didactika/prisma-autoread.git","type":"git"},"_npmVersion":"11.18.0","description":"Auto-generate Express search endpoints from your Prisma schema — GET/QUERY/POST, Prisma-native filtering, RSQL & OData, aggregations, cursor pagination and HAL/JSON:API/CSV output, zero boilerplate.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"halson":"^3.1.0","http-response-client":"^1.1.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","tsup":"^8.5.1","prisma":"^6.0.0","express":"^4.21.2","ts-jest":"^29.0.0","supertest":"^7.0.0","typescript":"^5.0.0","@types/jest":"^29.0.0","@types/node":"^20.0.0","@prisma/client":"^6.0.0","@types/express":"^5.0.0","@types/supertest":"^6.0.0"},"peerDependencies":{"express":">=4.0.0","@prisma/client":">=5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/prisma-autoread_1.1.2_1785332168633_0.9458013193070967","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@didactika/prisma-autoread","version":"1.2.0","description":"Auto-generate Prisma read/search APIs for Express, NestJS, Fastify and Hono — GET/QUERY/POST, filtering, RSQL/OData, aggregations, cursor pagination, OpenAPI, HAL, JSON:API and CSV.","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","require":"./dist/index.js","import":"./dist/index.mjs"},"./nest":{"types":"./dist/nest.d.ts","require":"./dist/nest.js","import":"./dist/nest.mjs"}},"scripts":{"build":"tsup","test":"jest","test:unit":"jest --testPathPattern=tests/unit","test:integration":"jest --testPathPattern=tests/integration","test:e2e":"prisma generate && prisma db push --force-reset && jest --testPathPattern=tests/e2e","test:coverage":"jest --coverage","prepublishOnly":"npm run test:unit && npm run test:integration && npm run build"},"keywords":["prisma","express","nestjs","fastify","hono","rest","openapi","swagger","filter","search","pagination","cursor","rsql","odata","jsonapi","hal","aggregate","query-method","middleware","autoread"],"author":{"name":"Didactika","email":"info@didactika.org"},"contributors":[{"name":"Eduardo Estrada","email":"me@e2rd0.com"},{"name":"Hector Arrechea","email":"hectorlazaroarrechea@gmail.com"}],"license":"MIT","repository":{"type":"git","url":"git+https://github.com/didactika/prisma-autoread.git"},"homepage":"https://github.com/didactika/prisma-autoread#readme","bugs":{"url":"https://github.com/didactika/prisma-autoread/issues"},"engines":{"node":">=20"},"peerDependencies":{"@nestjs/common":"^10.0.0 || ^11.0.0 || ^12.0.0","@nestjs/core":"^10.0.0 || ^11.0.0 || ^12.0.0","@nestjs/swagger":"^7.0.0 || ^8.0.0 || ^11.0.0 || ^12.0.0","@prisma/client":">=5.0.0","express":">=4.0.0","reflect-metadata":"^0.1.12 || ^0.2.0","rxjs":"^7.1.0"},"peerDependenciesMeta":{"@nestjs/common":{"optional":true},"@nestjs/core":{"optional":true},"@nestjs/swagger":{"optional":true},"reflect-metadata":{"optional":true},"rxjs":{"optional":true}},"dependencies":{"halson":"^3.1.0","http-response-client":"^2.0.1"},"devDependencies":{"@nestjs/common":"^11.2.3","@nestjs/core":"^11.2.3","@nestjs/platform-express":"^11.2.3","@nestjs/swagger":"^11.4.7","@prisma/client":"^6.0.0","@types/express":"^5.0.0","@types/jest":"^29.0.0","@types/node":"^20.0.0","@types/supertest":"^6.0.0","express":"^5.2.1","jest":"^29.0.0","prisma":"^6.0.0","reflect-metadata":"^0.2.2","rxjs":"^7.8.2","supertest":"^7.0.0","ts-jest":"^29.0.0","tsup":"^8.5.1","typescript":"^5.0.0"},"gitHead":"af8623964658d80f49c8e661881f8041a4c9842e","_id":"@didactika/prisma-autoread@1.2.0","_nodeVersion":"22.23.2","_npmVersion":"11.19.1","dist":{"integrity":"sha512-3C7i36fXw7rQFfsru0cBHp6cfBJYgE1MiZ3B+pef96mrPJc8iFJ+FbHs1NzhkF6nrQCPENv7JQXvQ7kSykkG5Q==","shasum":"e737dde25ff0b26386c678f77785ca85352094c0","tarball":"https://registry.npmjs.org/@didactika/prisma-autoread/-/prisma-autoread-1.2.0.tgz","fileCount":13,"unpackedSize":860201,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@didactika%2fprisma-autoread@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDP5sa707mqQVok1zdlfh/pfI+saTqnEibkeLuG6inf7AIhAMcAefZVNPTiNWzZFe1Ne3v1U5v7dn4jXmVUy96b3laZ"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:8b5a81ff-d262-4164-94e4-408b57a606f9"}},"directories":{},"maintainers":[{"name":"e2rd0","email":"me@e2rd0.com"},{"name":"hector21","email":"hectorlazaroarrechea@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/prisma-autoread_1.2.0_1788470493511_0.6010694631854632"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-12T08:30:09.273Z","modified":"2026-09-03T21:21:54.403Z","0.1.0":"2026-06-12T08:30:09.592Z","1.0.0":"2026-07-23T10:37:47.979Z","1.1.0":"2026-07-29T12:55:45.578Z","1.1.1":"2026-07-29T13:16:18.012Z","1.1.2":"2026-07-29T13:36:08.782Z","1.2.0":"2026-09-03T21:21:33.703Z"},"bugs":{"url":"https://github.com/didactika/prisma-autoread/issues"},"author":{"name":"Didactika","email":"info@didactika.org"},"license":"MIT","homepage":"https://github.com/didactika/prisma-autoread#readme","keywords":["prisma","express","nestjs","fastify","hono","rest","openapi","swagger","filter","search","pagination","cursor","rsql","odata","jsonapi","hal","aggregate","query-method","middleware","autoread"],"repository":{"type":"git","url":"git+https://github.com/didactika/prisma-autoread.git"},"description":"Auto-generate Prisma read/search APIs for Express, NestJS, Fastify and Hono — GET/QUERY/POST, filtering, RSQL/OData, aggregations, cursor pagination, OpenAPI, HAL, JSON:API and CSV.","contributors":[{"name":"Eduardo Estrada","email":"me@e2rd0.com"},{"name":"Hector Arrechea","email":"hectorlazaroarrechea@gmail.com"}],"maintainers":[{"name":"e2rd0","email":"me@e2rd0.com"},{"name":"hector21","email":"hectorlazaroarrechea@gmail.com"}],"readme":"# prisma-autoread\n\n<!-- Package -->\n[![npm version](https://img.shields.io/npm/v/@didactika/prisma-autoread.svg?logo=npm)](https://www.npmjs.com/package/@didactika/prisma-autoread)\n[![CI](https://img.shields.io/github/actions/workflow/status/didactika/prisma-autoread/ci.yml?branch=main&logo=github&label=CI)](https://github.com/didactika/prisma-autoread/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.x-3178C6.svg?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)\n\n<!-- Runtime -->\n[![Node](https://img.shields.io/badge/Node-20%20%7C%2022%20%7C%2024-339933?logo=nodedotjs&logoColor=white)](https://nodejs.org/en/about/previous-releases)\n[![Prisma](https://img.shields.io/badge/Prisma-5%20%7C%206%20%7C%207-2D3748?logo=prisma&logoColor=white)](https://www.prisma.io/)\n\n<!-- Frameworks -->\n[![Express](https://img.shields.io/badge/Express-4%20%7C%205-000000?logo=express&logoColor=white)](https://expressjs.com/)\n[![NestJS](https://img.shields.io/badge/NestJS-10%20%7C%2011%20%7C%2012-E0234E?logo=nestjs&logoColor=white)](https://nestjs.com/)\n[![Fastify](https://img.shields.io/badge/Fastify-4%20%7C%205-000000?logo=fastify&logoColor=white)](https://fastify.dev/)\n[![Hono](https://img.shields.io/badge/Hono-4-E36002?logo=hono&logoColor=white)](https://hono.dev/)\n\n<!-- Protocols -->\n[![HTTP](https://img.shields.io/badge/HTTP-GET%20%C2%B7%20QUERY%20%C2%B7%20POST-005571)](#http-methods)\n[![Formats](https://img.shields.io/badge/out-HAL%20%C2%B7%20JSON%3AAPI%20%C2%B7%20CSV-6f42c1)](#output-formats)\n\n> Drop-in Prisma **read/search APIs** for **Express, NestJS, Fastify and Hono**.\n> One declaration gives you filtering, sorting, field selection, relation includes,\n> aggregations, pagination\n> (offset **and** cursor) and multiple response formats — over `GET`, the new\n> `QUERY` method, or `POST`. Query it *as if you were writing Prisma*.\n\n```ts\ncreateAutoRead({ model: 'User', delegate: prisma.user }).applyTo(router);\n```\n```\nGET   /users?filter[age][gte]=30&sort=-createdAt&fields=id,firstName&page=2\nQUERY /users     { \"where\": { \"age\": { \"gte\": 30 } }, \"orderBy\": [{ \"createdAt\": \"desc\" }] }\n```\n\n---\n\n## Table of contents\n\n- [Features](#features)\n- [Compatibility](#compatibility)\n- [Installation](#installation)\n- [Quick start](#quick-start)\n- [HTTP methods](#http-methods)\n- [Filtering](#filtering)\n  - [Operators](#operators)\n  - [Logical groups, relations, JSON](#logical-groups-relations-json)\n  - [RSQL and OData](#rsql-and-odata)\n- [Sorting, selection, includes](#sorting-selection-includes)\n- [Pagination](#pagination)\n- [Routes: list, count, aggregate, group-by](#routes)\n- [Output formats](#output-formats)\n- [Configuration](#configuration)\n- [Security](#security)\n- [Performance](#performance)\n- [Error handling](#error-handling)\n- [Migrating from 0.x (legacy)](#migrating-from-0x-legacy)\n- [How it works](#how-it-works)\n- [License](#license)\n\n---\n\n## Features\n\n- **Prisma-native filtering** — the query mirrors Prisma's `where`, coerced and\n  validated against your schema (DMMF). Nothing Prisma can express is lost.\n- **Multiple input protocols** — bracket query strings, JSON bodies, **RSQL/FIQL**\n  and **OData `$filter`**, all producing the same query.\n- **GET, QUERY & POST** — including the new safe/idempotent [`QUERY`](https://www.ietf.org/archive/id/draft-ietf-httpbis-safe-method-w-body-02.html) method (body-based search).\n- **Full grammar** — `eq/ne/gt/gte/lt/lte/in/notIn/contains/startsWith/endsWith/mode/isNull`,\n  `AND`/`OR`/`NOT`, relation `some/every/none/is/isNot`, and JSON path filters.\n- **MongoDB embedded documents** — filter inside composite `type` blocks at any\n  depth; `is`/`some` wrappers are inserted for you.\n- **Aggregations** — `count`, `aggregate` (`sum`/`avg`/`min`/`max`) and `group-by`.\n- **Pagination** — offset (`page`/`limit`) and **cursor** (`cursor=`), with links.\n- **Output formats** — HAL (default), plain, JSON:API and CSV, with content negotiation.\n- **Security** — field/relation allow-lists, **hidden fields that never reach the\n  response**, **strict deny-by-default mode**, nesting guard.\n- **Renameable keywords** — a column called `fields` or `sort`? Rename the control parameter.\n- **Framework-agnostic** — Express, **NestJS**, **Fastify** and **Hono** bindings.\n- **Fast** — O(1) schema lookups, single-pass parsing, optional query-plan cache, telemetry.\n- **Backward compatible** — the original middleware still ships and works unchanged.\n- **Typed** — full TypeScript definitions, declared separately in `*.d.ts`.\n\n**[Full documentation →](./docs/README.md)** — guides, query reference and UML diagrams.\n\n---\n\n## Compatibility\n\nSupported versions and their current automated verification are listed below\n([`ci.yml`](.github/workflows/ci.yml)).\n\n| | Supported | Verified in CI |\n|---|---|---|\n| **Node.js** | `20` · `22` · `24` (the three current LTS lines) | full suite on each |\n| **Prisma** | `5` · `6` · `7` | unit + integration on all; end-to-end on 5 and 6 |\n| **Express** | `4` · `5` | full suite on both |\n| **NestJS** | `10` · `11` · `12` | native routing + Swagger integration on 11 |\n| **Fastify** | `4` · `5` | binding suite (not a dependency) |\n| **Hono** | `4` | binding suite (not a dependency) |\n| **TypeScript** | `5.x` | build emits CJS + ESM + `.d.ts` |\n\n<details>\n<summary><b>Notes on version differences</b></summary>\n\n- **Express 4 vs 5** — Express 5 changed the default query parser to the flat one, which\n  would break bracket notation. The engine parses the query string itself, so both work\n  with no configuration. *(Only the deprecated 0.x middleware, if you mount it directly,\n  needs `app.set('query parser', 'extended')` on Express 5.)*\n- **Prisma 7** — Prisma 7 moved the datasource URL out of `schema.prisma` into\n  `prisma.config.ts` and requires a driver adapter. That is a Prisma-level requirement of\n  *your* app; this library reads `Prisma.dmmf`, which is unchanged, so it works on 5, 6\n  and 7 alike.\n- **Fastify + `QUERY`** — register the method once before binding:\n  `fastify.addHttpMethod('QUERY', { hasBody: true })`.\n- **JSON filtering** — advanced JSON filters are only supported by PostgreSQL and MySQL\n  (a Prisma limitation). The JSON `path` format is detected from your datasource.\n\n</details>\n\n### Peer dependencies\n\n| Package | Range |\n|---|---|\n| `@prisma/client` | `>= 5.0.0` |\n| `express` | `>= 4.0.0` |\n| `@nestjs/common`, `@nestjs/core` | `10` · `11` · `12` (optional; Nest binding only) |\n| `@nestjs/swagger` | matching Nest version (optional; detected automatically) |\n\nGenerate your Prisma Client (`npx prisma generate`) — the engine reads field and\nrelation metadata from `Prisma.dmmf` at runtime.\n\n---\n\n## Installation\n\n```bash\nnpm install @didactika/prisma-autoread\nnpm install @prisma/client express   # peer dependencies\n```\n\n---\n\n## Quick start\n\n```ts\nimport express, { Router } from 'express';\nimport { PrismaClient } from '@prisma/client';\nimport { createAutoRead } from '@didactika/prisma-autoread';\n\nconst prisma = new PrismaClient();\nconst app = express();\nconst router = Router();\n\ncreateAutoRead({\n    model: 'User',\n    delegate: prisma.user,               // enables list + count + aggregate + group-by\n    methods: ['GET', 'QUERY'],\n    routes: ['list', 'count'],\n    searchable: ['firstName', 'lastName', 'email'],\n}).applyTo(router);\n\napp.use('/users', router);\n\n// Format thrown errors (they carry `.status`).\napp.use((err: any, _req: any, res: any, _next: any) => {\n    res.status(err.status ?? 500).json({ error: err.message });\n});\n\napp.listen(3000);\n```\n\n`GET /users` now supports filtering, sorting, selection, includes, search and\npagination; `GET /users/count` counts with the same filter.\n\n---\n\n## HTTP methods\n\nSet `methods` to choose the transports:\n\n| Method | Input | Notes |\n|---|---|---|\n| `GET` | query string | Simple, cacheable, linkable. Default. |\n| `QUERY` | JSON body | Safe & idempotent method with a body — for complex queries. |\n| `POST` | JSON body | Fallback for clients/proxies that don't speak `QUERY`. |\n\n`GET` reads a filter dialect (see below); `QUERY`/`POST` read a Prisma-shaped body:\n\n```jsonc\n// QUERY /users\n{\n  \"where\":   { \"age\": { \"gte\": 30 }, \"OR\": [{ \"active\": true }, { \"age\": { \"lt\": 18 } }] },\n  \"orderBy\": [{ \"createdAt\": \"desc\" }],\n  \"select\":  { \"id\": true, \"firstName\": true },\n  \"page\": 1, \"limit\": 20\n}\n```\n\n---\n\n## Filtering\n\nOn `GET` with `legacy: false`, the filter lives under `filter[…]` and mirrors Prisma:\n\n```\nGET /users?filter[age][gte]=30\nGET /users?filter[firstName][contains]=Al&filter[firstName][mode]=insensitive\nGET /users?filter[id][in]=1,2,3\n```\n\nValues are coerced to the column type from your schema; unknown fields return `400`.\n\n### Operators\n\n| Alias | Prisma | | Alias | Prisma |\n|---|---|---|---|---|\n| `eq` / `equals` | `equals` | | `contains` | `contains` |\n| `ne` / `not` | `not` | | `startsWith` / `sw` | `startsWith` |\n| `gt` `gte` `lt` `lte` | same | | `endsWith` / `ew` | `endsWith` |\n| `in` | `in` | | `mode` | `mode` |\n| `nin` / `notIn` | `notIn` | | `isNull` | `equals: null` / `not: null` |\n\nA bare list is treated as `in`: `filter[id]=1,2` → `{ id: { in: [1, 2] } }`.\n\n### Logical groups, relations, JSON\n\n```\n# OR / AND / NOT\nGET /users?filter[or][0][active]=true&filter[or][1][age][lt]=18\n→ { OR: [ { active: true }, { age: { lt: 18 } } ] }\n\n# Relations (to-many auto-wrapped in `some`; explicit some/every/none/is/isNot supported)\nGET /users?filter[posts][some][title][startsWith]=Hello\nGET /orders?filter[customer][email][contains]=@corp\n\n# MongoDB embedded documents (composite `type` blocks), wrapped in `is` / `some`\nGET /course-schedules?filter[program][shortname]=MAT\n→ { program: { is: { shortname: 'MAT' } } }\nGET /course-schedules?filter[program][subjects][type]=lab\n→ { program: { is: { subjects: { some: { type: 'lab' } } } } }\n\n# JSON columns (Prisma-native path filter)\nGET /users?filter[metadata][path][0]=theme&filter[metadata][equals]=dark\n```\n\n### RSQL and OData\n\nWith `legacy: false` the GET dialects are auto-detected by shape, so these all work\non the same endpoint:\n\n```\n# RSQL / FIQL  (; = AND, , = OR, * = wildcard)\nGET /users?filter=age=ge=30;name==Al*\nGET /users?filter=active==true,age=lt=18\nGET /users?filter=role=in=(admin,editor)\n\n# OData $filter\nGET /users?$filter=age gt 30 and startswith(name,'Al')\nGET /users?$filter=active eq true or age lt 18\nGET /users?$orderby=age desc&$select=id,name&$top=20&$skip=40\n```\n\nRestrict the accepted dialects with `formats: ['query']` (or `['query','rsql']`, …).\n\n---\n\n## Sorting, selection, includes\n\n```\nGET /users?sort=-createdAt,lastName     → orderBy: [{ createdAt: 'desc' }, { lastName: 'asc' }]\nGET /users?fields=id,firstName,email     → select: { id, firstName, email }\nGET /users?include=posts[comments]       → include posts with nested comments\nGET /users?distinct=email                → distinct: ['email']\nGET /users?search=alice                  → OR-contains across `searchable` fields\n```\n\n> `fields` (select) and `include` are mutually exclusive in Prisma — if both are\n> given, `select` wins.\n\n---\n\n## Pagination\n\n**Offset** (default):\n\n```\nGET /users?page=2&limit=20\n```\n\n**Cursor** — pass the last id you saw; the response echoes the next one in\n`pagination.nextCursor` and a `next` link:\n\n```\nGET /users?limit=20&cursor=42\n```\n\nA cursor is a **row identifier, not a row number**: `cursor=42` means \"start after\nthe row with id 42\", not \"start at row 42\" — for that, use `page`/`limit`. Follow\n`next` until it disappears: on the last page `nextCursor` is absent and `hasNext` is\n`false`. The value is validated against the id column, so a wrong-typed cursor\n(including a malformed MongoDB `@db.ObjectId`) returns `400` naming the problem\ninstead of a driver error. Page by another unique column with `?cursor[uuid]=…`.\n\n---\n\n## Routes\n\n`routes` accepts a short form or a map with custom paths:\n\n```ts\nroutes: ['list', 'count', 'aggregate', 'groupBy']\nroutes: { list: true, count: { path: '/total' } }\n```\n\n| Route | Prisma | Default path | Example |\n|---|---|---|---|\n| `list` | `findMany` (+ `count`) | `/` | `GET /users?filter[active]=true` |\n| `count` | `count` | `/count` | `GET /users/count?filter[active]=true` → `{ \"count\": 12 }` |\n| `aggregate` | `aggregate` | `/aggregate` | `GET /users/aggregate?avg=age&count=true` |\n| `groupBy` | `groupBy` | `/group-by` | `GET /users/group-by?by=role&count=true` |\n\nAggregation params: `sum`, `avg`, `min`, `max` (field lists) and `count` (`true` or a\nfield list); group-by adds `by` and an optional Prisma-native `having`.\n\n---\n\n## Output formats\n\n`hal` (default), `plain`, `jsonapi` and `csv` are built in. Pick a default with\n`output`, or let clients negotiate:\n\n```\nGET /users?format=csv\nGET /users            (Accept: application/vnd.api+json)   → JSON:API\n```\n\n---\n\n## Configuration\n\n```ts\ncreateAutoRead(options): { applyTo(router): Router }\n```\n\n| Option | Required | Default | Description |\n|---|:---:|---|---|\n| `model` | Yes | — | Prisma model name (schema casing). |\n| `delegate` | Yes* | — | Prisma model delegate (`prisma.user`). Enables all routes. |\n| `findByFilter` | Yes* | — | Legacy-style callback, alternative to `delegate`. *One of the two. |\n| `methods` | | `['GET']` | HTTP methods to expose. |\n| `routes` | | `['list']` | Routes to generate (short form or per-route path map). |\n| `output` | | `'hal'` | Default output format. |\n| `legacy` | | `true` | `true` = old GET syntax; `false` = modern dialects. |\n| `formats` | | all | GET dialects when `legacy: false` (`query`/`rsql`/`odata`). |\n| `searchable` | | `[]` | Fields scanned by `?search=`. |\n| `defaults` | | `{limit:10,maxLimit:100,sort:'id',order:'asc'}` | Pagination/sort defaults. |\n| `security` | | allow all | `{ fields, relations, hidden, maxDepth }`. |\n| `keywords` | | defaults | Rename reserved query params (see below). |\n| `provider` / `jsonPathSyntax` | | auto | JSON `path` syntax; auto-detected from the datasource. |\n| `cache` | | off | `true` or `{ max }` — cache parsed query plans. |\n| `onQuery` | | — | Telemetry hook `(t) => void` with per-request timings. |\n| `basePathPrefix` | | `''` | Prefix inserted into generated links. |\n\n### Renaming reserved parameters\n\nIf a column collides with a control parameter, rename the control — globally once, or\nper endpoint:\n\n```ts\nimport { Keywords } from '@didactika/prisma-autoread';\n\nKeywords.configure({ fields: 'select', filter: 'q' });   // global, once at bootstrap\ncreateAutoRead({ /* … */, keywords: { limit: 'size' } }); // per endpoint\n```\n```\nGET /users?q[age][gte]=30&select=id,firstName&size=20\n```\n\n### Frameworks\n\n```ts\ncreateAutoRead({ … }).applyTo(expressRouter);   // Express\ncreateAutoRead({ … }).applyToFastify(fastify);  // Fastify\ncreateAutoRead({ … }).applyToHono(honoApp);     // Hono\n```\n\nFor Nest, import the optional integration entry point:\n\n```ts\nimport { Module } from '@nestjs/common';\nimport { AutoReadModule } from '@didactika/prisma-autoread/nest';\nimport { prisma } from './prisma';\n\n@Module({\n    imports: [\n        AutoReadModule.register({\n            path: 'users',\n            model: 'User',\n            delegate: prisma.user,\n            methods: ['GET'],\n            routes: ['list', 'count'],\n            legacy: false,\n        }),\n    ],\n})\nexport class AppModule {}\n```\n\nThe generated handlers are native Nest routes, so `RouterExplorer` logs them normally.\nWhen `@nestjs/swagger` is installed, prisma-autoread detects it and automatically adds\nOpenAPI tags, operations, parameters, bodies, responses and content types. They appear\nin `SwaggerModule.createDocument()` with no prisma-autoread-specific Swagger setup.\nNest 12 is required only when `methods` includes `QUERY`; `GET` and `POST` work on\nNest 10–12.\n\nFastify and Hono are typed structurally, so neither is a dependency. See\n[docs/frameworks.md](./docs/frameworks.md).\n\n---\n\n## Security\n\n```ts\ncreateAutoRead({\n    model: 'User',\n    delegate: prisma.user,\n    security: {\n        fields: ['id', 'firstName', 'email'], // only these are filterable/sortable/selectable\n        relations: ['posts'],                 // only these can be traversed/included\n        hidden: ['password', 'resetToken'],   // never queryable AND never returned\n        maxDepth: 5,                           // reject deeply-nested filters\n    },\n});\n```\n\nAnything outside the allow-list returns `400`. Omit `security` (or use `'*'`) to allow\neverything. The policy applies to every dialect, the legacy one included.\n\n`fields` limits what a client may **ask for**; it does not change what Prisma returns.\nFor columns that must never leave the server — hashes, tokens, internal flags — use\n`hidden`: those are stripped from every response (including rows reached through\n`include`, `include=*` or an embedded document) and rejected in filters, sorts,\n`fields`, `distinct`, `group-by` and aggregations, worded as if the field did not\nexist. Dotted paths reach inside: `hidden: ['posts.draftNotes']`.\n\n---\n\n## Performance\n\n- **DMMF metadata** is cached per model as maps → O(1) field/relation lookups.\n- **Single-pass** parsing builds the Prisma `where` directly.\n- **`cache: true`** memoises parsed query plans by request signature (parsing only —\n  the database is always queried).\n- **`onQuery`** gives you `{ route, format, method, parseMs, execMs, cacheHit }`.\n- `list` reuses its `where` for the parallel `count`.\n\n---\n\n## Error handling\n\nErrors carry a `.status`; register an error handler after your routes:\n\n```ts\napp.use((err, _req, res, _next) => res.status(err.status ?? 500).json({ error: err.message }));\n```\n\n| Situation | Status |\n|---|---|\n| Unknown/again-disallowed field, bad operator, malformed RSQL/OData | `400` |\n| A backlog capability invoked before it exists | `501` |\n\nAn empty result is **not** an error (`200` with `data: []`).\n\n---\n\n## Migrating from 0.x (legacy)\n\nThe original middleware still ships and behaves exactly as before:\n\n```ts\nimport { AutoReadMiddleware, FilterMiddleware } from '@didactika/prisma-autoread';\nrouter.use(FilterMiddleware.processQueryFilters('User'));\nAutoReadMiddleware.applyToRouter(router, { modelName: 'User', findByFilter });\n```\n\nTo adopt the new engine while keeping the **old GET query syntax**, just declare it\nwith `createAutoRead({ ..., legacy: true })` (the default). When you're ready for the\nmodern grammar, set `legacy: false`. `QUERY`/`POST` bodies are always Prisma-native.\n\n---\n\n## How it works\n\n```\nHTTP (GET | QUERY | POST)\n  → Binding          (Express / NestJS / Fastify / Hono)\n    → EndpointController   (framework-agnostic pipeline)\n      → InputAdapter       (query / rsql / odata / json / legacy)\n        → QueryBuilder     (validate + coerce + map operators, DMMF- and security-aware)\n          → QuerySpec      (neutral, Prisma-shaped plan)\n            → Route        (list / count / aggregate / group-by)\n              → Executor   (findMany / count / aggregate / groupBy)\n                → OutputAdapter (hal / plain / jsonapi / csv)\n```\n\nEvery input protocol produces the same `QuerySpec`, and every output format consumes\nthe same result — so adding a protocol, format, route or framework is a self-contained\nclass plus one registration.\n\n---\n\n## Documentation\n\nFull docs live in **[`docs/`](./docs/README.md)**:\n\n| Guides | Internals |\n|---|---|\n| [Getting started](./docs/getting-started.md) · [Configuration](./docs/configuration.md) · [Query language](./docs/query-language.md) | [Architecture](./docs/ARCHITECTURE.md) |\n| [Protocols](./docs/protocols.md) · [Output formats](./docs/output-formats.md) · [Routes](./docs/routes.md) | [UML diagrams](./docs/diagrams/README.md) — context, containers, domain model, use cases, classes, sequences, state |\n| [Keywords](./docs/keywords.md) · [Security](./docs/security.md) · [Performance](./docs/performance.md) | |\n| [Frameworks](./docs/frameworks.md) · [Migration from 0.x](./docs/migration.md) | |\n\n**[14 runnable examples →](./examples/README.md)** — from a five-line endpoint to a\ncomplete API, covering every framework, protocol and output format.\n\n---\n\n## Contributors\n\nThanks to everyone who has contributed to this project:\n\n[![Contributors](https://contrib.rocks/image?repo=didactika/prisma-autoread)](https://github.com/didactika/prisma-autoread/graphs/contributors)\n\nWant to help? Read [CONTRIBUTING.md](./CONTRIBUTING.md).\n\n---\n\n## License\n\n[MIT](LICENSE) — © [Didactika](https://github.com/didactika)\n","readmeFilename":"README.md"}