{"_id":"@distilled.cloud/aws4signer","_rev":"5-9d4373f5a051c9cceeed2dd3d09ef151","name":"@distilled.cloud/aws4signer","dist-tags":{"latest":"1.0.0-rc.17"},"versions":{"0.0.0-stage":{"name":"@distilled.cloud/aws4signer","version":"0.0.0-stage","_id":"@distilled.cloud/aws4signer@0.0.0-stage","stub":true,"maintainers":[{"name":"sam-goodwin","email":"sam@alchemy.run"}],"dist":{"shasum":"e62e21bc9a7b726cdb0bafba184139814a07251f","tarball":"https://registry.npmjs.org/@distilled.cloud/aws4signer/-/aws4signer-0.0.0-stage.tgz","fileCount":2,"integrity":"sha512-PKYJ4FAV46KLvvM/O6V1GgnsXehCeYBgmc0n7L7ri4XmTiIud+V3NynrZGQfoI2iUpitx+ptOouHjBIB9X8Kwg==","signatures":[{"sig":"MEYCIQD/Gm6pJp84kMvLFniTpFxU5TqSxQOD5k+ITppk0P09nwIhAOwmHB+7LNV9pOlpZnyZZLU1tXPe8PDxmKmNC6RPiutf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":349},"_npmUser":{"name":"sam-goodwin","email":"sam@alchemy.run"},"description":"Temporary package placeholder for staged publishing","directories":{}},"0.0.0":{"name":"@distilled.cloud/aws4signer","version":"0.0.0","license":"Apache-2.0","_id":"@distilled.cloud/aws4signer@0.0.0","maintainers":[{"name":"pear-alchemy","email":"michael@alchemy.run"},{"name":"sam-goodwin","email":"sam@alchemy.run"},{"name":"blankparticle","email":"blankparticle@gmail.com"}],"homepage":"https://github.com/alchemy-run/distilled#readme","bugs":{"url":"https://github.com/alchemy-run/distilled/issues"},"dist":{"shasum":"5a9e0ea58c729452590fa53442dcf3439165b41f","tarball":"https://registry.npmjs.org/@distilled.cloud/aws4signer/-/aws4signer-0.0.0.tgz","fileCount":2,"integrity":"sha512-6R5VeDncQEjE6f4x/TfXeaH1qqQAv8RpICI6ahctjGaIvoetnK3aib+1XisMLYtyb1NSShlR5Ikk6rkPYSRtaQ==","signatures":[{"sig":"MEYCIQDcyY2Y6oFq7Len8ARPyGf4NSbbsGlT3STCvUPpGEkOiQIhAKSbj4Owh5R24OqROarag1pDMJIMdTRR3YlYNTeb8JRH","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIHZnARLjElil42KsQpTaRrmVy8wUa0gqMCgK16Otz0HKAiEAyai0NTFncCQ3mRdAGSDRDVqc/ZH8o4FVLXSauelwhbU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":919},"_npmUser":{"name":"sam-goodwin","email":"sam@alchemy.run"},"repository":{"url":"git+https://github.com/alchemy-run/distilled.git","type":"git","directory":"packages/aws4signer"},"_npmVersion":"11.19.0","description":"Effect-native AWS Signature Version 4: sign and presign requests, or sign every request an HttpClient sends. For AWS and every S3-compatible or SigV4-signed API.","directories":{},"_nodeVersion":"24.21.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/aws4signer_0.0.0_1792602085210_0.5432156389806204","host":"s3://npm-registry-packages-npm-production"}},"1.0.0-rc.16":{"name":"@distilled.cloud/aws4signer","version":"1.0.0-rc.16","license":"Apache-2.0","_id":"@distilled.cloud/aws4signer@1.0.0-rc.16","maintainers":[{"name":"pear-alchemy","email":"michael@alchemy.run"},{"name":"sam-goodwin","email":"sam@alchemy.run"},{"name":"blankparticle","email":"blankparticle@gmail.com"}],"dist":{"shasum":"14a4c67158ad4db19318a56c75a7c4d4f24034d7","tarball":"https://registry.npmjs.org/@distilled.cloud/aws4signer/-/aws4signer-1.0.0-rc.16.tgz","fileCount":13,"integrity":"sha512-zPEG5A5LogLjyCBdJ7zukRpDirb5Yz08NZ8ylK3RLRreihrtPPROOw9hZ3NraMzeFmsshiXNWUsg7SBu5RzK+w==","signatures":[{"sig":"MEYCIQCZMoUEahyzLc8JrxKEDYIKCcMTEavB4CmnD+UeBioYJAIhAPLsAp4sQnPier689e8KLwu8N65RNTqQCFtnIomY0dCc","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIGRYF6+yQTRlNHZsI7yQPFv/sjq4I9D1xXuwHqTqNaHRAiAxhm+e6VQHthcxxAZ/Io387rjMrvsquqXNQBYb0gbxbg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@distilled.cloud%2faws4signer@1.0.0-rc.16","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":108465},"type":"module","exports":{".":{"bun":"./src/index.ts","types":"./lib/index.d.ts","worker":"./src/index.ts","default":"./lib/index.js"},"./AwsClient":{"bun":"./src/client.ts","types":"./lib/client.d.ts","worker":"./src/client.ts","default":"./lib/client.js"}},"scripts":{"build":"tsc -b","typecheck":"tsc -p tsconfig.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"4f54d6e0-2c7d-4d1d-b630-0d4539b04d58"}},"repository":{"url":"https://github.com/alchemy-run/distilled","type":"git","directory":"packages/aws4signer"},"description":"Effect-native AWS Signature Version 4: sign and presign requests, or sign every request an HttpClient sends. For AWS and every S3-compatible or SigV4-signed API.","directories":{},"sideEffects":false,"dependencies":{"@distilled.cloud/core":"1.0.0-rc.16"},"_hasShrinkwrap":false,"devDependencies":{"effect":"^4.0.5","aws4fetch":"1.0.20","@types/node":"26.6.5"},"peerDependencies":{"effect":"^4.0.5"},"_npmOperationalInternal":{"tmp":"tmp/aws4signer_1.0.0-rc.16_1792708922597_0.6918939865984093","host":"s3://npm-registry-packages-npm-production"}},"1.0.0-rc.17":{"_id":"@distilled.cloud/aws4signer@1.0.0-rc.17","dist":{"shasum":"775c0bc6784561b503afaf768c840aa915421c3a","tarball":"https://registry.npmjs.org/@distilled.cloud/aws4signer/-/aws4signer-1.0.0-rc.17.tgz","fileCount":13,"integrity":"sha512-4wOoFuiadiKOEfDcL0VwGwg4XmZ3vmMxrNJAnTKf87k2WN2Shs7KeUp4GS1TzGGO3NrrpvVw8RFK+dOomDMj5w==","signatures":[{"sig":"MEUCIQDb57VIk6fh1P0SnvLM+yG2MJC7FeV4kmpTw0Tku8UUqAIgfKkz35JkhRHoNGWWviGs1Hi1JnoMXBHyzJCSogOmp9M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIB333if4N3NKVYAtxOVKYlDkLEQ7fVUYYvL9RItNbt/sAiEA5m/EdKaNtba6ov0IWLBf41YtYMVLyL0LCgvFlvUwnQo="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@distilled.cloud%2faws4signer@1.0.0-rc.17","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":90930},"name":"@distilled.cloud/aws4signer","type":"module","exports":{".":{"bun":"./src/index.ts","types":"./lib/index.d.ts","worker":"./src/index.ts","default":"./lib/index.js"},"./AwsClient":{"bun":"./src/client.ts","types":"./lib/client.d.ts","worker":"./src/client.ts","default":"./lib/client.js"}},"license":"Apache-2.0","scripts":{"build":"tsc -b","typecheck":"tsc -p tsconfig.json"},"version":"1.0.0-rc.17","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"4f54d6e0-2c7d-4d1d-b630-0d4539b04d58"}},"repository":{"url":"https://github.com/alchemy-run/distilled","type":"git","directory":"packages/aws4signer"},"description":"Effect-native AWS Signature Version 4: sign and presign requests, or sign every request an HttpClient sends. For AWS and every S3-compatible or SigV4-signed API.","directories":{},"maintainers":[{"name":"pear-alchemy","email":"michael@alchemy.run"},{"name":"sam-goodwin","email":"sam@alchemy.run"},{"name":"blankparticle","email":"blankparticle@gmail.com"}],"sideEffects":false,"dependencies":{"@distilled.cloud/core":"1.0.0-rc.17"},"_hasShrinkwrap":false,"devDependencies":{"effect":"^4.0.5","aws4fetch":"1.0.20","@types/node":"26.6.5"},"peerDependencies":{"effect":"^4.0.5"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/aws4signer_1.0.0-rc.17_1792796620488_0.685751941982131"}}},"time":{"created":"2026-10-21T16:58:47.389Z","modified":"2026-10-23T23:03:41.082Z","0.0.0-stage":"2026-10-21T16:58:47.389Z","0.0.0":"2026-10-21T17:01:25.293Z","1.0.0-rc.16":"2026-10-22T22:42:02.784Z","1.0.0-rc.17":"2026-10-23T23:03:40.709Z"},"license":"Apache-2.0","repository":{"url":"https://github.com/alchemy-run/distilled","type":"git","directory":"packages/aws4signer"},"description":"Effect-native AWS Signature Version 4: sign and presign requests, or sign every request an HttpClient sends. For AWS and every S3-compatible or SigV4-signed API.","maintainers":[{"name":"pear-alchemy","email":"michael@alchemy.run"},{"name":"sam-goodwin","email":"sam@alchemy.run"},{"name":"blankparticle","email":"blankparticle@gmail.com"}],"readme":"# @distilled.cloud/aws4signer\n\nEffect-native AWS Signature Version 4 (SigV4): an Effect port of\n[aws4fetch](https://github.com/mhart/aws4fetch). Sign or presign one request,\nor sign every request an Effect `HttpClient` sends.\n\nUse it to call AWS or any SigV4 API (Cloudflare R2, MinIO, Backblaze B2,\nAPI Gateway, Lambda function URLs, ...) without the full\n`@distilled.cloud/aws` SDK. It signs byte for byte like aws4fetch; a test\nsigns the same requests with both and compares the results. Its only\ndependencies are `@distilled.cloud/core` (for crypto) and `effect`.\n`@distilled.cloud/aws` uses this package and re-exports it as\n`@distilled.cloud/aws/SigV4`.\n\n## Installation\n\n```bash\nnpm install @distilled.cloud/aws4signer effect\n```\n\n## Sign every request: `AwsClient`\n\n`@distilled.cloud/aws4signer/AwsClient` is aws4fetch's `AwsClient` as an\n`HttpClient` transform.\n\n```typescript\nimport * as AwsClient from \"@distilled.cloud/aws4signer/AwsClient\";\nimport * as Effect from \"effect/Effect\";\nimport * as FetchHttpClient from \"effect/http/FetchHttpClient\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as Redacted from \"effect/Redacted\";\n\nconst credentials = {\n  accessKeyId: process.env.R2_ACCESS_KEY_ID!,\n  secretAccessKey: Redacted.make(process.env.R2_SECRET_ACCESS_KEY!),\n};\n\nconst program = Effect.gen(function* () {\n  // service \"s3\" and region \"auto\" come from the R2 host.\n  const r2 = (yield* HttpClient.HttpClient).pipe(\n    AwsClient.sign({ credentials }),\n    HttpClient.retryTransient({ times: 3 }),\n  );\n  const res = yield* r2.get(`https://${accountId}.r2.cloudflarestorage.com/my-bucket/hello.txt`);\n  return yield* res.text;\n});\n\nprogram.pipe(Effect.provide(FetchHttpClient.layer), Effect.runPromise);\n```\n\n- `AwsClient.make(options)` is the context's `HttpClient` with `sign(options)` applied.\n- `AwsClient.signRequest(request, options)` signs one `HttpClientRequest`.\n- `AwsClient.presign(url, { credentials, expiresIn })` returns a presigned URL.\n- `credentials` can be an `Effect` that returns the keys. It runs once per\n  request, so it can refresh temporary credentials.\n- The signing time comes from the Effect `Clock`, so `TestClock` controls it.\n- A stream or form-data body cannot be hashed. Set the `X-Amz-Content-Sha256`\n  header (for example `UNSIGNED-PAYLOAD`), or the request fails with\n  `UnsignableBody`. S3 signs `UNSIGNED-PAYLOAD` by default.\n\n## Presign a URL\n\n```typescript\nimport * as SigV4 from \"@distilled.cloud/aws4signer\";\n\nconst url = yield* SigV4.presign({\n  method: \"PUT\",\n  url: `https://${accountId}.r2.cloudflarestorage.com/uploads/avatar.png`,\n  accessKeyId,\n  secretAccessKey,\n  expiresIn: 900,\n});\n```\n\n## Sign one request\n\n```typescript\nconst signed = yield* SigV4.sign({\n  method: \"GET\",\n  url: `https://${accountId}.r2.cloudflarestorage.com/${bucket}/${key}`,\n  accessKeyId,\n  secretAccessKey,\n  service: \"s3\",\n  region: \"auto\",\n});\nconst response = yield* Effect.promise(() =>\n  fetch(signed.url, { method: signed.method, headers: signed.headers }),\n);\n```\n\n`sign` needs `service` and `region`. `SigV4.guessScope(options)` fills them\nfrom the host the way aws4fetch does (`*.amazonaws.com`, R2, B2, Lambda\nfunction URLs). `presign` and `AwsClient` guess on their own. The guessing\nlives outside `sign`, so a program that always passes both (the AWS SDK) does\nnot bundle the host rules.\n\nOptions that match aws4fetch: `signQuery`, `allHeaders`,\n`appendSessionToken`, `singleEncode`, `datetime`. `hashPayload` also sends\nthe body hash as `X-Amz-Content-Sha256`.\n\n## Errors\n\n`sign` fails with a typed `SigningError`: `InvalidSigningUrl`,\n`InvalidSigningHeaders`, or `CryptoError`. `AwsClient` can also fail with\n`UnsignableBody`.\n","readmeFilename":""}