import type { S3Client } from "@aws-sdk/client-s3"; import type { Adapter } from "../index.js"; import type { S3AdapterOptions, S3Sdk } from "../s3/core.js"; import type { EventCapability } from "./events.js"; export type S3Engine = "aws-sdk" | "fetch"; /** * Resolve the HTTP engine. An explicit choice always wins. Otherwise the * `"aws-sdk"` engine is the default — except on Cloudflare Workers, where it * is not workerd-compatible out of the box: the AWS SDK's client-s3 * browser-targeted bundle resolves xml-builder's *browser* XML * parser, which needs `DOMParser` — undefined in workerd. Every S3 XML parse * (list, error bodies) then throws `DOMParser is not defined` at runtime, long * after adapter construction. Default to the fetch engine there instead. * * `navigator.userAgent === "Cloudflare-Workers"` is the documented workerd * check. `navigator` is absent on compatibility dates before 2022-03-21 or * under the `no_global_navigator` flag; only *then* fall back to the * workerd-only `WebSocketPair` global — Node-hosted Workers shims (Miniflare * v2, jest-environment-miniflare) also define it, and `navigator` is the * signal that tells them apart from the real thing. * * A `DOMParser` on the global is the one precondition the aws-sdk engine * needs, and the standard workaround for this bug is to polyfill exactly that * (linkedom, @xmldom/xmldom). Keep those deployments on the full engine — * swapping them to fetch would silently drop multipart/resumable uploads, * batched deletes, and `raw` as an `S3Client`. */ export declare const resolveS3Engine: (explicit?: S3Engine) => S3Engine; /** * Load the `@aws-sdk/*` modules behind the `"aws-sdk"` engine. * * Each `import()` is awaited directly inside the `try`, and that shape is * load-bearing. Consumer bundlers resolve literal `import()` specifiers at * build time, so an unhandled `import("@aws-sdk/client-s3")` fails a Worker * build (`Could not resolve "@aws-sdk/client-s3"` from Wrangler's esbuild) * when the optional peers aren't installed, even though the binding and fetch * engines never run it. An import awaited inside a `try` is one whose failure * the code handles at run time: esbuild, Bun, and rolldown leave it unresolved * without an error, and webpack downgrades it to a warning. When the peers * *are* installed, every bundler still resolves and bundles them as before. * Moving an import out of the `try`, into a `Promise.all`, or into a default * parameter brings the build error back (`test/build-output.test.ts`). * * A missing peer doesn't always reject, though: Next.js's webpack resolves an * uninstalled optional peer to an empty module, so the import succeeds and the * first `new S3Client()` would fail with a bare "is not a constructor". Check * the loaded exports so both cases end in the same install hint. * * `permanent`: a missing module fails every attempt the same way, so * `retries` must not re-run the call. The importer is injectable only so the * missing-peer paths are testable. */ export declare const loadS3Sdk: (name: string, importSdk?: () => Promise) => Promise; /** * An `Adapter` whose every method `await`s a lazily-imported s3 * adapter (memoized after the first hit). The trade-off vs. a static import: * a bundle that imports the entry but runs on the fetch engine never includes * the AWS SDK's client-s3. The cost is one extra microtask on first call and a * `raw` getter that returns `undefined` until the import resolves (call any * method first to force the load). */ export declare const lazyS3Adapter: (config: S3AdapterOptions, name: string, events?: EventCapability | false) => Adapter & { readonly bucket: string; }; //# sourceMappingURL=s3-engine.d.ts.map