{"_id":"@gusnips/server","_rev":"51-b2e43799c066e5ac087c7bb8a427034c","name":"@gusnips/server","dist-tags":{"latest":"0.9.0"},"versions":{"0.1.0":{"name":"@gusnips/server","version":"0.1.0","keywords":["backend","hono","errors","logging","retry","typescript"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.1.0","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"88979d7a89ec9e1b5fd9b487c632acd855ee8f51","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.1.0.tgz","fileCount":57,"integrity":"sha512-43fB0T1jfaSoVQC6glV9LoaMRvLdqd5YZzDsy6i3z7LSnb+wL7ersqDOTw8hm2N9y3QZSxgZlvYpH8bdHnBtIw==","signatures":[{"sig":"MEUCIQCscFbg4dGuieThxkeE2Upzs6aTlOaTXhtIYqpI5y7CJAIgSHeYbxkLR1Wbtx5nzkcGjJvE1n89aCGA9W7QEZXW4S8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":243885},"type":"module","types":"./dist/index.d.ts","shasum":"88979d7a89ec9e1b5fd9b487c632acd855ee8f51","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-43fB0T1jfaSoVQC6glV9LoaMRvLdqd5YZzDsy6i3z7LSnb+wL7ersqDOTw8hm2N9y3QZSxgZlvYpH8bdHnBtIw==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1 <1"},"peerDependencies":{"hono":">=4.9.9 <5","@gusnips/http":">=0.1 <1"},"peerDependenciesMeta":{"hono":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.1.0_1789907844222_0.48771923014533924","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@gusnips/server","version":"0.1.1","keywords":["backend","hono","errors","logging","retry","typescript"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.1.1","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"b119baebe936da939b77b750d195da49f8f16780","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.1.1.tgz","fileCount":57,"integrity":"sha512-sAqnTO0ivnUrewpa323wkcZbJyK0LnTXd6tv2wQGb3xh5PbGWpTGxNsr7swGJIGJjPFlYXM2E+0E3GFEVLHaZA==","signatures":[{"sig":"MEQCIA8WFd2HDe4Su30byr8eJbV50eTDcnSfIT0dMVjuXp2xAiBy2CwhTYQ7He5WNZrfb9QfyKXIO59pPOmVHeKlDaVNJA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIG/21DvLQ3xAvjRefxCs15ExGM/x+JMUclGsyrLZYDtfAiAranYeDia1k3ZaQ4ixDQ7zjufi3QBfG6QDngyFx0azjQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":260559},"type":"module","types":"./dist/index.d.ts","shasum":"b119baebe936da939b77b750d195da49f8f16780","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-sAqnTO0ivnUrewpa323wkcZbJyK0LnTXd6tv2wQGb3xh5PbGWpTGxNsr7swGJIGJjPFlYXM2E+0E3GFEVLHaZA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1 <1"},"peerDependencies":{"hono":">=4.9.9 <5","@gusnips/http":">=0.1 <1"},"peerDependenciesMeta":{"hono":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.1.1_1789928426007_0.44910820449050326","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@gusnips/server","version":"0.2.0","keywords":["backend","hono","errors","logging","retry","typescript"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.2.0","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"b3a1fdee0f6cdcc19fb9948b27c7a59f3d5dcc71","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.2.0.tgz","fileCount":63,"integrity":"sha512-AQTZzKe+bWjFZzUGHSv0SXA0TAY/4ofuEMEYRrius0NwEkFRf/mAdbXkkH3tzp1G3IYvaZDoI+swanz7HXp6nQ==","signatures":[{"sig":"MEQCIGi9wCsUxIJGsGFqAEHvQm9ITB4IwubcD57XsQ9qOnn0AiBw6KkqQSrB5mxKhmB3IMA1VMbH9OoyYXlMK9R7sdETFw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCICW7QXs57i+Bqb0omnNCSfcOsHin9TSV6uuzXsjAlNPjAiEAk9cYxMBCm8Z8sbbjSTY7j3b5AkzrHgpvRV58bqvhDyM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":279609},"type":"module","types":"./dist/index.d.ts","shasum":"b3a1fdee0f6cdcc19fb9948b27c7a59f3d5dcc71","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-AQTZzKe+bWjFZzUGHSv0SXA0TAY/4ofuEMEYRrius0NwEkFRf/mAdbXkkH3tzp1G3IYvaZDoI+swanz7HXp6nQ==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1 <1"},"peerDependencies":{"hono":">=4.9.9 <5","@gusnips/http":">=0.1 <1"},"peerDependenciesMeta":{"hono":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.2.0_1789936220311_0.9770564323438402","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@gusnips/server","version":"0.2.1","keywords":["backend","hono","errors","logging","retry","typescript"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.2.1","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"311190d24934031f6079ca7f4d16f4a99cd2086c","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.2.1.tgz","fileCount":63,"integrity":"sha512-2tKvkcElKgOEFEP28k5pc0SHzDIApATlXpR4S3s/pClphrS/Gvk/DoeRHEhyVrbZiXZsDwYXCzwCs0Bj2FuzyQ==","signatures":[{"sig":"MEUCIQD7ST4VFZ1sWHA6d8LESd/j7dzrrBYC8YdQLJag5U1UcAIgJ5H9XgapCzas5wmfi3275ADwfzRsW5vHFvao3QSIMfk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQC1GY7myoJ9MqmKkcyof4dDgfuTyJMfhFgH/9q4YdXMYAIgVmQV5Oh3KF+HorArT7YCxcHKjrcS3mQCk7Y5uC7/acY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":283364},"type":"module","types":"./dist/index.d.ts","shasum":"311190d24934031f6079ca7f4d16f4a99cd2086c","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-2tKvkcElKgOEFEP28k5pc0SHzDIApATlXpR4S3s/pClphrS/Gvk/DoeRHEhyVrbZiXZsDwYXCzwCs0Bj2FuzyQ==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1 <1"},"peerDependencies":{"hono":">=4.9.9 <5","@gusnips/http":">=0.1 <1"},"peerDependenciesMeta":{"hono":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.2.1_1790006091752_0.8311179259978576","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@gusnips/server","version":"0.3.0","keywords":["backend","errors","hono","logging","retry","supabase","typescript"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.3.0","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"c8db180e30d05eca48a34a4160039bd3ead27af7","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.3.0.tgz","fileCount":69,"integrity":"sha512-uXmb0s8Sih0hcaelI/GWI45oTTZTTpA9b8OgdRDMBiY8DutSB2n+tURKrC35HHjd3Z0NbHhmGcilcvduRIZbuQ==","signatures":[{"sig":"MEYCIQD5RaEU/KdMBighc8GKBln8MbR0nOaa9+lQZU8eB1YyPAIhAIHb8LyJSGnD5HvsMk2piLNaPuo1ff+drF7tz2Wes8fP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDEhRVdIOKjSw6kZCVkkQw9BKgrmtqn8auZdPI4dHYJhwIgFywBdRPRy+1zvnrtVjAxPnCLkwJYRo+yUsJnNZYpCs8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":300313},"type":"module","types":"./dist/index.d.ts","shasum":"c8db180e30d05eca48a34a4160039bd3ead27af7","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-uXmb0s8Sih0hcaelI/GWI45oTTZTTpA9b8OgdRDMBiY8DutSB2n+tURKrC35HHjd3Z0NbHhmGcilcvduRIZbuQ==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1 <1","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"hono":">=4.9.9 <5","@gusnips/http":">=0.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"hono":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.3.0_1790014814481_0.9413789703266313","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"@gusnips/server","version":"0.3.1","keywords":["backend","errors","hono","logging","retry","supabase","typescript"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.3.1","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"70642fd2fbe667b0eeaa8378444ec64309a9b4a1","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.3.1.tgz","fileCount":69,"integrity":"sha512-cDTGZIwOnxB65mfzKgtRMUFttYa1xAfgJSi0ShCFNRwwgo6YaV9bv3hTnGhmozIHNf196z/h5IajJiGDLb+xjw==","signatures":[{"sig":"MEYCIQDXGMHvRdnxgwxzT2rTjfFA970Uv77OyAWm+ANqb5HoBQIhALqBo6UN6VKFTdvbwXMQ9fXLWJGbvMYw9MsDhRYJFHs1","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIF+LavmwR9HnIkvfHK0+fO4a2Nu7XKiVsCSsAtLKS33rAiEA6nW2YQZtvOeB3S/XWGJ+JC4P0W5ls/0GJTKU2llA7VA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":304916},"type":"module","types":"./dist/index.d.ts","shasum":"70642fd2fbe667b0eeaa8378444ec64309a9b4a1","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-cDTGZIwOnxB65mfzKgtRMUFttYa1xAfgJSi0ShCFNRwwgo6YaV9bv3hTnGhmozIHNf196z/h5IajJiGDLb+xjw==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1 <1","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"hono":">=4.9.9 <5","@gusnips/http":">=0.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"hono":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.3.1_1790016767005_0.8419808123648345","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@gusnips/server","version":"0.4.0","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.4.0","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"868d6e127409ef7597e083eab8a329eb7aecb5c0","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.4.0.tgz","fileCount":75,"integrity":"sha512-niBMycKDbW319rvJAlVvnJByLbySA62QOWLnC4/sQJQQWCORddz2y62jmsqO74mYcX9pKEwc/tDzeW2qZzeQcw==","signatures":[{"sig":"MEUCIBEa4mL0q5w1eAsT6RuOl+iIyKIwnlSMPe163NpqZqZ4AiEAwn+XhW0V+dodbut9Vmzwoyj2cYIAc9EYheLDQ2sbaFQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCclbxDJv8gpcts0jUj2QGp+87WQWbzAMHo8r6d0WAdMgIhAPLxZE21ApyPUClnDscTTVJeTzjqwfxeeixTNtUoX7RH","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":330551},"type":"module","types":"./dist/index.d.ts","shasum":"868d6e127409ef7597e083eab8a329eb7aecb5c0","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-niBMycKDbW319rvJAlVvnJByLbySA62QOWLnC4/sQJQQWCORddz2y62jmsqO74mYcX9pKEwc/tDzeW2qZzeQcw==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","@types/pg":"^8.15.0","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1 <1","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","@gusnips/http":">=0.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.4.0_1790017647793_0.2662827462953321","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@gusnips/server","version":"0.4.1","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.4.1","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"93be23c9d76e42b40a8e202290f4891c377eb6a6","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.4.1.tgz","fileCount":75,"integrity":"sha512-iHcPuC28wbdeNbMC7fLUaK3WdDH0jTSqw+GCgiVqCXcZtYK1KEkYPPjh2cRZCXjwFFqBfhmlJLQDgGQ+UNX/kw==","signatures":[{"sig":"MEQCIEG6uWGyltGhPok2bfUksD2bhHoqcC5mk5c9wFGZUIOBAiBHb1rOfmuvVeZfNdvkLGDgoPKRxC+L/sFUpvb6Lt80Ow==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCUlzNGGZ4NbCCyhfSqKD1NXN2G+KZvuMfxCB3mMLKtyQIgCiN1qm4hXl/kx48Va41D/JoPuJuUfmwGQQCrfLfs7rI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":330913},"type":"module","types":"./dist/index.d.ts","shasum":"93be23c9d76e42b40a8e202290f4891c377eb6a6","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-iHcPuC28wbdeNbMC7fLUaK3WdDH0jTSqw+GCgiVqCXcZtYK1KEkYPPjh2cRZCXjwFFqBfhmlJLQDgGQ+UNX/kw==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","@types/pg":"^8.15.0","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1 <1","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","@gusnips/http":">=0.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.4.1_1790020943455_0.6242725041534569","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@gusnips/server","version":"0.5.0","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.5.0","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"3bd4796633f08f8c48ad2aa640d99d655aa90ad5","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.5.0.tgz","fileCount":81,"integrity":"sha512-PW8T6K5yfpRqXrfZzKJ9FgbTvAbPK3kzfRHtFT/qjW1TTO4+3iETIcO5z7lj8DZXPOa0di3d2Wku0NTOgVq5AQ==","signatures":[{"sig":"MEUCIC1qy8EFjTtYqj4uc936D3HO70pCjYuE6e5wIhP8jf9IAiEAxVeLR2SZ/mEYFP4gUzzNyxMYOJgdeYsbo7O0+D9BAF4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQC74fNwRvcHNSTMh9Ka0AIUAMETFL6FIvbi4moASqywRAIhAOoQAXCCvyPNuXvusLSK9nxTI0aGUnwQpG60pTTxc05A","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":360300},"type":"module","types":"./dist/index.d.ts","shasum":"3bd4796633f08f8c48ad2aa640d99d655aa90ad5","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-PW8T6K5yfpRqXrfZzKJ9FgbTvAbPK3kzfRHtFT/qjW1TTO4+3iETIcO5z7lj8DZXPOa0di3d2Wku0NTOgVq5AQ==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1 <1","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","ioredis":">=5.6 <6","@gusnips/http":">=0.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"ioredis":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.5.0_1790028311328_0.7193533911864463","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"@gusnips/server","version":"0.5.1","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.5.1","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"444ab21bee6868700f9f72011c0dc6b17b113d3a","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.5.1.tgz","fileCount":81,"integrity":"sha512-eTrz5sjGq2AaFUnoIXhFFgXWncLMZin9X1HjMrVlVSPd0XHoI9NuFRhoZlljP5hHuibQT7tHoZCM6cwVYWQO6Q==","signatures":[{"sig":"MEUCIGGWcXSPuMMkY1URLT+FYIQEZ9CHUh6BT0WXb7nrj+uLAiEAxBGoPTwcXc8lg2TtPC91/SZksw99DUWp5seroOk1yXY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCyf1OIWSKDH0kPs3uPXMsz2+DvfkI4dcYZnHxXhgaTjgIgav9nx/LE4j5kisIA3nek7g1i2lUBy5QQ70iXEX1YrC0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":363037},"type":"module","types":"./dist/index.d.ts","shasum":"444ab21bee6868700f9f72011c0dc6b17b113d3a","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-eTrz5sjGq2AaFUnoIXhFFgXWncLMZin9X1HjMrVlVSPd0XHoI9NuFRhoZlljP5hHuibQT7tHoZCM6cwVYWQO6Q==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1 <1","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","ioredis":">=5.6 <6","@gusnips/http":">=0.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"ioredis":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.5.1_1790028711075_0.3848253303390372","host":"s3://npm-registry-packages-npm-production"}},"0.5.2":{"name":"@gusnips/server","version":"0.5.2","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.5.2","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"86454a0cfc88e88d7c133a1d0d39ab51d1a536a8","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.5.2.tgz","fileCount":81,"integrity":"sha512-dQ9PClq3FoMPuXaeXkuZwpIvUWP2K+4Css6gG85GG/DiLreyZk08E+xCghRuN0RH4nDTHYYAP/RXcBGAJ0Eb3w==","signatures":[{"sig":"MEYCIQCNJH+gTWmo6Dvp7l14Mwu5z5n5VPiRucJ9Lb0p4MNMcQIhAJESKxLzY7O9v36KGIDdloxIpMDwnPeyJGcA1j7UpVnC","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQD+WFEG82VLZamRKTWqFhN38gBjJF6okZBaAwAIgWW8pQIgAaf55D0YUDAxPkZmpel+2i/HojBfuE7cpK3gZdfXJF8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":367165},"type":"module","types":"./dist/index.d.ts","shasum":"86454a0cfc88e88d7c133a1d0d39ab51d1a536a8","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-dQ9PClq3FoMPuXaeXkuZwpIvUWP2K+4Css6gG85GG/DiLreyZk08E+xCghRuN0RH4nDTHYYAP/RXcBGAJ0Eb3w==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1 <1","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","ioredis":">=5.6 <6","@gusnips/http":">=0.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"ioredis":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.5.2_1790033079350_0.20476931529288755","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@gusnips/server","version":"0.6.0","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.6.0","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"40983e502dbe66f56b67e1780e58cbcd28440450","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.6.0.tgz","fileCount":98,"integrity":"sha512-OOp1I/OCCXVwreEjC3LKIldXrp9AxNViqoqaEO0oFZq3uZCN/vJqwff8lnAESMRcfS37nFm27gXBdgk4wj+vBg==","signatures":[{"sig":"MEUCICMNgfGkrKi8PaZyIl96eElYu0tF2D97rl1nSI3NlUxnAiEA3jdG8rclBwpEqPkbB8zTLjeDq14A3jXhJPr3bqutaXg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCID1ayen2skJKTQQ0rNV6UzazJIOPe+4wferOb0X7ONQUAiB+k5+yLUtXcUB7D+PwEqK+S81dgQtYW1j1jbIlluhADg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":485803},"type":"module","types":"./dist/index.d.ts","shasum":"40983e502dbe66f56b67e1780e58cbcd28440450","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-OOp1I/OCCXVwreEjC3LKIldXrp9AxNViqoqaEO0oFZq3uZCN/vJqwff8lnAESMRcfS37nFm27gXBdgk4wj+vBg==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","ioredis":">=5.6 <6","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"ioredis":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.6.0_1790233676755_0.36802150923507515","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"@gusnips/server","version":"0.7.0","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.7.0","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"0e11ca9b493aa39a563ec6c27f7cfa8b02f6071a","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.7.0.tgz","fileCount":175,"integrity":"sha512-yrnZI1J9otmRWhcyrgSkgv3WZAjIpO8b5VTUrxsaFmTrW9rhuiu9nSWPawsP2aBqzTSflaP5snwL+I/JVA5iFg==","signatures":[{"sig":"MEUCIQDAfMUu74kJpbwiDPulcg9ID/zN7ZiFRIpGnt0p5M7gcgIgEpSx/zqpw6/VlNWe7lwqnP6agvkMyiLRnxxoh78s4E4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCICK31jTJmFkk/BiOcQUB9LdY0EEXf3mCCuQ5piFWfQ63AiBuLcWPYamUjyLmJa2CDKRWdv436vvZTFNJzcCRmtMPww==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":748220},"type":"module","types":"./dist/index.d.ts","shasum":"0e11ca9b493aa39a563ec6c27f7cfa8b02f6071a","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-yrnZI1J9otmRWhcyrgSkgv3WZAjIpO8b5VTUrxsaFmTrW9rhuiu9nSWPawsP2aBqzTSflaP5snwL+I/JVA5iFg==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","ioredis":">=5.6 <6","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"ioredis":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.7.0_1790237686621_0.5209789163315086","host":"s3://npm-registry-packages-npm-production"}},"0.7.1":{"name":"@gusnips/server","version":"0.7.1","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.7.1","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"b53c0f4ca5dfbbc96d72f3eaa39b6ca196418aa0","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.7.1.tgz","fileCount":181,"integrity":"sha512-ipJmBPBH6zg41i6Aq6hXD0+mcp5hH/U5K2nncFA4DDAX4W3cD2wb377ZVAJ9UIg8pwGH49DQVMsNdn8ysw09hA==","signatures":[{"sig":"MEYCIQCpTid9mvR5fqvftXd8+P7koNbqT7Ssqz4VXGGroEAnZgIhALpn+r8WneUE2lHqEq6/KdL6AZrWBRyjm4iD+zQX2dVP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCICX0jB/zHdFe0WXpAyihoechD7Ugo3u684aukjtk0XJ8AiEAkvcup26in80W6lhCWj/QxM8FQ/AWmTWE9GhUmc1BrpQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":783507},"type":"module","types":"./dist/index.d.ts","shasum":"b53c0f4ca5dfbbc96d72f3eaa39b6ca196418aa0","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-ipJmBPBH6zg41i6Aq6hXD0+mcp5hH/U5K2nncFA4DDAX4W3cD2wb377ZVAJ9UIg8pwGH49DQVMsNdn8ysw09hA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","ioredis":">=5.6 <6","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"ioredis":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.7.1_1790259689461_0.5158099071110906","host":"s3://npm-registry-packages-npm-production"}},"0.7.2":{"name":"@gusnips/server","version":"0.7.2","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.7.2","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"871b52f0acbb67b69f7670526cf72a40e79ae440","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.7.2.tgz","fileCount":188,"integrity":"sha512-go7lP2TOogepd16+xYuR0j1bqzgWI80xhtY1bUG2A0PXoks8U+FUlCiooj/TEhpnnn+4EChcxE3yXcUlITTLQg==","signatures":[{"sig":"MEUCIQCerryje8EWSI/rnQwBwQ9StCQLUjNyv3DiP6uhiQLklgIgORJVWDpLZLcS9YJ1GmXhUl94ohLdn3IeQ/GnYrV4nrM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIBAgdQIAxNxuahgoOL9Bj1Gduon4/2Mc29q5oJWwc9GgAiEA9fFIgwO5nrALcfu0I3iobiJMptSHU7qGPbhIKPYJjMI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":841152},"type":"module","types":"./dist/index.d.ts","shasum":"871b52f0acbb67b69f7670526cf72a40e79ae440","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-go7lP2TOogepd16+xYuR0j1bqzgWI80xhtY1bUG2A0PXoks8U+FUlCiooj/TEhpnnn+4EChcxE3yXcUlITTLQg==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","typescript":"^5.9.3","@types/node":"^24.12.0","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.7.2_1790261366068_0.24954127855469777","host":"s3://npm-registry-packages-npm-production"}},"0.7.3":{"name":"@gusnips/server","version":"0.7.3","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.7.3","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"fdde759407466b45adba3b00ad7e025f7d78739f","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.7.3.tgz","fileCount":200,"integrity":"sha512-Z/aMHBlZtIYDxzt51hbL1GOgBpJPoLws6QDWJJU2jeAfH71BQDip1ysZfbwdckWc9C3MzREc8FJqyKg48nN3BQ==","signatures":[{"sig":"MEYCIQCGLCWw3oS2oLAP8eNzbhkAuKflYNbh+7sSa3+3b0plGAIhAOm5HiKebm+Qn9zdk8YKWQne4+EXMByiltGOsl1V+YWf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDKnhmz7AdqBSHnXtZDi7Qmxs/NHusBmFxwPCgSWQacSAIge7Q1M0oEG6RhoAmCO1Xv0pxytTXmVNKcNn0J18ZyePE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":880559},"type":"module","types":"./dist/index.d.ts","shasum":"fdde759407466b45adba3b00ad7e025f7d78739f","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-Z/aMHBlZtIYDxzt51hbL1GOgBpJPoLws6QDWJJU2jeAfH71BQDip1ysZfbwdckWc9C3MzREc8FJqyKg48nN3BQ==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.7.3_1790262983146_0.062440765428976475","host":"s3://npm-registry-packages-npm-production"}},"0.7.4":{"name":"@gusnips/server","version":"0.7.4","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.7.4","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"8e03beb99abb440c67f1f88f92d50415e6e5f1fc","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.7.4.tgz","fileCount":206,"integrity":"sha512-wQ3eqE2HI4ZdDUxh04QmvBg81l1wsz6WvYT9kea4ChZUDnGQTfvD+nuNuafvz/G5VBNTvwvhEmARGK5Nb7WlAg==","signatures":[{"sig":"MEQCIEjg3bRoe+RdDMQea9OzgVIbgTyHuEbau28dlkdc4Z4CAiAm80l6yXsu4abMy+O3X8AAecLeLayLckMwzGtZHR6L8g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIASCgYbyo+mI/REjPMOtsK54c91oW9YI/VtZidv10Q81AiEAw1Da4EoWMJM1JtZYtqqs1HJLPykcXwBcFTxUmp02gaU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":926030},"type":"module","types":"./dist/index.d.ts","shasum":"8e03beb99abb440c67f1f88f92d50415e6e5f1fc","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-wQ3eqE2HI4ZdDUxh04QmvBg81l1wsz6WvYT9kea4ChZUDnGQTfvD+nuNuafvz/G5VBNTvwvhEmARGK5Nb7WlAg==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.7.4_1790264089868_0.8612994726272494","host":"s3://npm-registry-packages-npm-production"}},"0.7.5":{"name":"@gusnips/server","version":"0.7.5","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.7.5","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"6b9b7066442472a9b4e2e65f7fde0eb037e83841","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.7.5.tgz","fileCount":212,"integrity":"sha512-neO/8FgPbTHB64s2FnBLnTwvJ/Zh7ZSNhbcrqbZVT9XPbaL9CglorhVojmY1fncmhQdkKjW2ERkRYF6wuJ0LBg==","signatures":[{"sig":"MEYCIQDPVgcmz5X+c8E1/JNBpOC1w1fgY4NzVQb3i2eR3/yTNQIhAN2LL5q9oVzmyCS2vZBgaF1CWa0bWomP96L2l5MrC/du","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDPc++W767wjrfqg4yOjPBAo2VMXi2RgvNQwKg6Npe34AIhAOs+RAb/B2HewjB91+E5rmuFJrpTZVKwh6kFuRcsDdSo","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":947128},"type":"module","types":"./dist/index.d.ts","shasum":"6b9b7066442472a9b4e2e65f7fde0eb037e83841","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-neO/8FgPbTHB64s2FnBLnTwvJ/Zh7ZSNhbcrqbZVT9XPbaL9CglorhVojmY1fncmhQdkKjW2ERkRYF6wuJ0LBg==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.7.5_1790265374200_0.773520714930866","host":"s3://npm-registry-packages-npm-production"}},"0.7.6":{"name":"@gusnips/server","version":"0.7.6","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.7.6","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"39c66a6c56fec19172907b921b544dc5fdc8c494","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.7.6.tgz","fileCount":219,"integrity":"sha512-Az+OzRaOfq/Cn2xRq0gqqQ3jDAd6uWbAPRiN6sOkjyPUw7xZGwPi1foGharqSU3Kj1HYTUOMhu8ZVoedIzB4Zg==","signatures":[{"sig":"MEUCIQD+qIbCWOEsr/mIG6ip8kW+1VvfNlFEhT/n8hKT6vnkZgIgX2cP100qcKJ2z8zHgF/pOJfcM4fOQZ73LUMBc1u9KCA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIDdPx2iXVDVGcCODaQTU1GebsidI8Xua8PYuiE/79BWrAiEAqEwF4eWZkihr7AwlQU9ejPkDsdq2MrXLDijYZlFG3ps=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":986974},"type":"module","types":"./dist/index.d.ts","shasum":"39c66a6c56fec19172907b921b544dc5fdc8c494","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-Az+OzRaOfq/Cn2xRq0gqqQ3jDAd6uWbAPRiN6sOkjyPUw7xZGwPi1foGharqSU3Kj1HYTUOMhu8ZVoedIzB4Zg==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.7.6_1790273445377_0.2594642490832082","host":"s3://npm-registry-packages-npm-production"}},"0.7.7":{"name":"@gusnips/server","version":"0.7.7","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.7.7","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"7ccd1ba9e7aa0f0bf3cf4dc266476f3c2ba38579","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.7.7.tgz","fileCount":225,"integrity":"sha512-l/Som9TjQA3M54Xq7RTTmLv+2/TW3KJFgsUIAzt2w6qxR8jpcvHH6yo97b6PmlOuQ2WwEeEjMHD16DBGrE4fNA==","signatures":[{"sig":"MEQCIAFZDcjU45s1DPNPGYPSG1bZzw/M9JzIK3Eju58tMOtJAiALT0Pm2vOUXbsTZ/HOstBLQC9W1E5w4zqmjzhDrZVMbA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCSRCeVbBmkz2yOrCEcTfmC+5g7Be4unW/l5naMGiKFbwIhANoiJN2u6L3ScsuLroX+C12K+xYzNNdG60L5r4jR/Iad","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1067167},"type":"module","types":"./dist/index.d.ts","shasum":"7ccd1ba9e7aa0f0bf3cf4dc266476f3c2ba38579","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-l/Som9TjQA3M54Xq7RTTmLv+2/TW3KJFgsUIAzt2w6qxR8jpcvHH6yo97b6PmlOuQ2WwEeEjMHD16DBGrE4fNA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.7.7_1790281807837_0.7687847395100957","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"@gusnips/server","version":"0.8.0","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.0","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"e0bb6af0fabcb4f4ba7b2576c7ed5169d6949c3e","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.0.tgz","fileCount":225,"integrity":"sha512-fQ38QWH5pyHk82d41Hhi29AAVLmgugnY39QXmRWzRbN6A6zKTzmOFNBjp4fAjNXOc6UBzOTAeRFlLB4d4LvMfQ==","signatures":[{"sig":"MEQCICWFWgdjTNOaJr1dNJ1LNgICSHLbd/c8Bcq5Uo/IhNACAiB5Npmj/o8UtyCu21Bj7xRlGjWyzuhGLhr5B0vOuvUTMg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDh7xJhfQdNGnjlhZy5sVFVBGKTwuTV/aHE6tsQMWUzBwIhAM7B89iLnnTHhUVYAN85kfSAYIi8DtqsuOZoMYPfmQu5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1074867},"type":"module","types":"./dist/index.d.ts","shasum":"e0bb6af0fabcb4f4ba7b2576c7ed5169d6949c3e","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-fQ38QWH5pyHk82d41Hhi29AAVLmgugnY39QXmRWzRbN6A6zKTzmOFNBjp4fAjNXOc6UBzOTAeRFlLB4d4LvMfQ==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.0_1790284280983_0.8527699820042958","host":"s3://npm-registry-packages-npm-production"}},"0.8.1":{"name":"@gusnips/server","version":"0.8.1","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.1","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"5de04b66e456b0585b311a18dc6b990d67d909c1","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.1.tgz","fileCount":225,"integrity":"sha512-GdOq31W8ISK19COeC8RluEdUYmebF5LBQGnWeJoxG2BOd3wtYZ2LWrZbVQZYsWm0rCUpLBCk2RFB7BqNJ4TljQ==","signatures":[{"sig":"MEUCICaie++emRrc6OGNMlxstRGCkfVpM16G+ShEO83omJnKAiEAktS+Hf02r6t/wWSIV7XDkkNa4xUhI0/BcDRO2sXC/2c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIQDvjDIxka0lziViEGLFjrdKzIYNB3/x9iXRbBng9bisXgIffcz2ZydiXDS2BOTMpAZy7p9D4pmPv9jClpYXOAzUOw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1089425},"type":"module","types":"./dist/index.d.ts","shasum":"5de04b66e456b0585b311a18dc6b990d67d909c1","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-GdOq31W8ISK19COeC8RluEdUYmebF5LBQGnWeJoxG2BOd3wtYZ2LWrZbVQZYsWm0rCUpLBCk2RFB7BqNJ4TljQ==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.1_1790284851695_0.7178546926005729","host":"s3://npm-registry-packages-npm-production"}},"0.8.2":{"name":"@gusnips/server","version":"0.8.2","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.2","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"281d8d8330e03870e83ee7899ccdbe428ef0cf3e","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.2.tgz","fileCount":225,"integrity":"sha512-q/ddBFxL7CTihFlO5zztP1Jy4X15/qoGmHPTqRcaiwcuwVbLT2DP3lQUVEeuYo0QoRXUuhebyHduGbnqW48laA==","signatures":[{"sig":"MEYCIQCA9/ThxE2/AjMIM47U7dqTY9yEUiRRRwLJXbCxza93UQIhAOXQraCjQsNrUj+W9bNaNnbbvqCqR7iYBfq75XXvMumD","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIAdTToncfuLJq7oOpkha8FUi4RiwlcW+yPHLphrxVtCLAiEAy8wPRjt3NCI8t1TOKLI6hTtKgAYedLPsGJRpF14rxhM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1091180},"type":"module","types":"./dist/index.d.ts","shasum":"281d8d8330e03870e83ee7899ccdbe428ef0cf3e","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-q/ddBFxL7CTihFlO5zztP1Jy4X15/qoGmHPTqRcaiwcuwVbLT2DP3lQUVEeuYo0QoRXUuhebyHduGbnqW48laA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.2_1790289420523_0.28492796937351916","host":"s3://npm-registry-packages-npm-production"}},"0.8.3":{"name":"@gusnips/server","version":"0.8.3","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.3","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"918ffe0e20ebbb706c945204006fa365a9ce1ba3","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.3.tgz","fileCount":225,"integrity":"sha512-Xohmop8lekU6p+1hbz0QToHASJp5abpIH+KWuBXdtzJ4JjKWs2Mk6JVzS+PKZ78BusCAaGzmD2UatPB3J45knA==","signatures":[{"sig":"MEYCIQCJ48IefGdy6EFhRAeZoXoyOO/NaLijHg/X+bu8HR2kwQIhAOXpwPFELBwAA308weIkWJ0gErycxUa7Pn4gTOFJAH9V","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDjFBKlXnXzUvRv9DlU650FddwvpsPMTWQbntUjX834gQIhAM0O62J7a4OWEWcui3baYuKWmS6QepwZtDz0sUDCWGu8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1093067},"type":"module","types":"./dist/index.d.ts","shasum":"918ffe0e20ebbb706c945204006fa365a9ce1ba3","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-Xohmop8lekU6p+1hbz0QToHASJp5abpIH+KWuBXdtzJ4JjKWs2Mk6JVzS+PKZ78BusCAaGzmD2UatPB3J45knA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.3_1790289865847_0.19930165950181644","host":"s3://npm-registry-packages-npm-production"}},"0.8.4":{"name":"@gusnips/server","version":"0.8.4","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.4","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"020b43b3a5b5b6a39538e7072d930060d4cceb39","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.4.tgz","fileCount":225,"integrity":"sha512-z4ncKa0vlPofEJQcype1Wy8Gs15iFXvGEFmKimG6+E79Gvivi8oUqe4b/Ykk8hHUxFXG7OMxXH2JHnEk7uC3xQ==","signatures":[{"sig":"MEYCIQCtonRXt6ouYI9YT8eJD8whk80O85D3IsqMpD1CnqGgqwIhANwga/qDoAMs4diPCAZfxCDnus0/qfs5yEedxvrfNtQ2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDnnr1jZTQJCW3178/LExWWq3ultfB12qS0xk+mu5WqeQIhAL4QCLhY/TLKpi/mquZidO5wYUJ9NYnGkM5pyCv0g5wb","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1096186},"type":"module","types":"./dist/index.d.ts","shasum":"020b43b3a5b5b6a39538e7072d930060d4cceb39","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-z4ncKa0vlPofEJQcype1Wy8Gs15iFXvGEFmKimG6+E79Gvivi8oUqe4b/Ykk8hHUxFXG7OMxXH2JHnEk7uC3xQ==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.4_1790293928822_0.14809666125766352","host":"s3://npm-registry-packages-npm-production"}},"0.8.5":{"name":"@gusnips/server","version":"0.8.5","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.5","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"45e72fa4255dee1cef2bdc2b5ce9a0095a8d9bd9","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.5.tgz","fileCount":225,"integrity":"sha512-hve55hdN3zcEudrYgeHq8WlN9nCra0UsAuQj4p+WltVZkKUnChYMEYFUfbJpF4Q/qQxo82EYBhkX5eVhH+z83Q==","signatures":[{"sig":"MEQCIBmrN3BRhcyWL+zz8sB4Ha72LcI+f4JeJO7WC8JZLsOeAiBtstmqmEZQYIo3H0kwt5m6Lw1CXvthXiqI2s9BwxOlPw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIB/XcfPqB2Xt7mt6NFWvTGbk0m7PkK123CfgYF4UoNX8AiEAy4+NY79HM9tFKSuZtNk3bSgGPFygLPb0aPK1xxQwsnU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1099681},"type":"module","types":"./dist/index.d.ts","shasum":"45e72fa4255dee1cef2bdc2b5ce9a0095a8d9bd9","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-hve55hdN3zcEudrYgeHq8WlN9nCra0UsAuQj4p+WltVZkKUnChYMEYFUfbJpF4Q/qQxo82EYBhkX5eVhH+z83Q==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.5_1790294941226_0.19314285686425903","host":"s3://npm-registry-packages-npm-production"}},"0.8.6":{"name":"@gusnips/server","version":"0.8.6","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.6","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"2d55cc72809aac6cfd2d2ff2ae7fabd5a520cb3c","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.6.tgz","fileCount":225,"integrity":"sha512-s/0OToNGA9rE6nbj7RrM5fgUO8wqz7ag7XNJciziePHD5jKkhT9pF4Cwpz/GjcZx57M8ISZ/kKUJ+LDMLkisrg==","signatures":[{"sig":"MEQCIHL5WaplmHUrBd6K9q1xDhSmDN8Iv1TbD5SFjc48uAV4AiBA59O3dCZSQvpwVD8KifDKt5Ta0IWV+qrim9TFWpAy6w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIESNgM3iMK4N0kyE7Br5OXiu1HsGY9cPagzlmnpeMFrYAiEAv8mk3+cKOC+69QTS3t8KNoxDOo1pOAy+ZhN9lLtRt0A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1101199},"type":"module","types":"./dist/index.d.ts","shasum":"2d55cc72809aac6cfd2d2ff2ae7fabd5a520cb3c","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-s/0OToNGA9rE6nbj7RrM5fgUO8wqz7ag7XNJciziePHD5jKkhT9pF4Cwpz/GjcZx57M8ISZ/kKUJ+LDMLkisrg==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.6_1790295613333_0.7112711603775932","host":"s3://npm-registry-packages-npm-production"}},"0.8.7":{"name":"@gusnips/server","version":"0.8.7","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.7","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"a15de753f44eaa7b02885c3bfdd100a6533c2c54","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.7.tgz","fileCount":225,"integrity":"sha512-1I5TitPOFabNMf8C47QLsPM+fTtLjoWBgE74783++IsbAtoJ5JyuYzfO9sxQQ2IQqoyCJBKqXqx/IVHNj3++gA==","signatures":[{"sig":"MEQCIEhDufX74T/r3jVn0VlaN758JrMBHw7A1UUjKjsuzr9hAiAVL5RcZ53NzuQ3plBDRvTAEXjlJ1KwKhNfPomT8awnEg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDyIAPNSrlJ89eV0qu/j6ZrB+zZxCYho/8zff1+f4bAiQIgHy1J/lEhLB9ixHSmORfjEzjs9f88KK5tIfhkCdZfY3I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1103800},"type":"module","types":"./dist/index.d.ts","shasum":"a15de753f44eaa7b02885c3bfdd100a6533c2c54","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-1I5TitPOFabNMf8C47QLsPM+fTtLjoWBgE74783++IsbAtoJ5JyuYzfO9sxQQ2IQqoyCJBKqXqx/IVHNj3++gA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.7_1790301450532_0.9349689603498874","host":"s3://npm-registry-packages-npm-production"}},"0.8.8":{"name":"@gusnips/server","version":"0.8.8","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.8","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"f684f1cde29308140a346b8b744bebddf6786ae2","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.8.tgz","fileCount":225,"integrity":"sha512-HSZgfrhizM1Ttzd1LQqslKIFs4CHdtPAHMbFRPaiIE8GLcvcmOnBO2gpE2bDYeIeiOZo7vMfXIwGI/eMgeSgnw==","signatures":[{"sig":"MEQCIH9WfWZIu1sQJ04dEtfFeTqcsM7Bd+Ooj5RAHMLw83y+AiAE9Q18Yfe3SzsUCELIzUCZ9cSfRTQVBkfo9ldhPd+M6g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIHSIuAuc7M9NRORLOAsmnRetPX6BwEZBD6gmfAvKUxTXAiEAzevX09ZHOJ/UDP4e2+gPE7w1lM0TbxoFQv9CbcVEAfE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1106869},"type":"module","types":"./dist/index.d.ts","shasum":"f684f1cde29308140a346b8b744bebddf6786ae2","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-HSZgfrhizM1Ttzd1LQqslKIFs4CHdtPAHMbFRPaiIE8GLcvcmOnBO2gpE2bDYeIeiOZo7vMfXIwGI/eMgeSgnw==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.8_1790304820978_0.8174228286806222","host":"s3://npm-registry-packages-npm-production"}},"0.8.9":{"name":"@gusnips/server","version":"0.8.9","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.9","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"d1d57962a23d4a1bedf83ca5f1d90b4d5e5e51bc","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.9.tgz","fileCount":225,"integrity":"sha512-olDJpClYKRMFEEzO1sh0sAPGCv+sJGQzMKREyVJauePLoZItYCdtkj0qWqb04NCf4/szOSMpcUE2QLBR7auQZQ==","signatures":[{"sig":"MEUCIQClSfl7r4mtiWkINy8i6tkqC655q5pntQ9/e44PJ5nGpwIgHLQnNoYWNzxlchAEzEHhjsytsjhqOY5KsfIv3P4RwdI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDyGLnvP9NYpuPAzyJJhEB4VTYmN42HjP0hXehHsPPqkAIhALPtp5TdEVRQhiOOO5pmXvA6UOj/zqycJHULu8EXPcPG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1109606},"type":"module","types":"./dist/index.d.ts","shasum":"d1d57962a23d4a1bedf83ca5f1d90b4d5e5e51bc","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-olDJpClYKRMFEEzO1sh0sAPGCv+sJGQzMKREyVJauePLoZItYCdtkj0qWqb04NCf4/szOSMpcUE2QLBR7auQZQ==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.9_1790305351335_0.6515308517662897","host":"s3://npm-registry-packages-npm-production"}},"0.8.10":{"name":"@gusnips/server","version":"0.8.10","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.10","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"bbb4c20a8035ae244a3e97b3c5576fbdab26e36e","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.10.tgz","fileCount":225,"integrity":"sha512-uNnDZqf+VX7OKT1xtB5k/7O/CD/bj0JG7cnTH73WnRGpu0g8F9eBeEc2BSBQj/qVxoQgK+yiuXN8QdGDuAXHdA==","signatures":[{"sig":"MEUCIQDvWIjUmUr9S+pisevzckOuFuUe9c+oczADmrUEMR7O9QIgSsgSeGb2ZezEu+83cJGQhPq/I8lKG+ZYNOOeug3c2g0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDzMAPP8ZJNaz47wOLAi6AqHyqgqdZIj/9ilZUxWcQ0mAIhAKEcVagQLrpgGD3AZ5NPYbz/1lm2nqmqRr9Pd6D1LRMf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1110365},"type":"module","types":"./dist/index.d.ts","shasum":"bbb4c20a8035ae244a3e97b3c5576fbdab26e36e","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-uNnDZqf+VX7OKT1xtB5k/7O/CD/bj0JG7cnTH73WnRGpu0g8F9eBeEc2BSBQj/qVxoQgK+yiuXN8QdGDuAXHdA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.10_1790312967274_0.9070701558616572","host":"s3://npm-registry-packages-npm-production"}},"0.8.11":{"name":"@gusnips/server","version":"0.8.11","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.11","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"185018372d5a1590b1d40e56bf8c51b8b90f6731","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.11.tgz","fileCount":225,"integrity":"sha512-ndoZldNJ8CKYbM3Fc0b1Mi3I+Gz9hwnK4bbtdYxMFM/BwJQsqMWbmsN3MjH9QWwGI2sK7dHC6hEQAApCzfv7UA==","signatures":[{"sig":"MEUCIQDmibZ6GzV04s3BzFCgKgyF9ZmxWTkYoUZqeCf9l2HlpwIgFpMo5PVWZQt7VUDbL4UaAJjm753yi7wp7rd7y1rsvEY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCyivAFmVIsMoeaoHJlzOdfYAOcEWNwAZ3uYOrti+2B9gIhAOUC+TeHmQwSgj4Y2LB8J+rgI4l3Sdfr4haTAO2iw7Ge","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1117354},"type":"module","types":"./dist/index.d.ts","shasum":"185018372d5a1590b1d40e56bf8c51b8b90f6731","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-ndoZldNJ8CKYbM3Fc0b1Mi3I+Gz9hwnK4bbtdYxMFM/BwJQsqMWbmsN3MjH9QWwGI2sK7dHC6hEQAApCzfv7UA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.11_1790334996453_0.9521144266432018","host":"s3://npm-registry-packages-npm-production"}},"0.8.12":{"name":"@gusnips/server","version":"0.8.12","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.12","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"809a9f8ab8441c5ba6323a3ac07bfe742dce6f7b","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.12.tgz","fileCount":225,"integrity":"sha512-fMSttj1MxRH9DQZzc51KqHl5qsRM9zdHPLa61OKXzq25zegBKsytsWWRqYlYWmEhw/O8EFbDy5kop+h/raPZhg==","signatures":[{"sig":"MEUCIQDjLhB7W04hUhDyscjo84cRAnvJc5YzBJsQxuru9qwB6AIgG8rBdfHVqPPB73/A6DnsjrwvImD18pM7CzRZeJGvtR4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQC85f4TU1MgDQeCr8Njbshd1Opu5FQ6NIEGTykeg+VzJQIgKua21NgPGTBs6/4Dsy92gmTzgyvSBWmkyV8baYWa23o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1117710},"type":"module","types":"./dist/index.d.ts","shasum":"809a9f8ab8441c5ba6323a3ac07bfe742dce6f7b","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-fMSttj1MxRH9DQZzc51KqHl5qsRM9zdHPLa61OKXzq25zegBKsytsWWRqYlYWmEhw/O8EFbDy5kop+h/raPZhg==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.12_1790335747421_0.10910909313524253","host":"s3://npm-registry-packages-npm-production"}},"0.8.13":{"name":"@gusnips/server","version":"0.8.13","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.13","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"743e67d55fd124c0c47b544e8987972aba570632","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.13.tgz","fileCount":225,"integrity":"sha512-eD5crRa0LqiN5Lrfnf/4R7m1Hrw906CoLsM0S7LwVgJPgVs76YG6HSgR0TiSgAjVSawTD7NOY+RwjjNiHSRDLA==","signatures":[{"sig":"MEYCIQD7VSqyG740kUI/ZJlPMrm5nIOIrVt+2K5P8zB7AYNHVQIhAMOIC/rpP66qdhBbPfeXZhmgmEGml82RfE45pFJCTpUe","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQD/jVehiVMXifN0C2KFh7GWzK8WCAwDnelgqtQL8M8CfwIhAM3+v4LY9xI/QPwSJaXZOguPoDNgRgrLO6QJpZHBc56b","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1119898},"type":"module","types":"./dist/index.d.ts","shasum":"743e67d55fd124c0c47b544e8987972aba570632","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-eD5crRa0LqiN5Lrfnf/4R7m1Hrw906CoLsM0S7LwVgJPgVs76YG6HSgR0TiSgAjVSawTD7NOY+RwjjNiHSRDLA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.13_1790336413067_0.49480557023815375","host":"s3://npm-registry-packages-npm-production"}},"0.8.14":{"name":"@gusnips/server","version":"0.8.14","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.14","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"6d7775d41318f2f9167e289d7c878cc0a38911b7","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.14.tgz","fileCount":225,"integrity":"sha512-4AA/9igf1lfbLsW39yhEzPsunHQZ+CFGyt7RZxZkC7Exoo8EMSvlA327x03hyGqZeXNZ2Hgmcy1AuR8LgFXTMw==","signatures":[{"sig":"MEYCIQDs/+Q63pB7NL1tZkHHSBt0uLDQkyZQk+WjVbCknHED4QIhAOs21LBNKK2JRvzsHo02yE0/TSbBcgtLgcoDhuLhMFP3","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCL3EWhfPGVu9x9JDVonwBFywNYKuGPYR+yWzDa06T+rAIgXRKZrgF/9+xT566QWlrFlkJ1Ib2NN/aLZUgeJQD1vqI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1123257},"type":"module","types":"./dist/index.d.ts","shasum":"6d7775d41318f2f9167e289d7c878cc0a38911b7","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-4AA/9igf1lfbLsW39yhEzPsunHQZ+CFGyt7RZxZkC7Exoo8EMSvlA327x03hyGqZeXNZ2Hgmcy1AuR8LgFXTMw==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.14_1790337055646_0.4669171838893622","host":"s3://npm-registry-packages-npm-production"}},"0.8.15":{"name":"@gusnips/server","version":"0.8.15","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.15","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"2cb12e8c7dbb5e07627b9cd8abbb1c31ea23ef69","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.15.tgz","fileCount":225,"integrity":"sha512-dIaLJkMguv7En4T6doKnc9/P0zpMbIDWz+a2IO5jpg5Q32UAchjdt0dhn9s7HOO9wUWjy36k5kD/mStxKDDv1A==","signatures":[{"sig":"MEUCIEfqsyRAH57SrFqhSKw6kL8Eu65VnA2gj36BLvE+bS5UAiEA7/taMvyOExPRzvt5PtCySFZ3nGfHWqjyRcWz6ohRNb8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDNK5t749kODm0Mh17P/9nAxCagkxL4PhcVzvehQvrjtAIgZcvCQn80hD5GKq/LW5kJI5LV1zXIaLdDMWNhTmIkWL4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1132907},"type":"module","types":"./dist/index.d.ts","shasum":"2cb12e8c7dbb5e07627b9cd8abbb1c31ea23ef69","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-dIaLJkMguv7En4T6doKnc9/P0zpMbIDWz+a2IO5jpg5Q32UAchjdt0dhn9s7HOO9wUWjy36k5kD/mStxKDDv1A==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.15_1790338274566_0.8252620462627269","host":"s3://npm-registry-packages-npm-production"}},"0.8.16":{"name":"@gusnips/server","version":"0.8.16","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.16","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"9bd9af5e6818e4de15163a9ca8f2a0b0d846de79","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.16.tgz","fileCount":225,"integrity":"sha512-AlJyaWs4sh52gkFS3+0inoGRt7ons9n3jJh/CzL7X5fCS3DEMut88sBPuc5jIESRITVZ507kSxcfcAayDczScw==","signatures":[{"sig":"MEUCIQDJ1+vHKwIQsaLr1DwwpMnhjYP9/28Qs0rEoLHmRy/CkwIgclJotPfre64b359n6dVHvmUl8F22PWsd/3kEh5YVMsg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCufuxWSCBNxSBsInQyiMHMEosFUvzITny5AOf7+rs0LAIhAO569zMOUZu4Vo0CGyGoIXJNNMjzE0WxhGvMLlNOfC91","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1142109},"type":"module","types":"./dist/index.d.ts","shasum":"9bd9af5e6818e4de15163a9ca8f2a0b0d846de79","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-AlJyaWs4sh52gkFS3+0inoGRt7ons9n3jJh/CzL7X5fCS3DEMut88sBPuc5jIESRITVZ507kSxcfcAayDczScw==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.16_1790339320837_0.2130063537790292","host":"s3://npm-registry-packages-npm-production"}},"0.8.17":{"name":"@gusnips/server","version":"0.8.17","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.17","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"232f2b5e83ce1c219d11ea45fa37f67d8bd98010","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.17.tgz","fileCount":225,"integrity":"sha512-OSH7mYtP9Ik3JnGbLrZ1fjBpyvVSaJsHPM3FQ65+KcRpKk2ttZ7lbgEAM6/hwwteNTkBxFcyALopelzYY6PIkQ==","signatures":[{"sig":"MEUCID/IEehJNBnS4ctxU2pzVemYsRTDze4m7UWs/J6dxhzrAiEAoTjt08HE6oZqFIuE/ZttqQxS21UTETnaTxUmjZnPIMY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIHiq3GHY7Ow/UEXORS39gv9cirU8cbSdzzLvzGRk/eQ5AiEAmtq6rtgqG2c8SU6wOnTw58j4zROH1g5QLgyuADfp9JU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1148172},"type":"module","types":"./dist/index.d.ts","shasum":"232f2b5e83ce1c219d11ea45fa37f67d8bd98010","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-OSH7mYtP9Ik3JnGbLrZ1fjBpyvVSaJsHPM3FQ65+KcRpKk2ttZ7lbgEAM6/hwwteNTkBxFcyALopelzYY6PIkQ==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.17_1790346351194_0.7081555853953141","host":"s3://npm-registry-packages-npm-production"}},"0.8.18":{"name":"@gusnips/server","version":"0.8.18","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.18","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"2dffe142490323626522fd2f76ca9e6ed962e3ab","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.18.tgz","fileCount":225,"integrity":"sha512-NQGV234ygKsVvhRE0q3ID/LiWD1n7RI6lH5RqDBBkx/GRaVhZ1sMRrgCRKFdJ010YRNr9XlA32c2t4NSoxBfsQ==","signatures":[{"sig":"MEUCIF3PlWD0M54qWWN3Qi4V07w4vtUdc5JEkazd3OKlcuEsAiEAnSKfkNVGY7/1lOgR+BWyqyA9iV+NHKK4lVa2sZ9/G14=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDerCwEkAf/XU0F8jjngDQ79JloOHZOkZHQmOowk4Oi8AIgCe18xQnZAwWZ9ryDqnxWWNtKwr2jaqR7ahTRvXQYtLY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1150740},"type":"module","types":"./dist/index.d.ts","shasum":"2dffe142490323626522fd2f76ca9e6ed962e3ab","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-NQGV234ygKsVvhRE0q3ID/LiWD1n7RI6lH5RqDBBkx/GRaVhZ1sMRrgCRKFdJ010YRNr9XlA32c2t4NSoxBfsQ==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.18_1790351311307_0.9200897901124068","host":"s3://npm-registry-packages-npm-production"}},"0.8.19":{"name":"@gusnips/server","version":"0.8.19","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.19","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"e6397d44779dc005c7998209b2d928420ebebe50","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.19.tgz","fileCount":225,"integrity":"sha512-juvdTYRPZa0PsaiRkY0QU7EZpKOLej87Kd9iO+laPAwRgIgsACBQNujkCNR9RwzmUZk+Zj2oumTrvm3iY6WFVg==","signatures":[{"sig":"MEUCIQDrskq5IPIiqxDcMbD58e/8ao+uZ/+14qinyLeeZVQTUQIgahyN0PWWwqmW8e7/M+Fy2fp54VUv0Z17eLFtTrIK4c8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQD+2B1CeKXuFRFeytvn6RKI4MpmouVjPcqCg+45RhpIyAIhAICne14JWZtCTwCrbjBbcL5TLFUt7467WPNH2g4tPxHv","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1157556},"type":"module","types":"./dist/index.d.ts","shasum":"e6397d44779dc005c7998209b2d928420ebebe50","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-juvdTYRPZa0PsaiRkY0QU7EZpKOLej87Kd9iO+laPAwRgIgsACBQNujkCNR9RwzmUZk+Zj2oumTrvm3iY6WFVg==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.19_1790371558599_0.5971859024073938","host":"s3://npm-registry-packages-npm-production"}},"0.8.20":{"name":"@gusnips/server","version":"0.8.20","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.20","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"23f8dbb4cfe025be484fb0849f88869f33591408","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.20.tgz","fileCount":225,"integrity":"sha512-r2W4SysNZOcbfOnWTJ6YgLqRuenN6GjkXnYyTYCzE2FPzf8Slztm09egVNaxh8RAipXP4/EFI9K2/XWBHp0nLg==","signatures":[{"sig":"MEUCIE75FCACrQ7EQf9eihff1S6lf6u24LKv/DR85ekook+oAiEAhoYsGi5wkeTuzXaAZfvNO6PLhpLqjFjF/fRZuUTndpI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDZLI1gJq2s9ysoMccl9QSW+TeCFh9X0wlJFx0UzNHIygIhAPFbqHyOtCH5njUG/pDruwTXt+Yub+HzhjhHfpKWf+RV","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1164594},"type":"module","types":"./dist/index.d.ts","shasum":"23f8dbb4cfe025be484fb0849f88869f33591408","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-r2W4SysNZOcbfOnWTJ6YgLqRuenN6GjkXnYyTYCzE2FPzf8Slztm09egVNaxh8RAipXP4/EFI9K2/XWBHp0nLg==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <6","ioredis":">=5.6 <6","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.20_1790381220632_0.7689704961491719","host":"s3://npm-registry-packages-npm-production"}},"0.8.21":{"name":"@gusnips/server","version":"0.8.21","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.21","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"144322e5bbbc3e956bbc5b2c868ea79389ad3d84","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.21.tgz","fileCount":225,"integrity":"sha512-k1bRWQJXK92rgsJTw0QIK4gnYDHTnTFVV1/8yEHeuxPKjBK2UAPNACbbmwm0m7HEiRRX7UmywKbkSHNqR3d5EA==","signatures":[{"sig":"MEQCIBxA6AkPc4XzZryn8U9uQV1My8d+YA2MDEM/YJE389hWAiB4l+Z+EGPGgTWeuOyHQmWpByTiFho0FjcTX24IgNqrKQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDtB7W+lBtVOWAukGDyrLOo9gydAaQcLlXf8uOJ5oghVgIhAJFSCNhJP1mm4ZmBtIEf3zt6TvOrrDJUlOt8IwY+n+gz","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1165698},"type":"module","types":"./dist/index.d.ts","shasum":"144322e5bbbc3e956bbc5b2c868ea79389ad3d84","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-k1bRWQJXK92rgsJTw0QIK4gnYDHTnTFVV1/8yEHeuxPKjBK2UAPNACbbmwm0m7HEiRRX7UmywKbkSHNqR3d5EA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <7","ioredis":">=5.6 <7","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.21_1790386492333_0.4163528109915706","host":"s3://npm-registry-packages-npm-production"}},"0.8.22":{"name":"@gusnips/server","version":"0.8.22","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.22","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"42fa75b40712cb45109d94cd7fb2c43e10feecf4","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.22.tgz","fileCount":225,"integrity":"sha512-wvCjw7Oi0XAvNcWN5Lj2PZAtQEhHs6uZe52kfIX4dRVyQXVDOFnMY++iaQ4hmc6IcAImvBbpzq/PI6ueccwk5g==","signatures":[{"sig":"MEYCIQDoD96LfXbnxXSmEmEkqMojv0XXVpXva7Ab2nrBTageSQIhAP5+vEiPhO4ceUcGWAu8aKuJR47CWfFhbVPoplSyO17i","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQC3JtCYrhLh/v/MhuXBjZ26/L41OXceRFx6p3E3yFwPtQIgaW9+Ym3iItVlGST3ndQXT5a5aPvV9uqmDtdqC1wFWew=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1176961},"type":"module","types":"./dist/index.d.ts","shasum":"42fa75b40712cb45109d94cd7fb2c43e10feecf4","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-wvCjw7Oi0XAvNcWN5Lj2PZAtQEhHs6uZe52kfIX4dRVyQXVDOFnMY++iaQ4hmc6IcAImvBbpzq/PI6ueccwk5g==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <7","ioredis":">=5.6 <7","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.22_1790397811534_0.9823994842268091","host":"s3://npm-registry-packages-npm-production"}},"0.8.23":{"name":"@gusnips/server","version":"0.8.23","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.23","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"679624b4fc17ed27b373f021352d002bd8c615bb","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.23.tgz","fileCount":225,"integrity":"sha512-joFyMrh1vTX8rXfIx+YYNCPFaKnTfXecC3a+qVUEXtKyBiB6U6BBjqVc5grhS8vPDFGNjc/SYPR10s5p8fcmzA==","signatures":[{"sig":"MEUCIQCsf+OfS1Jyw/1xHvFnHUAyrEeWc0sO7oCOaL5BqdOU2gIgGn1ZMWYJez/eH+RtntMjmsfgNk1BbH4Qhi/rxSLYYZ8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCICVciEQe6dlF4Q1sfsULFyN/q4N9N/+fpjq5IpGy6RauAiBt3vMvyUiyo0Mrlmr8gm+bKhvCxzU+ZFhoJNUrubOUGw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1178244},"type":"module","types":"./dist/index.d.ts","shasum":"679624b4fc17ed27b373f021352d002bd8c615bb","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-joFyMrh1vTX8rXfIx+YYNCPFaKnTfXecC3a+qVUEXtKyBiB6U6BBjqVc5grhS8vPDFGNjc/SYPR10s5p8fcmzA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <7","ioredis":">=5.6 <7","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.23_1790399215482_0.04090360345326638","host":"s3://npm-registry-packages-npm-production"}},"0.8.24":{"name":"@gusnips/server","version":"0.8.24","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.24","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"3b395e33dcb935db39555cd9b6d2497b416c4f77","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.24.tgz","fileCount":225,"integrity":"sha512-Mq6WUIWRnS0Am1g9DOYT3k3h+o5Nd8YAUk9wShjJgBX/InPqB9URU11q1wtwN+PB8gDHhjgGOSeCAHUtjQNv3w==","signatures":[{"sig":"MEUCIE7zJlHE/fIISHQV773O2mGpIC+r1NhmVO+87xXpB7yfAiEAzAfcIhJFTqMl2hVczaRA6qN9CaKgdgfSi6kki9TKc+E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIEcAY8Cqe4NFxobXIWJXPZV+odbvQz9bP4Dzcuga7M6gAiAc7X+AA5wCxguOdMO/Y6Fw+jUpozoknqE/jzK/VOibCA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1187860},"type":"module","types":"./dist/index.d.ts","shasum":"3b395e33dcb935db39555cd9b6d2497b416c4f77","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-Mq6WUIWRnS0Am1g9DOYT3k3h+o5Nd8YAUk9wShjJgBX/InPqB9URU11q1wtwN+PB8gDHhjgGOSeCAHUtjQNv3w==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <7","ioredis":">=5.6 <7","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.24_1790399565094_0.828899363433315","host":"s3://npm-registry-packages-npm-production"}},"0.8.25":{"name":"@gusnips/server","version":"0.8.25","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.25","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"9328bf8ba4f23470d3df1f0b501f0289fb2749f0","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.25.tgz","fileCount":225,"integrity":"sha512-TZa2JE7m2P0emWaAsMrTLr5GrCC32FQ+Jcut0MS9/+wtJPDaRN+JXTZjIiYoXuTtDQznGEq1NFT27mVd7quvCw==","signatures":[{"sig":"MEUCIQCwHGJwG+We1P4VFTyjmyyCSop7VoNus/Ji/+kVjuJt6AIgKkd7ljKM6j4WxGMAp+5T5Dco8faBgi4oRdMTtgcLEf4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCpXxKKXhb9WtN2dCyc6ig0FY4C37+fc96FkrZNZimYtAIgKIYFTDUAbbPvESrOBl0Y7BEs5e5rbajtw+3EIpblwbU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1190810},"type":"module","types":"./dist/index.d.ts","shasum":"9328bf8ba4f23470d3df1f0b501f0289fb2749f0","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-TZa2JE7m2P0emWaAsMrTLr5GrCC32FQ+Jcut0MS9/+wtJPDaRN+JXTZjIiYoXuTtDQznGEq1NFT27mVd7quvCw==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <7","ioredis":">=5.6 <7","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.25_1790401126103_0.14720463540273365","host":"s3://npm-registry-packages-npm-production"}},"0.8.26":{"name":"@gusnips/server","version":"0.8.26","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.26","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"e8338bde4a9935c23af225a67c4668245478bac6","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.26.tgz","fileCount":231,"integrity":"sha512-aCCp6/76+DVgvuCa5Nkz3V2+tMqI6kBKD/ZTfoW/U/NLoaVybex/+fuf1Vp5tpOd97XBqVKYxz3NngdcIRZWqw==","signatures":[{"sig":"MEUCIAPuM/ipV4fucnra/VH2TtQlragNzFF7oFU7ElohMLf9AiEA4dOJ8IOQZzwCaxbCuNlRDiN9f7hTEXj2SoG/x3qYrXQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCFvnsRqhVXFzdkTPY/3wnH5wGRnEqAsaj/xG1pKGAh7gIgfqXbxbYiTVOVKjm8rPF3KtF5TESJ5PtmpaTR1IYOCfw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1209825},"type":"module","types":"./dist/index.d.ts","shasum":"e8338bde4a9935c23af225a67c4668245478bac6","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-aCCp6/76+DVgvuCa5Nkz3V2+tMqI6kBKD/ZTfoW/U/NLoaVybex/+fuf1Vp5tpOd97XBqVKYxz3NngdcIRZWqw==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <7","ioredis":">=5.6 <7","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.26_1790422444359_0.7515045303136827","host":"s3://npm-registry-packages-npm-production"}},"0.8.27":{"name":"@gusnips/server","version":"0.8.27","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.27","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"78c70b32e8b7f4578a5f8785dd156d17b4353f5d","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.27.tgz","fileCount":231,"integrity":"sha512-zMNYcw76Z/Zg9Zpvve8vA82FPmJuZP8Md1e2sbJuVSRjnN96hSPLEYKZ8mQPLUevWxVOBM6x1oWsn0VaWkMlQA==","signatures":[{"sig":"MEQCIEfm+0lp5hhSw7os+vL4uK2EqXhu8ODVDBnYzMVqpl/xAiBvtyDix4izv+br3fhdIJpJ9yF5Mp2jKvY4n5wfhNGmkA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQC0ZRCB8NyxsigtRDDLITSe3M2nUEUa5pg2N37UOev/pAIgcE2jGrfvqR5BpQBe1qYmBKrcQ0piccowSmW5IQHLJ2A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1215181},"type":"module","types":"./dist/index.d.ts","shasum":"78c70b32e8b7f4578a5f8785dd156d17b4353f5d","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-zMNYcw76Z/Zg9Zpvve8vA82FPmJuZP8Md1e2sbJuVSRjnN96hSPLEYKZ8mQPLUevWxVOBM6x1oWsn0VaWkMlQA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <7","ioredis":">=5.6 <7","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.27_1790441565882_0.44476913235408744","host":"s3://npm-registry-packages-npm-production"}},"0.8.28":{"name":"@gusnips/server","version":"0.8.28","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.28","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"e51f7f0a76686bcb833436988b5300acbb264655","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.28.tgz","fileCount":231,"integrity":"sha512-3vsqTCYzZlRofGkCSU5YN+54GUU8kie2pu6ofpkz9A6WuGVJ4iETJ7lwhkvqcYCuAh8eohVKcQPK/N57wm67SA==","signatures":[{"sig":"MEUCIQD2TRPc177Eu+ynsBtNrwjDCA4MphL68G6b0yCWaKMcKwIgPryzEmcaMaJeH0WI44LNFVAeBxwfTMPR9WSvYGUq8jQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDikVJQ7qYMWHV8hNJI46ncGPTtzv9pevpfxvGtzssA5gIgQ7INrHiUtKMbtod7acGHtz4UbEcomRqB++z3RWfxnfc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1220706},"type":"module","types":"./dist/index.d.ts","shasum":"e51f7f0a76686bcb833436988b5300acbb264655","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-3vsqTCYzZlRofGkCSU5YN+54GUU8kie2pu6ofpkz9A6WuGVJ4iETJ7lwhkvqcYCuAh8eohVKcQPK/N57wm67SA==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <7","ioredis":">=5.6 <7","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.28_1790801446095_0.6646873356796514","host":"s3://npm-registry-packages-npm-production"}},"0.8.29":{"name":"@gusnips/server","version":"0.8.29","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"author":"Gustavo Salomé","license":"MIT","_id":"@gusnips/server@0.8.29","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"3161d0ae6314b86a5506c00565cafc0c5920a41a","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.8.29.tgz","fileCount":236,"integrity":"sha512-rPnn42I3sg2pNC/AhEYmDZFAAk+kUQaI8cQoHSNSQUxh72YWnz0hndk1T6mM2BBxi9tvrfNwYkYd8ekQZLNiKw==","signatures":[{"sig":"MEUCIQDfhMyfYjN9s8kzXivvBIo3c64oLB1Sh5uHKyZFEQKS6AIgK3TEHpcbmotBDVb3s2GzhNIzb8t+PMOKXNa7OeGIyaI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIF7hOCv8l0WsTOzazSdIIDjrPrtsCAhss58uC7zx/nByAiB0jKlQENXpVUkWWL6luP2b98vpjRoB9rVuOl11zeArWg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1227284},"type":"module","types":"./dist/index.d.ts","shasum":"3161d0ae6314b86a5506c00565cafc0c5920a41a","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"_integrity":"sha512-rPnn42I3sg2pNC/AhEYmDZFAAk+kUQaI8cQoHSNSQUxh72YWnz0hndk1T6mM2BBxi9tvrfNwYkYd8ekQZLNiKw==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.1.1 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <7","ioredis":">=5.6 <7","nodemailer":">=6.10 <11","@gusnips/http":">=0.1.1 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/server_0.8.29_1790805934717_0.6526231155771665","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"_id":"@gusnips/server@0.9.0","bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"dist":{"shasum":"3f5c1dbf6e992703ed6b10374b66faa57f8d194f","tarball":"https://registry.npmjs.org/@gusnips/server/-/server-0.9.0.tgz","fileCount":236,"integrity":"sha512-2/GJQ7nKs0A+sr/0RTqSGMDwuDw/qBNlpQ7WNlmSSTmaWmwhkeA+Al2CS904asOdACKtPKG0PbrprMTo4Li4+Q==","signatures":[{"sig":"MEQCIAJrVqEREluricjTBnAiwmI6QZ6xD17mTdEQQtIT7Q9iAiAImrab+ac8/VFDKoqfDC2++k2YlcWNGqVoePtJb0WUTw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHNM6cvuusesqxV12CD8LFav2T0Mr01pcLDPFD799QE9AiAKtroAuR8r41qKO7HL6PKSAjjLJzro3mvjg4cZ0YeZ9w=="}],"unpackedSize":1227303},"name":"@gusnips/server","type":"module","types":"./dist/index.d.ts","author":"Gustavo Salomé","shasum":"3f5c1dbf6e992703ed6b10374b66faa57f8d194f","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./pg":{"types":"./dist/pg/index.d.ts","default":"./dist/pg/index.js"},"./mcp":{"types":"./dist/mcp/index.d.ts","default":"./dist/mcp/index.js"},"./hono":{"types":"./dist/hono/index.d.ts","default":"./dist/hono/index.js"},"./mail":{"types":"./dist/node/mail/index.d.ts","default":"./dist/node/mail/index.js"},"./node":{"types":"./dist/node/index.d.ts","default":"./dist/node/index.js"},"./redis":{"types":"./dist/redis/index.d.ts","default":"./dist/redis/index.js"},"./bullmq":{"types":"./dist/bullmq/index.d.ts","default":"./dist/bullmq/index.js"},"./openapi":{"types":"./dist/openapi/index.d.ts","default":"./dist/openapi/index.js"},"./supabase":{"types":"./dist/supabase/index.d.ts","default":"./dist/supabase/index.js"}},"license":"MIT","scripts":{"lint":"eslint src","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","purity":"bun run scripts/check-purity.ts","sync:docs":"cp ../LICENSE .","typecheck":"tsc --noEmit && tsc --noEmit -p tsconfig.node.json","test:watch":"vitest","release:major":"bun pm version major && bun publish --access public","release:minor":"bun pm version minor && bun publish --access public","release:patch":"bun pm version patch && bun publish --access public","prepublishOnly":"bun run lint && bun run typecheck && bun run purity && bun run test && bun run build && bun run sync:docs"},"version":"0.9.0","_npmUser":{"name":"gusnips","email":"gustavonips@gmail.com"},"homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"_integrity":"sha512-2/GJQ7nKs0A+sr/0RTqSGMDwuDw/qBNlpQ7WNlmSSTmaWmwhkeA+Al2CS904asOdACKtPKG0PbrprMTo4Li4+Q==","repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"_npmVersion":"10.8.3","description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","directories":{},"maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"sideEffects":false,"_nodeVersion":"26.3.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.16.0","zod":"^4.3.6","hono":"^4.10.6","bullmq":"^5.81.5","vitest":"^4.1.2","ioredis":"^5.10.1","@types/pg":"^8.15.0","nodemailer":"^7.0.13","typescript":"^5.9.3","@types/node":"^24.12.0","smtp-server":"^3.19.13","@gusnips/http":">=0.2.0 <1","@types/nodemailer":"^7.0.11","@types/smtp-server":"^3.5.13","@supabase/supabase-js":"^2.113.0","@modelcontextprotocol/sdk":"^1.30.1"},"peerDependencies":{"pg":">=8.13 <9","hono":">=4.9.9 <5","bullmq":">=5.76 <7","ioredis":">=5.6 <7","nodemailer":">=6.10 <11","@gusnips/http":">=0.2.0 <1","@supabase/supabase-js":">=2.91 <3","@modelcontextprotocol/sdk":">=1.29 <2"},"peerDependenciesMeta":{"pg":{"optional":true},"hono":{"optional":true},"bullmq":{"optional":true},"ioredis":{"optional":true},"nodemailer":{"optional":true},"@gusnips/http":{"optional":true},"@supabase/supabase-js":{"optional":true},"@modelcontextprotocol/sdk":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/server_0.9.0_1790907811965_0.0027824042704815977"}}},"time":{"created":"2026-09-20T12:37:24.114Z","modified":"2026-10-02T02:23:32.194Z","0.1.0":"2026-09-20T12:37:24.359Z","0.1.1":"2026-09-20T18:20:26.112Z","0.2.0":"2026-09-20T20:30:20.427Z","0.2.1":"2026-09-21T15:54:51.835Z","0.3.0":"2026-09-21T18:20:14.575Z","0.3.1":"2026-09-21T18:52:47.114Z","0.4.0":"2026-09-21T19:07:27.933Z","0.4.1":"2026-09-21T20:02:23.549Z","0.5.0":"2026-09-21T22:05:11.434Z","0.5.1":"2026-09-21T22:11:51.411Z","0.5.2":"2026-09-21T23:24:39.443Z","0.6.0":"2026-09-24T07:07:56.929Z","0.7.0":"2026-09-24T08:14:46.752Z","0.7.1":"2026-09-24T14:21:29.557Z","0.7.2":"2026-09-24T14:49:26.148Z","0.7.3":"2026-09-24T15:16:23.237Z","0.7.4":"2026-09-24T15:34:50.068Z","0.7.5":"2026-09-24T15:56:14.290Z","0.7.6":"2026-09-24T18:10:45.489Z","0.7.7":"2026-09-24T20:30:07.956Z","0.8.0":"2026-09-24T21:11:21.150Z","0.8.1":"2026-09-24T21:20:51.775Z","0.8.2":"2026-09-24T22:37:00.632Z","0.8.3":"2026-09-24T22:44:25.943Z","0.8.4":"2026-09-24T23:52:08.952Z","0.8.5":"2026-09-25T00:09:01.323Z","0.8.6":"2026-09-25T00:20:13.448Z","0.8.7":"2026-09-25T01:57:30.631Z","0.8.8":"2026-09-25T02:53:41.097Z","0.8.9":"2026-09-25T03:02:31.464Z","0.8.10":"2026-09-25T05:09:27.394Z","0.8.11":"2026-09-25T11:16:36.533Z","0.8.12":"2026-09-25T11:29:07.511Z","0.8.13":"2026-09-25T11:40:13.152Z","0.8.14":"2026-09-25T11:50:55.743Z","0.8.15":"2026-09-25T12:11:14.701Z","0.8.16":"2026-09-25T12:28:40.953Z","0.8.17":"2026-09-25T14:25:51.309Z","0.8.18":"2026-09-25T15:48:31.420Z","0.8.19":"2026-09-25T21:25:58.693Z","0.8.20":"2026-09-26T00:07:00.733Z","0.8.21":"2026-09-26T01:34:52.448Z","0.8.22":"2026-09-26T04:43:31.645Z","0.8.23":"2026-09-26T05:06:55.582Z","0.8.24":"2026-09-26T05:12:45.207Z","0.8.25":"2026-09-26T05:38:46.196Z","0.8.26":"2026-09-26T11:34:04.449Z","0.8.27":"2026-09-26T16:52:45.963Z","0.8.28":"2026-09-30T20:50:46.212Z","0.8.29":"2026-09-30T22:05:34.819Z","0.9.0":"2026-10-02T02:23:32.065Z"},"bugs":{"url":"https://github.com/gusnips/serverkit/issues"},"author":"Gustavo Salomé","license":"MIT","homepage":"https://github.com/gusnips/serverkit/tree/main/server#readme","keywords":["backend","errors","hono","logging","retry","supabase","typescript","postgres","redis","ssrf","bullmq","nodemailer","mcp","openapi"],"repository":{"url":"git+https://github.com/gusnips/serverkit.git","type":"git","directory":"server"},"description":"The layer under a TypeScript backend: one error shape, one response envelope, one retry rule, one logger.","maintainers":[{"name":"gusnips","email":"gustavonips@gmail.com"}],"readme":"# @gusnips/server\n\nOne error shape, one response envelope, and one function that turns a thrown thing into an HTTP\nanswer. No framework at the root: it runs in a Cloudflare Worker, in a Bun or Node server, in a\nqueue consumer, and in an MCP tool handler.\n\n```bash\nbun add @gusnips/server @gusnips/http\n```\n\n`@gusnips/http` declares the envelope, and your API and your browser client both import it, so\nthere is one declaration of the wire contract and not two. Install it whenever you answer a\nrequest. It is an optional peer rather than a required one because this package uses it for its\ntypes only, so its code never runs here — which means a server reaching only for a subpath like\n`@gusnips/server/pg` installs the one package it actually loads:\n\n```bash\nbun add @gusnips/server pg\n```\n\n```ts\nimport { ok } from \"@gusnips/server\";\n\nok({ id: 1 });\n// → { status: 200, body: { data: { id: 1 } } }\n```\n\nEvery 2xx body is `{ data }`. Every refusal is `{ error: { code, message, messageKey?, params?,\ndetails? } }`. That is the envelope `@gusnips/http` declares and a browser client parses, so the\ntwo ends of one request never disagree about the shape.\n\n**Import `ApiErrorBody`, `ApiSuccess` and `PaginationMeta` from `@gusnips/http`, not from here.**\nThis package does not re-export them, on purpose: two names for one type is how a version skew\nbecomes invisible. You already have the import — the contract is the package your client reads\nit from too.\n\n## Answering a request\n\n`ok`, `created`, `paginated` and `noContent` return a plain `{ status, body }`. Hand it to\nwhatever is holding the connection.\n\n```ts\nimport { paginated } from \"@gusnips/server\";\n\npaginated(rows, { total: 128, limit: 20, offset: 100 });\n// → { status: 200, body: { data: rows, meta: { total: 128, limit: 20, offset: 100, hasMore: true } } }\n```\n\n`hasMore` is computed from the rows you actually returned, not from `limit`, so a page cut short\nby a filter still answers honestly.\n\n**What comes back is an answer, not a body.** A framework wants the `body`:\n\n```ts\nreturn c.json(ok(data), 200); // WRONG: {\"status\":200,\"body\":{\"data\":…}}\nreturn c.json(ok(data).body, 200); // the envelope\n```\n\nNothing catches the first line. `c.json` takes any JSON value, so the types hold; the status is\nstill 200, so a health probe and a deploy gate both pass; and a test that calls `ok` never sees\nthe body its caller sends. That shipped, and a client found it fifty minutes later. On Hono,\nimport the four adapters from `@gusnips/server/hono` and the question does not arise.\n\n## Refusing a request\n\nDeclare your own codes and what status each one answers with. The `satisfies` is the line that\nmatters: adding a code without a status becomes a build error instead of a route answering 500\nfor a refusal it knew how to explain.\n\n```ts\nimport { createAppError } from \"@gusnips/server\";\n\nexport const ERROR_STATUS = {\n  VALIDATION_ERROR: 400,\n  UNAUTHORIZED: 401,\n  NOT_FOUND: 404,\n  RATE_LIMIT_EXCEEDED: 429,\n  INTERNAL_ERROR: 500,\n} as const satisfies Record<ErrorCode, number>;\n\nconst appError = createAppError<typeof ERROR_STATUS, MessageKey>(ERROR_STATUS);\n\nexport const errors = {\n  notFound: (what = \"Resource\") => appError(\"NOT_FOUND\", `${what} not found`),\n  rateLimit: (retryAfterSecs: number) =>\n    appError(\"RATE_LIMIT_EXCEEDED\", \"Too many requests\", { retryAfterSecs }),\n};\n```\n\nThen throw one, anywhere:\n\n```ts\nthrow errors.notFound(\"Workspace\");\n```\n\n`AppError` has no `toJSON()`. `JSON.stringify` calls a value's own `toJSON()` **before** it calls\nthe replacer, so a class that defines one hands a logger whatever that method returns instead of\nthe error: `logger.error(\"failed\", { error: err })` writes `{\"error\":{\"error\":{code,message}}}`\nwith no stack and no cause. Seven backends on this stack define one and all seven log exactly\nthat.\n\n`createLogger` recovers the error anyway — the replacer reads it back off the holder — so your\nown classes are safe either way. `AppError` still does not define one, because the wire body\nbelongs to `errorResponse`, where the mask lives: one function owns the shape a client sees, and\nthe error stays an error.\n\nThe map has to be `as const`, or every value reads as `number` and the rule below cannot see a 429. A map without it is refused, with the instruction in the compiler's message.\n\n### A 429 says how it clears\n\n`RATE_LIMIT_EXCEEDED` maps to 429, so `retryAfterSecs` is a **required argument**: the seconds\nuntil the caller may retry, or `null` for a refusal that waiting cannot fix. Leave it out and\nthe code does not compile.\n\n```ts\nrateLimit: (retryAfterSecs: number) =>\n  appError(\"RATE_LIMIT_EXCEEDED\", \"Too many requests\", { retryAfterSecs }),\n\nconcurrency: (limit: number) =>\n  // A slot frees when somebody else's job finishes. There is no wait to state.\n  appError(\"QUOTA_EXCEEDED\", `${limit} jobs already running`, { retryAfterSecs: null }),\n```\n\nThis is the rule with the best bug-per-line ratio in the whole extraction. One backend writes a\n`resetAt` ISO date that no HTTP client parses, and then keeps a hand-written list of \"codes that\ndo not clear by waiting\" in its browser app to compensate — its own comment says that is why the\nlist exists. Another backend needs no list, because every 429 it sends states its wait. A third\nraises a spent daily cap with no wait at all, on a code its client reads as transient, so the\nbrowser retries a limit that clears at midnight — twice, immediately, and says the same thing\nthree times to a limiter that is already counting.\n\nAsking each refusal how it clears answers the question those lists were guessing at, and it\nanswers it in the one place that knows: where the refusal is raised. A code cannot know — the\nsame `QUOTA_EXCEEDED` can be a month that clears in days or a slot that clears in two seconds.\n\nOf 40 places that raise a 429 in the fleet this came from, 34 already state a wait. Of the six\nleft, two genuinely cannot: a concurrency slot frees when another job finishes, and a cap on\nlive objects clears by archiving one, never by waiting. `null` is for those. An omission is\ninvisible in a diff; a `null` is a claim somebody has to read.\n\n`errorResponse` renders a number as the standard `Retry-After` header **and** folds it into\n`details`, so an HTTP client, a proxy and your own SDK all learn the same wait from one value. A\n`null` is folded in without a header, because a `Retry-After` that names no time is worse than\nnone. Both places get whole seconds, never below zero: `1.2` goes out as `2`, and a window that\nalready reset (`-3`) as `0`.\n\nTwo edges worth knowing:\n\n- The obligation follows the code's whole status set. A code narrowed to a union that _could_ be\n  the 429 owes the wait too — `appError(code, msg)` where `code` is\n  `\"NOT_FOUND\" | \"RATE_LIMIT_EXCEEDED\"` does not compile without one.\n- **Only the obligation is 429-only.** Any code may state a wait, and a number renders\n  `Retry-After` at any status. Reach for it when ONE of your codes is raised in two senses —\n  one that clears on its own and one that does not. A `SERVICE_UNAVAILABLE` meaning \"not\n  configured on this deployment\" and one meaning \"did not answer just now\" are the same code and\n  the same status, so a client cannot separate them; the raiser can, with a number or an\n  explicit `null`.\n\n`new AppError(429, …)` skips the rule, because the rule lives on the factory: only the factory\nknows your map. That is the reason to prefer `createAppError`.\n\n## Turning a throw into an answer\n\n```ts\nimport { createErrorResponse } from \"@gusnips/server\";\n\nexport const errorResponse = createErrorResponse<ErrorCode, MessageKey>({\n  internal: { code: \"INTERNAL_ERROR\", message: \"Something on our side failed\" },\n  validation: { code: \"VALIDATION_ERROR\", message: \"The request could not be read\" },\n});\n\nerrorResponse(err);\n// → { status, body, headers, kind }\n```\n\nEvery throw lands in one of four arms:\n\n| What was thrown              | Answer                                       | `kind`       |\n| ---------------------------- | -------------------------------------------- | ------------ |\n| a validation failure         | 400, with the field path and the failed rule | `client`     |\n| an `AppError` under 500      | itself                                       | `client`     |\n| an `AppError` of 500 or more | itself, or the masked body                   | `server`     |\n| anything else                | a generic 500                                | `unexpected` |\n\n`kind` is the one thing you cannot read off the status. A 500 you raised and a `TypeError` that\nescaped are both 500s, and only the second one means nobody is watching a log for it — which is\nthe branch where an alert belongs.\n\nBind it once, at the edge of your app, and import that one function everywhere else. A tool\nhandler and a worker's health port then cannot disagree with the API about what a refusal looks\nlike. They did, in the fleet this came from: a worker's health route answered a caught Redis\nmessage on a 503 while the API next door masked exactly that.\n\n### What reaches the client, and what does not\n\n**A validation failure ships the field path, the failed rule, and — for a range — the bound it\nfailed against. Nothing else.** Handing your validator's issues straight through ships back the\ncaller's own key names, the enum's allowed values, the validator's English sentence and the\nexpected type. The bound is the exception and it belongs to the caller: it is your published\ncontract, and a \"too big\" without it costs somebody a bisect to rediscover a number your docs\nalready state.\n\nValidation is recognized by shape, not by an import, so your validator does not become this\npackage's dependency. Measured against zod 3.25, 4.4 and 4.5. A tool or queue consumer can use\n`validationIssues(error)` from the root package to apply the same allow-list without building an\nHTTP answer.\n\n**Recognized by shape also means ANY failed parse reads as the caller's mistake, including a\nparse of your own data.** A response checked against its schema, or a database row parsed on the\nway out, throws the same error as a bad request body. Let it escape and the caller gets a 400\nnaming your response's own fields, for a bug that is yours. Check your own data with\n`safeParse`, and raise a failure as your internal 500, with the parse error as its `cause`. One\nadopter had it on every operation it served.\n\nThe answer's `messageKey` is typed as the `MessageKey` you bound, so `errorResponse(err).body.error`\nfits a slot of your own, like a stream's error frame or a failed job's record, with no cast.\n\n**A 5xx keeps its message unless its code is masked.** By default only `INTERNAL_ERROR` is,\nbecause that is the code you raise when something unexpected broke, so its message may carry\ninternals. The others were written for the client, and flattening a `GATEWAY_ERROR` into a\ngeneric 500 takes away the one thing that tells a developer whether to retry.\n\n> That default is safe because of your call sites, not because of this code. It holds only while\n> every unmasked 5xx is handed a message somebody wrote for a reader. If your data layer\n> interpolates the driver's error into what it raises, use `maskAll` and let `expose` opt the\n> authored sentences back in.\n\n`maskDetails` is a separate knob, because it is a separate decision. Some backends put a\nreadiness report in a 503's `details` — which dependency is down, for the deploy gate and for a\nhuman at 3am — and need it on the wire. Others record caught error text there, and must never\nsend it. Both are right about their own repo.\n\n**When a message is masked, the status is not.** A status comes from your own map and discloses\nnothing, and it is the last thing telling a client whether waiting can help.\n\n**An unexpected throw never reaches the client.** Log it with its `cause` and its stack; answer\nthe generic 500.\n\n## Logging a failure\n\n`createLogger` writes one JSON line per event to stdout, and nothing else. Twelve backends were\nread for this and not one installs a logging library, so this ships no transports, no file\nrotation and no extra levels — every one of them runs under something that already owns stdout.\n\n```ts\nimport { createLogger } from \"@gusnips/server\";\n\nconst logger = createLogger({ level: process.env.LOG_LEVEL });\n\nlogger.error(\"charge failed\", { orderId, error: err }); // the RAW error, never String(err)\n```\n\n**Pass the error itself.** `message` and `stack` are non-enumerable, so a plain\n`JSON.stringify(err)` is `{}` — which is how a logger ends up printing nothing about the failure\nit was called to report. The serializer adds them, follows the `cause` chain and an\n`AggregateError`'s `errors`, and collapses a circular reference instead of crashing the log call.\nAn error passed on its own, `logger.error(\"drain failed\", err)`, is written under `error` too.\n\n**What it keeps off an error is an allow-list**, and that is the one thing here that exists\nbecause of an incident rather than because of duplication. An SDK hangs its own INPUTS off the\nerror it throws: a payment vendor's signature-verification error carries the unparsed webhook\nbody and the signature, a Redis client puts the AUTH password in `command.args`, and a Postgres\n`DatabaseError` carries statement text with its literals in it. A loop over own properties copies\nall of that, and a webhook route is unauthenticated by definition — so anyone on the internet\ncould choose what went into the log. The list admits 4 of that payment error's 25 properties, and\nit covers the `cause` chain, including a link that is not an `Error`.\n\n**It hides the secrets it can recognize.** A key ending in `authorization`, `cookie`, `password`,\n`secret`, `token` or `apiKey` gets `\"[redacted]\"` instead of its value, at any depth, so logging a\nrequest's headers does not print the `Authorization` one. Plurals count too (`apiKeys`, `secrets`),\nexcept `tokens`, which in a log is a count. In every string, the message and an\nerror's stack included, `Bearer …` and the `user:password@` in a URL are replaced too. The key has\nto END with the word, so `apiKeyId`, `inputTokens` and `tokenId` still print. You cannot turn this\noff. To hide more, add your own rules:\n\n```ts\nconst logger = createLogger({\n  level: process.env.LOG_LEVEL,\n  redact: { keys: /cpf$/i, values: [[/\\bacme_[\\w-]+/g, \"[redacted]\"]] },\n});\n```\n\nThey run beside the defaults, not instead of them. A value pattern needs the `g` flag, because\nwithout it only the first match in each string is hidden; `createLogger` throws if one is missing.\n\n`level` is an argument rather than a `process.env` read, and that is the boundary the package is\nbuilt on: a Cloudflare Worker has no `process` at all, so a module-scope read makes a package\nNode-only by accident. A Worker passes `env.LOG_LEVEL` from its handler argument. An unrecognized\nlevel throws at construction, because a box running at the wrong level is discovered during the\nincident it was meant to explain.\n\n## Hono\n\n`@gusnips/server/hono` is the only part that knows a framework, which is why it is a subpath:\n`hono` is an optional peer and nothing in the root entry imports it. Needs `hono >= 4.9.9` —\nbefore that, `routePath(c, -1)` silently ignores the `-1` and the request line names the wrong\nroute.\n\n```ts\nimport {\n  apiSecureHeaders,\n  corsAllowList,\n  errorBoundary,\n  errorHandler,\n  notFoundHandler,\n  requestLogger,\n} from \"@gusnips/server/hono\";\n\napp.use(requestLogger({ logger })); // first, so it times and sees everything under it\napp.use(apiSecureHeaders()); // before errorBoundary, or a plain-object throw loses them\napp.use(corsAllowList([env.APP_URL, env.SITE_URL]));\napp.use(errorBoundary);\napp.onError(errorHandler({ errorResponse, logger }));\napp.notFound(notFoundHandler(errorResponse(errors.notFound(\"Route\"))));\n```\n\n```ts\nimport { created, noContent, ok, paginated } from \"@gusnips/server/hono\";\n\napp.get(\"/users/:id\", (c) => ok(c, user)); // { data: user }, 200\napp.post(\"/users\", (c) => created(c, user)); // 201\napp.get(\"/users\", (c) => paginated(c, rows, { total, limit, offset }));\napp.delete(\"/users/:id\", (c) => noContent(c)); // 204, no body, no content-type\n```\n\nThree adopters wrote those four functions by hand before they were here, and one of the three\ngot the unwrap wrong in production. `ok` takes an explicit status for the cases that are not\n200 — `ok(c, job, 202)` where the route accepted rather than answered — and a fourth argument for\na product's own meta, so a metered read answers `{ data, meta }` without leaving the adapter:\n\n```ts\napp.get(\"/lookup\", (c) => ok(c, profile, 200, { creditsCharged: 1, cache: \"hit\" }));\n```\n\n**`errorBoundary` is not optional.** Hono hands `onError` only what is `instanceof Error`.\nAnything else is rethrown past every layer and escapes as an unhandled rejection: no answer, a\ndropped connection, and a browser that reports it as a CORS failure — which sends whoever reads\nit to the wrong layer entirely. A PostgREST client rejects with plain objects, so this is not\nhypothetical. The boundary wraps one in an `Error` and keeps the original as `cause`.\n\n**The request line names the route TEMPLATE, never the path.** A path is what puts a customer's\ndocument number in a log and in whatever reads that log afterwards. `/health` is skipped with\neverything under it, because every deploy polls it in a loop; a throw is logged anyway.\n\nAdd safe product metadata with `requestLogger<AppEnv>({ logger, fields: (c) => ({ … }) })`.\n`fields` runs after the response exists, so it can read values a handler set and `c.res`; return only\nbounded, sanitized values, never a raw path, query, header set, body or authentication object. Your\nfields are written first, so they cannot replace the canonical request id, method, route, status,\nduration or error code. A hook that throws is caught: the line is written with\n`requestFieldsFailed: true` instead of your fields. A value whose own `toJSON` throws is not — that\none loses the whole line, request id included — so return plain data, not live objects.\n\nThe request id goes back on `X-Request-ID`, on every answer including `onError`'s and\n`notFound`'s. A caller's own id is echoed only if it is 64 characters of `A-Z a-z 0-9 . _ -`,\nso the id in a line is always either the caller's or ours. Cross-origin, list that header in your\nCORS `exposeHeaders` or the browser hides it from the page.\n\n### The headers on every answer\n\n`apiSecureHeaders()` is Hono's `secureHeaders`, set for an API that answers JSON: HSTS for two\nyears with `preload`, `X-Frame-Options: DENY`, and a CSP that loads nothing,\n`default-src 'none'; frame-ancestors 'none'`. For a route that serves a page, pass overrides. A CSP\ndirective you add keeps the others.\n\n**Mount it before `errorBoundary`.** It writes its headers after the route has answered, and a\nthrow that is not an `Error` skips that step in every middleware inside the boundary. Seven APIs\nin the fleet had it inside, so a plain-object throw answered 500 with none of the headers.\n\nIts `Cross-Origin-Resource-Policy: same-origin` does not block your web app. CORP applies to an\n`<img>` or a `<script>` from another origin. A `fetch` from your app is a CORS request.\n\n`corsAllowList(origins)` answers only the origins you list, compared exactly:\n\n- Each entry is reduced to its origin at boot. A blank entry is skipped, and anything that is not\n  an origin, such as `localhost:5173` or `*`, throws.\n- A page can always read `Retry-After` and `X-Request-ID`. A browser hides both unless CORS lists\n  them.\n- No `Access-Control-Allow-Credentials` unless you pass `credentials: true`. A Bearer token does\n  not need it. A client that sends `credentials: \"include\"` does.\n- A browser keeps a preflight for 10 minutes, where the default is 5 seconds.\n- `.has(origin)` gives the same answer, for a door that reads `Origin` itself, such as MCP.\n\nUnder those, put every check that needs only the headers before Hono's `bodyLimit`. It reads a\nchunked body whole before the next middleware runs, so a refusal placed after it has already paid\nfor the upload:\n\n```ts\napp.use(\"/v1/*\", addressLimit); // rateLimit keyed on the client's address\napp.use(\"/v1/*\", requireUser);\napp.use(\"/v1/*\", bodyLimit({ maxSize: 1024 * 1024 })); // from hono/body-limit\n```\n\nA webhook's signature covers its body, so there `bodyLimit` goes right after the address limit.\nIt hands on the same bytes it read, so the signature still verifies. And give `Bun.serve` a\n`maxRequestBodySize`: without one, Bun takes a body of up to 128 MiB (measured on 1.3.8 and 1.4.2).\n\n### The guard check\n\n```ts\nimport { assertEveryRouteGuarded, guard, underAny } from \"@gusnips/server/hono\";\n\nexport const requireUser = guard(async (c, next) => { … });   // mark it where it is defined\n\n// in a test\nassertEveryRouteGuarded(buildApp(), { isPublic: underAny(PUBLIC_PREFIXES) });\n```\n\nIt walks every registered route through Hono's **own matcher** and fails naming each endpoint no\nguard runs in front of. The matcher is the point: a `use` registered AFTER its `route` never runs\n— the handler answers and the guard silently does not fire. A route whose guard did not fire is\nindistinguishable from one with no guard, and comparing pattern lists cannot tell you which you\nhave.\n\nPass the app's own public rule, never a second list kept for the test — an exemption list nothing\nelse reads is the next thing to drift. It also fails a guard that runs in front of nothing, and\nan app with no endpoints, so the check cannot pass by asking nothing.\n\n## Supabase Auth\n\nIf your API verifies a Supabase token, it makes one decision every client depends on: did auth\nsay **no**, or did auth **not answer**?\n\n```bash\nbun add @supabase/supabase-js\n```\n\n```ts\nimport { isAuthOutage } from \"@gusnips/server/supabase\";\n\nisAuthOutage(error);\n// → true when auth failed to answer, false when it looked at the token and refused it\n```\n\nAt the door:\n\n```ts\nconst { data, error } = await supabase.auth.getUser(token);\nif (isAuthOutage(error)) throw errors.serviceUnavailable(\"Authentication service unreachable\");\nif (error || !data.user) throw errors.invalidToken();\n```\n\nOnly a refusal ends a session. Browser clients read a 401 as \"your session is over\" and sign the\nperson out, so answering an outage with a 401 signs out everyone who made a request during it —\nwhile the refresh they are all waiting on is still in flight. A 503 is retried instead.\n\nIt tests two things and both are needed. The SDK's own `isAuthRetryableFetchError` catches a\nfetch that never landed, plus the statuses on its `NETWORK_ERROR_CODES` list. That list is a\nlist and not a range, so it has holes at every version ever shipped: nothing for 505 through\n519, nothing from 531 up. A 507 out of a proxy in front of GoTrue is auth failing to answer, and\nthe SDK's predicate says false for it. The status check covers the holes.\n\nIt takes `unknown`, so you can also ask it about whatever a `catch` around your own user lookup\ncaught. A driver's `TypeError` is not an auth outage and answers false.\n\n`@supabase/supabase-js` is an optional peer, behind the `/supabase` subpath, so importing\n`@gusnips/server` never installs it.\n\n## Postgres\n\nIf your API talks to Postgres through `pg`, two lines in the pool decide whether a bad minute\nshows up as an error or as silence.\n\n```bash\nbun add pg\n```\n\n```ts\nimport { createPgPool } from \"@gusnips/server/pg\";\n\nconst pool = createPgPool({\n  connectionString: env.DATABASE_URL,\n  onIdleError: (error) => logger.error(\"[pg] idle client error — client discarded\", { error }),\n});\n```\n\n**It bounds the wait for a free connection.** Without `connectionTimeoutMillis`, node-postgres\nputs a caller that finds the pool full on a queue with no timer, and it waits forever. `max`\ndefaults to 10, so ten slow queries at once are enough: every request after them — auth,\nbilling, the workers, `/health` — hangs with no error, no log and no metric. That is not a 500,\nit is silence, which is why it survives in a codebase. Eleven backends were measured for this\nand one had it bounded. The default here is 10 seconds; pass\n`connectionTimeoutMillis: 0` to wait forever on purpose, which a batch job may want.\n\n**It makes the idle-error handler impossible to forget.** A `Pool` emits `error` when the server\ncloses an idle client — a restart, a failover, a dropped tunnel. With no listener, Node turns\nthat into an uncaught exception and a crash handler exits the process, so a connection nobody\nwas using takes the API down. `onIdleError` is a required field, not an option.\n\n**It reads a `date` column as the day.** `'2026-09-23'` comes back as the string `\"2026-09-23\"`.\nnode-postgres would give you a Date at midnight in the machine's own time zone, so the same row\nis a different moment on every server, and on one east of UTC `toISOString()` gives the day\nbefore. A `timestamptz` still comes back as a Date, because it is a real moment. This applies to\nthis pool only; pass `dateColumns: \"date\"` to get Dates back.\n\nReadiness gets its own call, and it has a deadline:\n\n```ts\nconst ok = await pingPool(pool, {\n  timeoutMs: 2_000,\n  onError: (e) => logger.warn(\"[pg] down\", { e }),\n});\n```\n\nA raw `SELECT 1` hangs when the database hangs, which is the one thing a health check must not\ndo: an orchestrator reads a timeout as \"unknown\" where it would read `false` as \"replace this\ncontainer\". `connectionTimeoutMillis` does not cover it — that bounds getting a connection, not\nthe query once you hold one.\n\nTwo things stay yours. The pool **singleton** — a package that holds it decides when your process\ncan exit. And the **`ssl` option**: `@gusnips/migrate` exports `pgSsl`, which infers it from the\nconnection URL, so spread it in beside `connectionString`.\n\n`pg` is an optional peer, behind the `/pg` subpath, so importing `@gusnips/server` never\ninstalls it.\n\n### A retry that does not run twice\n\nA client that timed out on a write cannot tell whether the write happened. If it sends a key of\nits own, `Idempotency-Key: 5f0c…`, the retry gets the first answer back instead of sending a\nsecond message or charging a second time. Add the table in a migration:\n\n```sql\nCREATE TABLE app.idempotency_keys (\n  owner text NOT NULL,\n  key_hash text NOT NULL,\n  fingerprint text NOT NULL,\n  lease uuid NOT NULL,\n  answer json,\n  created_at timestamptz NOT NULL DEFAULT now(),\n  PRIMARY KEY (owner, key_hash)\n);\nCREATE INDEX idempotency_keys_created_at_idx ON app.idempotency_keys (created_at);\n```\n\nThen run each write through it:\n\n```ts\nimport { created } from \"@gusnips/server/hono\";\nimport { createIdempotency } from \"@gusnips/server/pg\";\n\nconst idempotency = createIdempotency(pool, {\n  table: \"app.idempotency_keys\",\n  onError: (error) => logger.error(\"idempotency store failed\", { error }),\n});\n\nconst outcome = await idempotency.run(\n  { owner: workspaceId, operation: \"send_message\", key: c.req.header(\"idempotency-key\") },\n  input,\n  () => sendMessage(input),\n);\nif (outcome.kind === \"running\")\n  throw errors.conflict(\"A request with this key is still running\", { retryAfterSecs: 2 });\nif (outcome.kind === \"mismatch\")\n  throw errors.keyReused(\"This key was already used for a different request. Send a new one.\");\nreturn created(c, outcome.answer);\n```\n\n- **With no key, it just runs.** Nothing is stored.\n- **A key that is still running answers 409, with a wait.** Waiting fixes it.\n- **A key used for other input or another operation answers 422**, as the IETF\n  `Idempotency-Key` draft says. Waiting never fixes it, so it must not share a status with the\n  409 a client is meant to retry.\n- **Check who may call the operation before `run`.** A replay hands back a stored answer, and\n  it must never reach a caller who could not get it now.\n- **A throw lets the key go**, so a retry with the same key runs again. That is right when the\n  throw means nothing happened. When it can mean the work already ran, as with a timeout after a\n  provider took the message, catch it inside the work and return it as the answer. A retry then\n  gets the same failure back instead of sending a second time:\n\n  ```ts\n  async () => {\n    try {\n      return { messageId: await sendMessage(input) };\n    } catch (error) {\n      // The provider had the message when this timed out, so it may have arrived.\n      if (isTimeoutAfterHandoff(error)) return { timedOut: true };\n      throw error;\n    }\n  };\n  ```\n\n  Turn `{ timedOut: true }` into your error on the first answer and on every replay.\n\n- **A failed save still answers.** The work happened, so `onError` gets the failure and the\n  client gets its answer. Its retries see \"running\" until `abandonedSecs` passes, then run again.\n  That is the one path that can still run twice, which is why `onError` is required.\n- **A claim nobody answered is taken over after 15 minutes** (`abandonedSecs`), because the\n  process that made it died. Set it well past your slowest operation.\n- **An MCP door takes the key as an argument.** A tool call has no headers of its own, so add an\n  optional `idempotencyKey` to the tool's input schema and pass it as `key`.\n- **Delete old answers** once an hour or once a night: `await idempotency.prune()`.\n\n`owner` can be a `uuid` column that references your workspaces, if you want a deleted\nworkspace's keys to go with it.\n\n## Redis\n\nIf your API uses Redis — for BullMQ, for rate-limit windows, for a cache — the connection and\nthe probe that reads it are one decision, because the first makes the second necessary.\n\n```bash\nbun add ioredis\n```\n\n```ts\nimport { createRedis, pingRedis } from \"@gusnips/server/redis\";\n\nconst redis = createRedis({\n  url: env.REDIS_URL,\n  onError: (error) => logger.error(\"[redis] connection error\", { error }),\n});\n```\n\n**It makes the error handler impossible to forget.** Without one, a failed connect prints a bare\nstack to stderr through ioredis's own `console.error` and reaches the app's logger not at all — so\nthe one signal that a dependency has stopped answering lands outside the place an operator is\nalready looking. `onError` is a required field, not an option. Four backends were measured for\nthis: all four wrote the listener, all four wrote a comment saying it is not optional, and the\nfunction around it was byte-identical in every one.\n\n**Their stated reason for it is wrong, which is worth knowing before you copy it again.** All four\nsay an EventEmitter with no `error` listener throws, so a blip becomes a process exit through a\ncrash handler. True of an EventEmitter, false of ioredis: `silentEmit` checks the listener count\nand, finding none, logs and returns without ever emitting. Measured on ioredis 5.10.1 under bun\n1.3.8 and node 22 — the process survives and `uncaughtException` never fires. `createPgPool`'s\n`onIdleError` is NOT the same case, checked the same way rather than assumed: `pg-pool` calls\n`pool.emit(\"error\", err, client)` with no listener-count guard, so there the listener really is what\nstands between an idle-client error and a crash. One library's sentence was copied onto another.\n\n**It defaults `maxRetriesPerRequest` to `null`, and that is the opposite kind of default from\n`createPgPool`'s.** There the default makes an unbounded wait bounded; here it makes commands\nwait forever — because BullMQ requires it, since its blocking reads must never be cut short by a\nretry limit. So the default is right and it has a consequence worth saying once:\n\n**every read on this connection needs its own bound.** A `ping`, a cache lookup, a limiter\ncheck — with Redis down, each waits rather than failing. Pass `maxRetriesPerRequest: 3` for a\nconnection that serves ordinary commands instead of BullMQ's. A `queue.add()` waits too, and a\nbound is not enough for it (below).\n\nA queue's first command also waits until its connection is ready, whatever the connection's retry\noptions say. BullMQ's `skipWaitingForReady` does not help. On a connection with\n`enableOfflineQueue: false`, a queue built while the connection is still connecting fails its\nfirst add, and every add after it, even once Redis is up. We reproduced it with one backend's\nsettings: an API that builds its queue on its first request loses that queue for as long as the\nprocess runs. So leave `skipWaitingForReady` off.\n\n**A timer around `add()` ends the request, not the add.** A queue built at boot waits as well.\nWith one on this connection, we stopped Redis for 35 seconds, and `add()` waited the whole time.\nA 2-second timer around it failed the request at 2 seconds, and the job was still added once\nRedis came back. So check the connection before you add:\n\n```ts\nif (redis.status !== \"ready\") throw errors.unavailable(\"Jobs are paused. Try again in a minute.\");\nawait queue.add(\"report\", { userId });\n```\n\nWhile Redis is down, the connection reads `reconnecting`, and a job you never sent cannot turn up\nlater. A Redis that hangs with the connection still open, such as a paused process, still reads\n`ready`, and `maxRetriesPerRequest` does not help there either. With `maxRetriesPerRequest: 1`,\nan `add()` to a stopped Redis failed in 0.3 seconds, but one to a paused Redis waited all 35\nseconds, then added the job. So keep a deadline on the request too, and give the job a `jobId`\nwhen a retry must not add it twice.\n\n**A URL with options after its `?` is refused.** ioredis lets those beat the options you pass,\nand reads each as a string: `?maxRetriesPerRequest=7` replaces the `null` BullMQ needs, and\n`?enableOfflineQueue=false` is the string \"false\", which ioredis reads as on. Pass them to\n`createRedis` instead, such as `family: 6`.\n\nReadiness is the worked example, and it has a deadline:\n\n```ts\nconst ok = await pingRedis(redis, {\n  timeoutMs: 2_000,\n  onError: (e) => logger.warn(\"[redis] down\", { e }),\n});\n```\n\nFour hand-written copies of that bound exist in this fleet and all four leak their timer — a\npending 2-second timer per health check, in a process something probes every few seconds. This\none clears it.\n\nA worker gets a boot gate, because a process whose queues can never connect must not sit there\nlooking healthy — that looks exactly like an empty queue:\n\n```ts\nawait assertRedisReachable(redis, {\n  url: env.REDIS_URL,\n  hint: \"Start it (the dev compose runs one) or fix REDIS_URL.\",\n});\n```\n\nIt takes the URL and parses it so the error can name the host. It never prints the password.\n\n`hint` is the sentence a package cannot write for you. The generic half says what failed and\nits likely cause; the fix is local, and \"the dev compose runs one\" names a command that exists\nin one repo and not the next. Three backends wrote this gate: two said \"check REDIS_URL\" and the\nthird named the tool, and the third is the only one a reader can act on without knowing the repo\nalready.\n\nClose it with `quitRedis` when the process stops:\n\n```ts\n{ name: \"redis\", run: () => quitRedis(redis) }\n```\n\nA bare `redis.quit()` can hang the drain in two ways. If Redis is down and a command is still\nwaiting to be sent, `quit()` waits for that command first, and it is never sent. If Redis is frozen,\n`QUIT` gets no answer. Either way the steps after it, Postgres included, never run, and your process\nmanager kills the process at its timeout. `quitRedis` sends `QUIT`, waits up to a second, then\ncloses the socket. It never throws.\n\nThe client **singleton** stays yours, for the same reason the pool's does: a package that holds\nit decides when your process can exit.\n\n`ioredis` is an optional peer, behind the `/redis` subpath, so importing `@gusnips/server` never\ninstalls it.\n\nVersions 5 and 6 both work. Version 6 speaks RESP3 unless the server is older than Redis 6, and\nthen falls back.\n\n## Background jobs\n\nQueues and workers for BullMQ, on the connection `createRedis` gives you:\n\n```bash\nbun add bullmq\n```\n\n```ts\nimport {\n  createQueue,\n  createWorker,\n  retryStalledFailures,\n  wireDeadLetter,\n  type DeadLetter,\n} from \"@gusnips/server/bullmq\";\n\nconst onError = (error: Error) => logger.error(\"[bullmq] connection error\", { error });\nconst reports = createQueue<{ userId: string }>(\"reports\", { connection: redis, onError });\nconst deadLetters = createQueue<DeadLetter>(\"dead-letters\", { connection: redis, onError });\n\nconst worker = createWorker<{ userId: string }>(\"reports\", buildReport, {\n  connection: redis,\n  onError,\n  concurrency: 5,\n});\nconst flush = wireDeadLetter(worker, deadLetters, { onError });\nawait retryStalledFailures(reports);\n```\n\n- **Finished jobs are deleted.** BullMQ keeps them forever unless told otherwise, and one backend's\n  Redis grew to about 16 GB before anyone noticed. Completed jobs stay for a day, 200 at most.\n  Failed ones stay for a week, 1,000 at most. The worker sets the same limits, so a job a script\n  adds through a plain `new Queue` is deleted too. If something waits for a job with\n  `job.waitUntilFinished()`, don't set `removeOnComplete: true` on that queue: the job can be gone\n  before the wait reads it, and the wait fails with \"Missing key\".\n- **A worker starts taking jobs as soon as you build it.** If the same process also listens on a\n  port or sets up its shutdown, pass `autorun: false` and call `worker.run()` once both are ready.\n  Otherwise, during a deploy, a second process can take a job and then die on the port the first\n  one still holds. That job runs again later, or never, if its queue runs jobs at most once.\n- **A job whose worker dies runs again, twice at most, 15 to 90 seconds later.** The third time\n  its worker dies, the job fails. The wait comes from how BullMQ finds such a job. A live worker\n  checks every 30 seconds. Each check marks every running job, the worker running it clears the\n  mark when it renews the job's 30-second lock, and the next check re-runs a job that is still\n  marked and whose lock has run out. In 14 runs with `kill -9`, the job ran again 35 to 69\n  seconds later, and about 62 seconds later when the process manager restarted the only worker\n  at once. While no worker runs on the queue, nothing checks. For a job that must never run\n  twice, such as one that sends an email, pass `maxStalledCount: 0` and give its jobs\n  `attempts: 1`.\n- **`wireDeadLetter` records every job that failed for good**, in a queue of its own. Run a worker\n  on that queue to log each record or tell a person. It asks BullMQ whether the job will run again,\n  instead of counting attempts, so it also records a job that threw `UnrecoverableError` or\n  stalled too often on its first attempt. Three of the five dead letters it replaces missed those.\n  Each record keeps a copy of the job's `data` for a week, so don't wire a worker whose jobs carry a\n  secret, such as a password or a login. Log its job id from its own `failed` listener instead;\n  `isFinalFailure(job)` tells you the job will not run again.\n  In your shutdown, call `flush()` after the worker closes and before Redis does. While Redis is\n  down, `worker.close()` never returns: see [Stopping for a deploy](#stopping-for-a-deploy).\n- **`retryStalledFailures` re-runs the jobs a deploy killed.** Two deploys during one long job use\n  up its two retries. It only matches the reason BullMQ writes, so a job that failed with the word\n  \"stalled\" in its own error stays failed. A job that leaves the failed set while it runs is\n  skipped, so two processes starting at once can both call it. Never call it on a queue whose jobs\n  must run at most once.\n- **`isStalledOut(job)`** is for a `failed` listener. It is true when BullMQ gave up on the job\n  because its worker kept dying, not because the job threw. BullMQ never runs your code again for\n  that job, so if the job was driving a row, set the row's status here. \"We lost the worker\" is a\n  different answer from \"the job failed\".\n- **`CAPPED_EXPONENTIAL`** waits a random time before each retry, between half of a step and the\n  whole step. The step starts at 5 seconds and doubles up to 120, so the first retry comes 2.5 to\n  5 seconds after the failure, the second 5 to 10, then 10 to 20, 20 to 40, 40 to 80, and 60 to\n  120 from the sixth on. The random part keeps jobs that failed together from retrying together.\n  Ask for it per job: `{ attempts: 5, backoff: { type: CAPPED_EXPONENTIAL } }`.\n- **`removeLeftoverJob`** is for jobs you add under an id you chose. BullMQ skips the add, with no\n  error, while a finished job with that id is still kept. If the job starts running again while it\n  works, it leaves the job alone instead of throwing, so two callers can race on one id.\n\nRecurring jobs come from one table, synced on every boot:\n\n```ts\nawait syncJobSchedulers(maintenance, {\n  \"session-prune\": { pattern: \"20 4 * * *\", tz: \"UTC\" },\n  \"job-reaper\": { every: 2 * 60_000 },\n});\n```\n\nA cron pattern without a time zone does not compile, because without one it runs on the server's\nclock. An entry you delete or rename stops running: the sync removes every scheduler on the queue\nthat the table does not name, so give the table a queue of its own.\n\n`bullmq` is an optional peer, behind the `/bullmq` subpath.\n\nVersions 5 and 6 both work, with one pairing to avoid: BullMQ 5 with ioredis 6 runs, but fails your\ntypecheck. BullMQ 5 brings its own ioredis 5, and its types refuse a version 6 client, so move both\nto 6 together. BullMQ 6 also dropped the `repeat` option on `add()`. `syncJobSchedulers` still\nremoves a repeat that version 5 created, with its next run.\n\n## A rate limit\n\n```ts\nimport { memoryWindowStore } from \"@gusnips/server\";\nimport { rateLimit } from \"@gusnips/server/hono\";\n\napp.use(\n  \"/app/*\",\n  rateLimit<AppEnv>({\n    scope: \"app\",\n    store: memoryWindowStore(),\n    limit: 300, // requests a minute, per user\n    windowMs: 60_000,\n    key: (c) => c.get(\"userId\") ?? null,\n    refuse: (hit) => errors.rateLimit(hit.retryAfterSecs),\n  }),\n);\n```\n\nThe 301st request in a minute gets your own 429, through your `onError`, and `Retry-After` says\nhow many seconds are left in that minute. Windows start on the clock's minute, so the number is\nexact rather than a constant. A `key` that returns `null` lets the request through uncounted.\n\n**`key` must be something the server checked.** Before auth, that is the client's address. After\nauth, it is the verified user, key or account, never the raw bearer token: a limiter that counts\nthe token counts whatever string the caller sends. On one backend, 300 requests from one address\nwith a new random token each were refused 0 times.\n\n### The client's address\n\nA limit in front of sign-in counts per address, and the address has to be one the caller cannot\nmake up:\n\n```ts\nimport { ipSubject, memoryWindowStore } from \"@gusnips/server\";\nimport { bunPeer, clientIp, rateLimit } from \"@gusnips/server/hono\";\n\napp.use(clientIp({ peerOf: bunPeer }));\napp.use(\n  \"/auth/*\",\n  rateLimit<AppEnv>({\n    scope: \"pre-auth\",\n    store: memoryWindowStore(),\n    limit: 3_000,\n    windowMs: 60_000,\n    key: (c) => ipSubject(c.get(\"clientIp\")),\n    refuse: (hit) => errors.rateLimit(hit.retryAfterSecs),\n  }),\n);\n```\n\n- **The socket first.** `clientIp` reads the last `X-Forwarded-For` hop only when the socket peer\n  is loopback, which is your proxy on the same box, because that hop is the one the proxy wrote.\n  From anywhere else the peer is the client, and its `X-Forwarded-For` is its own claim. So an API\n  that also answers on its public interface cannot be handed a made-up address. `X-Real-IP` is\n  never read: by its documented default, Caddy passes a client's own copy through.\n- **On a Worker or on Fly**, pass the edge's header instead: `clientIp({ header:\n\"cf-connecting-ip\" })`. Not on a box behind a proxied Cloudflare record, where anyone who finds\n  the box's address can send that header too.\n- **`null` when no address can be trusted**, never `\"unknown\"`. A shared `\"unknown\"` window is one\n  any caller can fill for everyone. A `key` of `null` lets the request through uncounted; write\n  `?? \"unknown\"` if you would rather count those together.\n- **`ipSubject` counts an IPv6 address by its /56**, the network one customer is usually given.\n  Counted by the full address, one customer has 2^64 fresh windows. IPv4 is left as it is.\n- **`bunPeer`, not `hono/bun`.** It reads the address `hono/bun`'s `getConnInfo` reads, from the\n  server Bun hands `fetch`, without importing `hono/bun`. That import reads the `Bun` global as\n  it loads, so an app file that has it cannot load at all in a test run under Node. In a test's\n  `app.request()` there is no server, so `clientIp` is `null` and the limiters let it through. On\n  another runtime, pass its own `getConnInfo`: a `peerOf` that throws reads as no peer.\n\n**The memory store counts per process** and starts again on every deploy. That is right for a\nburst limit in front of an auth round trip. It tracks 50,000 windows at most, and past that it\nrefuses new ones, which `refuse` gets as `hit.outcome === \"shed\"`: that caller hit no limit, so\nyour 429 can say the server is busy instead. It clears the closed windows once per window, not\nonce per request. The copies it replaces did it once per request, which cost about 3.8 ms each\non a full map, so a flood of spoofed addresses could keep a process busy doing nothing else.\n\n**A limit a plan sells goes in Redis**, so it holds across a restart and a second process:\n\n```ts\nimport { createRedis, redisWindowStore } from \"@gusnips/server/redis\";\n\n// Its own connection, one that fails at once when Redis is down.\nconst limitsRedis = createRedis({\n  url: env.REDIS_URL,\n  maxRetriesPerRequest: 1,\n  enableOfflineQueue: false,\n  commandTimeout: 1_000,\n  onError: (error) => logger.error(\"[redis] limiter connection\", { error }),\n});\n\napp.use(\n  \"/v1/*\",\n  rateLimit<AppEnv>({\n    scope: \"api\",\n    store: redisWindowStore(limitsRedis, { timeoutMs: 500 }),\n    whenStoreFails: \"allow\",\n    logger,\n    limit: (c) => planOf(c.get(\"user\")).requestsPerMinute,\n    windowMs: 60_000,\n    key: (c) => c.get(\"user\").accountId,\n    refuse: (hit) => errors.rateLimit(hit.retryAfterSecs),\n  }),\n);\n```\n\n- **`whenStoreFails` is required for a store that can fail, and it has no default.** Say\n  `\"allow\"` for a limit that guards a promise, like a plan's requests per minute: refusing every\n  paying caller over a Redis blip trades a real outage for a limit nobody was hitting. Pass your\n  503 for one that guards a bill or a stranger's inbox, like a keyless demo or a form that sends\n  mail: `whenStoreFails: () => errors.unavailable(\"…\")`. Either way `rateLimit` writes the\n  failure to `logger`, with the scope and never the subject. `hitWindow`, below, writes nothing.\n- **Give it its own connection.** Three limiters in the fleet said \"fails open\" and hung instead,\n  because the connection `createRedis` makes by default waits for Redis to come back, and so did\n  every request behind them. `timeoutMs` is required as the backstop. The connection above fails\n  in a few milliseconds, so the backstop never runs.\n- **A count sent while that connection is still opening waits for it.** The connection refuses\n  any command before it is ready, so without the wait the first count after every boot failed.\n  It waits for `ready` or `close`, inside `timeoutMs`, so a Redis that is down still fails at\n  once.\n- One MULTI counts the request and re-arms the key's expiry, so no key outlives its window. Keys\n  start with `rl:`; pass `prefix` to change that.\n\n`hitWindow(store, key, { limit, windowMs })` is the same count without Hono, for a Worker, a job\nor an MCP tool. It answers `{ outcome, allowed, retryAfterSecs, … }` and never throws for a limit.\nWith a store that can fail, it also takes `whenStoreFails`, and it logs nothing: a failed store\ncomes back as `outcome: \"store-failed\"`, and the log line is yours to write. The MCP door below\nshows it.\n\n## A URL somebody else gave you\n\nA webhook endpoint, a link to read, an image to fetch: each is a customer telling your server to\nsend a request. Your server shares a network with Postgres, Redis and the cloud metadata service\nat 169.254.169.254, so an unchecked URL lets anyone who can save one aim it inward.\n\n```ts\nimport { checkUrlShape } from \"@gusnips/server\";\n\ncheckUrlShape(\"https://169.254.169.254/latest/meta-data/\");\n// → { ok: false, reason: \"private-address\" }\n```\n\nIt answers with a result, not a throw, so the 400 is in your words. The reasons are `invalid`,\n`scheme`, `credentials`, `port`, `internal-name` and `private-address`.\n\n- **Only `https:` by default.** A reader of pasted links passes\n  `{ schemes: [\"http:\", \"https:\"] }`.\n- **`ports: [80, 443]`** is the smaller blast radius when nothing needs more. DNS can move a\n  host; it cannot move a port.\n- **`allowLoopback: true`** lets `localhost`, 127.0.0.0/8 and `::1` through for a test, and\n  nothing else. Never a private range, never the metadata service. It leaves the scheme alone,\n  so a receiver on your machine that speaks plain HTTP also needs `schemes: [\"http:\", \"https:\"]`.\n  Without it, `http://localhost:4000/` is refused as `scheme`. `fetchPublic` takes the same\n  options as `policy`.\n\nTwelve backends wrote this check. The most-copied version let carrier-grade NAT through, and\nanother judged `::ffff:127.0.0.1` safe once the URL parser had rewritten it as `::ffff:7f00:1`.\n`isPublicAddress` accepts only global addresses, so a spelling nobody thought of is refused\nrather than waved through.\n\n**Follow a redirect yourself, and check every hop.** With `redirect: \"follow\"`, fetch has already\nsent a request to each hop by the time you can check where it ended:\n\n```ts\nconst hop = nextHop(url, response, { method: \"POST\", headers });\n// null: not a redirect. { ok: false, reason }: refuse. Otherwise the next request:\n// hop.url, hop.method, hop.headers, and hop.dropBody when a 302 turned a POST into a GET.\n```\n\nIt rewrites the method the way fetch does, and it keeps `Authorization`, `Cookie` and\n`Proxy-Authorization` from reaching another origin.\n\n**Read the answer with a limit.** `readBounded(response.body, 1_000_000)` stops at a million\nbytes and cancels the rest. It never trusts `Content-Length`. When `truncated` is true, the body\nwas longer, and a caller that needs all of it (an image, a JSON document) refuses.\n\nIn a Cloudflare Worker, that is the whole check: a Worker cannot resolve a name, and the network\nbehind its `fetch` is not your box's. On a server, a name still has to be resolved, and the\nrequest sent to the address you checked rather than to whatever DNS answers a moment later.\nThat is `/node`:\n\n```ts\nimport { fetchPublic } from \"@gusnips/server/node\";\n\nconst result = await fetchPublic(endpoint.url, {\n  method: \"POST\",\n  headers: { \"content-type\": \"application/json\" },\n  body: JSON.stringify(event),\n  maxRedirects: 0,\n  signal: AbortSignal.timeout(10_000),\n});\nif (!result.ok) return refuse(result.reason); // your words, as above\nresult.response.status; // a real Response\n```\n\n- **It resolves the name once and refuses it if any answer is private.** A name with one public\n  and one private record is refused as a whole. Then it sends the request to one of the addresses\n  it checked, with the name in the TLS check and in `Host`. Checking a name and then calling\n  `fetch` resolves it twice, and a DNS server that changes its answer in between wins.\n- **It follows up to 5 redirects and checks each one before sending it.** `maxRedirects: 0` hands\n  a redirect back as the answer, which is what a webhook wants.\n- **`signal` is required.** It bounds the DNS lookup, the connection, the wait and the body.\n- **It tries another address only when one refused the connection.** After a timeout it stops:\n  the first address may have received the webhook, and the next would deliver it twice.\n- **A name DNS does not know is `unresolvable`. A DNS lookup that fails throws**, because telling\n  a customer their host does not exist when your resolver is down names the wrong cause.\n- **The body is decoded**, so `readBounded` counts the bytes that come out. Ten megabytes of\n  gzipped zeros is ten kilobytes on the wire.\n\nCheck once when the URL is saved, with `resolvePublic`, so a bad one gets a 400 right away.\n`fetchPublic` checks again when it sends, because DNS can change in between.\n\n**Run it on Bun 1.4.2 or later, or on Node 22.** Bun 1.3.8 checks the certificate against the\n`Host` header rather than the name it is given, so an https URL on a port other than 443 fails.\nIt also sends a request a second time on its own when a reused connection is reset.\n\n## A webhook\n\nA webhook URL is public, so anyone can POST to it. The signature is how the receiver tells your\ndelivery from a forgery.\n\n```ts\nimport { signWebhook } from \"@gusnips/server\";\n\nconst signature = await signWebhook({ secret: endpoint.secret, body });\n// → \"t=1700000000,v1=5f1c…\", sent as your own header, such as x-acme-signature\n```\n\nReceiving one:\n\n```ts\nimport { verifyWebhook } from \"@gusnips/server\";\n\nconst verdict = await verifyWebhook({\n  secrets: [env.WEBHOOK_SECRET],\n  header: c.req.header(\"x-acme-signature\"),\n  body: await c.req.text(),\n});\nif (!verdict.ok) throw errors.badSignature(); // log verdict.reason; do not send it back\n```\n\n- **Two formats.** `signWebhook` and `verifyWebhook` use one header, the format Stripe uses.\n  `signStandardWebhook` and `verifyStandardWebhook` use Standard Webhooks: three headers, the\n  format Supabase Auth's hooks send.\n- **A delivery signed more than five minutes ago is refused**, however well signed, so a captured\n  one cannot be sent again. `toleranceSecs` changes the limit. Sign each attempt, not each event,\n  or a retry arrives already too old.\n- **`secrets` is a list**, so a rotation is `[env.SECRET, env.OLD_SECRET]`. An unset one is\n  skipped. When none is set, the answer is `no-secret`, never a pass.\n- **`body` is the raw text.** Parse it after it passes: JSON parsed and written out again is a\n  different string, and its signature never matches.\n- **Every `v1` signature in the header is tried.** Supabase Auth sends one per secret it holds,\n  joined by `\", \"`.\n\n`newWebhookSecret()` makes a secret both formats accept: `whsec_` and 24 random bytes.\n\nAnother vendor's format is one line on the same two functions. GitHub's:\n\n```ts\nconst expected = `sha256=${await hmacSha256(env.GITHUB_WEBHOOK_SECRET, body, \"hex\")}`;\nif (!safeEqual(c.req.header(\"x-hub-signature-256\") ?? \"\", expected)) throw errors.badSignature();\n```\n\n`hmacSha256` throws on an empty key and `safeEqual` answers `false` when either side is empty, so\nan unset secret cannot let a request through.\n\n### Sending one, and trying again\n\n```ts\nimport { nextDeliveryStep } from \"@gusnips/server\";\n\nconst step = nextDeliveryStep(response, delivery.attempts + 1);\n// → { outcome: \"retry\", afterSecs: 60 }\n```\n\n`response` is what the receiver answered, or `null` when nothing came back: a refused connection, a\ntimeout, or DNS failing. The second argument is the attempt that just ran, counting from 1.\n\n| The receiver answered            | The step                                                       |\n| -------------------------------- | -------------------------------------------------------------- |\n| 2xx                              | `delivered`                                                    |\n| 408, 425, 429, 5xx, or no answer | `retry` after `afterSecs`, until the fifth attempt `exhausted` |\n| 3xx                              | `failed`, `reason: \"redirected\"`                               |\n| any other 4xx                    | `failed`, `reason: \"refused\"`                                  |\n\n- **A 4xx is final.** The receiver's code answered on purpose, and the same body gets the same\n  answer. Six of seven senders tried it again. What this gives up is a 404 while their\n  deploy swaps routes, which is rarer than a 502 and shows in the delivery log.\n- **A redirect is final.** A webhook follows none, because the new address was never checked, so\n  the next attempt would get the same redirect. Ask the customer to register the final URL.\n- **The wait doubles from 30 seconds**: 30, 60, 120 and 240, then the fifth attempt is the last.\n  `{ attempts, baseSecs, maxWaitSecs }` in the third argument changes that.\n- **A `Retry-After` longer than the ladder's wait is believed**, in seconds or as a date. No\n  sender read it before. It is capped at an hour (`maxWaitSecs`), so a receiver asking for three\n  hours gets an attempt each hour instead of being given up on.\n- **Schedule the retry with `afterSecs`, not with your queue's own backoff**, or the two disagree\n  and the row's \"next attempt\" is wrong. In BullMQ, delay the job by hand:\n  `await job.moveToDelayed(Date.now() + step.afterSecs * 1000, token); throw new DelayedError();`.\n- **Keep the attempt count on the delivery row.** A job delayed by hand keeps `attemptsMade` at 0\n  (measured on BullMQ 5.81.5), so `job.attemptsMade + 1` would say \"first attempt\" forever and the\n  delivery would never stop.\n\n**A breaker counts deliveries that failed for good, never attempts.** A receiver down for ten\nminutes should not use up ten failures on one event while it is still being retried. So count a\n`failed` step, and turn the endpoint off in one statement:\n\n```sql\n-- $1 is the endpoint, $2 how many failures in a row turn it off\nUPDATE webhook_endpoints\n   SET consecutive_failures = consecutive_failures + 1,\n       enabled = consecutive_failures + 1 < $2\n WHERE id = $1 AND enabled\nRETURNING NOT enabled AS tripped\n```\n\n`tripped` is true for exactly one failure, so the mail saying \"we turned your endpoint off\" goes\nonce. Measured on Postgres 18 with 20 failures at once and a limit of 10: one trip, with the count\nat 10. Reading the count and then writing it, as two senders do, kept 1 of the 20 and never tripped.\nA `delivered` step resets it:\n`UPDATE webhook_endpoints SET consecutive_failures = 0 WHERE id = $1 AND consecutive_failures > 0`.\nWith supabase-js, put the statement in a Postgres function and call it with `.rpc()`, because\n`.update()` cannot add one to a column.\n\n## A secret you store\n\nAn OAuth token or a mailbox password in your database is one leaked backup away from being\nsomebody else's. Seal it before you store it:\n\n```ts\nimport { createSealer } from \"@gusnips/server\";\n\nconst vault = createSealer({ current: \"v1\", keys: { v1: env.SEAL_KEY } });\n\nconst sealed = await vault.seal(refreshToken); // \"v1.Xq3…\", safe to store\nawait vault.open(sealed); // refreshToken\n```\n\n- **A key is 32 random bytes in base64.** Make one with `openssl rand -base64 32`. A key of any\n  other length is refused when the sealer is created, so a wrong one stops the boot instead of the\n  first sign-in.\n- **The `v1` at the front names the key.** To change keys, add the new one, point `current` at\n  it, seal the stored values again, then remove the old key. Until you remove it, both open.\n- **`open` throws a `SealError`**, whose `reason` is `malformed`, `unknown-key` or\n  `did-not-open`. The last one has two causes that encryption cannot tell apart: this process\n  holds a different key from the one that sealed the value, or the value was changed.\n- It is AES-256-GCM with a random 12-byte IV and a 16-byte tag, and it runs in a Worker.\n\nRows sealed under a passphrase with Node's `scryptSync(passphrase, salt, 32)` open with the key\n`/node` derives the same way:\n\n```ts\nimport { scryptSealKey } from \"@gusnips/server/node\";\n\nconst vault = createSealer({\n  current: \"v1\",\n  keys: { v1: await scryptSealKey(env.CREDENTIALS_ENCRYPTION_KEY, \"acme-credentials-v1\") },\n});\n```\n\n## A link that proves who it is for\n\nAn unsubscribe link, an OAuth `state`, an approval link: your server writes a token, hands it to a\nperson, and reads it back later with no session behind it. The signature proves you wrote it.\n\n```ts\nimport { signToken, verifyToken } from \"@gusnips/server\";\n\nconst token = await signToken({ secret, purpose: \"unsubscribe:v1\", payload: userId });\n// → \"dXNlcl80Mg.Xq3…\", safe in a URL\n\nconst verdict = await verifyToken({ secret, purpose: \"unsubscribe:v1\", token });\nif (!verdict.ok) return c.html(linkNotValidPage); // one page for every reason\nverdict.payload; // userId\n```\n\n- **`purpose` is mixed into the key.** A token made for one purpose never verifies for another,\n  and the secret itself never signs, so a service key you already hold can be the secret.\n- **`ttlSecs` makes it expire.** Leave it out only for a link that must work forever, such as\n  unsubscribe: the button sits in old mail, and old mail is where people look for it.\n- **It is signed, not encrypted.** Anyone holding the token can read the payload. For structured\n  data, pass `JSON.stringify(data)`, and parse it after it verifies.\n- **`reason` is `malformed`, `bad-signature` or `expired`.** `expired` is only said of a token you\n  signed, so a page that says \"this link expired, ask for a new one\" is telling the truth.\n\nWithout `ttlSecs`, a token is `<base64url(payload)>.<signature>`, keyed by the HMAC of the secret\nand the purpose. Links you signed that way by hand keep verifying after you switch.\n\n## An MCP door\n\nServe your API's operations to AI agents over MCP, the protocol agents use to call tools, with the\nsame errors and limits as your REST routes.\n\n```bash\nbun add @modelcontextprotocol/sdk\n```\n\n```ts\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { hitWindow, memoryWindowStore } from \"@gusnips/server\";\nimport { mcpRoutes, registerOperation } from \"@gusnips/server/mcp\";\n\nconst toolCalls = memoryWindowStore();\n\nfunction buildMcpServer(c: Context<AppEnv>) {\n  const server = new McpServer({ name: \"acme\", version: \"1.0.0\" });\n  const userId = c.get(\"userId\");\n  for (const op of OPERATIONS)\n    registerOperation(server, op, {\n      errorResponse,\n      logger,\n      requestId: c.get(\"requestId\"),\n      deps: () => ({ userId }),\n      // Once per tool call. One POST can carry many.\n      beforeCall: async () => {\n        const hit = await hitWindow(toolCalls, userId, { limit: 60, windowMs: 60_000 });\n        if (hit.outcome === \"limited\" || hit.outcome === \"shed\")\n          throw errors.rateLimit(hit.retryAfterSecs);\n      },\n    });\n  return server;\n}\n\n// The key check is yours. The kit ships none, because where your keys live is up to you.\napp.use(\"/mcp/*\", async (c, next) => {\n  const account = await accountForKey(c.req.header(\"authorization\")); // your own lookup\n  if (!account) throw errors.invalidKey();\n  c.set(\"userId\", account.userId);\n  await next();\n});\napp.route(\"/\", mcpRoutes(\"/mcp\", buildMcpServer, { allowedOrigins: new Set() }));\n```\n\nAn operation is `{ name, description, inputSchema, run(deps, args) }`, plus an optional `title`\nand `annotations`. Pass the same list to `buildOpenApi` as `mcpTools` (below), and the reference\nlists exactly the tools you register, with their own arguments, in your order. A tool that takes\nmore than its REST route needs this. A tool call has no headers, so a key that makes a retry safe\ntravels as an argument, such as `idempotencyKey`. A card built from the route's `input` leaves that\nargument out, and its `additionalProperties: false` tells a model the key would be refused.\n\n- **A tool call answers what the REST route answers.** A success is `{ data }`, as one text block.\n  A failure is the same `{ error }` body your `errorResponse` gives REST, marked `isError`. Pass\n  `present` to answer a success differently, for example with an image first. It gets the call's\n  own `deps`, so an image the operation handed back on the side stays with that call, and it may\n  be async. A throw in `present` answers the call as failed after the work is done, so catch what\n  is only nice to have.\n- **A tool handler never throws.** The MCP SDK answers a throw with the error's own message, so\n  `connect ECONNREFUSED 10.0.0.5:5432` reaches the agent and no log line sees it. Three of eight\n  backends shipped that. `registerOperation` catches every failure: a 5xx and an unexpected throw\n  are logged with the raw error, and an unexpected throw is masked, as on REST. `onUnexpected` is\n  where an alert goes. If you register a tool yourself, return `toolError(err, name, door)` from its\n  `catch`.\n- **Your limit goes in `beforeCall`, not on the route.** One POST can carry a batch of tool calls,\n  and the SDK runs every one of them. A limit on the route counts the POST, so 50 calls cost one.\n  `beforeCall` runs before each call. Throw your 429 there and only that call is refused. It is\n  required, so a door with no limit says `null`.\n- **With a Redis store, you write the log line.** `hitWindow` logs nothing. When the store does\n  not answer, it returns `outcome: \"store-failed\"`, and a limit that has quietly stopped limiting\n  is the failure you want to see:\n\n  ```ts\n  const toolLimits = redisWindowStore(limitsRedis, { timeoutMs: 500 });\n\n  // in beforeCall:\n  const hit = await hitWindow(toolLimits, userId, {\n    limit: 60,\n    windowMs: 60_000,\n    whenStoreFails: \"allow\",\n  });\n  if (hit.outcome === \"store-failed\") {\n    logger.warn(\"[mcp] the limit store did not answer\", { allowed: hit.allowed, error: hit.error });\n    if (!hit.allowed) throw errors.unavailable(\"…\"); // with whenStoreFails: \"refuse\"\n  } else if (!hit.allowed) throw errors.rateLimit(hit.retryAfterSecs);\n  ```\n\n- **Pass the zod object, made `.strict()`, not its `.shape`.** Given a shape, the SDK builds a loose\n  object and quietly drops an argument the agent made up. Given the strict object, it refuses the\n  call and names the key. A `.shape` does not compile here.\n- **Only POST is served.** This door keeps no sessions. A GET gets a 405 instead of an event stream\n  that nothing writes to and that stays open until the server's idle timeout.\n- **A web page must be on `allowedOrigins`.** The MCP spec asks serv","readmeFilename":"README.md"}