diff --git a/.changeset/quick-timers-fail.md b/.changeset/quick-timers-fail.md new file mode 100644 index 00000000..be6af030 --- /dev/null +++ b/.changeset/quick-timers-fail.md @@ -0,0 +1,7 @@ +--- +"@opennextjs/cloudflare": patch +--- + +fix: @vercel/og failing due to using the node version. + +Patches usage of the @vercel/og library to require the edge runtime version, and enables importing of the fallback font. diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index dafd1144..408104e8 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -4,7 +4,6 @@ on: push: branches: [main, experimental] pull_request: - branches: [main, experimental] jobs: checks: diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 4fc920b3..d83daec8 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -4,7 +4,6 @@ on: push: branches: [main] pull_request: - branches: [main] jobs: test: diff --git a/.github/workflows/prereleases.yml b/.github/workflows/prereleases.yml index a52603a2..a70ea2ea 100644 --- a/.github/workflows/prereleases.yml +++ b/.github/workflows/prereleases.yml @@ -4,7 +4,6 @@ on: push: branches: [main, experimental] pull_request: - branches: [main, experimental] jobs: release: diff --git a/examples/api/app/og/route.tsx b/examples/api/app/og/route.tsx new file mode 100644 index 00000000..3f48fb0f --- /dev/null +++ b/examples/api/app/og/route.tsx @@ -0,0 +1,65 @@ +import { ImageResponse } from "next/og"; + +export const dynamic = "force-dynamic"; + +export async function GET() { + try { + return new ImageResponse( + ( +
+
+ Vercel +
+
+ 'next/og' +
+
+ ), + { + width: 1200, + height: 630, + } + ); + } catch (e: any) { + return new Response("Failed to generate the image", { + status: 500, + }); + } +} diff --git a/examples/api/e2e/base.spec.ts b/examples/api/e2e/base.spec.ts index 60024131..9a5c3e9a 100644 --- a/examples/api/e2e/base.spec.ts +++ b/examples/api/e2e/base.spec.ts @@ -1,4 +1,16 @@ import { test, expect } from "@playwright/test"; +import type { BinaryLike } from "node:crypto"; +import { createHash } from "node:crypto"; + +const OG_MD5 = "2f7b724d62d8c7739076da211aa62e7b"; + +export function validateMd5(data: Buffer, expectedHash: string) { + return ( + createHash("md5") + .update(data as BinaryLike) + .digest("hex") === expectedHash + ); +} test("the application's noop index page is visible and it allows navigating to the hello-world api route", async ({ page, @@ -42,3 +54,10 @@ test("returns correct information about the request from a route handler", async const expectedURL = expect.stringMatching(/https?:\/\/localhost:(?!3000)\d+\/api\/request/); await expect(res.json()).resolves.toEqual({ nextUrl: expectedURL, url: expectedURL }); }); + +test("generates an og image successfully", async ({ page }) => { + const res = await page.request.get("/og"); + expect(res.status()).toEqual(200); + expect(res.headers()["content-type"]).toEqual("image/png"); + expect(validateMd5(await res.body(), OG_MD5)).toEqual(true); +}); diff --git a/packages/cloudflare/package.json b/packages/cloudflare/package.json index 5f02417f..24b57b45 100644 --- a/packages/cloudflare/package.json +++ b/packages/cloudflare/package.json @@ -73,7 +73,7 @@ "dependencies": { "@ast-grep/napi": "^0.34.1", "@dotenvx/dotenvx": "catalog:", - "@opennextjs/aws": "https://pkg.pr.new/@opennextjs/aws@704", + "@opennextjs/aws": "https://pkg.pr.new/@opennextjs/aws@712", "enquirer": "^2.4.1", "glob": "catalog:", "ts-morph": "catalog:", diff --git a/packages/cloudflare/src/cli/build/build.ts b/packages/cloudflare/src/cli/build/build.ts index 9f3d8d6d..b9270f79 100644 --- a/packages/cloudflare/src/cli/build/build.ts +++ b/packages/cloudflare/src/cli/build/build.ts @@ -1,6 +1,5 @@ -import { cpSync } from "node:fs"; import { createRequire } from "node:module"; -import { dirname, join } from "node:path"; +import { dirname } from "node:path"; import { buildNextjsApp, setStandaloneBuildMode } from "@opennextjs/aws/build/buildNextApp.js"; import { compileCache } from "@opennextjs/aws/build/compileCache.js"; @@ -11,8 +10,7 @@ import * as buildHelper from "@opennextjs/aws/build/helper.js"; import { printHeader, showWarningOnWindows } from "@opennextjs/aws/build/utils.js"; import logger from "@opennextjs/aws/logger.js"; -import type { ProjectOptions } from "../config.js"; -import { containsDotNextDir, getConfig } from "../config.js"; +import type { ProjectOptions } from "../project-options.js"; import { bundleServer } from "./bundle-server.js"; import { compileEnvFiles } from "./open-next/compile-env-files.js"; import { copyCacheAssets } from "./open-next/copyCacheAssets.js"; @@ -69,10 +67,6 @@ export async function build(projectOpts: ProjectOptions): Promise { buildNextjsApp(options); } - if (!containsDotNextDir(projectOpts.sourceDir)) { - throw new Error(`.next folder not found in ${projectOpts.sourceDir}`); - } - // Generate deployable bundle printHeader("Generating bundle"); buildHelper.initOutputDir(options); @@ -95,14 +89,7 @@ export async function build(projectOpts: ProjectOptions): Promise { await createServerBundle(options); - // TODO: drop this copy. - // Copy the .next directory to the output directory so it can be mutated. - cpSync(join(projectOpts.sourceDir, ".next"), join(projectOpts.outputDir, ".next"), { recursive: true }); - - const projConfig = getConfig(projectOpts); - - // TODO: rely on options only. - await bundleServer(projConfig, options); + await bundleServer(options); if (!projectOpts.skipWranglerConfigCheck) { await createWranglerConfigIfNotExistent(projectOpts); diff --git a/packages/cloudflare/src/cli/build/bundle-server.ts b/packages/cloudflare/src/cli/build/bundle-server.ts index 0c308ca2..72f254c3 100644 --- a/packages/cloudflare/src/cli/build/bundle-server.ts +++ b/packages/cloudflare/src/cli/build/bundle-server.ts @@ -4,11 +4,10 @@ import path from "node:path"; import { fileURLToPath } from "node:url"; import { Lang, parse } from "@ast-grep/napi"; -import type { BuildOptions } from "@opennextjs/aws/build/helper.js"; +import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js"; import { getCrossPlatformPathRegex } from "@opennextjs/aws/utils/regex.js"; import { build, Plugin } from "esbuild"; -import { Config } from "../config.js"; import { patchOptionalDependencies } from "./patches/ast/optional-deps.js"; import * as patches from "./patches/index.js"; import { normalizePath, patchCodeWithValidations } from "./utils/index.js"; @@ -19,22 +18,26 @@ const packageDistDir = path.join(path.dirname(fileURLToPath(import.meta.url)), " /** * Bundle the Open Next server. */ -export async function bundleServer(config: Config, openNextOptions: BuildOptions): Promise { - patches.copyPackageCliFiles(packageDistDir, config, openNextOptions); - - const nextConfigStr = - fs - .readFileSync(path.join(config.paths.output.standaloneApp, "server.js"), "utf8") - ?.match(/const nextConfig = ({.+?})\n/)?.[1] ?? {}; +export async function bundleServer(buildOpts: BuildOptions): Promise { + patches.copyPackageCliFiles(packageDistDir, buildOpts); + + const { appPath, outputDir, monorepoRoot } = buildOpts; + const serverFiles = path.join( + outputDir, + "server-functions/default", + getPackagePath(buildOpts), + ".next/required-server-files.json" + ); + const nextConfig = JSON.parse(fs.readFileSync(serverFiles, "utf-8")).config; console.log(`\x1b[35m⚙️ Bundling the OpenNext server...\n\x1b[0m`); - patches.patchWranglerDeps(config); - patches.updateWebpackChunksFile(config); + patches.patchWranglerDeps(buildOpts); + await patches.updateWebpackChunksFile(buildOpts); + patches.patchVercelOgLibrary(buildOpts); - const { appBuildOutputPath, appPath, outputDir, monorepoRoot } = openNextOptions; const outputPath = path.join(outputDir, "server-functions", "default"); - const packagePath = path.relative(monorepoRoot, appBuildOutputPath); + const packagePath = getPackagePath(buildOpts); const openNextServer = path.join(outputPath, packagePath, `index.mjs`); const openNextServerBundle = path.join(outputPath, packagePath, `handler.mjs`); @@ -45,25 +48,28 @@ export async function bundleServer(config: Config, openNextOptions: BuildOptions format: "esm", target: "esnext", minify: false, - plugins: [createFixRequiresESBuildPlugin(config)], + plugins: [createFixRequiresESBuildPlugin(buildOpts)], external: ["./middleware/handler.mjs", "caniuse-lite"], alias: { // Note: we apply an empty shim to next/dist/compiled/ws because it generates two `eval`s: // eval("require")("bufferutil"); // eval("require")("utf-8-validate"); - "next/dist/compiled/ws": path.join(config.paths.internal.templates, "shims", "empty.js"), + "next/dist/compiled/ws": path.join(buildOpts.outputDir, "cloudflare-templates/shims/empty.js"), // Note: we apply an empty shim to next/dist/compiled/edge-runtime since (amongst others) it generated the following `eval`: // eval(getModuleCode)(module, module.exports, throwingRequire, params.context, ...Object.values(params.scopedContext)); // which comes from https://github.com/vercel/edge-runtime/blob/6e96b55f/packages/primitives/src/primitives/load.js#L57-L63 // QUESTION: Why did I encountered this but mhart didn't? - "next/dist/compiled/edge-runtime": path.join(config.paths.internal.templates, "shims", "empty.js"), + "next/dist/compiled/edge-runtime": path.join( + buildOpts.outputDir, + "cloudflare-templates/shims/empty.js" + ), // `@next/env` is a library Next.js uses for loading dotenv files, for obvious reasons we need to stub it here // source: https://github.com/vercel/next.js/tree/0ac10d79720/packages/next-env - "@next/env": path.join(config.paths.internal.templates, "shims", "env.js"), + "@next/env": path.join(buildOpts.outputDir, "cloudflare-templates/shims/env.js"), }, define: { // config file used by Next.js, see: https://github.com/vercel/next.js/blob/68a7128/packages/next/src/build/utils.ts#L2137-L2139 - "process.env.__NEXT_PRIVATE_STANDALONE_CONFIG": JSON.stringify(nextConfigStr), + "process.env.__NEXT_PRIVATE_STANDALONE_CONFIG": `${JSON.stringify(nextConfig)}`, // Next.js tried to access __dirname so we need to define it __dirname: '""', // Note: we need the __non_webpack_require__ variable declared as it is used by next-server: @@ -117,7 +123,7 @@ globalThis.__BUILD_TIMESTAMP_MS__ = ${Date.now()}; }, }); - await updateWorkerBundledCode(openNextServerBundle, config, openNextOptions); + await updateWorkerBundledCode(openNextServerBundle, buildOpts); const isMonorepo = monorepoRoot !== appPath; if (isMonorepo) { @@ -127,35 +133,26 @@ globalThis.__BUILD_TIMESTAMP_MS__ = ${Date.now()}; ); } - console.log(`\x1b[35mWorker saved in \`${getOutputWorkerPath(openNextOptions)}\` 🚀\n\x1b[0m`); + console.log(`\x1b[35mWorker saved in \`${getOutputWorkerPath(buildOpts)}\` 🚀\n\x1b[0m`); } /** - * This function applies string replacements on the bundled worker code necessary to get it to run in workerd - * - * Needless to say all the logic in this function is something we should avoid as much as possible! - * - * @param workerOutputFile - * @param config + * This function applies patches required for the code to run on workers. */ -async function updateWorkerBundledCode( - workerOutputFile: string, - config: Config, - openNextOptions: BuildOptions -): Promise { +async function updateWorkerBundledCode(workerOutputFile: string, buildOpts: BuildOptions): Promise { const code = await readFile(workerOutputFile, "utf8"); const patchedCode = await patchCodeWithValidations(code, [ ["require", patches.patchRequire], - ["`buildId` function", (code) => patches.patchBuildId(code, config)], - ["`loadManifest` function", (code) => patches.patchLoadManifest(code, config)], - ["next's require", (code) => patches.inlineNextRequire(code, config)], - ["`findDir` function", (code) => patches.patchFindDir(code, config)], - ["`evalManifest` function", (code) => patches.inlineEvalManifest(code, config)], - ["cacheHandler", (code) => patches.patchCache(code, openNextOptions)], + ["`buildId` function", (code) => patches.patchBuildId(code, buildOpts)], + ["`loadManifest` function", (code) => patches.patchLoadManifest(code, buildOpts)], + ["next's require", (code) => patches.inlineNextRequire(code, buildOpts)], + ["`findDir` function", (code) => patches.patchFindDir(code, buildOpts)], + ["`evalManifest` function", (code) => patches.inlineEvalManifest(code, buildOpts)], + ["cacheHandler", (code) => patches.patchCache(code, buildOpts)], [ "'require(this.middlewareManifestPath)'", - (code) => patches.inlineMiddlewareManifestRequire(code, config), + (code) => patches.inlineMiddlewareManifestRequire(code, buildOpts), ], ["exception bubbling", patches.patchExceptionBubbling], ["`loadInstrumentationModule` function", patches.patchLoadInstrumentationModule], @@ -180,12 +177,12 @@ async function updateWorkerBundledCode( const bundle = parse(Lang.TypeScript, patchedCode).root(); - const edits = patchOptionalDependencies(bundle); + const { edits } = patchOptionalDependencies(bundle); await writeFile(workerOutputFile, bundle.commitEdits(edits)); } -function createFixRequiresESBuildPlugin(config: Config): Plugin { +function createFixRequiresESBuildPlugin(options: BuildOptions): Plugin { return { name: "replaceRelative", setup(build) { @@ -193,7 +190,7 @@ function createFixRequiresESBuildPlugin(config: Config): Plugin { build.onResolve( { filter: getCrossPlatformPathRegex(String.raw`^\./require-hook$`, { escape: false }) }, () => ({ - path: path.join(config.paths.internal.templates, "shims", "empty.js"), + path: path.join(options.outputDir, "cloudflare-templates/shims/empty.js"), }) ); }, @@ -203,9 +200,9 @@ function createFixRequiresESBuildPlugin(config: Config): Plugin { /** * Gets the path of the worker.js file generated by the build process * - * @param openNextOptions the open-next build options + * @param buildOpts the open-next build options * @returns the path of the worker.js file that the build process generates */ -export function getOutputWorkerPath(openNextOptions: BuildOptions): string { - return path.join(openNextOptions.outputDir, "worker.js"); +export function getOutputWorkerPath(buildOpts: BuildOptions): string { + return path.join(buildOpts.outputDir, "worker.js"); } diff --git a/packages/cloudflare/src/cli/build/open-next/compile-env-files.ts b/packages/cloudflare/src/cli/build/open-next/compile-env-files.ts index 6d8a678a..cd35593e 100644 --- a/packages/cloudflare/src/cli/build/open-next/compile-env-files.ts +++ b/packages/cloudflare/src/cli/build/open-next/compile-env-files.ts @@ -8,11 +8,11 @@ import { extractProjectEnvVars } from "../utils/index.js"; /** * Compiles the values extracted from the project's env files to the output directory for use in the worker. */ -export function compileEnvFiles(options: BuildOptions) { +export function compileEnvFiles(buildOpts: BuildOptions) { ["production", "development", "test"].forEach((mode) => fs.appendFileSync( - path.join(options.outputDir, `.env.mjs`), - `export const ${mode} = ${JSON.stringify(extractProjectEnvVars(mode, options))};\n` + path.join(buildOpts.outputDir, `.env.mjs`), + `export const ${mode} = ${JSON.stringify(extractProjectEnvVars(mode, buildOpts))};\n` ) ); } diff --git a/packages/cloudflare/src/cli/build/patches/ast/optional-deps.ts b/packages/cloudflare/src/cli/build/patches/ast/optional-deps.ts index 9a6f0b8b..9ca7be80 100644 --- a/packages/cloudflare/src/cli/build/patches/ast/optional-deps.ts +++ b/packages/cloudflare/src/cli/build/patches/ast/optional-deps.ts @@ -1,6 +1,6 @@ import { type SgNode } from "@ast-grep/napi"; -import { getRuleEdits } from "./util.js"; +import { applyRule } from "./util.js"; /** * Handle optional dependencies. @@ -31,5 +31,5 @@ fix: |- `; export function patchOptionalDependencies(root: SgNode) { - return getRuleEdits(optionalDepRule, root); + return applyRule(optionalDepRule, root); } diff --git a/packages/cloudflare/src/cli/build/patches/ast/util.ts b/packages/cloudflare/src/cli/build/patches/ast/util.ts index 30392770..404964f7 100644 --- a/packages/cloudflare/src/cli/build/patches/ast/util.ts +++ b/packages/cloudflare/src/cli/build/patches/ast/util.ts @@ -1,3 +1,5 @@ +import { readFileSync } from "node:fs"; + import { type Edit, Lang, type NapiConfig, parse, type SgNode } from "@ast-grep/napi"; import yaml from "yaml"; @@ -8,7 +10,7 @@ import yaml from "yaml"; export type RuleConfig = NapiConfig & { fix?: string }; /** - * Returns the `Edit`s for an ast-grep rule in yaml format + * Returns the `Edit`s and `Match`es for an ast-grep rule in yaml format * * The rule must have a `fix` to rewrite the matched node. * @@ -17,9 +19,9 @@ export type RuleConfig = NapiConfig & { fix?: string }; * @param rule The rule. Either a yaml string or an instance of `RuleConfig` * @param root The root node * @param once only apply once - * @returns A list of edits. + * @returns A list of edits and a list of matches. */ -export function getRuleEdits(rule: string | RuleConfig, root: SgNode, { once = false } = {}) { +export function applyRule(rule: string | RuleConfig, root: SgNode, { once = false } = {}) { const ruleConfig: RuleConfig = typeof rule === "string" ? yaml.parse(rule) : rule; if (ruleConfig.transform) { throw new Error("transform is not supported"); @@ -50,7 +52,18 @@ export function getRuleEdits(rule: string | RuleConfig, root: SgNode, { once = f ); }); - return edits; + return { edits, matches }; +} + +/** + * Parse a file and obtain its root. + * + * @param path The file path + * @param lang The language to parse. Defaults to TypeScript. + * @returns The root for the file. + */ +export function parseFile(path: string, lang = Lang.TypeScript) { + return parse(lang, readFileSync(path, { encoding: "utf-8" })).root(); } /** @@ -71,6 +84,6 @@ export function patchCode( { lang = Lang.TypeScript, once = false } = {} ): string { const node = parse(lang, code).root(); - const edits = getRuleEdits(rule, node, { once }); + const { edits } = applyRule(rule, node, { once }); return node.commitEdits(edits); } diff --git a/packages/cloudflare/src/cli/build/patches/ast/vercel-og.spec.ts b/packages/cloudflare/src/cli/build/patches/ast/vercel-og.spec.ts new file mode 100644 index 00000000..8c65fbbd --- /dev/null +++ b/packages/cloudflare/src/cli/build/patches/ast/vercel-og.spec.ts @@ -0,0 +1,27 @@ +import { describe, expect, it } from "vitest"; + +import { patchCode } from "./util"; +import { vercelOgFallbackFontRule, vercelOgImportRule } from "./vercel-og"; + +describe("vercelOgImportRule", () => { + it("should rewrite a node import to an edge import", () => { + const code = `e.exports=import("next/dist/compiled/@vercel/og/index.node.js")`; + expect(patchCode(code, vercelOgImportRule)).toMatchInlineSnapshot( + `"e.exports=import("next/dist/compiled/@vercel/og/index.edge.js")"` + ); + }); +}); + +describe("vercelOgFallbackFontRule", () => { + it("should replace a fetch call for a font with an import", () => { + const code = `var fallbackFont = fetch(new URL("./noto-sans-v27-latin-regular.ttf", import.meta.url)).then((res) => res.arrayBuffer());`; + expect(patchCode(code, vercelOgFallbackFontRule)).toMatchInlineSnapshot(` + "async function getFallbackFont() { + // .bin is used so that a loader does not need to be configured for .ttf files + return (await import("./noto-sans-v27-latin-regular.ttf.bin")).default; + } + + var fallbackFont = getFallbackFont();" + `); + }); +}); diff --git a/packages/cloudflare/src/cli/build/patches/ast/vercel-og.ts b/packages/cloudflare/src/cli/build/patches/ast/vercel-og.ts new file mode 100644 index 00000000..e2bbf20c --- /dev/null +++ b/packages/cloudflare/src/cli/build/patches/ast/vercel-og.ts @@ -0,0 +1,64 @@ +import { SgNode } from "@ast-grep/napi"; + +import { applyRule } from "./util.js"; + +export const vercelOgImportRule = ` +rule: + pattern: $NODE + kind: string + regex: "next/dist/compiled/@vercel/og/index\\\\.node\\\\.js" +inside: + kind: arguments + inside: + kind: call_expression + stopBy: end + has: + field: function + regex: "import" + +fix: |- + "next/dist/compiled/@vercel/og/index.edge.js" +`; + +/** + * Patches Node.js imports for the library to be Edge imports. + * + * @param root Root node. + * @returns Results of applying the rule. + */ +export function patchVercelOgImport(root: SgNode) { + return applyRule(vercelOgImportRule, root); +} + +export const vercelOgFallbackFontRule = ` +rule: + kind: variable_declaration + all: + - has: + kind: variable_declarator + has: + kind: identifier + regex: ^fallbackFont$ + - has: + kind: call_expression + pattern: fetch(new URL("$PATH", $$$REST)) + stopBy: end + +fix: |- + async function getFallbackFont() { + // .bin is used so that a loader does not need to be configured for .ttf files + return (await import("$PATH.bin")).default; + } + + var fallbackFont = getFallbackFont(); +`; + +/** + * Patches the default font fetching to use a .bin import. + * + * @param root Root node. + * @returns Results of applying the rule. + */ +export function patchVercelOgFallbackFont(root: SgNode) { + return applyRule(vercelOgFallbackFontRule, root); +} diff --git a/packages/cloudflare/src/cli/build/patches/investigated/copy-package-cli-files.ts b/packages/cloudflare/src/cli/build/patches/investigated/copy-package-cli-files.ts index e0cb6931..263b480f 100644 --- a/packages/cloudflare/src/cli/build/patches/investigated/copy-package-cli-files.ts +++ b/packages/cloudflare/src/cli/build/patches/investigated/copy-package-cli-files.ts @@ -3,21 +3,21 @@ import path from "node:path"; import type { BuildOptions } from "@opennextjs/aws/build/helper.js"; -import { Config } from "../../../config.js"; import { getOutputWorkerPath } from "../../bundle-server.js"; /** - * Copies the template files present in the cloudflare adapter package into the standalone node_modules folder + * Copies + * - the template files present in the cloudflare adapter package to `.open-next/cloudflare-templates` + * - `worker.js` to `.open-next/` */ -export function copyPackageCliFiles(packageDistDir: string, config: Config, openNextOptions: BuildOptions) { +export function copyPackageCliFiles(packageDistDir: string, buildOpts: BuildOptions) { console.log("# copyPackageTemplateFiles"); - const sourceDir = path.join(packageDistDir, "cli"); - const destinationDir = path.join(config.paths.internal.package, "cli"); + const sourceDir = path.join(packageDistDir, "cli/templates"); + const destinationDir = path.join(buildOpts.outputDir, "cloudflare-templates"); + + fs.mkdirSync(destinationDir, { recursive: true }); fs.cpSync(sourceDir, destinationDir, { recursive: true }); - fs.copyFileSync( - path.join(packageDistDir, "cli", "templates", "worker.js"), - getOutputWorkerPath(openNextOptions) - ); + fs.copyFileSync(path.join(packageDistDir, "cli/templates/worker.js"), getOutputWorkerPath(buildOpts)); } diff --git a/packages/cloudflare/src/cli/build/patches/investigated/index.ts b/packages/cloudflare/src/cli/build/patches/investigated/index.ts index 9d46a4d8..55f1684f 100644 --- a/packages/cloudflare/src/cli/build/patches/investigated/index.ts +++ b/packages/cloudflare/src/cli/build/patches/investigated/index.ts @@ -1,4 +1,5 @@ export * from "./copy-package-cli-files.js"; export * from "./patch-cache.js"; export * from "./patch-require.js"; +export * from "./patch-vercel-og-library.js"; export * from "./update-webpack-chunks-file/index.js"; diff --git a/packages/cloudflare/src/cli/build/patches/investigated/patch-cache.ts b/packages/cloudflare/src/cli/build/patches/investigated/patch-cache.ts index 58bf16f1..4e66ab3f 100644 --- a/packages/cloudflare/src/cli/build/patches/investigated/patch-cache.ts +++ b/packages/cloudflare/src/cli/build/patches/investigated/patch-cache.ts @@ -1,6 +1,6 @@ import path from "node:path"; -import type { BuildOptions } from "@opennextjs/aws/build/helper.js"; +import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js"; import { normalizePath } from "../../utils/index.js"; @@ -15,17 +15,17 @@ import { normalizePath } from "../../utils/index.js"; * build-time. Therefore, we have to manually override the default way that the cache handler is * instantiated with a dynamic require that uses a string literal for the path. */ -export async function patchCache(code: string, openNextOptions: BuildOptions): Promise { - const { appBuildOutputPath, outputDir, monorepoRoot } = openNextOptions; +export async function patchCache(code: string, buildOpts: BuildOptions): Promise { + const { outputDir } = buildOpts; // TODO: switch to cache.mjs - const outputPath = path.join(outputDir, "server-functions", "default"); - const packagePath = path.relative(monorepoRoot, appBuildOutputPath); - const cacheFile = path.join(outputPath, packagePath, "cache.cjs"); + const outputPath = path.join(outputDir, "server-functions/default"); + const cacheFile = path.join(outputPath, getPackagePath(buildOpts), "cache.cjs"); return code.replace( "const { cacheHandler } = this.nextConfig;", - `const cacheHandler = null; + ` +const cacheHandler = null; CacheHandler = require('${normalizePath(cacheFile)}').default; ` ); diff --git a/packages/cloudflare/src/cli/build/patches/investigated/patch-require.ts b/packages/cloudflare/src/cli/build/patches/investigated/patch-require.ts index 12f40160..d86ff3a9 100644 --- a/packages/cloudflare/src/cli/build/patches/investigated/patch-require.ts +++ b/packages/cloudflare/src/cli/build/patches/investigated/patch-require.ts @@ -1,8 +1,5 @@ /** - * ESBuild does not support CJS format - * See https://github.com/evanw/esbuild/issues/1921 and linked issues - * Some of the solutions are based on `module.createRequire()` not implemented in workerd. - * James on Aug 29: `module.createRequire()` is planned. + * Replaces webpack `__require` with actual `require` */ export function patchRequire(code: string): string { return code.replace(/__require\d?\(/g, "require(").replace(/__require\d?\./g, "require."); diff --git a/packages/cloudflare/src/cli/build/patches/investigated/patch-vercel-og-library.spec.ts b/packages/cloudflare/src/cli/build/patches/investigated/patch-vercel-og-library.spec.ts new file mode 100644 index 00000000..51d09584 --- /dev/null +++ b/packages/cloudflare/src/cli/build/patches/investigated/patch-vercel-og-library.spec.ts @@ -0,0 +1,71 @@ +import { mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs"; +import path from "node:path"; + +import { BuildOptions } from "@opennextjs/aws/build/helper.js"; +import mockFs from "mock-fs"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; + +import { patchVercelOgLibrary } from "./patch-vercel-og-library"; + +const nodeModulesVercelOgDir = "node_modules/.pnpm/next@14.2.11/node_modules/next/dist/compiled/@vercel/og"; +const nextServerOgNftPath = "examples/api/.next/server/app/og/route.js.nft.json"; +const openNextFunctionDir = "examples/api/.open-next/server-functions/default/examples/api"; +const openNextOgRoutePath = path.join(openNextFunctionDir, ".next/server/app/og/route.js"); +const openNextVercelOgDir = path.join(openNextFunctionDir, "node_modules/next/dist/compiled/@vercel/og"); + +const buildOpts = { + appBuildOutputPath: "examples/api", + monorepoRoot: "", + outputDir: "examples/api/.open-next", +} as BuildOptions; + +describe("patchVercelOgLibrary", () => { + beforeAll(() => { + mockFs(); + + mkdirSync(nodeModulesVercelOgDir, { recursive: true }); + mkdirSync(path.dirname(nextServerOgNftPath), { recursive: true }); + mkdirSync(path.dirname(openNextOgRoutePath), { recursive: true }); + mkdirSync(openNextVercelOgDir, { recursive: true }); + + writeFileSync( + nextServerOgNftPath, + JSON.stringify({ version: 1, files: [`../../../../../../${nodeModulesVercelOgDir}/index.node.js`] }) + ); + writeFileSync( + path.join(nodeModulesVercelOgDir, "index.edge.js"), + `var fallbackFont = fetch(new URL("./noto-sans-v27-latin-regular.ttf", import.meta.url)).then((res) => res.arrayBuffer());` + ); + writeFileSync(openNextOgRoutePath, `e.exports=import("next/dist/compiled/@vercel/og/index.node.js")`); + writeFileSync(path.join(openNextVercelOgDir, "index.node.js"), ""); + writeFileSync(path.join(openNextVercelOgDir, "noto-sans-v27-latin-regular.ttf"), ""); + }); + + afterAll(() => mockFs.restore()); + + it("should patch the open-next files correctly", () => { + patchVercelOgLibrary(buildOpts); + + expect(readdirSync(openNextVercelOgDir)).toMatchInlineSnapshot(` + [ + "index.edge.js", + "index.node.js", + "noto-sans-v27-latin-regular.ttf.bin", + ] + `); + + expect(readFileSync(path.join(openNextVercelOgDir, "index.edge.js"), { encoding: "utf-8" })) + .toMatchInlineSnapshot(` + "async function getFallbackFont() { + // .bin is used so that a loader does not need to be configured for .ttf files + return (await import("./noto-sans-v27-latin-regular.ttf.bin")).default; + } + + var fallbackFont = getFallbackFont();" + `); + + expect(readFileSync(openNextOgRoutePath, { encoding: "utf-8" })).toMatchInlineSnapshot( + `"e.exports=import("next/dist/compiled/@vercel/og/index.edge.js")"` + ); + }); +}); diff --git a/packages/cloudflare/src/cli/build/patches/investigated/patch-vercel-og-library.ts b/packages/cloudflare/src/cli/build/patches/investigated/patch-vercel-og-library.ts new file mode 100644 index 00000000..63fdbfc0 --- /dev/null +++ b/packages/cloudflare/src/cli/build/patches/investigated/patch-vercel-og-library.ts @@ -0,0 +1,57 @@ +import { copyFileSync, existsSync, readFileSync, renameSync, writeFileSync } from "node:fs"; +import path from "node:path"; + +import type { BuildOptions } from "@opennextjs/aws/build/helper.js"; +import { getPackagePath } from "@opennextjs/aws/build/helper.js"; +import { globSync } from "glob"; + +import { parseFile } from "../ast/util.js"; +import { patchVercelOgFallbackFont, patchVercelOgImport } from "../ast/vercel-og.js"; + +type TraceInfo = { version: number; files: string[] }; + +/** + * Patches the usage of @vercel/og to be compatible with Cloudflare Workers. + * + * @param buildOpts Build options. + */ +export function patchVercelOgLibrary(buildOpts: BuildOptions) { + const { appBuildOutputPath, outputDir } = buildOpts; + + const packagePath = path.join(outputDir, "server-functions/default", getPackagePath(buildOpts)); + + for (const traceInfoPath of globSync(path.join(appBuildOutputPath, ".next/server/**/*.nft.json"))) { + const traceInfo: TraceInfo = JSON.parse(readFileSync(traceInfoPath, { encoding: "utf8" })); + const tracedNodePath = traceInfo.files.find((p) => p.endsWith("@vercel/og/index.node.js")); + + if (!tracedNodePath) continue; + + const outputDir = path.join(packagePath, "node_modules/next/dist/compiled/@vercel/og"); + const outputEdgePath = path.join(outputDir, "index.edge.js"); + + // Ensure the edge version is available in the OpenNext node_modules. + if (!existsSync(outputEdgePath)) { + const tracedEdgePath = path.join( + path.dirname(traceInfoPath), + tracedNodePath.replace("index.node.js", "index.edge.js") + ); + + copyFileSync(tracedEdgePath, outputEdgePath); + + // Change font fetches in the library to use imports. + const node = parseFile(outputEdgePath); + const { edits, matches } = patchVercelOgFallbackFont(node); + writeFileSync(outputEdgePath, node.commitEdits(edits)); + + const fontFileName = matches[0]!.getMatch("PATH")!.text(); + renameSync(path.join(outputDir, fontFileName), path.join(outputDir, `${fontFileName}.bin`)); + } + + // Change node imports for the library to edge imports. + const routeFilePath = traceInfoPath.replace(appBuildOutputPath, packagePath).replace(".nft.json", ""); + + const node = parseFile(routeFilePath); + const { edits } = patchVercelOgImport(node); + writeFileSync(routeFilePath, node.commitEdits(edits)); + } +} diff --git a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/index.ts b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/index.ts index 38464a52..e4e057d4 100644 --- a/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/index.ts +++ b/packages/cloudflare/src/cli/build/patches/investigated/update-webpack-chunks-file/index.ts @@ -1,22 +1,30 @@ import { readdirSync, readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import { Config } from "../../../../config.js"; +import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js"; + import { getUpdatedWebpackChunksFileContent } from "./get-updated-webpack-chunks-file-content.js"; /** * Fixes the webpack-runtime.js file by removing its webpack dynamic requires. - * - * This hack is particularly bad as it indicates that files inside the output directory still get a hold of files from the outside: `${nextjsAppPaths.standaloneAppServerDir}/webpack-runtime.js` - * so this shows that not everything that's needed to deploy the application is in the output directory... */ -export async function updateWebpackChunksFile(config: Config) { +export async function updateWebpackChunksFile(buildOpts: BuildOptions) { console.log("# updateWebpackChunksFile"); - const webpackRuntimeFile = join(config.paths.output.standaloneAppServer, "webpack-runtime.js"); + + const { outputDir } = buildOpts; + + const dotNextServerDir = join( + outputDir, + "server-functions/default", + getPackagePath(buildOpts), + ".next/server" + ); + + const webpackRuntimeFile = join(dotNextServerDir, "webpack-runtime.js"); const fileContent = readFileSync(webpackRuntimeFile, "utf-8"); - const chunks = readdirSync(join(config.paths.output.standaloneAppServer, "chunks")) + const chunks = readdirSync(join(dotNextServerDir, "chunks")) .filter((chunk) => /^\d+\.js$/.test(chunk)) .map((chunk) => { console.log(` - chunk ${chunk}`); diff --git a/packages/cloudflare/src/cli/build/patches/to-investigate/inline-eval-manifest.ts b/packages/cloudflare/src/cli/build/patches/to-investigate/inline-eval-manifest.ts index 510b0ce7..b0f34ce0 100644 --- a/packages/cloudflare/src/cli/build/patches/to-investigate/inline-eval-manifest.ts +++ b/packages/cloudflare/src/cli/build/patches/to-investigate/inline-eval-manifest.ts @@ -1,8 +1,8 @@ -import { join, posix } from "node:path"; +import { join, relative } from "node:path"; +import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js"; import { globSync } from "glob"; -import { Config } from "../../../config.js"; import { normalizePath } from "../../utils/index.js"; /** @@ -12,32 +12,35 @@ import { normalizePath } from "../../utils/index.js"; * Note: we could/should probably just patch readFileSync here or something, but here the issue is that after the readFileSync call * there is a vm `runInNewContext` call which we also don't support (source: https://github.com/vercel/next.js/blob/b1e32c5d1f/packages/next/src/server/load-manifest.ts#L88) */ -export function inlineEvalManifest(code: string, config: Config): string { - const manifestJss = globSync( - normalizePath(join(config.paths.output.standaloneAppDotNext, "**/*_client-reference-manifest.js")) - ).map((file) => - normalizePath(file).replace(normalizePath(config.paths.output.standaloneApp) + posix.sep, "") - ); +export function inlineEvalManifest(code: string, buildOpts: BuildOptions): string { + const { outputDir } = buildOpts; + + const baseDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next"); + const appDir = join(baseDir, "server/app"); + + const manifests = globSync(join(baseDir, "**/*_client-reference-manifest.js")); + return code.replace( /function evalManifest\((.+?), .+?\) {/, `$& - ${manifestJss - .map( - (manifestJs) => ` - if ($1.endsWith("${manifestJs}")) { - require(${JSON.stringify(join(config.paths.output.standaloneApp, manifestJs))}); - return { - __RSC_MANIFEST: { - "${manifestJs - .replace(".next/server/app", "") - .replace("_client-reference-manifest.js", "")}": globalThis.__RSC_MANIFEST["${manifestJs - .replace(".next/server/app", "") - .replace("_client-reference-manifest.js", "")}"], - }, - }; + ${manifests + .map((manifest) => { + const endsWith = normalizePath(relative(baseDir, manifest)); + const key = normalizePath("/" + relative(appDir, manifest)).replace( + "_client-reference-manifest.js", + "" + ); + return ` + if ($1.endsWith("${endsWith}")) { + require(${JSON.stringify(manifest)}); + return { + __RSC_MANIFEST: { + "${key}": globalThis.__RSC_MANIFEST["${key}"], + }, + }; } - ` - ) + `; + }) .join("\n")} throw new Error("Unknown evalManifest: " + $1); ` diff --git a/packages/cloudflare/src/cli/build/patches/to-investigate/inline-middleware-manifest-require.ts b/packages/cloudflare/src/cli/build/patches/to-investigate/inline-middleware-manifest-require.ts index 8e25afd2..0874c2c6 100644 --- a/packages/cloudflare/src/cli/build/patches/to-investigate/inline-middleware-manifest-require.ts +++ b/packages/cloudflare/src/cli/build/patches/to-investigate/inline-middleware-manifest-require.ts @@ -1,14 +1,21 @@ import { existsSync, readFileSync } from "node:fs"; import { join } from "node:path"; -import { Config } from "../../../config.js"; +import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js"; /** * Inlines the middleware manifest from the build output to prevent a dynamic require statement * as they result in runtime failures. */ -export function inlineMiddlewareManifestRequire(code: string, config: Config) { - const middlewareManifestPath = join(config.paths.output.standaloneAppServer, "middleware-manifest.json"); +export function inlineMiddlewareManifestRequire(code: string, buildOpts: BuildOptions) { + const { outputDir } = buildOpts; + + const middlewareManifestPath = join( + outputDir, + "server-functions/default", + getPackagePath(buildOpts), + ".next/server/middleware-manifest.json" + ); const middlewareManifest = existsSync(middlewareManifestPath) ? JSON.parse(readFileSync(middlewareManifestPath, "utf-8")) diff --git a/packages/cloudflare/src/cli/build/patches/to-investigate/inline-next-require.ts b/packages/cloudflare/src/cli/build/patches/to-investigate/inline-next-require.ts index 6e92f909..ab45ec3e 100644 --- a/packages/cloudflare/src/cli/build/patches/to-investigate/inline-next-require.ts +++ b/packages/cloudflare/src/cli/build/patches/to-investigate/inline-next-require.ts @@ -1,30 +1,30 @@ import { existsSync, readFileSync } from "node:fs"; import { join } from "node:path"; -import { Config } from "../../../config.js"; +import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js"; /** * The following avoid various Next.js specific files `require`d at runtime since we can just read * and inline their content during build time */ -export function inlineNextRequire(code: string, config: Config) { - const pagesManifestFile = join(config.paths.output.standaloneAppServer, "pages-manifest.json"); - const appPathsManifestFile = join(config.paths.output.standaloneAppServer, "app-paths-manifest.json"); +// TODO(vicb): __NEXT_PRIVATE_RUNTIME_TYPE is not handled by this patch +export function inlineNextRequire(code: string, buildOpts: BuildOptions) { + const { outputDir } = buildOpts; + const serverDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next/server"); - const pagesManifestFiles = existsSync(pagesManifestFile) - ? Object.values(JSON.parse(readFileSync(pagesManifestFile, "utf-8"))).map( - (file) => ".next/server/" + file - ) + const pagesManifestFile = join(serverDir, "pages-manifest.json"); + const appPathsManifestFile = join(serverDir, "app-paths-manifest.json"); + + const pagesManifests: string[] = existsSync(pagesManifestFile) + ? Object.values(JSON.parse(readFileSync(pagesManifestFile, "utf-8"))) : []; - const appPathsManifestFiles = existsSync(appPathsManifestFile) - ? Object.values(JSON.parse(readFileSync(appPathsManifestFile, "utf-8"))).map( - (file) => ".next/server/" + file - ) + const appPathsManifests: string[] = existsSync(appPathsManifestFile) + ? Object.values(JSON.parse(readFileSync(appPathsManifestFile, "utf-8"))) : []; - const allManifestFiles = pagesManifestFiles.concat(appPathsManifestFiles); + const manifests = pagesManifests.concat(appPathsManifests); - const htmlPages = allManifestFiles.filter((file) => file.endsWith(".html")); - const pageModules = allManifestFiles.filter((file) => file.endsWith(".js")); + const htmlPages = manifests.filter((file) => file.endsWith(".html")); + const pageModules = manifests.filter((file) => file.endsWith(".js")); return code.replace( /const pagePath = getPagePath\(.+?\);/, @@ -33,7 +33,7 @@ export function inlineNextRequire(code: string, config: Config) { .map( (htmlPage) => ` if (pagePath.endsWith("${htmlPage}")) { - return ${JSON.stringify(readFileSync(join(config.paths.output.standaloneApp, htmlPage), "utf-8"))}; + return ${JSON.stringify(readFileSync(join(serverDir, htmlPage), "utf-8"))}; } ` ) @@ -42,7 +42,7 @@ export function inlineNextRequire(code: string, config: Config) { .map( (module) => ` if (pagePath.endsWith("${module}")) { - return require(${JSON.stringify(join(config.paths.output.standaloneApp, module))}); + return require(${JSON.stringify(join(serverDir, module))}); } ` ) diff --git a/packages/cloudflare/src/cli/build/patches/to-investigate/patch-find-dir.ts b/packages/cloudflare/src/cli/build/patches/to-investigate/patch-find-dir.ts index 471b8fa9..d7f22a4f 100644 --- a/packages/cloudflare/src/cli/build/patches/to-investigate/patch-find-dir.ts +++ b/packages/cloudflare/src/cli/build/patches/to-investigate/patch-find-dir.ts @@ -1,25 +1,26 @@ import { existsSync } from "node:fs"; import { join } from "node:path"; -import { Config } from "../../../config.js"; +import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js"; /** - * Here we patch `findDir` so that the next server can detect whether the `app` or `pages` directory exists - * (source: https://github.com/vercel/next.js/blob/ba995993/packages/next/src/lib/find-pages-dir.ts#L4-L13) - * (usage source: https://github.com/vercel/next.js/blob/ba995993/packages/next/src/server/next-server.ts#L450-L451) - * Note: `findDir` uses `fs.existsSync` under the hood, so patching that should be enough to make this work + * Patches `findDir` so that the next server can detect whether the `app` or `pages` directory exists */ -export function patchFindDir(code: string, config: Config): string { +export function patchFindDir(code: string, buildOpts: BuildOptions): string { + const { outputDir } = buildOpts; + + const baseDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts), ".next/server"); + return code.replace( /function findDir\((?dir\d*), (?name\d*)\) {/, `function findDir($dir, $name) { if ($dir.endsWith(".next/server")) { - if ($name === "app") { - return ${existsSync(`${join(config.paths.output.standaloneAppServer, "app")}`)}; - } - if ($name === "pages") { - return ${existsSync(`${join(config.paths.output.standaloneAppServer, "pages")}`)}; - } + if ($name === "app") { + return ${existsSync(`${join(baseDir, "app")}`)}; + } + if ($name === "pages") { + return ${existsSync(`${join(baseDir, "pages")}`)}; + } } throw new Error("Unknown findDir call: " + $dir + " " + $name); ` diff --git a/packages/cloudflare/src/cli/build/patches/to-investigate/patch-read-file.ts b/packages/cloudflare/src/cli/build/patches/to-investigate/patch-read-file.ts index 6a2dd368..83ba4cf2 100644 --- a/packages/cloudflare/src/cli/build/patches/to-investigate/patch-read-file.ts +++ b/packages/cloudflare/src/cli/build/patches/to-investigate/patch-read-file.ts @@ -1,41 +1,39 @@ import { readFileSync } from "node:fs"; -import { join, posix } from "node:path"; +import { join, relative } from "node:path"; +import { type BuildOptions, getBuildId, getPackagePath } from "@opennextjs/aws/build/helper.js"; import { globSync } from "glob"; -import { Config } from "../../../config.js"; import { normalizePath } from "../../utils/index.js"; -export function patchBuildId(code: string, config: Config): string { - // The next-server code gets the buildId from the filesystem, resulting in a `[unenv] fs.readFileSync is not implemented yet!` error - // so we add an early return to the `getBuildId` function so that the `readyFileSync` is never encountered - // (source: https://github.com/vercel/next.js/blob/15aeb92efb34c09a36/packages/next/src/server/next-server.ts#L438-L451) - // Note: we could/should probably just patch readFileSync here or something! +export function patchBuildId(code: string, buildOpts: BuildOptions): string { + // The Next code gets the buildId from the filesystem so we hardcode the value at build time. return code.replace( "getBuildId() {", `getBuildId() { - return ${JSON.stringify(readFileSync(join(config.paths.output.standaloneAppDotNext, "BUILD_ID"), "utf-8"))}; + return ${JSON.stringify(getBuildId(buildOpts))}; ` ); } -export function patchLoadManifest(code: string, config: Config): string { - // Same as patchBuildId, the next-server code loads the manifests with `readFileSync` and we want to avoid that - // (source: https://github.com/vercel/next.js/blob/15aeb92e/packages/next/src/server/load-manifest.ts#L34-L56) - // Note: we could/should probably just patch readFileSync here or something! - const manifestJsons = globSync( - normalizePath(join(config.paths.output.standaloneAppDotNext, "**/*-manifest.json")) - ).map((file) => - normalizePath(file).replace(normalizePath(config.paths.output.standaloneApp) + posix.sep, "") - ); +export function patchLoadManifest(code: string, buildOpts: BuildOptions): string { + // Inline manifest that Next would otherwise retrieve from the file system. + + const { outputDir } = buildOpts; + + const baseDir = join(outputDir, "server-functions/default", getPackagePath(buildOpts)); + const dotNextDir = join(baseDir, ".next"); + + const manifests = globSync(join(dotNextDir, "**/*-manifest.json")); + return code.replace( /function loadManifest\((.+?), .+?\) {/, `$& - ${manifestJsons + ${manifests .map( - (manifestJson) => ` - if ($1.endsWith("${manifestJson}")) { - return ${readFileSync(join(config.paths.output.standaloneApp, manifestJson), "utf-8")}; + (manifest) => ` + if ($1.endsWith("${normalizePath("/" + relative(dotNextDir, manifest))}")) { + return ${readFileSync(manifest, "utf-8")}; } ` ) diff --git a/packages/cloudflare/src/cli/build/patches/to-investigate/wrangler-deps.ts b/packages/cloudflare/src/cli/build/patches/to-investigate/wrangler-deps.ts index f12b9dce..466895f2 100644 --- a/packages/cloudflare/src/cli/build/patches/to-investigate/wrangler-deps.ts +++ b/packages/cloudflare/src/cli/build/patches/to-investigate/wrangler-deps.ts @@ -1,44 +1,45 @@ -import { readFileSync, statSync, writeFileSync } from "node:fs"; +import { readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; +import { type BuildOptions, getPackagePath } from "@opennextjs/aws/build/helper.js"; import * as ts from "ts-morph"; -import { Config } from "../../../config.js"; import { tsParseFile } from "../../utils/index.js"; -export function patchWranglerDeps(config: Config) { +export function patchWranglerDeps(buildOpts: BuildOptions) { console.log("# patchWranglerDeps"); - const distPath = getDistPath(config); - // Patch .next/standalone/node_modules/next/dist/compiled/next-server/pages.runtime.prod.js - // - // Remove the need for an alias in wrangler.toml: - // - // [alias] - // # critters is `require`d from `pages.runtime.prod.js` when running wrangler dev, so we need to stub it out - // "critters" = "./.next/standalone/node_modules/cf/templates/shims/empty.ts" - const pagesRuntimeFile = join(distPath, "compiled/next-server/pages.runtime.prod.js"); + const { outputDir } = buildOpts; + + const nextDistDir = join( + outputDir, + "server-functions/default", + getPackagePath(buildOpts), + "node_modules/next/dist" + ); + + const pagesRuntimeFile = join(nextDistDir, "compiled/next-server/pages.runtime.prod.js"); const patchedPagesRuntime = readFileSync(pagesRuntimeFile, "utf-8").replace( `e.exports=require("critters")`, - `e.exports={}` + ` +try { + e.exports=require("critters"); +} +catch { + console.error('critters is not installed'); +} +` ); writeFileSync(pagesRuntimeFile, patchedPagesRuntime); - patchRequireReactDomServerEdge(config); + patchRequireReactDomServerEdge(nextDistDir); - // Patch .next/standalone/node_modules/next/dist/server/lib/trace/tracer.js - // - // Remove the need for an alias in wrangler.toml: - // - // [alias] - // # @opentelemetry/api is `require`d when running wrangler dev, so we need to stub it out - // # IMPORTANT: we shim @opentelemetry/api to the throwing shim so that it will throw right away, this is so that we throw inside the - // # try block here: https://github.com/vercel/next.js/blob/9e8266a7/packages/next/src/server/lib/trace/tracer.ts#L27-L31 - // # causing the code to require the 'next/dist/compiled/@opentelemetry/api' module instead (which properly works) - // #"@opentelemetry/api" = "./.next/standalone/node_modules/cf/templates/shims/throw.ts" - const tracerFile = join(distPath, "server/lib/trace/tracer.js"); + // we shim @opentelemetry/api to the throwing shim so that it will throw right away, this is so that we throw inside the + // try block here: https://github.com/vercel/next.js/blob/9e8266a7/packages/next/src/server/lib/trace/tracer.ts#L27-L31 + // causing the code to require the 'next/dist/compiled/@opentelemetry/api' module instead (which properly works) + const tracerFile = join(nextDistDir, "server/lib/trace/tracer.js"); const patchedTracer = readFileSync(tracerFile, "utf-8").replaceAll( /\w+\s*=\s*require\([^/]*opentelemetry.*\)/g, @@ -48,31 +49,6 @@ export function patchWranglerDeps(config: Config) { writeFileSync(tracerFile, patchedTracer); } -/** - * Next.js saves the node_modules/next/dist directory in either the standaloneApp path or in the - * standaloneRoot path, this depends on where the next dependency is actually saved ( - * https://github.com/vercel/next.js/blob/39e06c75/packages/next/src/build/webpack-config.ts#L103-L104 - * ) and can depend on the package manager used, if it is using workspaces, etc... - * - * This function checks the two potential paths for the dist directory and returns the first that it finds, - * it throws an error if it can't find either - * - * @param config - * @returns the node_modules/next/dist directory path - */ -function getDistPath(config: Config): string { - for (const root of [config.paths.output.standaloneApp, config.paths.output.standaloneRoot]) { - try { - const distPath = join(root, "node_modules/next/dist"); - if (statSync(distPath).isDirectory()) return distPath; - } catch { - /* empty */ - } - } - - throw new Error("Unexpected error: unable to detect the node_modules/next/dist directory"); -} - /** * `react-dom` v>=19 has a `server.edge` export: https://github.com/facebook/react/blob/a160102f3/packages/react-dom/package.json#L79 * but version of `react-dom` <= 18 do not have this export but have a `server.browser` export instead: https://github.com/facebook/react/blob/8a015b68/packages/react-dom/package.json#L49 @@ -88,11 +64,9 @@ function getDistPath(config: Config): string { * it's not clear what code and how might be rely on this require call) * */ -function patchRequireReactDomServerEdge(config: Config) { - const distPath = getDistPath(config); - +function patchRequireReactDomServerEdge(nextDistDir: string) { // Patch .next/standalone/node_modules/next/dist/compiled/next-server/pages.runtime.prod.js - const pagesRuntimeFile = join(distPath, "compiled/next-server/pages.runtime.prod.js"); + const pagesRuntimeFile = join(nextDistDir, "compiled/next-server/pages.runtime.prod.js"); const code = readFileSync(pagesRuntimeFile, "utf-8"); const file = tsParseFile(code); @@ -166,24 +140,22 @@ function patchRequireReactDomServerEdge(config: Config) { return; } - arrowFunction.setBodyText( - ` - "use strict"; - let ReactDOMServer; - try { - ReactDOMServer = require('react-dom/server.edge'); - } catch (error) { - if ( - error.code !== 'MODULE_NOT_FOUND' && - error.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED' - ) { - throw error; - } - ReactDOMServer = require('react-dom/server.browser'); - } - ${parameterName}.exports = ReactDOMServer; - `.replace(/\ns*/g, " ") - ); + arrowFunction.setBodyText(` +// OpenNext patch +let ReactDOMServer; +try { + ReactDOMServer = require('react-dom/server.edge'); +} catch (error) { + if ( + error.code !== 'MODULE_NOT_FOUND' && + error.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED' + ) { + throw error; + } + ReactDOMServer = require('react-dom/server.browser'); +} +${parameterName}.exports = ReactDOMServer; +`); }); const updatedCode = file.print(); diff --git a/packages/cloudflare/src/cli/build/utils/create-config-files.ts b/packages/cloudflare/src/cli/build/utils/create-config-files.ts index 96d176d5..d7a9068f 100644 --- a/packages/cloudflare/src/cli/build/utils/create-config-files.ts +++ b/packages/cloudflare/src/cli/build/utils/create-config-files.ts @@ -2,7 +2,7 @@ import { cpSync, existsSync, readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { getPackageTemplatesDirPath } from "../../../utils/get-package-templates-dir-path.js"; -import type { ProjectOptions } from "../../config.js"; +import type { ProjectOptions } from "../../project-options.js"; import { askConfirmation } from "../../utils/ask-confirmation.js"; /** diff --git a/packages/cloudflare/src/cli/config.ts b/packages/cloudflare/src/cli/config.ts deleted file mode 100644 index 7b683c5b..00000000 --- a/packages/cloudflare/src/cli/config.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { readdirSync, statSync } from "node:fs"; -import { join, relative } from "node:path"; - -const PACKAGE_NAME = "@opennextjs/cloudflare"; - -export type Config = { - build: { - // Whether to skip building the Next.js app or not - skipNextBuild: boolean; - // Whether minification should be enabled or not - shouldMinify: boolean; - }; - - paths: { - source: { - // Path to the next application - root: string; - // Path to the app's `.next` directory (where `next build` saves the build output) - dotNext: string; - // Path to the application standalone root directory - standaloneRoot: string; - }; - output: { - // Path to the output directory - root: string; - // Path to the OpenNext static assets directory - assets: string; - // Path to the app's `.next` directory in the OpenNext output directory - dotNext: string; - // Path to the application standalone root directory - standaloneRoot: string; - // Path to the application standalone directory (where `next build` saves the standalone app) - standaloneApp: string; - // Path to the `.next` directory specific to the standalone application - standaloneAppDotNext: string; - // Path to the `server` directory specific to the standalone application - standaloneAppServer: string; - }; - internal: { - // Package in the standalone node_modules - package: string; - // Templates in the package in the standalone node_modules - templates: string; - }; - }; - - // Internal name for the copy of the package - internalPackageName: string; -}; - -/** - * Computes the configuration. - * - * @param projectOpts The options for the project - * @returns The configuration, see `Config` - */ -export function getConfig(projectOpts: ProjectOptions): Config { - const sourceDirDotNext = join(projectOpts.sourceDir, ".next"); - - const dotNext = join(projectOpts.outputDir, ".next"); - const appPath = getNextjsApplicationPath(dotNext).replace(/\/$/, ""); - const standaloneRoot = join(dotNext, "standalone"); - const standaloneApp = join(standaloneRoot, appPath); - const standaloneAppDotNext = join(standaloneApp, ".next"); - const standaloneAppServer = join(standaloneAppDotNext, "server"); - - const nodeModules = join(standaloneApp, "node_modules"); - const internalPackage = join(nodeModules, ...PACKAGE_NAME.split("/")); - const internalTemplates = join(internalPackage, "cli/templates"); - - return { - build: { - skipNextBuild: projectOpts.skipNextBuild, - shouldMinify: projectOpts.minify, - }, - - paths: { - source: { - root: projectOpts.sourceDir, - dotNext: sourceDirDotNext, - standaloneRoot: join(sourceDirDotNext, "standalone"), - }, - output: { - root: projectOpts.outputDir, - assets: join(projectOpts.outputDir, "assets"), - dotNext, - standaloneRoot, - standaloneApp, - standaloneAppDotNext, - standaloneAppServer, - }, - internal: { - package: internalPackage, - templates: internalTemplates, - }, - }, - - internalPackageName: PACKAGE_NAME, - }; -} - -export function containsDotNextDir(folder: string): boolean { - try { - return statSync(join(folder, ".next")).isDirectory(); - } catch { - return false; - } -} - -export type ProjectOptions = { - // Next app root folder - sourceDir: string; - // The directory to save the output to (defaults to the app's directory) - outputDir: string; - // Whether the Next.js build should be skipped (i.e. if the `.next` dir is already built) - skipNextBuild: boolean; - // Whether the check to see if a wrangler config file exists should be skipped - skipWranglerConfigCheck: boolean; - // Whether minification of the worker should be enabled - minify: boolean; -}; - -/** - * It basically tries to find the path that the application is under inside the `.next/standalone` directory, using the `.next/server` directory - * presence as the condition that needs to be met. - * - * For example: - * When I build the api application the `.next/server` directory is located in: - * `/standalone/next-apps/api/.next/server` - * and the function here given the `dotNextDir` returns `next-apps/api` - */ -function getNextjsApplicationPath(dotNextDir: string): string { - const serverPath = findServerParentPath(dotNextDir); - - if (!serverPath) { - throw new Error(`Unexpected Error: no \`.next/server\` folder could be found in \`${serverPath}\``); - } - - return relative(join(dotNextDir, "standalone"), serverPath); -} - -function findServerParentPath(parentPath: string): string | undefined { - try { - if (statSync(join(parentPath, ".next/server")).isDirectory()) { - return parentPath; - } - } catch { - /* empty */ - } - - const folders = readdirSync(parentPath); - - for (const folder of folders) { - const subFolder = join(parentPath, folder); - if (statSync(join(parentPath, folder)).isDirectory()) { - const dirServerPath = findServerParentPath(subFolder); - if (dirServerPath) { - return dirServerPath; - } - } - } -} diff --git a/packages/cloudflare/src/cli/project-options.ts b/packages/cloudflare/src/cli/project-options.ts new file mode 100644 index 00000000..0ceb3d96 --- /dev/null +++ b/packages/cloudflare/src/cli/project-options.ts @@ -0,0 +1,12 @@ +export type ProjectOptions = { + // Next app root folder + sourceDir: string; + // The directory to save the output to (defaults to the app's directory) + outputDir: string; + // Whether the Next.js build should be skipped (i.e. if the `.next` dir is already built) + skipNextBuild: boolean; + // Whether the check to see if a wrangler config file exists should be skipped + skipWranglerConfigCheck: boolean; + // Whether minification of the worker should be enabled + minify: boolean; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eac18364..556549f1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -449,8 +449,8 @@ importers: specifier: 'catalog:' version: 1.31.0 '@opennextjs/aws': - specifier: https://pkg.pr.new/@opennextjs/aws@704 - version: https://pkg.pr.new/@opennextjs/aws@704 + specifier: https://pkg.pr.new/@opennextjs/aws@712 + version: https://pkg.pr.new/@opennextjs/aws@712 enquirer: specifier: ^2.4.1 version: 2.4.1 @@ -2200,9 +2200,9 @@ packages: '@octokit/types@13.6.1': resolution: {integrity: sha512-PHZE9Z+kWXb23Ndik8MKPirBPziOc0D2/3KH1P+6jK5nGWe96kadZuE4jev2/Jq7FvIfTlT2Ltg8Fv2x1v0a5g==} - '@opennextjs/aws@https://pkg.pr.new/@opennextjs/aws@704': - resolution: {tarball: https://pkg.pr.new/@opennextjs/aws@704} - version: 3.4.0 + '@opennextjs/aws@https://pkg.pr.new/@opennextjs/aws@712': + resolution: {tarball: https://pkg.pr.new/@opennextjs/aws@712} + version: 3.4.1 hasBin: true '@pkgjs/parseargs@0.11.0': @@ -6189,14 +6189,14 @@ snapshots: '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.696.0 - tslib: 2.6.3 + '@aws-sdk/types': 3.723.0 + tslib: 2.8.1 '@aws-crypto/crc32c@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.696.0 - tslib: 2.6.3 + '@aws-sdk/types': 3.723.0 + tslib: 2.8.1 '@aws-crypto/ie11-detection@3.0.0': dependencies: @@ -6206,10 +6206,10 @@ snapshots: dependencies: '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.723.0 '@aws-sdk/util-locate-window': 3.693.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-crypto/sha256-browser@3.0.0': dependencies: @@ -6227,10 +6227,10 @@ snapshots: '@aws-crypto/sha256-js': 5.2.0 '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.723.0 '@aws-sdk/util-locate-window': 3.693.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-crypto/sha256-js@3.0.0': dependencies: @@ -6241,8 +6241,8 @@ snapshots: '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.696.0 - tslib: 2.6.3 + '@aws-sdk/types': 3.723.0 + tslib: 2.8.1 '@aws-crypto/supports-web-crypto@3.0.0': dependencies: @@ -6250,7 +6250,7 @@ snapshots: '@aws-crypto/supports-web-crypto@5.2.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@aws-crypto/util@3.0.0': dependencies: @@ -6260,9 +6260,9 @@ snapshots: '@aws-crypto/util@5.2.0': dependencies: - '@aws-sdk/types': 3.696.0 + '@aws-sdk/types': 3.723.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/client-cloudfront@3.398.0': dependencies: @@ -6305,7 +6305,7 @@ snapshots: '@smithy/util-utf8': 2.3.0 '@smithy/util-waiter': 2.2.0 fast-xml-parser: 4.2.5 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6354,7 +6354,7 @@ snapshots: '@smithy/util-utf8': 3.0.0 '@smithy/util-waiter': 3.1.9 '@types/uuid': 9.0.8 - tslib: 2.6.3 + tslib: 2.8.1 uuid: 9.0.1 transitivePeerDependencies: - aws-crt @@ -6406,7 +6406,7 @@ snapshots: '@smithy/util-stream': 3.3.1 '@smithy/util-utf8': 3.0.0 '@smithy/util-waiter': 3.1.9 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6469,7 +6469,7 @@ snapshots: '@smithy/util-stream': 4.0.1 '@smithy/util-utf8': 4.0.0 '@smithy/util-waiter': 4.0.2 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6517,7 +6517,7 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-retry': 3.0.10 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6562,7 +6562,7 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-retry': 3.0.10 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6607,7 +6607,7 @@ snapshots: '@smithy/util-middleware': 4.0.1 '@smithy/util-retry': 4.0.1 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6645,7 +6645,7 @@ snapshots: '@smithy/util-defaults-mode-node': 2.3.1 '@smithy/util-retry': 2.2.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6688,7 +6688,7 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-retry': 3.0.10 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6731,7 +6731,7 @@ snapshots: '@smithy/util-middleware': 4.0.1 '@smithy/util-retry': 4.0.1 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6773,7 +6773,7 @@ snapshots: '@smithy/util-retry': 2.2.0 '@smithy/util-utf8': 2.3.0 fast-xml-parser: 4.2.5 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6818,7 +6818,7 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-retry': 3.0.10 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6863,7 +6863,7 @@ snapshots: '@smithy/util-middleware': 4.0.1 '@smithy/util-retry': 4.0.1 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6879,7 +6879,7 @@ snapshots: '@smithy/types': 3.7.1 '@smithy/util-middleware': 3.0.10 fast-xml-parser: 4.4.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/core@3.723.0': dependencies: @@ -6893,14 +6893,14 @@ snapshots: '@smithy/types': 4.1.0 '@smithy/util-middleware': 4.0.1 fast-xml-parser: 4.4.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/credential-provider-env@3.398.0': dependencies: '@aws-sdk/types': 3.398.0 '@smithy/property-provider': 2.2.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/credential-provider-env@3.696.0': dependencies: @@ -6908,7 +6908,7 @@ snapshots: '@aws-sdk/types': 3.696.0 '@smithy/property-provider': 3.1.10 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/credential-provider-env@3.723.0': dependencies: @@ -6916,7 +6916,7 @@ snapshots: '@aws-sdk/types': 3.723.0 '@smithy/property-provider': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/credential-provider-http@3.696.0': dependencies: @@ -6929,7 +6929,7 @@ snapshots: '@smithy/smithy-client': 3.4.5 '@smithy/types': 3.7.1 '@smithy/util-stream': 3.3.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/credential-provider-http@3.723.0': dependencies: @@ -6942,7 +6942,7 @@ snapshots: '@smithy/smithy-client': 4.1.0 '@smithy/types': 4.1.0 '@smithy/util-stream': 4.0.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/credential-provider-ini@3.398.0': dependencies: @@ -6955,7 +6955,7 @@ snapshots: '@smithy/property-provider': 2.2.0 '@smithy/shared-ini-file-loader': 2.4.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -6973,7 +6973,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' - aws-crt @@ -6992,7 +6992,7 @@ snapshots: '@smithy/property-provider': 4.0.1 '@smithy/shared-ini-file-loader': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' - aws-crt @@ -7009,7 +7009,7 @@ snapshots: '@smithy/property-provider': 2.2.0 '@smithy/shared-ini-file-loader': 2.4.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -7026,7 +7026,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' - '@aws-sdk/client-sts' @@ -7045,7 +7045,7 @@ snapshots: '@smithy/property-provider': 4.0.1 '@smithy/shared-ini-file-loader': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' - '@aws-sdk/client-sts' @@ -7057,7 +7057,7 @@ snapshots: '@smithy/property-provider': 2.2.0 '@smithy/shared-ini-file-loader': 2.4.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/credential-provider-process@3.696.0': dependencies: @@ -7066,7 +7066,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/credential-provider-process@3.723.0': dependencies: @@ -7075,7 +7075,7 @@ snapshots: '@smithy/property-provider': 4.0.1 '@smithy/shared-ini-file-loader': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/credential-provider-sso@3.398.0': dependencies: @@ -7085,7 +7085,7 @@ snapshots: '@smithy/property-provider': 2.2.0 '@smithy/shared-ini-file-loader': 2.4.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -7098,7 +7098,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' - aws-crt @@ -7112,7 +7112,7 @@ snapshots: '@smithy/property-provider': 4.0.1 '@smithy/shared-ini-file-loader': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - '@aws-sdk/client-sso-oidc' - aws-crt @@ -7122,7 +7122,7 @@ snapshots: '@aws-sdk/types': 3.398.0 '@smithy/property-provider': 2.2.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/credential-provider-web-identity@3.696.0(@aws-sdk/client-sts@3.699.0)': dependencies: @@ -7131,7 +7131,7 @@ snapshots: '@aws-sdk/types': 3.696.0 '@smithy/property-provider': 3.1.10 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/credential-provider-web-identity@3.723.0(@aws-sdk/client-sts@3.726.1)': dependencies: @@ -7140,12 +7140,12 @@ snapshots: '@aws-sdk/types': 3.723.0 '@smithy/property-provider': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/endpoint-cache@3.693.0': dependencies: mnemonist: 0.38.3 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-bucket-endpoint@3.726.0': dependencies: @@ -7155,7 +7155,7 @@ snapshots: '@smithy/protocol-http': 5.0.1 '@smithy/types': 4.1.0 '@smithy/util-config-provider': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-endpoint-discovery@3.696.0': dependencies: @@ -7164,14 +7164,14 @@ snapshots: '@smithy/node-config-provider': 3.1.11 '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-expect-continue@3.723.0': dependencies: '@aws-sdk/types': 3.723.0 '@smithy/protocol-http': 5.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-flexible-checksums@3.723.0': dependencies: @@ -7187,73 +7187,73 @@ snapshots: '@smithy/util-middleware': 4.0.1 '@smithy/util-stream': 4.0.1 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-host-header@3.398.0': dependencies: '@aws-sdk/types': 3.398.0 '@smithy/protocol-http': 2.0.5 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-host-header@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-host-header@3.723.0': dependencies: '@aws-sdk/types': 3.723.0 '@smithy/protocol-http': 5.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-location-constraint@3.723.0': dependencies: '@aws-sdk/types': 3.723.0 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-logger@3.398.0': dependencies: '@aws-sdk/types': 3.398.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-logger@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-logger@3.723.0': dependencies: '@aws-sdk/types': 3.723.0 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-recursion-detection@3.398.0': dependencies: '@aws-sdk/types': 3.398.0 '@smithy/protocol-http': 2.0.5 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-recursion-detection@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-recursion-detection@3.723.0': dependencies: '@aws-sdk/types': 3.723.0 '@smithy/protocol-http': 5.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-sdk-s3@3.723.0': dependencies: @@ -7270,7 +7270,7 @@ snapshots: '@smithy/util-middleware': 4.0.1 '@smithy/util-stream': 4.0.1 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-sdk-sqs@3.696.0': dependencies: @@ -7279,14 +7279,14 @@ snapshots: '@smithy/types': 3.7.1 '@smithy/util-hex-encoding': 3.0.0 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-sdk-sts@3.398.0': dependencies: '@aws-sdk/middleware-signing': 3.398.0 '@aws-sdk/types': 3.398.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-signing@3.398.0': dependencies: @@ -7296,13 +7296,13 @@ snapshots: '@smithy/signature-v4': 2.3.0 '@smithy/types': 2.12.0 '@smithy/util-middleware': 2.2.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-ssec@3.723.0': dependencies: '@aws-sdk/types': 3.723.0 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-user-agent@3.398.0': dependencies: @@ -7310,7 +7310,7 @@ snapshots: '@aws-sdk/util-endpoints': 3.398.0 '@smithy/protocol-http': 2.0.5 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-user-agent@3.696.0': dependencies: @@ -7320,7 +7320,7 @@ snapshots: '@smithy/core': 2.5.4 '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/middleware-user-agent@3.726.0': dependencies: @@ -7330,7 +7330,7 @@ snapshots: '@smithy/core': 3.1.0 '@smithy/protocol-http': 5.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/region-config-resolver@3.696.0': dependencies: @@ -7339,7 +7339,7 @@ snapshots: '@smithy/types': 3.7.1 '@smithy/util-config-provider': 3.0.0 '@smithy/util-middleware': 3.0.10 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/region-config-resolver@3.723.0': dependencies: @@ -7348,7 +7348,7 @@ snapshots: '@smithy/types': 4.1.0 '@smithy/util-config-provider': 4.0.0 '@smithy/util-middleware': 4.0.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/signature-v4-multi-region@3.723.0': dependencies: @@ -7357,7 +7357,7 @@ snapshots: '@smithy/protocol-http': 5.0.1 '@smithy/signature-v4': 5.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/token-providers@3.398.0': dependencies: @@ -7395,7 +7395,7 @@ snapshots: '@smithy/util-defaults-mode-node': 2.3.1 '@smithy/util-retry': 2.2.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.6.3 + tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -7406,7 +7406,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/token-providers@3.723.0(@aws-sdk/client-sso-oidc@3.726.0(@aws-sdk/client-sts@3.699.0))': dependencies: @@ -7415,77 +7415,77 @@ snapshots: '@smithy/property-provider': 4.0.1 '@smithy/shared-ini-file-loader': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/types@3.398.0': dependencies: '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/types@3.696.0': dependencies: '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/types@3.723.0': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-arn-parser@3.723.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-endpoints@3.398.0': dependencies: '@aws-sdk/types': 3.398.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-endpoints@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/types': 3.7.1 '@smithy/util-endpoints': 2.1.6 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-endpoints@3.726.0': dependencies: '@aws-sdk/types': 3.723.0 '@smithy/types': 4.1.0 '@smithy/util-endpoints': 3.0.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-locate-window@3.693.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-user-agent-browser@3.398.0': dependencies: '@aws-sdk/types': 3.398.0 '@smithy/types': 2.12.0 bowser: 2.11.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-user-agent-browser@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 '@smithy/types': 3.7.1 bowser: 2.11.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-user-agent-browser@3.723.0': dependencies: '@aws-sdk/types': 3.723.0 '@smithy/types': 4.1.0 bowser: 2.11.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-user-agent-node@3.398.0': dependencies: '@aws-sdk/types': 3.398.0 '@smithy/node-config-provider': 2.3.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-user-agent-node@3.696.0': dependencies: @@ -7493,7 +7493,7 @@ snapshots: '@aws-sdk/types': 3.696.0 '@smithy/node-config-provider': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-user-agent-node@3.726.0': dependencies: @@ -7501,20 +7501,20 @@ snapshots: '@aws-sdk/types': 3.723.0 '@smithy/node-config-provider': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/util-utf8-browser@3.259.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/xml-builder@3.310.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@aws-sdk/xml-builder@3.723.0': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@babel/code-frame@7.24.7': dependencies: @@ -8510,7 +8510,7 @@ snapshots: dependencies: '@octokit/openapi-types': 22.2.0 - '@opennextjs/aws@https://pkg.pr.new/@opennextjs/aws@704': + '@opennextjs/aws@https://pkg.pr.new/@opennextjs/aws@712': dependencies: '@aws-sdk/client-cloudfront': 3.398.0 '@aws-sdk/client-dynamodb': 3.699.0 @@ -8634,26 +8634,26 @@ snapshots: '@smithy/abort-controller@2.2.0': dependencies: '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/abort-controller@3.1.8': dependencies: '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/abort-controller@4.0.1': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/chunked-blob-reader-native@4.0.0': dependencies: '@smithy/util-base64': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/chunked-blob-reader@5.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/config-resolver@2.2.0': dependencies: @@ -8661,7 +8661,7 @@ snapshots: '@smithy/types': 2.12.0 '@smithy/util-config-provider': 2.3.0 '@smithy/util-middleware': 2.2.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/config-resolver@3.0.12': dependencies: @@ -8669,7 +8669,7 @@ snapshots: '@smithy/types': 3.7.1 '@smithy/util-config-provider': 3.0.0 '@smithy/util-middleware': 3.0.10 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/config-resolver@4.0.1': dependencies: @@ -8677,7 +8677,7 @@ snapshots: '@smithy/types': 4.1.0 '@smithy/util-config-provider': 4.0.0 '@smithy/util-middleware': 4.0.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/core@2.5.4': dependencies: @@ -8688,7 +8688,7 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-stream': 3.3.1 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/core@3.1.0': dependencies: @@ -8699,7 +8699,7 @@ snapshots: '@smithy/util-middleware': 4.0.1 '@smithy/util-stream': 4.0.1 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/credential-provider-imds@2.3.0': dependencies: @@ -8707,7 +8707,7 @@ snapshots: '@smithy/property-provider': 2.2.0 '@smithy/types': 2.12.0 '@smithy/url-parser': 2.2.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/credential-provider-imds@3.2.7': dependencies: @@ -8715,7 +8715,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/types': 3.7.1 '@smithy/url-parser': 3.0.10 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/credential-provider-imds@4.0.1': dependencies: @@ -8723,67 +8723,67 @@ snapshots: '@smithy/property-provider': 4.0.1 '@smithy/types': 4.1.0 '@smithy/url-parser': 4.0.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/eventstream-codec@3.1.9': dependencies: '@aws-crypto/crc32': 5.2.0 '@smithy/types': 3.7.1 '@smithy/util-hex-encoding': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/eventstream-codec@4.0.1': dependencies: '@aws-crypto/crc32': 5.2.0 '@smithy/types': 4.1.0 '@smithy/util-hex-encoding': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/eventstream-serde-browser@3.0.13': dependencies: '@smithy/eventstream-serde-universal': 3.0.12 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/eventstream-serde-browser@4.0.1': dependencies: '@smithy/eventstream-serde-universal': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/eventstream-serde-config-resolver@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/eventstream-serde-config-resolver@4.0.1': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/eventstream-serde-node@3.0.12': dependencies: '@smithy/eventstream-serde-universal': 3.0.12 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/eventstream-serde-node@4.0.1': dependencies: '@smithy/eventstream-serde-universal': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/eventstream-serde-universal@3.0.12': dependencies: '@smithy/eventstream-codec': 3.1.9 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/eventstream-serde-universal@4.0.1': dependencies: '@smithy/eventstream-codec': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/fetch-http-handler@2.5.0': dependencies: @@ -8791,7 +8791,7 @@ snapshots: '@smithy/querystring-builder': 2.2.0 '@smithy/types': 2.12.0 '@smithy/util-base64': 2.3.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/fetch-http-handler@4.1.1': dependencies: @@ -8799,7 +8799,7 @@ snapshots: '@smithy/querystring-builder': 3.0.10 '@smithy/types': 3.7.1 '@smithy/util-base64': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/fetch-http-handler@5.0.1': dependencies: @@ -8807,98 +8807,98 @@ snapshots: '@smithy/querystring-builder': 4.0.1 '@smithy/types': 4.1.0 '@smithy/util-base64': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/hash-blob-browser@4.0.1': dependencies: '@smithy/chunked-blob-reader': 5.0.0 '@smithy/chunked-blob-reader-native': 4.0.0 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/hash-node@2.2.0': dependencies: '@smithy/types': 2.12.0 '@smithy/util-buffer-from': 2.2.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/hash-node@3.0.10': dependencies: '@smithy/types': 3.7.1 '@smithy/util-buffer-from': 3.0.0 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/hash-node@4.0.1': dependencies: '@smithy/types': 4.1.0 '@smithy/util-buffer-from': 4.0.0 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/hash-stream-node@4.0.1': dependencies: '@smithy/types': 4.1.0 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/invalid-dependency@2.2.0': dependencies: '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/invalid-dependency@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/invalid-dependency@4.0.1': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/is-array-buffer@3.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/is-array-buffer@4.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/md5-js@3.0.10': dependencies: '@smithy/types': 3.7.1 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/md5-js@4.0.1': dependencies: '@smithy/types': 4.1.0 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-content-length@2.2.0': dependencies: '@smithy/protocol-http': 3.3.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-content-length@3.0.12': dependencies: '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-content-length@4.0.1': dependencies: '@smithy/protocol-http': 5.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-endpoint@2.5.1': dependencies: @@ -8908,7 +8908,7 @@ snapshots: '@smithy/types': 2.12.0 '@smithy/url-parser': 2.2.0 '@smithy/util-middleware': 2.2.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-endpoint@3.2.4': dependencies: @@ -8919,7 +8919,7 @@ snapshots: '@smithy/types': 3.7.1 '@smithy/url-parser': 3.0.10 '@smithy/util-middleware': 3.0.10 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-endpoint@4.0.1': dependencies: @@ -8930,7 +8930,7 @@ snapshots: '@smithy/types': 4.1.0 '@smithy/url-parser': 4.0.1 '@smithy/util-middleware': 4.0.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-retry@2.3.1': dependencies: @@ -8941,7 +8941,7 @@ snapshots: '@smithy/types': 2.12.0 '@smithy/util-middleware': 2.2.0 '@smithy/util-retry': 2.2.0 - tslib: 2.6.3 + tslib: 2.8.1 uuid: 9.0.1 '@smithy/middleware-retry@3.0.28': @@ -8953,7 +8953,7 @@ snapshots: '@smithy/types': 3.7.1 '@smithy/util-middleware': 3.0.10 '@smithy/util-retry': 3.0.10 - tslib: 2.6.3 + tslib: 2.8.1 uuid: 9.0.1 '@smithy/middleware-retry@4.0.1': @@ -8965,59 +8965,59 @@ snapshots: '@smithy/types': 4.1.0 '@smithy/util-middleware': 4.0.1 '@smithy/util-retry': 4.0.1 - tslib: 2.6.3 + tslib: 2.8.1 uuid: 9.0.1 '@smithy/middleware-serde@2.3.0': dependencies: '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-serde@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-serde@4.0.1': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-stack@2.2.0': dependencies: '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-stack@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/middleware-stack@4.0.1': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/node-config-provider@2.3.0': dependencies: '@smithy/property-provider': 2.2.0 '@smithy/shared-ini-file-loader': 2.4.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/node-config-provider@3.1.11': dependencies: '@smithy/property-provider': 3.1.10 '@smithy/shared-ini-file-loader': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/node-config-provider@4.0.1': dependencies: '@smithy/property-provider': 4.0.1 '@smithy/shared-ini-file-loader': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/node-http-handler@2.5.0': dependencies: @@ -9025,7 +9025,7 @@ snapshots: '@smithy/protocol-http': 3.3.0 '@smithy/querystring-builder': 2.2.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/node-http-handler@3.3.1': dependencies: @@ -9033,7 +9033,7 @@ snapshots: '@smithy/protocol-http': 4.1.7 '@smithy/querystring-builder': 3.0.10 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/node-http-handler@4.0.1': dependencies: @@ -9041,75 +9041,75 @@ snapshots: '@smithy/protocol-http': 5.0.1 '@smithy/querystring-builder': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/property-provider@2.2.0': dependencies: '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/property-provider@3.1.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/property-provider@4.0.1': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/protocol-http@2.0.5': dependencies: '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/protocol-http@3.3.0': dependencies: '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/protocol-http@4.1.7': dependencies: '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/protocol-http@5.0.1': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/querystring-builder@2.2.0': dependencies: '@smithy/types': 2.12.0 '@smithy/util-uri-escape': 2.2.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/querystring-builder@3.0.10': dependencies: '@smithy/types': 3.7.1 '@smithy/util-uri-escape': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/querystring-builder@4.0.1': dependencies: '@smithy/types': 4.1.0 '@smithy/util-uri-escape': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/querystring-parser@2.2.0': dependencies: '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/querystring-parser@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/querystring-parser@4.0.1': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/service-error-classification@2.1.5': dependencies: @@ -9126,17 +9126,17 @@ snapshots: '@smithy/shared-ini-file-loader@2.4.0': dependencies: '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/shared-ini-file-loader@3.1.11': dependencies: '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/shared-ini-file-loader@4.0.1': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/signature-v4@2.3.0': dependencies: @@ -9146,7 +9146,7 @@ snapshots: '@smithy/util-middleware': 2.2.0 '@smithy/util-uri-escape': 2.2.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/signature-v4@4.2.3': dependencies: @@ -9157,7 +9157,7 @@ snapshots: '@smithy/util-middleware': 3.0.10 '@smithy/util-uri-escape': 3.0.0 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/signature-v4@5.0.1': dependencies: @@ -9168,7 +9168,7 @@ snapshots: '@smithy/util-middleware': 4.0.1 '@smithy/util-uri-escape': 4.0.0 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/smithy-client@2.5.1': dependencies: @@ -9177,7 +9177,7 @@ snapshots: '@smithy/protocol-http': 3.3.0 '@smithy/types': 2.12.0 '@smithy/util-stream': 2.2.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/smithy-client@3.4.5': dependencies: @@ -9187,7 +9187,7 @@ snapshots: '@smithy/protocol-http': 4.1.7 '@smithy/types': 3.7.1 '@smithy/util-stream': 3.3.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/smithy-client@4.1.0': dependencies: @@ -9197,106 +9197,106 @@ snapshots: '@smithy/protocol-http': 5.0.1 '@smithy/types': 4.1.0 '@smithy/util-stream': 4.0.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/types@2.12.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/types@3.7.1': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/types@4.1.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/url-parser@2.2.0': dependencies: '@smithy/querystring-parser': 2.2.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/url-parser@3.0.10': dependencies: '@smithy/querystring-parser': 3.0.10 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/url-parser@4.0.1': dependencies: '@smithy/querystring-parser': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-base64@2.3.0': dependencies: '@smithy/util-buffer-from': 2.2.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-base64@3.0.0': dependencies: '@smithy/util-buffer-from': 3.0.0 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-base64@4.0.0': dependencies: '@smithy/util-buffer-from': 4.0.0 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-body-length-browser@2.2.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-body-length-browser@3.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-body-length-browser@4.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-body-length-node@2.3.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-body-length-node@3.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-body-length-node@4.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-buffer-from@2.2.0': dependencies: '@smithy/is-array-buffer': 2.2.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-buffer-from@3.0.0': dependencies: '@smithy/is-array-buffer': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-buffer-from@4.0.0': dependencies: '@smithy/is-array-buffer': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-config-provider@2.3.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-config-provider@3.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-config-provider@4.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-defaults-mode-browser@2.2.1': dependencies: @@ -9304,7 +9304,7 @@ snapshots: '@smithy/smithy-client': 2.5.1 '@smithy/types': 2.12.0 bowser: 2.11.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-defaults-mode-browser@3.0.28': dependencies: @@ -9312,7 +9312,7 @@ snapshots: '@smithy/smithy-client': 3.4.5 '@smithy/types': 3.7.1 bowser: 2.11.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-defaults-mode-browser@4.0.1': dependencies: @@ -9320,7 +9320,7 @@ snapshots: '@smithy/smithy-client': 4.1.0 '@smithy/types': 4.1.0 bowser: 2.11.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-defaults-mode-node@2.3.1': dependencies: @@ -9330,7 +9330,7 @@ snapshots: '@smithy/property-provider': 2.2.0 '@smithy/smithy-client': 2.5.1 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-defaults-mode-node@3.0.28': dependencies: @@ -9340,7 +9340,7 @@ snapshots: '@smithy/property-provider': 3.1.10 '@smithy/smithy-client': 3.4.5 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-defaults-mode-node@4.0.1': dependencies: @@ -9350,64 +9350,64 @@ snapshots: '@smithy/property-provider': 4.0.1 '@smithy/smithy-client': 4.1.0 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-endpoints@2.1.6': dependencies: '@smithy/node-config-provider': 3.1.11 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-endpoints@3.0.1': dependencies: '@smithy/node-config-provider': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-hex-encoding@2.2.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-hex-encoding@3.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-hex-encoding@4.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-middleware@2.2.0': dependencies: '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-middleware@3.0.10': dependencies: '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-middleware@4.0.1': dependencies: '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-retry@2.2.0': dependencies: '@smithy/service-error-classification': 2.1.5 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-retry@3.0.10': dependencies: '@smithy/service-error-classification': 3.0.10 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-retry@4.0.1': dependencies: '@smithy/service-error-classification': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-stream@2.2.0': dependencies: @@ -9418,7 +9418,7 @@ snapshots: '@smithy/util-buffer-from': 2.2.0 '@smithy/util-hex-encoding': 2.2.0 '@smithy/util-utf8': 2.3.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-stream@3.3.1': dependencies: @@ -9429,7 +9429,7 @@ snapshots: '@smithy/util-buffer-from': 3.0.0 '@smithy/util-hex-encoding': 3.0.0 '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-stream@4.0.1': dependencies: @@ -9440,52 +9440,52 @@ snapshots: '@smithy/util-buffer-from': 4.0.0 '@smithy/util-hex-encoding': 4.0.0 '@smithy/util-utf8': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-uri-escape@2.2.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-uri-escape@3.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-uri-escape@4.0.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-utf8@2.3.0': dependencies: '@smithy/util-buffer-from': 2.2.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-utf8@3.0.0': dependencies: '@smithy/util-buffer-from': 3.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-utf8@4.0.0': dependencies: '@smithy/util-buffer-from': 4.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-waiter@2.2.0': dependencies: '@smithy/abort-controller': 2.2.0 '@smithy/types': 2.12.0 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-waiter@3.1.9': dependencies: '@smithy/abort-controller': 3.1.8 '@smithy/types': 3.7.1 - tslib: 2.6.3 + tslib: 2.8.1 '@smithy/util-waiter@4.0.2': dependencies: '@smithy/abort-controller': 4.0.1 '@smithy/types': 4.1.0 - tslib: 2.6.3 + tslib: 2.8.1 '@swc/counter@0.1.3': {}