← all parts

Part · storage.upload

What's actually behind storage.upload

The part exactly as partkit add storage.upload vendors it into your repo — verified, locked, every byte readable. Nothing here is mocked.

storage.uploadv1.1.0

✓ attested🔒 read-onlystorage.upload@1

Lives at parts/storage.upload/ in your repo — open, owned, readable. Not buried in node_modules. 392 lines of source you can audit.

13 conformance tests passedverified 2026-06-15↗ CI run
content hash 5f495fb04f…0fc5fbpinned in parts.lockctrlai guard fails CI if a single byte changes
tested against node 25.3.0

Public API — what your seam calls

  • presignUpload(key: string, opts?: PresignUploadOptions): Promise<PresignedRequest>
  • presignDownload(key: string, opts?: PresignDownloadOptions): Promise<PresignedRequest>
  • class StorageError extends Error { code: StorageErrorCode }
  • types: PresignedRequest, PresignUploadOptions, PresignDownloadOptions, StorageErrorCode

Invariants — guarantees the contract pins

  1. Importing the part performs no I/O and never throws; presigning is pure computation (no network), and configuration and inputs are validated at call time with typed errors
  2. Presigned signatures conform to AWS Signature Version 4 exactly: byte-for-byte identical to the canonical AWS implementation (AWS CLI / botocore) for the same inputs, across path-style and virtual-hosted addressing
  3. Each presigned request carries the required X-Amz-* query parameters with the correct credential scope (date/region/s3/aws4_request), host, SignedHeaders, and UNSIGNED-PAYLOAD; method is PUT for upload and GET for download
  4. The signature binds the whole request: changing the key, method, expiry, region, or secret changes the signature, so a presigned URL cannot be repurposed
  5. Object keys with spaces, Unicode, and S3-special characters are URI-encoded per the S3 rules so they sign and address correctly; empty, over-long, or control-character keys are rejected with a typed error and no output
  6. Expiry is bounded to 1..604800 seconds and reflected in both X-Amz-Expires and the returned expiresAt; an out-of-range expiry fails fast with a typed error
  7. The secret access key never appears in any URL, header, or error message; all failures surface as typed StorageError values

Dependencies

zero-dep — runs on your Postgres
SOURCEparts/storage.upload/15 files · click to read
parts/storage.upload/src/index.tstypescript · 1,592 bytes
/**
 * storage.upload — public interface. The ONLY legal import surface.
 * Contract: ../contract.json · What your app must provide: ../seams.md
 */
import { buildPresigned } from "./internal/presign";
import type {
  PresignDownloadOptions,
  PresignedRequest,
  PresignUploadOptions,
} from "./internal/types";

export { StorageError } from "./internal/errors";
export type { StorageErrorCode } from "./internal/errors";
export type {
  PresignDownloadOptions,
  PresignedRequest,
  PresignUploadOptions,
} from "./internal/types";

/**
 * Presign a direct-to-storage upload (HTTP PUT). Hand the returned URL to a
 * browser or client; the bytes go straight to your S3-compatible provider,
 * never through your app.
 *
 * Importing this module performs no I/O and never throws; the SigV4 signature
 * is pure computation (no network), and configuration is validated here, at
 * call time, with typed errors (contract invariants 1, 7).
 */
// `async` so that validation/config errors thrown by buildPresigned surface as
// a rejected promise, not a synchronous throw, regardless of call site.
export async function presignUpload(
  key: string,
  opts?: PresignUploadOptions,
): Promise<PresignedRequest> {
  return buildPresigned("PUT", key, opts?.expiresInSeconds);
}

/**
 * Presign a direct-from-storage download (HTTP GET) — a time-limited URL for a
 * private object, without making it public.
 */
export async function presignDownload(
  key: string,
  opts?: PresignDownloadOptions,
): Promise<PresignedRequest> {
  return buildPresigned("GET", key, opts?.expiresInSeconds);
}