{"_id":"@archival/carrier","_rev":"3-4c380382327f9ce0f7426e6549fd5477","name":"@archival/carrier","dist-tags":{"latest":"0.18.0"},"versions":{"0.16.0":{"name":"@archival/carrier","version":"0.16.0","author":{"name":"Jesse Ditson","email":"jesse@archival.dev"},"license":"Unlicense","_id":"@archival/carrier@0.16.0","maintainers":[{"name":"jesseditson","email":"jesse.ditson@gmail.com"}],"bin":{"archival-carrier-types":"bin/archival-carrier-types.js"},"dist":{"shasum":"abdcc5d19cf510a2a8a364331e5180a01b00d9c8","tarball":"https://registry.npmjs.org/@archival/carrier/-/carrier-0.16.0.tgz","fileCount":5,"integrity":"sha512-sa1EpDNrpdUNMJQPyDSLwFucoKvjvlmRsOVSV9/zqeQHdG1+jgb+rFfFTSpP4oPmSy6qaCCfG1jKhKSLdkSy2A==","signatures":[{"sig":"MEUCIFrki/MAjNvCwy6h87O/6VyO/UIQsTqqUu/GkXaZsjSeAiEA0uVxJcRF8hQA+82L0CGj6HmIAuQQil7yVHVwp8cuJ+8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":15108},"main":"index.js","type":"module","types":"index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"}},"gitHead":"8820f70bee144abdc2f114afe66a9e108947cb7a","_npmUser":{"name":"jesseditson","email":"jesse.ditson@gmail.com"},"_npmVersion":"11.13.0","description":"TypeScript types for archival carriers","directories":{},"_nodeVersion":"25.5.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/carrier_0.16.0_1785017775166_0.2239692973004377","host":"s3://npm-registry-packages-npm-production"}},"0.17.0":{"name":"@archival/carrier","version":"0.17.0","author":{"name":"Jesse Ditson","email":"jesse@archival.dev"},"license":"Unlicense","_id":"@archival/carrier@0.17.0","maintainers":[{"name":"jesseditson","email":"jesse.ditson@gmail.com"}],"bin":{"archival-carrier-types":"bin/archival-carrier-types.js"},"dist":{"shasum":"b23792d3b8210e3b96a69dd81aa17ad243b041d6","tarball":"https://registry.npmjs.org/@archival/carrier/-/carrier-0.17.0.tgz","fileCount":5,"integrity":"sha512-xxpUPaDDjR8qqcQvteoo0328bJVS+JFnzn+s+RXmjzSo68lT0Feorjjgf1NZ8jY4YTG9BzvlxSN6rM7NU8NkaQ==","signatures":[{"sig":"MEQCIE6TjDPtgRL1cP1ORc0Dpp0eh8iheHnGPa22hVau0tKpAiBb9iihbIt39tvQa7LNqehAk06sdn/S1AdK388Eef0sjw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":19015},"main":"index.js","type":"module","types":"index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"}},"gitHead":"7be0020c5e8d32e0b4f2a9c0ff6116b15f8eb8fd","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:18962055-75cd-4562-8713-c75fccf49567"}},"_npmVersion":"11.17.0","description":"TypeScript types for archival carriers","directories":{},"_nodeVersion":"26.5.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/carrier_0.17.0_1785475960464_0.9360034865510016","host":"s3://npm-registry-packages-npm-production"}},"0.18.0":{"_id":"@archival/carrier@0.18.0","bin":{"archival-carrier-types":"bin/archival-carrier-types.js"},"dist":{"shasum":"79f2d68b8dac4ad187db3546059d13ff4a48caba","tarball":"https://registry.npmjs.org/@archival/carrier/-/carrier-0.18.0.tgz","fileCount":5,"integrity":"sha512-FNBsVE7nnTLDeqA3eRdrWK08Xr6VV3Bgq+v7SZYLxaCwKZzS/ODZFYIa5lif3jJ/MR14JYohTjbOA4HTcjveXw==","signatures":[{"sig":"MEQCIDqwZMfJ5wc5Ka9NgVzWSIO4jQw7lRHEqnl7AsAlbI01AiADuQ6Gtn+e34LP7ak+rW/3Edafh1DtA9dPLcYAgnUTbQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBbaRQnYJyUs0JQgjzFGDnnM9rfDOoNDgq9cty3ML+ANAiEAzR811ldRXQ4WEJ2GW6Qr/H5E84xvmaROJt4QA3GibuQ="}],"unpackedSize":21979},"main":"index.js","name":"@archival/carrier","type":"module","types":"index.d.ts","author":{"name":"Jesse Ditson","email":"jesse@archival.dev"},"exports":{".":{"types":"./index.d.ts","default":"./index.js"}},"gitHead":"4c5157b0e35af300c7af7377271626a5fa56a466","license":"Unlicense","version":"0.18.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:960bcb05-5f3c-48ba-acb8-42078f8fccdf"}},"_npmVersion":"11.19.0","description":"TypeScript types for archival carriers","directories":{},"maintainers":[{"name":"jesseditson","email":"jesse.ditson@gmail.com"}],"_nodeVersion":"26.8.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/carrier_0.18.0_1790194531291_0.4225395366602922"}}},"time":{"created":"2026-07-25T22:16:14.980Z","modified":"2026-09-23T20:15:31.550Z","0.16.0":"2026-07-25T22:16:15.353Z","0.17.0":"2026-07-31T05:32:40.602Z","0.18.0":"2026-09-23T20:15:31.380Z"},"author":{"name":"Jesse Ditson","email":"jesse@archival.dev"},"license":"Unlicense","description":"TypeScript types for archival carriers","maintainers":[{"name":"jesseditson","email":"jesse.ditson@gmail.com"}],"readme":"# @archival/carrier\n\nTypeScript types for [archival](https://archival.dev) carriers — server side\nfunctions deployed alongside your site, one per directory under `carriers/`.\n\n```sh\ncd carriers/my-carrier\nnpm install --save-dev @archival/carrier\n```\n\n## Typing a carrier\n\nA carrier default-exports a function of `(params, body, objects)`:\n\n```ts\nimport type { Carrier } from \"@archival/carrier\";\n\nconst carrier: Carrier = async (params, body, objects) => ({\n  hello: params.get(\"name\"),\n  site: objects.SITE_URL,\n});\n\nexport default carrier;\n```\n\nReturn an object to send JSON, or a string to send `text/plain`. A string\nprefixed with `redirect:` becomes a 302 to the rest of the string. Return a\n`Response` to send anything else.\n\n## Reading uploads\n\n`objects.UPLOADS` reads the files uploaded to your site. Reads are scoped to\nyour site, and there is no way to write.\n\n`list()` gives every upload, as the name it was uploaded with and the content\nhash it is stored under:\n\n```ts\nawait objects.UPLOADS.list();\n// [{ sha: \"0c1f…\", filename: \"menu.pdf\" }, …]\n```\n\n`get()` reads one, by name:\n\n```ts\nconst upload = await objects.UPLOADS.get(\"menu.pdf\");\n```\n\nIt resolves to `null` when nothing matches. Names are not unique — the same\nname can be uploaded more than once, under different hashes — so looking one up\nby name alone throws when it is ambiguous. Pass the hash to say which you meant,\nor pass a file straight off `objects`, which carries its own:\n\n```ts\nawait objects.UPLOADS.get(\"menu.pdf\", \"0c1f…\");\nawait objects.UPLOADS.get(objects.settings.menu);\n```\n\nServing one back is a `Response`, which is what lets a carrier put a file behind\na check the site itself can't make:\n\n```ts\nconst carrier: Carrier = async (params, body, objects) => {\n  if (params.get(\"password\") !== objects.settings.download_password) {\n    return \"redirect:/login\";\n  }\n  const upload = await objects.UPLOADS.get(\"private-menu.pdf\");\n  if (!upload) {\n    return \"redirect:/404\";\n  }\n  const headers = new Headers();\n  upload.writeHttpMetadata(headers);\n  headers.set(\"etag\", upload.httpEtag);\n  return new Response(upload.body, { headers });\n};\n```\n\n## Sending email\n\n`objects.EMAIL.send` sends mail from one of your site's own email addresses.\nIt needs a plan that includes email and at least one address on one of your\nsite's domains; add those in the site's email settings first.\n\n```ts\nconst carrier: Carrier = async (params, body, objects) => {\n  await objects.EMAIL.send({\n    to: body.email,\n    subject: \"Thanks for getting in touch\",\n    text: `We got your message and will reply within a day.`,\n  });\n  return \"redirect:/thanks\";\n};\n```\n\n`from` defaults to the first address on your site's primary domain; pass one\nof your other addresses to send from that instead. A copy of every message\nlands in that address's Sent folder. `to` takes a single address or up to ten;\n`text`, `html` (at least one) and `replyTo` do what they say.\n\n`send` resolves once archival has accepted the message, with an `id` for its\nlogs and the `from` it resolved. Delivery happens afterwards - if it fails, the\nsite's owner is emailed about it. It rejects when the message is not accepted:\nthe site has no email, `from` is not one of its addresses, a recipient is\nmalformed, or the site is over its hourly sending limit (100 messages).\n\n## Typing your site's objects\n\n`objects` is your site's archival objects merged with the vars archival injects\n(`SITE_URL`, `UPLOADS`, `EMAIL`). Every site's objects are different, so the types for\nthem are generated from your `archival_objects.toml`:\n\n```sh\nnpx archival-carrier-types\n```\n\nThat runs `archival types` and writes an `archival-objects.d.ts` next to each\ncarrier. **Commit those files** — they contain no object values, only your\nschema, and committing them means your editor and CI work on a fresh clone with\nno extra setup.\n\nAfter generating, `objects` is fully typed:\n\n```ts\nconst carrier: Carrier = async (params, body, objects) => ({\n  titles: objects.posts.map((post) => post.title), // (string | null)[]\n  contact: objects.settings.contact,\n  hero: objects.posts[0].hero?.url,\n});\n```\n\nObjects backed by a directory (`objects/posts/*.toml`) are arrays; objects\nbacked by a single file (`objects/settings.toml`) are not. Unset fields are\n`null`. Child objects default to `[]`. Every object read from its own file also\ncarries `path` and `order`.\n\nUntil you generate, reading anything but the injected vars off `objects` is a\ncompile error — deliberately, so a carrier can't silently read an object that\nisn't there.\n\nYou need the `archival` binary on your `PATH` or in your `node_modules`\n(`npm install --save-dev archival`, or `cargo install archival`).\n\n### Options\n\n| Flag                    |                                                                |\n| ----------------------- | -------------------------------------------------------------- |\n| `--check`               | Don't write; exit non-zero if anything is out of date. For CI. |\n| `--carrier <name>`      | Only generate for one carrier.                                 |\n| `--carriers-dir <path>` | Carriers directory, if not `carriers`.                         |\n| `--site <path>`         | Site root, if not an ancestor of the working directory.        |\n| `--out <path>`          | Write a single file here instead of one per carrier.           |\n| `--archival <path>`     | Path to the archival binary.                                   |\n\nTo keep generated types honest in CI:\n\n```sh\nnpx archival-carrier-types --check\n```\n\n## Note on `secret` fields\n\nFields declared `secret` are hidden from templates, but carriers run on the\nserver and do receive their values. They are typed as `string | null` like any\nother string.\n","readmeFilename":"README.md"}