@opennextjs/aws 3.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +94 -0
  3. package/dist/adapters/binary.d.ts +1 -0
  4. package/dist/adapters/binary.js +63 -0
  5. package/dist/adapters/cache.d.ts +96 -0
  6. package/dist/adapters/cache.js +278 -0
  7. package/dist/adapters/config/index.d.ts +27 -0
  8. package/dist/adapters/config/index.js +21 -0
  9. package/dist/adapters/config/util.d.ts +28 -0
  10. package/dist/adapters/config/util.js +84 -0
  11. package/dist/adapters/dynamo-provider.d.ts +8 -0
  12. package/dist/adapters/dynamo-provider.js +42 -0
  13. package/dist/adapters/edge-adapter.d.ts +8 -0
  14. package/dist/adapters/edge-adapter.js +54 -0
  15. package/dist/adapters/image-optimization-adapter.d.ts +4 -0
  16. package/dist/adapters/image-optimization-adapter.js +193 -0
  17. package/dist/adapters/logger.d.ts +13 -0
  18. package/dist/adapters/logger.js +51 -0
  19. package/dist/adapters/middleware.d.ts +5 -0
  20. package/dist/adapters/middleware.js +84 -0
  21. package/dist/adapters/plugins/14.1/util.d.ts +1 -0
  22. package/dist/adapters/plugins/14.1/util.js +29 -0
  23. package/dist/adapters/plugins/image-optimization/image-optimization.d.ts +11 -0
  24. package/dist/adapters/plugins/image-optimization/image-optimization.js +14 -0
  25. package/dist/adapters/plugins/image-optimization/image-optimization.replacement.d.ts +11 -0
  26. package/dist/adapters/plugins/image-optimization/image-optimization.replacement.js +22 -0
  27. package/dist/adapters/plugins/without-routing/requestHandler.d.ts +2 -0
  28. package/dist/adapters/plugins/without-routing/requestHandler.js +10 -0
  29. package/dist/adapters/revalidate.d.ts +9 -0
  30. package/dist/adapters/revalidate.js +71 -0
  31. package/dist/adapters/server-adapter.d.ts +4 -0
  32. package/dist/adapters/server-adapter.js +27 -0
  33. package/dist/adapters/util.d.ts +10 -0
  34. package/dist/adapters/util.js +28 -0
  35. package/dist/adapters/warmer-function.d.ts +12 -0
  36. package/dist/adapters/warmer-function.js +80 -0
  37. package/dist/build/bundleNextServer.d.ts +1 -0
  38. package/dist/build/bundleNextServer.js +87 -0
  39. package/dist/build/compileConfig.d.ts +3 -0
  40. package/dist/build/compileConfig.js +64 -0
  41. package/dist/build/copyTracedFiles.d.ts +1 -0
  42. package/dist/build/copyTracedFiles.js +207 -0
  43. package/dist/build/createServerBundle.d.ts +3 -0
  44. package/dist/build/createServerBundle.js +228 -0
  45. package/dist/build/edge/createEdgeBundle.d.ts +20 -0
  46. package/dist/build/edge/createEdgeBundle.js +149 -0
  47. package/dist/build/generateOutput.d.ts +2 -0
  48. package/dist/build/generateOutput.js +239 -0
  49. package/dist/build/helper.d.ts +33 -0
  50. package/dist/build/helper.js +193 -0
  51. package/dist/build/patch/patchedAsyncStorage.d.ts +5 -0
  52. package/dist/build/patch/patchedAsyncStorage.js +16 -0
  53. package/dist/build/validateConfig.d.ts +2 -0
  54. package/dist/build/validateConfig.js +76 -0
  55. package/dist/build.d.ts +7 -0
  56. package/dist/build.js +533 -0
  57. package/dist/cache/incremental/s3-lite.d.ts +3 -0
  58. package/dist/cache/incremental/s3-lite.js +72 -0
  59. package/dist/cache/incremental/s3.d.ts +3 -0
  60. package/dist/cache/incremental/s3.js +44 -0
  61. package/dist/cache/incremental/types.d.ts +34 -0
  62. package/dist/cache/incremental/types.js +1 -0
  63. package/dist/cache/next-types.d.ts +62 -0
  64. package/dist/cache/next-types.js +1 -0
  65. package/dist/cache/tag/constants.d.ts +2 -0
  66. package/dist/cache/tag/constants.js +17 -0
  67. package/dist/cache/tag/dynamodb-lite.d.ts +3 -0
  68. package/dist/cache/tag/dynamodb-lite.js +174 -0
  69. package/dist/cache/tag/dynamodb.d.ts +3 -0
  70. package/dist/cache/tag/dynamodb.js +129 -0
  71. package/dist/cache/tag/types.d.ts +11 -0
  72. package/dist/cache/tag/types.js +1 -0
  73. package/dist/converters/aws-apigw-v1.d.ts +3 -0
  74. package/dist/converters/aws-apigw-v1.js +89 -0
  75. package/dist/converters/aws-apigw-v2.d.ts +3 -0
  76. package/dist/converters/aws-apigw-v2.js +99 -0
  77. package/dist/converters/aws-cloudfront.d.ts +3 -0
  78. package/dist/converters/aws-cloudfront.js +170 -0
  79. package/dist/converters/dummy.d.ts +7 -0
  80. package/dist/converters/dummy.js +16 -0
  81. package/dist/converters/edge.d.ts +6 -0
  82. package/dist/converters/edge.js +88 -0
  83. package/dist/converters/node.d.ts +3 -0
  84. package/dist/converters/node.js +45 -0
  85. package/dist/converters/sqs-revalidate.d.ts +4 -0
  86. package/dist/converters/sqs-revalidate.js +22 -0
  87. package/dist/converters/utils.d.ts +1 -0
  88. package/dist/converters/utils.js +9 -0
  89. package/dist/core/createGenericHandler.d.ts +11 -0
  90. package/dist/core/createGenericHandler.js +16 -0
  91. package/dist/core/createMainHandler.d.ts +18 -0
  92. package/dist/core/createMainHandler.js +24 -0
  93. package/dist/core/edgeFunctionHandler.d.ts +54 -0
  94. package/dist/core/edgeFunctionHandler.js +21 -0
  95. package/dist/core/patchAsyncStorage.d.ts +1 -0
  96. package/dist/core/patchAsyncStorage.js +16 -0
  97. package/dist/core/requestHandler.d.ts +3 -0
  98. package/dist/core/requestHandler.js +162 -0
  99. package/dist/core/require-hooks.d.ts +3 -0
  100. package/dist/core/require-hooks.js +102 -0
  101. package/dist/core/resolve.d.ts +31 -0
  102. package/dist/core/resolve.js +81 -0
  103. package/dist/core/routing/cacheInterceptor.d.ts +2 -0
  104. package/dist/core/routing/cacheInterceptor.js +162 -0
  105. package/dist/core/routing/i18n/accept-header.d.ts +1 -0
  106. package/dist/core/routing/i18n/accept-header.js +101 -0
  107. package/dist/core/routing/i18n/index.d.ts +2 -0
  108. package/dist/core/routing/i18n/index.js +36 -0
  109. package/dist/core/routing/matcher.d.ts +25 -0
  110. package/dist/core/routing/matcher.js +294 -0
  111. package/dist/core/routing/middleware.d.ts +7 -0
  112. package/dist/core/routing/middleware.js +167 -0
  113. package/dist/core/routing/util.d.ts +105 -0
  114. package/dist/core/routing/util.js +415 -0
  115. package/dist/core/routingHandler.d.ts +8 -0
  116. package/dist/core/routingHandler.js +127 -0
  117. package/dist/core/util.d.ts +5 -0
  118. package/dist/core/util.js +84 -0
  119. package/dist/helpers/withCloudflare.d.ts +65 -0
  120. package/dist/helpers/withCloudflare.js +58 -0
  121. package/dist/helpers/withSST.d.ts +54 -0
  122. package/dist/helpers/withSST.js +28 -0
  123. package/dist/http/index.d.ts +2 -0
  124. package/dist/http/index.js +4 -0
  125. package/dist/http/openNextResponse.d.ts +78 -0
  126. package/dist/http/openNextResponse.js +281 -0
  127. package/dist/http/request.d.ts +12 -0
  128. package/dist/http/request.js +35 -0
  129. package/dist/http/util.d.ts +4 -0
  130. package/dist/http/util.js +34 -0
  131. package/dist/index.d.ts +2 -0
  132. package/dist/index.js +37 -0
  133. package/dist/logger.d.ts +12 -0
  134. package/dist/logger.js +13 -0
  135. package/dist/minimize-js.d.ts +1 -0
  136. package/dist/minimize-js.js +101 -0
  137. package/dist/overrides/imageLoader/host.d.ts +3 -0
  138. package/dist/overrides/imageLoader/host.js +29 -0
  139. package/dist/overrides/imageLoader/s3.d.ts +3 -0
  140. package/dist/overrides/imageLoader/s3.js +33 -0
  141. package/dist/plugins/edge.d.ts +15 -0
  142. package/dist/plugins/edge.js +157 -0
  143. package/dist/plugins/replacement.d.ts +42 -0
  144. package/dist/plugins/replacement.js +74 -0
  145. package/dist/plugins/resolve.d.ts +18 -0
  146. package/dist/plugins/resolve.js +45 -0
  147. package/dist/queue/sqs-lite.d.ts +3 -0
  148. package/dist/queue/sqs-lite.js +52 -0
  149. package/dist/queue/sqs.d.ts +3 -0
  150. package/dist/queue/sqs.js +20 -0
  151. package/dist/queue/types.d.ts +12 -0
  152. package/dist/queue/types.js +1 -0
  153. package/dist/types/aws-lambda.d.ts +22 -0
  154. package/dist/types/aws-lambda.js +1 -0
  155. package/dist/types/next-types.d.ts +155 -0
  156. package/dist/types/next-types.js +2 -0
  157. package/dist/types/open-next.d.ts +303 -0
  158. package/dist/types/open-next.js +1 -0
  159. package/dist/utils/error.d.ts +23 -0
  160. package/dist/utils/error.js +32 -0
  161. package/dist/utils/fetch.d.ts +2 -0
  162. package/dist/utils/fetch.js +23 -0
  163. package/dist/utils/promise.d.ts +18 -0
  164. package/dist/utils/promise.js +48 -0
  165. package/dist/utils/stream.d.ts +5 -0
  166. package/dist/utils/stream.js +30 -0
  167. package/dist/wrappers/aws-lambda-streaming.d.ts +7 -0
  168. package/dist/wrappers/aws-lambda-streaming.js +88 -0
  169. package/dist/wrappers/aws-lambda.d.ts +7 -0
  170. package/dist/wrappers/aws-lambda.js +39 -0
  171. package/dist/wrappers/cloudflare.d.ts +11 -0
  172. package/dist/wrappers/cloudflare.js +20 -0
  173. package/dist/wrappers/node.d.ts +7 -0
  174. package/dist/wrappers/node.js +57 -0
  175. package/package.json +66 -0
@@ -0,0 +1,228 @@
1
+ import { existsSync } from "node:fs";
2
+ import { createRequire as topLevelCreateRequire } from "node:module";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import url from "url";
6
+ import { compileCache } from "../build.js";
7
+ import logger from "../logger.js";
8
+ import { minifyAll } from "../minimize-js.js";
9
+ import { openNextReplacementPlugin } from "../plugins/replacement.js";
10
+ import { openNextResolvePlugin } from "../plugins/resolve.js";
11
+ import { bundleNextServer } from "./bundleNextServer.js";
12
+ import { copyTracedFiles } from "./copyTracedFiles.js";
13
+ import { generateEdgeBundle } from "./edge/createEdgeBundle.js";
14
+ import { compareSemver, copyEnvFile, copyOpenNextConfig, esbuildAsync, traverseFiles, } from "./helper.js";
15
+ const require = topLevelCreateRequire(import.meta.url);
16
+ const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
17
+ export async function createServerBundle(config, options) {
18
+ const foundRoutes = new Set();
19
+ // Get all functions to build
20
+ const defaultFn = config.default;
21
+ const functions = Object.entries(config.functions ?? {});
22
+ // Recompile cache.ts as ESM if any function is using Deno runtime
23
+ if (defaultFn.runtime === "deno" ||
24
+ functions.some(([, fn]) => fn.runtime === "deno")) {
25
+ compileCache("esm");
26
+ }
27
+ const promises = functions.map(async ([name, fnOptions]) => {
28
+ const routes = fnOptions.routes;
29
+ routes.forEach((route) => foundRoutes.add(route));
30
+ if (fnOptions.runtime === "edge") {
31
+ await generateEdgeBundle(name, config, options, fnOptions);
32
+ }
33
+ else {
34
+ await generateBundle(name, config, options, fnOptions);
35
+ }
36
+ });
37
+ //TODO: throw an error if not all edge runtime routes has been bundled in a separate function
38
+ // We build every other function than default before so we know which route there is left
39
+ await Promise.all(promises);
40
+ const remainingRoutes = new Set();
41
+ const { monorepoRoot, appBuildOutputPath } = options;
42
+ const packagePath = path.relative(monorepoRoot, appBuildOutputPath);
43
+ // Find remaining routes
44
+ const serverPath = path.join(appBuildOutputPath, ".next", "standalone", packagePath, ".next", "server");
45
+ // Find app dir routes
46
+ if (existsSync(path.join(serverPath, "app"))) {
47
+ const appPath = path.join(serverPath, "app");
48
+ traverseFiles(appPath, (file) => {
49
+ if (file.endsWith("page.js") || file.endsWith("route.js")) {
50
+ const route = `app/${file.replace(/\.js$/, "")}`;
51
+ if (!foundRoutes.has(route)) {
52
+ remainingRoutes.add(route);
53
+ }
54
+ }
55
+ return false;
56
+ }, () => { });
57
+ }
58
+ // Find pages dir routes
59
+ if (existsSync(path.join(serverPath, "pages"))) {
60
+ const pagePath = path.join(serverPath, "pages");
61
+ traverseFiles(pagePath, (file) => {
62
+ if (file.endsWith(".js")) {
63
+ const route = `pages/${file.replace(/\.js$/, "")}`;
64
+ if (!foundRoutes.has(route)) {
65
+ remainingRoutes.add(route);
66
+ }
67
+ }
68
+ return false;
69
+ }, () => { });
70
+ }
71
+ // Generate default function
72
+ await generateBundle("default", config, options, {
73
+ ...defaultFn,
74
+ // @ts-expect-error - Those string are RouteTemplate
75
+ routes: Array.from(remainingRoutes),
76
+ patterns: ["*"],
77
+ });
78
+ }
79
+ async function generateBundle(name, config, options, fnOptions) {
80
+ const { appPath, appBuildOutputPath, outputDir, monorepoRoot } = options;
81
+ logger.info(`Building server function: ${name}...`);
82
+ // Create output folder
83
+ const outputPath = path.join(outputDir, "server-functions", name);
84
+ // Resolve path to the Next.js app if inside the monorepo
85
+ // note: if user's app is inside a monorepo, standalone mode places
86
+ // `node_modules` inside `.next/standalone`, and others inside
87
+ // `.next/standalone/package/path` (ie. `.next`, `server.js`).
88
+ // We need to output the handler file inside the package path.
89
+ const isMonorepo = monorepoRoot !== appPath;
90
+ const packagePath = path.relative(monorepoRoot, appBuildOutputPath);
91
+ fs.mkdirSync(path.join(outputPath, packagePath), { recursive: true });
92
+ const ext = fnOptions.runtime === "deno" ? "mjs" : "cjs";
93
+ fs.copyFileSync(path.join(outputDir, ".build", `cache.${ext}`), path.join(outputPath, packagePath, "cache.cjs"));
94
+ if (fnOptions.runtime === "deno") {
95
+ addDenoJson(outputPath, packagePath);
96
+ }
97
+ // Bundle next server if necessary
98
+ const isBundled = fnOptions.experimentalBundledNextServer ?? false;
99
+ if (isBundled) {
100
+ await bundleNextServer(path.join(outputPath, packagePath), appPath);
101
+ }
102
+ // // Copy middleware
103
+ if (!config.middleware?.external &&
104
+ existsSync(path.join(outputDir, ".build", "middleware.mjs"))) {
105
+ fs.copyFileSync(path.join(outputDir, ".build", "middleware.mjs"), path.join(outputPath, packagePath, "middleware.mjs"));
106
+ }
107
+ // Copy open-next.config.mjs
108
+ copyOpenNextConfig(path.join(outputDir, ".build"), path.join(outputPath, packagePath));
109
+ //Copy env files
110
+ copyEnvFile(appBuildOutputPath, packagePath, outputPath);
111
+ // Copy all necessary traced files
112
+ await copyTracedFiles(appBuildOutputPath, packagePath, outputPath, fnOptions.routes ?? ["app/page.tsx"], isBundled);
113
+ // Build Lambda code
114
+ // note: bundle in OpenNext package b/c the adapter relies on the
115
+ // "serverless-http" package which is not a dependency in user's
116
+ // Next.js app.
117
+ const disableNextPrebundledReact = compareSemver(options.nextVersion, "13.5.1") >= 0 ||
118
+ compareSemver(options.nextVersion, "13.4.1") <= 0;
119
+ const overrides = fnOptions.override ?? {};
120
+ const isBefore13413 = compareSemver(options.nextVersion, "13.4.13") <= 0;
121
+ const isAfter141 = compareSemver(options.nextVersion, "14.0.4") >= 0;
122
+ const disableRouting = isBefore13413 || config.middleware?.external;
123
+ const plugins = [
124
+ openNextReplacementPlugin({
125
+ name: `requestHandlerOverride ${name}`,
126
+ target: /core(\/|\\)requestHandler\.js/g,
127
+ deletes: disableNextPrebundledReact ? ["applyNextjsPrebundledReact"] : [],
128
+ replacements: disableRouting
129
+ ? [
130
+ require.resolve("../adapters/plugins/without-routing/requestHandler.js"),
131
+ ]
132
+ : [],
133
+ }),
134
+ openNextReplacementPlugin({
135
+ name: `utilOverride ${name}`,
136
+ target: /core(\/|\\)util\.js/g,
137
+ deletes: [
138
+ ...(disableNextPrebundledReact ? ["requireHooks"] : []),
139
+ ...(disableRouting ? ["trustHostHeader"] : []),
140
+ ...(!isBefore13413 ? ["requestHandlerHost"] : []),
141
+ ...(!isAfter141 ? ["stableIncrementalCache"] : []),
142
+ ...(isAfter141 ? ["experimentalIncrementalCacheHandler"] : []),
143
+ ],
144
+ }),
145
+ openNextResolvePlugin({
146
+ fnName: name,
147
+ overrides: overrides,
148
+ }),
149
+ ];
150
+ if (plugins && plugins.length > 0) {
151
+ logger.debug(`Applying plugins:: [${plugins
152
+ .map(({ name }) => name)
153
+ .join(",")}] for Next version: ${options.nextVersion}`);
154
+ }
155
+ const outfileExt = fnOptions.runtime === "deno" ? "ts" : "mjs";
156
+ await esbuildAsync({
157
+ entryPoints: [path.join(__dirname, "../adapters", "server-adapter.js")],
158
+ external: ["next", "./middleware.mjs", "./next-server.runtime.prod.js"],
159
+ outfile: path.join(outputPath, packagePath, `index.${outfileExt}`),
160
+ banner: {
161
+ js: [
162
+ `globalThis.monorepoPackagePath = "${packagePath}";`,
163
+ "import process from 'node:process';",
164
+ "import { Buffer } from 'node:buffer';",
165
+ "import { createRequire as topLevelCreateRequire } from 'module';",
166
+ "const require = topLevelCreateRequire(import.meta.url);",
167
+ "import bannerUrl from 'url';",
168
+ "const __dirname = bannerUrl.fileURLToPath(new URL('.', import.meta.url));",
169
+ name === "default" ? "" : `globalThis.fnName = "${name}";`,
170
+ ].join(""),
171
+ },
172
+ plugins,
173
+ alias: {
174
+ "next/dist/server/next-server.js": isBundled
175
+ ? "./next-server.runtime.prod.js"
176
+ : "next/dist/server/next-server.js",
177
+ },
178
+ }, options);
179
+ if (isMonorepo) {
180
+ addMonorepoEntrypoint(outputPath, packagePath);
181
+ }
182
+ if (fnOptions.minify) {
183
+ await minifyServerBundle(outputPath);
184
+ }
185
+ const shouldGenerateDocker = shouldGenerateDockerfile(fnOptions);
186
+ if (shouldGenerateDocker) {
187
+ fs.writeFileSync(path.join(outputPath, "Dockerfile"), typeof shouldGenerateDocker === "string"
188
+ ? shouldGenerateDocker
189
+ : `
190
+ FROM node:18-alpine
191
+ WORKDIR /app
192
+ COPY . /app
193
+ EXPOSE 3000
194
+ CMD ["node", "index.mjs"]
195
+ `);
196
+ }
197
+ }
198
+ function shouldGenerateDockerfile(options) {
199
+ return options.override?.generateDockerfile ?? false;
200
+ }
201
+ // Add deno.json file to enable "bring your own node_modules" mode.
202
+ // TODO: this won't be necessary in Deno 2. See https://github.com/denoland/deno/issues/23151
203
+ function addDenoJson(outputPath, packagePath) {
204
+ const config = {
205
+ // Enable "bring your own node_modules" mode
206
+ // and allow `__proto__`
207
+ unstable: ["byonm", "fs", "unsafe-proto"],
208
+ };
209
+ fs.writeFileSync(path.join(outputPath, packagePath, "deno.json"), JSON.stringify(config, null, 2));
210
+ }
211
+ //TODO: check if this PR is still necessary https://github.com/sst/open-next/pull/341
212
+ function addMonorepoEntrypoint(outputPath, packagePath) {
213
+ // Note: in the monorepo case, the handler file is output to
214
+ // `.next/standalone/package/path/index.mjs`, but we want
215
+ // the Lambda function to be able to find the handler at
216
+ // the root of the bundle. We will create a dummy `index.mjs`
217
+ // that re-exports the real handler.
218
+ // Always use posix path for import path
219
+ const packagePosixPath = packagePath.split(path.sep).join(path.posix.sep);
220
+ fs.writeFileSync(path.join(outputPath, "index.mjs"), [`export * from "./${packagePosixPath}/index.mjs";`].join(""));
221
+ }
222
+ async function minifyServerBundle(outputDir) {
223
+ logger.info(`Minimizing server function...`);
224
+ await minifyAll(outputDir, {
225
+ compress_json: true,
226
+ mangle: true,
227
+ });
228
+ }
@@ -0,0 +1,20 @@
1
+ import { MiddlewareInfo } from "../../types/next-types";
2
+ import { IncludedConverter, OpenNextConfig, OverrideOptions, SplittedFunctionOptions } from "../../types/open-next";
3
+ import { BuildOptions } from "../helper.js";
4
+ interface BuildEdgeBundleOptions {
5
+ appBuildOutputPath: string;
6
+ middlewareInfo: MiddlewareInfo;
7
+ entrypoint: string;
8
+ outfile: string;
9
+ options: BuildOptions;
10
+ overrides?: OverrideOptions;
11
+ defaultConverter?: IncludedConverter;
12
+ additionalInject?: string;
13
+ includeCache?: boolean;
14
+ additionalExternals?: string[];
15
+ onlyBuildOnce?: boolean;
16
+ }
17
+ export declare function buildEdgeBundle({ appBuildOutputPath, middlewareInfo, entrypoint, outfile, options, defaultConverter, overrides, additionalInject, includeCache, additionalExternals, onlyBuildOnce, }: BuildEdgeBundleOptions): Promise<void>;
18
+ export declare function copyMiddlewareAssetsAndWasm({}: {}): void;
19
+ export declare function generateEdgeBundle(name: string, config: OpenNextConfig, options: BuildOptions, fnOptions: SplittedFunctionOptions): Promise<void>;
20
+ export {};
@@ -0,0 +1,149 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import url from "node:url";
3
+ import { build } from "esbuild";
4
+ import fs from "fs";
5
+ import path from "path";
6
+ import logger from "../../logger.js";
7
+ import { openNextEdgePlugins } from "../../plugins/edge.js";
8
+ import { openNextReplacementPlugin } from "../../plugins/replacement.js";
9
+ import { openNextResolvePlugin } from "../../plugins/resolve.js";
10
+ import { copyOpenNextConfig, esbuildAsync } from "../helper.js";
11
+ const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
12
+ export async function buildEdgeBundle({ appBuildOutputPath, middlewareInfo, entrypoint, outfile, options, defaultConverter, overrides, additionalInject, includeCache, additionalExternals, onlyBuildOnce, }) {
13
+ const isInCloudfare = typeof overrides?.wrapper === "string"
14
+ ? overrides.wrapper === "cloudflare"
15
+ : (await overrides?.wrapper?.())?.edgeRuntime;
16
+ await esbuildAsync({
17
+ entryPoints: [entrypoint],
18
+ // inject: ,
19
+ bundle: true,
20
+ outfile,
21
+ external: ["node:*", "next", "@aws-sdk/*"],
22
+ target: "es2022",
23
+ platform: "neutral",
24
+ plugins: [
25
+ openNextResolvePlugin({
26
+ overrides: {
27
+ wrapper: typeof overrides?.wrapper === "string"
28
+ ? overrides.wrapper
29
+ : "aws-lambda",
30
+ converter: typeof overrides?.converter === "string"
31
+ ? overrides.converter
32
+ : defaultConverter,
33
+ ...(includeCache
34
+ ? {
35
+ tagCache: typeof overrides?.tagCache === "string"
36
+ ? overrides.tagCache
37
+ : "dynamodb-lite",
38
+ incrementalCache: typeof overrides?.incrementalCache === "string"
39
+ ? overrides.incrementalCache
40
+ : "s3-lite",
41
+ queue: typeof overrides?.queue === "string"
42
+ ? overrides.queue
43
+ : "sqs-lite",
44
+ }
45
+ : {}),
46
+ },
47
+ }),
48
+ openNextReplacementPlugin({
49
+ name: "externalMiddlewareOverrides",
50
+ target: /adapters(\/|\\)middleware\.js/g,
51
+ deletes: includeCache ? [] : ["includeCacheInMiddleware"],
52
+ }),
53
+ openNextEdgePlugins({
54
+ middlewareInfo,
55
+ nextDir: path.join(appBuildOutputPath, ".next"),
56
+ edgeFunctionHandlerPath: path.join(__dirname, "../../core", "edgeFunctionHandler.js"),
57
+ isInCloudfare,
58
+ }),
59
+ ],
60
+ treeShaking: true,
61
+ alias: {
62
+ path: "node:path",
63
+ stream: "node:stream",
64
+ fs: "node:fs",
65
+ },
66
+ conditions: ["module"],
67
+ mainFields: ["module", "main"],
68
+ banner: {
69
+ js: `
70
+ import {Buffer} from "node:buffer";
71
+ globalThis.Buffer = Buffer;
72
+
73
+ import {AsyncLocalStorage} from "node:async_hooks";
74
+ globalThis.AsyncLocalStorage = AsyncLocalStorage;
75
+ ${isInCloudfare
76
+ ? ""
77
+ : `
78
+ const require = (await import("node:module")).createRequire(import.meta.url);
79
+ const __filename = (await import("node:url")).fileURLToPath(import.meta.url);
80
+ const __dirname = (await import("node:path")).dirname(__filename);
81
+
82
+ const defaultDefineProperty = Object.defineProperty;
83
+ Object.defineProperty = function(o, p, a) {
84
+ if(p=== '__import_unsupported' && Boolean(globalThis.__import_unsupported)) {
85
+ return;
86
+ }
87
+ return defaultDefineProperty(o, p, a);
88
+ };
89
+ `}
90
+ ${additionalInject ?? ""}
91
+ `,
92
+ },
93
+ }, options);
94
+ if (!onlyBuildOnce) {
95
+ await build({
96
+ entryPoints: [outfile],
97
+ outfile,
98
+ allowOverwrite: true,
99
+ bundle: true,
100
+ minify: true,
101
+ platform: "node",
102
+ format: "esm",
103
+ conditions: ["workerd", "worker", "browser"],
104
+ external: ["node:*", ...(additionalExternals ?? [])],
105
+ banner: {
106
+ js: 'import * as process from "node:process";',
107
+ },
108
+ });
109
+ }
110
+ }
111
+ export function copyMiddlewareAssetsAndWasm({}) { }
112
+ export async function generateEdgeBundle(name, config, options, fnOptions) {
113
+ const { appBuildOutputPath, outputDir } = options;
114
+ logger.info(`Generating edge bundle for: ${name}`);
115
+ // Create output folder
116
+ const outputPath = path.join(outputDir, "server-functions", name);
117
+ fs.mkdirSync(outputPath, { recursive: true });
118
+ // Copy open-next.config.mjs
119
+ copyOpenNextConfig(path.join(outputDir, ".build"), outputPath, true);
120
+ // Load middleware manifest
121
+ const middlewareManifest = JSON.parse(fs.readFileSync(path.join(appBuildOutputPath, ".next/server/middleware-manifest.json"), "utf8"));
122
+ // Find functions
123
+ const functions = Object.values(middlewareManifest.functions).filter((fn) => fnOptions.routes.includes(fn.name));
124
+ if (functions.length > 1) {
125
+ throw new Error("Only one function is supported for now");
126
+ }
127
+ const fn = functions[0];
128
+ //Copy wasm files
129
+ const wasmFiles = fn.wasm;
130
+ mkdirSync(path.join(outputPath, "wasm"), { recursive: true });
131
+ for (const wasmFile of wasmFiles) {
132
+ fs.copyFileSync(path.join(appBuildOutputPath, ".next", wasmFile.filePath), path.join(outputPath, `wasm/${wasmFile.name}.wasm`));
133
+ }
134
+ // Copy assets
135
+ const assets = fn.assets;
136
+ mkdirSync(path.join(outputPath, "assets"), { recursive: true });
137
+ for (const asset of assets) {
138
+ fs.copyFileSync(path.join(appBuildOutputPath, ".next", asset.filePath), path.join(outputPath, `assets/${asset.name}`));
139
+ }
140
+ await buildEdgeBundle({
141
+ appBuildOutputPath,
142
+ middlewareInfo: fn,
143
+ entrypoint: path.join(__dirname, "../../adapters", "edge-adapter.js"),
144
+ outfile: path.join(outputPath, "index.mjs"),
145
+ options,
146
+ overrides: fnOptions.override,
147
+ additionalExternals: config.edgeExternals,
148
+ });
149
+ }
@@ -0,0 +1,2 @@
1
+ import { OpenNextConfig } from "../types/open-next";
2
+ export declare function generateOutput(outputPath: string, config: OpenNextConfig): Promise<void>;
@@ -0,0 +1,239 @@
1
+ import * as fs from "node:fs";
2
+ import path from "node:path";
3
+ import { getBuildId } from "./helper.js";
4
+ async function canStream(opts) {
5
+ if (!opts.override?.wrapper) {
6
+ return false;
7
+ }
8
+ else {
9
+ if (typeof opts.override.wrapper === "string") {
10
+ return opts.override.wrapper === "aws-lambda-streaming";
11
+ }
12
+ else {
13
+ const wrapper = await opts.override.wrapper();
14
+ return wrapper.supportStreaming;
15
+ }
16
+ }
17
+ }
18
+ async function extractOverrideName(defaultName, override) {
19
+ if (!override) {
20
+ return defaultName;
21
+ }
22
+ if (typeof override === "string") {
23
+ return override;
24
+ }
25
+ else {
26
+ const overrideModule = await override();
27
+ return overrideModule.name;
28
+ }
29
+ }
30
+ async function extractOverrideFn(override) {
31
+ if (!override) {
32
+ return {
33
+ wrapper: "aws-lambda",
34
+ converter: "aws-apigw-v2",
35
+ };
36
+ }
37
+ const wrapper = await extractOverrideName("aws-lambda", override.wrapper);
38
+ const converter = await extractOverrideName("aws-apigw-v2", override.converter);
39
+ return { wrapper, converter };
40
+ }
41
+ async function extractCommonOverride(override) {
42
+ if (!override) {
43
+ return {
44
+ queue: "sqs",
45
+ incrementalCache: "s3",
46
+ tagCache: "dynamodb",
47
+ };
48
+ }
49
+ const queue = await extractOverrideName("sqs", override.queue);
50
+ const incrementalCache = await extractOverrideName("s3", override.incrementalCache);
51
+ const tagCache = await extractOverrideName("dynamodb", override.tagCache);
52
+ return { queue, incrementalCache, tagCache };
53
+ }
54
+ function prefixPattern(basePath) {
55
+ // Prefix CloudFront distribution behavior path patterns with `basePath` if configured
56
+ return (pattern) => {
57
+ return basePath && basePath.length > 0
58
+ ? `${basePath.slice(1)}/${pattern}`
59
+ : pattern;
60
+ };
61
+ }
62
+ export async function generateOutput(outputPath, config) {
63
+ const edgeFunctions = {};
64
+ const isExternalMiddleware = config.middleware?.external ?? false;
65
+ if (isExternalMiddleware) {
66
+ edgeFunctions.middleware = {
67
+ bundle: ".open-next/middleware",
68
+ handler: "handler.handler",
69
+ pathResolver: await extractOverrideName("pattern-env", config.middleware.originResolver),
70
+ ...(await extractOverrideFn(config.middleware?.override)),
71
+ };
72
+ }
73
+ // Add edge functions
74
+ Object.entries(config.functions ?? {}).forEach(async ([key, value]) => {
75
+ if (value.placement === "global") {
76
+ edgeFunctions[key] = {
77
+ bundle: `.open-next/functions/${key}`,
78
+ handler: "index.handler",
79
+ ...(await extractOverrideFn(value.override)),
80
+ };
81
+ }
82
+ });
83
+ const defaultOriginCanstream = await canStream(config.default);
84
+ //Load required-server-files.json
85
+ const requiredServerFiles = JSON.parse(fs.readFileSync(path.join(outputPath, ".next", "required-server-files.json"), "utf-8")).config;
86
+ const prefixer = prefixPattern(requiredServerFiles.basePath ?? "");
87
+ // First add s3 origins and image optimization
88
+ const defaultOrigins = {
89
+ s3: {
90
+ type: "s3",
91
+ originPath: "_assets",
92
+ copy: [
93
+ {
94
+ from: ".open-next/assets",
95
+ to: requiredServerFiles.basePath
96
+ ? `_assets${requiredServerFiles.basePath}`
97
+ : "_assets",
98
+ cached: true,
99
+ versionedSubDir: prefixer("_next"),
100
+ },
101
+ ...(config.dangerous?.disableIncrementalCache
102
+ ? []
103
+ : [
104
+ {
105
+ from: ".open-next/cache",
106
+ to: "_cache",
107
+ cached: false,
108
+ },
109
+ ]),
110
+ ],
111
+ },
112
+ imageOptimizer: {
113
+ type: "function",
114
+ handler: "index.handler",
115
+ bundle: ".open-next/image-optimization-function",
116
+ streaming: false,
117
+ imageLoader: await extractOverrideName("s3", config.imageOptimization?.loader),
118
+ ...(await extractOverrideFn(config.imageOptimization?.override)),
119
+ },
120
+ default: config.default.override?.generateDockerfile
121
+ ? {
122
+ type: "ecs",
123
+ bundle: ".open-next/server-functions/default",
124
+ dockerfile: ".open-next/server-functions/default/Dockerfile",
125
+ ...(await extractOverrideFn(config.default.override)),
126
+ ...(await extractCommonOverride(config.default.override)),
127
+ }
128
+ : {
129
+ type: "function",
130
+ handler: "index.handler",
131
+ bundle: ".open-next/server-functions/default",
132
+ streaming: defaultOriginCanstream,
133
+ ...(await extractOverrideFn(config.default.override)),
134
+ ...(await extractCommonOverride(config.default.override)),
135
+ },
136
+ };
137
+ //@ts-expect-error - Not sure how to fix typing here, it complains about the type of imageOptimizer and s3
138
+ const origins = defaultOrigins;
139
+ // Then add function origins
140
+ await Promise.all(Object.entries(config.functions ?? {}).map(async ([key, value]) => {
141
+ if (!value.placement || value.placement === "regional") {
142
+ if (value.override?.generateDockerfile) {
143
+ origins[key] = {
144
+ type: "ecs",
145
+ bundle: `.open-next/server-functions/${key}`,
146
+ dockerfile: `.open-next/server-functions/${key}/Dockerfile`,
147
+ ...(await extractOverrideFn(value.override)),
148
+ ...(await extractCommonOverride(value.override)),
149
+ };
150
+ }
151
+ else {
152
+ const streaming = await canStream(value);
153
+ origins[key] = {
154
+ type: "function",
155
+ handler: "index.handler",
156
+ bundle: `.open-next/server-functions/${key}`,
157
+ streaming,
158
+ ...(await extractOverrideFn(value.override)),
159
+ ...(await extractCommonOverride(value.override)),
160
+ };
161
+ }
162
+ }
163
+ }));
164
+ // Then we need to compute the behaviors
165
+ const behaviors = [
166
+ { pattern: prefixer("_next/image*"), origin: "imageOptimizer" },
167
+ ];
168
+ // Then we add the routes
169
+ Object.entries(config.functions ?? {}).forEach(([key, value]) => {
170
+ const patterns = "patterns" in value ? value.patterns : ["*"];
171
+ patterns.forEach((pattern) => {
172
+ behaviors.push({
173
+ pattern: prefixer(pattern.replace(/BUILD_ID/, getBuildId(outputPath))),
174
+ origin: value.placement === "global" ? undefined : key,
175
+ edgeFunction: value.placement === "global"
176
+ ? key
177
+ : isExternalMiddleware
178
+ ? "middleware"
179
+ : undefined,
180
+ });
181
+ });
182
+ });
183
+ // We finish with the default behavior so that they don't override the others
184
+ behaviors.push({
185
+ pattern: prefixer("_next/data/*"),
186
+ origin: "default",
187
+ edgeFunction: isExternalMiddleware ? "middleware" : undefined,
188
+ });
189
+ behaviors.push({
190
+ pattern: "*",
191
+ origin: "default",
192
+ edgeFunction: isExternalMiddleware ? "middleware" : undefined,
193
+ });
194
+ //Compute behaviors for assets files
195
+ const assetPath = path.join(outputPath, ".open-next", "assets");
196
+ fs.readdirSync(assetPath).forEach((item) => {
197
+ if (fs.statSync(path.join(assetPath, item)).isDirectory()) {
198
+ behaviors.push({
199
+ pattern: prefixer(`${item}/*`),
200
+ origin: "s3",
201
+ });
202
+ }
203
+ else {
204
+ behaviors.push({
205
+ pattern: prefixer(item),
206
+ origin: "s3",
207
+ });
208
+ }
209
+ });
210
+ // Check if we produced a dynamodb provider output
211
+ const isTagCacheDisabled = config.dangerous?.disableTagCache ||
212
+ !fs.existsSync(path.join(outputPath, ".open-next", "dynamodb-provider"));
213
+ const output = {
214
+ edgeFunctions,
215
+ origins,
216
+ behaviors,
217
+ additionalProps: {
218
+ disableIncrementalCache: config.dangerous?.disableIncrementalCache,
219
+ disableTagCache: config.dangerous?.disableTagCache,
220
+ warmer: {
221
+ handler: "index.handler",
222
+ bundle: ".open-next/warmer-function",
223
+ },
224
+ initializationFunction: isTagCacheDisabled
225
+ ? undefined
226
+ : {
227
+ handler: "index.handler",
228
+ bundle: ".open-next/dynamodb-provider",
229
+ },
230
+ revalidationFunction: config.dangerous?.disableIncrementalCache
231
+ ? undefined
232
+ : {
233
+ handler: "index.handler",
234
+ bundle: ".open-next/revalidation-function",
235
+ },
236
+ },
237
+ };
238
+ fs.writeFileSync(path.join(outputPath, ".open-next", "open-next.output.json"), JSON.stringify(output));
239
+ }
@@ -0,0 +1,33 @@
1
+ import { BuildOptions as ESBuildOptions } from "esbuild";
2
+ import { OpenNextConfig } from "../types/open-next.js";
3
+ export type BuildOptions = ReturnType<typeof normalizeOptions>;
4
+ export declare function normalizeOptions(config: OpenNextConfig, root: string): {
5
+ openNextVersion: string;
6
+ nextVersion: string;
7
+ appPackageJsonPath: string;
8
+ appPath: string;
9
+ appBuildOutputPath: string;
10
+ appPublicPath: string;
11
+ outputDir: string;
12
+ tempDir: string;
13
+ debug: boolean;
14
+ monorepoRoot: string;
15
+ };
16
+ export declare function esbuildSync(esbuildOptions: ESBuildOptions, options: BuildOptions): void;
17
+ export declare function esbuildAsync(esbuildOptions: ESBuildOptions, options: BuildOptions): Promise<void>;
18
+ export declare function removeFiles(root: string, conditionFn: (file: string) => boolean, searchingDir?: string): void;
19
+ /**
20
+ * Recursively traverse files in a directory and call `callbackFn` when `conditionFn` returns true
21
+ * @param root - Root directory to search
22
+ * @param conditionFn - Called to determine if `callbackFn` should be called
23
+ * @param callbackFn - Called when `conditionFn` returns true
24
+ * @param searchingDir - Directory to search (used for recursion)
25
+ */
26
+ export declare function traverseFiles(root: string, conditionFn: (file: string) => boolean, callbackFn: (filePath: string) => void, searchingDir?: string): void;
27
+ export declare function getHtmlPages(dotNextPath: string): Set<string>;
28
+ export declare function getBuildId(dotNextPath: string): string;
29
+ export declare function getOpenNextVersion(): string;
30
+ export declare function getNextVersion(appPath: string): string;
31
+ export declare function compareSemver(v1: string, v2: string): number;
32
+ export declare function copyOpenNextConfig(tempDir: string, outputPath: string, isEdge?: boolean): void;
33
+ export declare function copyEnvFile(appPath: string, packagePath: string, outputPath: string): void;