{"_id":"@021.is/spine-email","_rev":"2-597ae904a9e29423ef9105149f5c3ebb","name":"@021.is/spine-email","dist-tags":{"latest":"0.4.3"},"versions":{"0.4.0":{"name":"@021.is/spine-email","version":"0.4.0","license":"MIT","_id":"@021.is/spine-email@0.4.0","maintainers":[{"name":"edvone","email":"edvard@edvone.dev"}],"homepage":"https://github.com/021is/spine-ts#readme","bugs":{"url":"https://github.com/021is/spine-ts/issues"},"dist":{"shasum":"00ca77ce619655711b6777c66d126c39b6f5bbc9","tarball":"https://registry.npmjs.org/@021.is/spine-email/-/spine-email-0.4.0.tgz","fileCount":4,"integrity":"sha512-LfZwUblKXqFYIJ3QUhYzTo3PbMPWM2rpGKwRuYRJzCn9ITxC4nBaUZWxSS0zs4DpqAZJuvZ0++kGAPE2TilL8Q==","signatures":[{"sig":"MEQCIHW+SoXavwFuB0VLPpUrw6y6Nnv7v/Ud8XXzM40Oj5yLAiApx0EyHzW83PSf8NCaqJMpzs9nf1COt3bOZ/vmtkLYZQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":6152},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"e4434c6f59db8f586e0f05ffdb3b88a96e68e67b","scripts":{"build":"tsup src/index.ts --format esm --dts --clean","typecheck":"tsc --noEmit"},"_npmUser":{"name":"edvone","email":"edvard@edvone.dev"},"repository":{"url":"git+https://github.com/021is/spine-ts.git","type":"git","directory":"packages/email"},"_npmVersion":"10.9.4","description":"Resend wrapper with structured logging, retries, and a uniform send API. Templates live in the consuming app.","directories":{},"_nodeVersion":"22.22.0","dependencies":{"@021.is/spine-errors":"^0.4.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/spine-email_0.4.0_1779981942259_0.9233704977567683","host":"s3://npm-registry-packages-npm-production"}},"0.4.3":{"name":"@021.is/spine-email","version":"0.4.3","license":"MIT","description":"Resend wrapper with structured logging, retries, and a uniform send API. Templates live in the consuming app.","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsup src/index.ts --format esm --dts --clean","typecheck":"tsc --noEmit"},"dependencies":{"@021.is/spine-errors":"^0.4.3"},"repository":{"type":"git","url":"git+https://github.com/021is/spine-ts.git","directory":"packages/email"},"publishConfig":{"access":"public"},"_id":"@021.is/spine-email@0.4.3","gitHead":"b9f9333776fa55686cc2feb05f851aa6000b0e05","bugs":{"url":"https://github.com/021is/spine-ts/issues"},"homepage":"https://github.com/021is/spine-ts#readme","_nodeVersion":"22.22.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-hAxbYw9cattjwIAeaVTwB2fuBfKz0yeHEj9JTUTFJ2ZI0CK5ccpmRTw8CNMgN69Hc8IdMfty5ffu/TaTR5cdqQ==","shasum":"0d88832eb97ffa40dce95e20f5072003c9a0f4dd","tarball":"https://registry.npmjs.org/@021.is/spine-email/-/spine-email-0.4.3.tgz","fileCount":5,"unpackedSize":7418,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDi090NJZ8FdGqvb4O7CdFOKfoI3K/oMDoRwdTK4wNYGgIgTbqznMYenBNAYo1mwTOk/KmnqAL0qbCEuWXkMUt+BE4="}]},"_npmUser":{"name":"edvone","email":"edvard@edvone.dev"},"directories":{},"maintainers":[{"name":"edvone","email":"edvard@edvone.dev"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/spine-email_0.4.3_1779995233360_0.6171250292382751"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-28T15:25:42.100Z","modified":"2026-05-28T19:07:13.617Z","0.4.0":"2026-05-28T15:25:42.429Z","0.4.3":"2026-05-28T19:07:13.499Z"},"bugs":{"url":"https://github.com/021is/spine-ts/issues"},"license":"MIT","homepage":"https://github.com/021is/spine-ts#readme","repository":{"type":"git","url":"git+https://github.com/021is/spine-ts.git","directory":"packages/email"},"description":"Resend wrapper with structured logging, retries, and a uniform send API. Templates live in the consuming app.","maintainers":[{"name":"edvone","email":"edvard@edvone.dev"}],"readme":"# @021.is/spine-email\n\nResend wrapper. Bearer auth, retry on 5xx, terminal on 4xx (no infinite-loop on permanent client errors), idempotency-key passthrough, structured logging hook.\n\n## Use\n\n```ts\nimport { makeEmailClient } from \"@021.is/spine-email\";\n\nconst email = makeEmailClient({\n  apiKey: env.RESEND_API_KEY,\n  defaultFrom: \"My App <noreply@example.com>\",\n  retries: 2,\n  logger: console, // optional pino-compatible logger\n});\n\nawait email.send({\n  to: \"you@example.com\",\n  subject: \"Welcome to My App\",\n  html: renderToString(<WelcomeEmail name=\"Sam\" />),\n  tags: { app: \"my-app\", flow: \"signup\" },\n  idempotencyKey: `signup-${userId}`,\n});\n```\n\n## Behavior\n\n- 5xx → up to `retries` more attempts (default 2)\n- 4xx → throws `SomethingWentWrongException` immediately, no retries (4xx is permanent — looping wastes time + money)\n- Missing both `html` and `text` → throws\n- Sets `idempotency-key` header when provided (Resend dedupes server-side)\n\n## React Email templates\n\nTemplates live in the consuming app (React Email, MJML, plain HTML — your call). spine-email is just the transport.\n\n## Why not just `fetch`\n\nDefault fetch has no retry, no logging, no terminal-on-4xx logic, no idempotency. After the third app reimplemented it, it became a package.\n","readmeFilename":"README.md"}