@netlify/plugin-nextjs 4.40.1 → 4.41.0-alpha-isr-blobs.0

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 (186) hide show
  1. package/lib/constants.js +1 -0
  2. package/lib/helpers/edge.js +1 -0
  3. package/lib/helpers/files.js +34 -6
  4. package/lib/helpers/functions.js +3 -0
  5. package/lib/index.js +12 -1
  6. package/lib/templates/blob.js +341 -0
  7. package/lib/templates/blobStorage.js +31 -0
  8. package/lib/templates/getHandler.js +28 -8
  9. package/lib/templates/handlerUtils.js +46 -26
  10. package/lib/templates/server.js +26 -3
  11. package/lib/templates/vendor.js +20 -0
  12. package/package.json +10 -5
  13. package/src/templates/edge/next-dev.js +3 -3
  14. package/src/templates/edge/shims.js +6 -6
  15. package/src/templates/edge-shared/next-utils.ts +3 -3
  16. package/src/templates/edge-shared/utils.ts +1 -1
  17. package/src/templates/vendor/deno.land/std@0.134.0/fmt/colors.ts +536 -0
  18. package/src/templates/vendor/deno.land/std@0.134.0/testing/_diff.ts +360 -0
  19. package/src/templates/vendor/deno.land/std@0.134.0/testing/asserts.ts +866 -0
  20. package/src/templates/vendor/deno.land/std@0.175.0/_util/asserts.ts +25 -0
  21. package/src/templates/vendor/deno.land/std@0.175.0/_util/os.ts +23 -0
  22. package/src/templates/vendor/deno.land/std@0.175.0/async/abortable.ts +149 -0
  23. package/src/templates/vendor/deno.land/std@0.175.0/async/deadline.ts +30 -0
  24. package/src/templates/vendor/deno.land/std@0.175.0/async/debounce.ts +79 -0
  25. package/src/templates/vendor/deno.land/std@0.175.0/async/deferred.ts +48 -0
  26. package/src/templates/vendor/deno.land/std@0.175.0/async/delay.ts +67 -0
  27. package/src/templates/vendor/deno.land/std@0.175.0/async/mod.ts +18 -0
  28. package/src/templates/vendor/deno.land/std@0.175.0/async/mux_async_iterator.ts +97 -0
  29. package/src/templates/vendor/deno.land/std@0.175.0/async/pool.ts +95 -0
  30. package/src/templates/vendor/deno.land/std@0.175.0/async/retry.ts +81 -0
  31. package/src/templates/vendor/deno.land/std@0.175.0/async/tee.ts +100 -0
  32. package/src/templates/vendor/deno.land/std@0.175.0/bytes/index_of_needle.ts +49 -0
  33. package/src/templates/vendor/deno.land/std@0.175.0/crypto/timing_safe_equal.ts +29 -0
  34. package/src/templates/vendor/deno.land/std@0.175.0/datetime/to_imf.ts +45 -0
  35. package/src/templates/vendor/deno.land/std@0.175.0/encoding/base64.ts +144 -0
  36. package/src/templates/vendor/deno.land/std@0.175.0/encoding/base64url.ts +70 -0
  37. package/src/templates/vendor/deno.land/std@0.175.0/flags/mod.ts +785 -0
  38. package/src/templates/vendor/deno.land/std@0.175.0/fmt/colors.ts +569 -0
  39. package/src/templates/vendor/deno.land/std@0.175.0/fmt/printf.ts +939 -0
  40. package/src/templates/vendor/deno.land/std@0.175.0/http/cookie.ts +403 -0
  41. package/src/templates/vendor/deno.land/std@0.175.0/node/_core.ts +77 -0
  42. package/src/templates/vendor/deno.land/std@0.175.0/node/_events.d.ts +848 -0
  43. package/src/templates/vendor/deno.land/std@0.175.0/node/_events.mjs +1033 -0
  44. package/src/templates/vendor/deno.land/std@0.175.0/node/_global.d.ts +66 -0
  45. package/src/templates/vendor/deno.land/std@0.175.0/node/_next_tick.ts +173 -0
  46. package/src/templates/vendor/deno.land/std@0.175.0/node/_process/exiting.ts +4 -0
  47. package/src/templates/vendor/deno.land/std@0.175.0/node/_process/process.ts +131 -0
  48. package/src/templates/vendor/deno.land/std@0.175.0/node/_process/stdio.mjs +7 -0
  49. package/src/templates/vendor/deno.land/std@0.175.0/node/_process/streams.mjs +146 -0
  50. package/src/templates/vendor/deno.land/std@0.175.0/node/_stream.d.ts +1488 -0
  51. package/src/templates/vendor/deno.land/std@0.175.0/node/_stream.mjs +746 -0
  52. package/src/templates/vendor/deno.land/std@0.175.0/node/_util/_util_callbackify.ts +129 -0
  53. package/src/templates/vendor/deno.land/std@0.175.0/node/_utils.ts +206 -0
  54. package/src/templates/vendor/deno.land/std@0.175.0/node/assert.ts +940 -0
  55. package/src/templates/vendor/deno.land/std@0.175.0/node/assertion_error.ts +579 -0
  56. package/src/templates/vendor/deno.land/std@0.175.0/node/async_hooks.ts +331 -0
  57. package/src/templates/vendor/deno.land/std@0.175.0/node/buffer.ts +13 -0
  58. package/src/templates/vendor/deno.land/std@0.175.0/node/events.ts +14 -0
  59. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/buffer.d.ts +2074 -0
  60. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/buffer.mjs +2607 -0
  61. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/crypto/_keys.ts +16 -0
  62. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/crypto/constants.ts +5 -0
  63. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/error_codes.ts +7 -0
  64. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/errors.ts +2867 -0
  65. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/fixed_queue.ts +123 -0
  66. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/hide_stack_frames.ts +16 -0
  67. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/net.ts +95 -0
  68. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/normalize_encoding.mjs +72 -0
  69. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/options.ts +45 -0
  70. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/primordials.mjs +30 -0
  71. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/process/per_thread.mjs +272 -0
  72. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/readline/callbacks.mjs +137 -0
  73. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/readline/utils.mjs +580 -0
  74. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/streams/destroy.mjs +320 -0
  75. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/streams/end-of-stream.mjs +229 -0
  76. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/streams/utils.mjs +242 -0
  77. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/util/comparisons.ts +669 -0
  78. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/util/debuglog.ts +118 -0
  79. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/util/inspect.mjs +2237 -0
  80. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/util/types.ts +113 -0
  81. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/util.mjs +143 -0
  82. package/src/templates/vendor/deno.land/std@0.175.0/node/internal/validators.mjs +317 -0
  83. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_libuv_winerror.ts +229 -0
  84. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_listen.ts +16 -0
  85. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_node.ts +18 -0
  86. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_timingSafeEqual.ts +12 -0
  87. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_utils.ts +86 -0
  88. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_winerror.ts +16873 -0
  89. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/ares.ts +66 -0
  90. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/async_wrap.ts +152 -0
  91. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/buffer.ts +130 -0
  92. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/cares_wrap.ts +541 -0
  93. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/config.ts +3 -0
  94. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/connection_wrap.ts +80 -0
  95. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/constants.ts +900 -0
  96. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/contextify.ts +3 -0
  97. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/credentials.ts +3 -0
  98. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/crypto.ts +14 -0
  99. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/errors.ts +3 -0
  100. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/fs.ts +3 -0
  101. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/fs_dir.ts +3 -0
  102. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/fs_event_wrap.ts +3 -0
  103. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/handle_wrap.ts +50 -0
  104. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/heap_utils.ts +3 -0
  105. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/http_parser.ts +3 -0
  106. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/icu.ts +3 -0
  107. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/inspector.ts +3 -0
  108. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/js_stream.ts +3 -0
  109. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/messaging.ts +3 -0
  110. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/mod.ts +108 -0
  111. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/module_wrap.ts +3 -0
  112. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/native_module.ts +3 -0
  113. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/natives.ts +3 -0
  114. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/node_file.ts +84 -0
  115. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/node_options.ts +39 -0
  116. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/options.ts +3 -0
  117. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/os.ts +3 -0
  118. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/performance.ts +3 -0
  119. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/pipe_wrap.ts +392 -0
  120. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/process_methods.ts +3 -0
  121. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/report.ts +3 -0
  122. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/serdes.ts +3 -0
  123. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/signal_wrap.ts +3 -0
  124. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/spawn_sync.ts +3 -0
  125. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/stream_wrap.ts +354 -0
  126. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/string_decoder.ts +15 -0
  127. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/symbols.ts +27 -0
  128. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/task_queue.ts +3 -0
  129. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/tcp_wrap.ts +488 -0
  130. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/timers.ts +3 -0
  131. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/tls_wrap.ts +3 -0
  132. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/trace_events.ts +3 -0
  133. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/tty_wrap.ts +3 -0
  134. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/types.ts +186 -0
  135. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/udp_wrap.ts +496 -0
  136. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/url.ts +3 -0
  137. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/util.ts +126 -0
  138. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/uv.ts +437 -0
  139. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/v8.ts +3 -0
  140. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/worker.ts +3 -0
  141. package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/zlib.ts +3 -0
  142. package/src/templates/vendor/deno.land/std@0.175.0/node/process.ts +705 -0
  143. package/src/templates/vendor/deno.land/std@0.175.0/node/stream.ts +37 -0
  144. package/src/templates/vendor/deno.land/std@0.175.0/node/string_decoder.ts +337 -0
  145. package/src/templates/vendor/deno.land/std@0.175.0/node/util/types.ts +4 -0
  146. package/src/templates/vendor/deno.land/std@0.175.0/node/util.ts +289 -0
  147. package/src/templates/vendor/deno.land/std@0.175.0/path/_constants.ts +49 -0
  148. package/src/templates/vendor/deno.land/std@0.175.0/path/_interface.ts +30 -0
  149. package/src/templates/vendor/deno.land/std@0.175.0/path/_util.ts +194 -0
  150. package/src/templates/vendor/deno.land/std@0.175.0/path/common.ts +40 -0
  151. package/src/templates/vendor/deno.land/std@0.175.0/path/glob.ts +418 -0
  152. package/src/templates/vendor/deno.land/std@0.175.0/path/mod.ts +53 -0
  153. package/src/templates/vendor/deno.land/std@0.175.0/path/posix.ts +487 -0
  154. package/src/templates/vendor/deno.land/std@0.175.0/path/separator.ts +7 -0
  155. package/src/templates/vendor/deno.land/std@0.175.0/path/win32.ts +962 -0
  156. package/src/templates/vendor/deno.land/std@0.175.0/streams/write_all.ts +64 -0
  157. package/src/templates/vendor/deno.land/std@0.175.0/testing/_diff.ts +440 -0
  158. package/src/templates/vendor/deno.land/std@0.175.0/testing/_format.ts +23 -0
  159. package/src/templates/vendor/deno.land/std@0.175.0/testing/asserts.ts +906 -0
  160. package/src/templates/vendor/deno.land/std@0.175.0/types.d.ts +89 -0
  161. package/src/templates/vendor/deno.land/x/html_rewriter@v0.1.0-pre.17/index.ts +133 -0
  162. package/src/templates/vendor/deno.land/x/html_rewriter@v0.1.0-pre.17/vendor/asyncify.js +112 -0
  163. package/src/templates/vendor/deno.land/x/html_rewriter@v0.1.0-pre.17/vendor/html_rewriter.d.ts +88 -0
  164. package/src/templates/vendor/deno.land/x/html_rewriter@v0.1.0-pre.17/vendor/html_rewriter.js +974 -0
  165. package/src/templates/vendor/deno.land/x/path_to_regexp@v6.2.1/index.ts +621 -0
  166. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/compiled/cookie.js +8 -0
  167. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/error.js +9 -0
  168. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/next-url.js +2 -0
  169. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/spec-extension/cookies.js +2 -0
  170. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/spec-extension/request.js +2 -0
  171. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/spec-extension/response.js +2 -0
  172. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/utils.js +2 -0
  173. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/get-hostname.js +2 -0
  174. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/i18n/detect-domain-locale.js +2 -0
  175. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/i18n/normalize-locale-path.js +2 -0
  176. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/add-locale.js +2 -0
  177. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/add-path-prefix.js +2 -0
  178. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/add-path-suffix.js +2 -0
  179. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/format-next-pathname-info.js +2 -0
  180. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/get-next-pathname-info.js +2 -0
  181. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/parse-path.js +2 -0
  182. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/path-has-prefix.js +2 -0
  183. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/remove-path-prefix.js +2 -0
  184. package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/remove-trailing-slash.js +2 -0
  185. package/src/templates/vendor/import_map.json +29 -0
  186. package/src/templates/vendor/raw.githubusercontent.com/worker-tools/resolvable-promise/master/index.ts +50 -0
package/lib/constants.js CHANGED
@@ -38,6 +38,7 @@ exports.HIDDEN_PATHS = (0, destr_1.default)(process.env.NEXT_KEEP_METADATA_FILES
38
38
  '/prerender-manifest.js',
39
39
  '/required-server-files.json',
40
40
  '/static-manifest.json',
41
+ '/blobs-manifest.json',
41
42
  ];
42
43
  exports.ODB_FUNCTION_PATH = `/.netlify/builders/${exports.ODB_FUNCTION_NAME}`;
43
44
  exports.HANDLER_FUNCTION_PATH = `/.netlify/functions/${exports.HANDLER_FUNCTION_NAME}`;
@@ -210,6 +210,7 @@ const writeEdgeFunctions = async ({ netlifyConfig, routesManifest, constants: {
210
210
  const nextConfigFile = await (0, config_1.getRequiredServerFiles)(publish);
211
211
  const nextConfig = nextConfigFile.config;
212
212
  const usesAppDir = (_a = nextConfig.experimental) === null || _a === void 0 ? void 0 : _a.appDir;
213
+ await (0, fs_extra_1.copy)(getEdgeTemplatePath('../vendor'), (0, path_1.join)(edgeFunctionRoot, 'vendor'));
213
214
  await (0, fs_extra_1.copy)(getEdgeTemplatePath('../edge-shared'), (0, path_1.join)(edgeFunctionRoot, 'edge-shared'));
214
215
  await (0, fs_extra_1.writeJSON)((0, path_1.join)(edgeFunctionRoot, 'edge-shared', 'nextConfig.json'), nextConfig);
215
216
  await (0, fs_extra_1.copy)((0, path_1.join)(publish, 'prerender-manifest.json'), (0, path_1.join)(edgeFunctionRoot, 'edge-shared', 'prerender-manifest.json'));
@@ -13,6 +13,7 @@ const p_limit_1 = __importDefault(require("p-limit"));
13
13
  const pathe_1 = require("pathe");
14
14
  const slash_1 = __importDefault(require("slash"));
15
15
  const constants_1 = require("../constants");
16
+ const blobStorage_1 = require("../templates/blobStorage");
16
17
  const edge_1 = require("./edge");
17
18
  const utils_1 = require("./utils");
18
19
  const TEST_ROUTE = /(|\/)\[[^/]+?](\/|\.html|$)/;
@@ -66,7 +67,8 @@ const getMiddleware = async (publish) => {
66
67
  };
67
68
  exports.getMiddleware = getMiddleware;
68
69
  // eslint-disable-next-line max-lines-per-function
69
- const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
70
+ const moveStaticPages = async ({ netlifyConfig, target, nextConfig, netliBlob, }) => {
71
+ const { i18n, basePath } = nextConfig;
70
72
  console.log('Moving static page files to serve from CDN...');
71
73
  const outputDir = (0, pathe_1.join)(netlifyConfig.build.publish, target === 'serverless' ? 'serverless' : 'server');
72
74
  const buildId = (0, fs_extra_1.readFileSync)((0, pathe_1.join)(netlifyConfig.build.publish, 'BUILD_ID'), 'utf8').trim();
@@ -93,15 +95,24 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
93
95
  }
94
96
  });
95
97
  let fileCount = 0;
98
+ let blobCount = 0;
96
99
  const filesManifest = {};
97
- const moveFile = async (file) => {
100
+ const blobsManifest = new Set();
101
+ const getSourceAndTargetPath = (file) => {
102
+ const source = (0, pathe_1.join)(outputDir, file);
98
103
  // Strip the initial 'app' or 'pages' directory from the output path
99
104
  const pathname = file.split('/').slice(1).join('/');
100
105
  // .rsc data files go next to the html file
101
106
  const isData = file.endsWith('.json');
102
- const source = (0, pathe_1.join)(outputDir, file);
103
107
  const targetFile = isData ? (0, pathe_1.join)(dataDir, pathname) : pathname;
104
108
  const targetPath = basePath ? (0, pathe_1.join)(basePath, targetFile) : targetFile;
109
+ return {
110
+ targetPath,
111
+ source,
112
+ };
113
+ };
114
+ const moveFile = async (file) => {
115
+ const { source, targetPath } = getSourceAndTargetPath(file);
105
116
  fileCount += 1;
106
117
  filesManifest[file] = targetPath;
107
118
  const dest = (0, pathe_1.join)(netlifyConfig.build.publish, targetPath);
@@ -112,6 +123,14 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
112
123
  console.warn('Error moving file', source, error);
113
124
  }
114
125
  };
126
+ const uploadFileToBlobStorageAndDelete = async (file) => {
127
+ const { source } = getSourceAndTargetPath(file);
128
+ blobsManifest.add(file);
129
+ const content = await (0, fs_extra_1.readFile)(source, 'utf8');
130
+ blobCount += 1;
131
+ await netliBlob.set((0, blobStorage_1.getNormalizedBlobKey)(file), content);
132
+ await (0, fs_extra_1.remove)(source);
133
+ };
115
134
  // Move all static files, except nft manifests
116
135
  const pages = await (0, globby_1.default)(['{app,pages}/**/*.{html,json,rsc}', '!**/*.js.nft.{html,json}'], {
117
136
  cwd: outputDir,
@@ -128,8 +147,13 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
128
147
  const filePath = (0, slash_1.default)(rawPath);
129
148
  // Remove the initial 'app' or 'pages' directory from the output path
130
149
  const pagePath = filePath.split('/').slice(1).join('/');
131
- // Don't move ISR files, as they're used for the first request
132
150
  if (isrFiles.has(pagePath)) {
151
+ if (netliBlob) {
152
+ // if netliblob is enabled, we will move ISR assets to blob store and delete files after that
153
+ // to minimize the number of files needed in lambda
154
+ return limit(uploadFileToBlobStorageAndDelete, filePath);
155
+ }
156
+ // Don't move ISR files, as they're used for the first request
133
157
  return;
134
158
  }
135
159
  if ((0, exports.isDynamicRoute)(pagePath)) {
@@ -155,7 +179,10 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
155
179
  return limit(moveFile, filePath);
156
180
  });
157
181
  await Promise.all(promises);
158
- console.log(`Moved ${fileCount} files`);
182
+ console.log(`Moved ${fileCount} files to CDN`);
183
+ if (netliBlob) {
184
+ console.log(`Moved ${blobCount} files to Blob Storage`);
185
+ }
159
186
  if (matchedPages.size !== 0) {
160
187
  console.log((0, chalk_1.yellowBright)((0, outdent_1.outdent) `
161
188
  Skipped moving ${matchedPages.size} ${matchedPages.size === 1 ? 'file because it matches' : 'files because they match'} middleware, so cannot be deployed to the CDN and will be served from the origin instead.
@@ -198,8 +225,9 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
198
225
  `);
199
226
  }
200
227
  }
201
- // Write the manifest for use in the serverless functions
228
+ // Write the manifests for use in the serverless functions
202
229
  await (0, fs_extra_1.writeJson)((0, pathe_1.join)(netlifyConfig.build.publish, 'static-manifest.json'), Object.entries(filesManifest));
230
+ await (0, fs_extra_1.writeJson)((0, pathe_1.join)(netlifyConfig.build.publish, 'blobs-manifest.json'), [...blobsManifest]);
203
231
  if (i18n === null || i18n === void 0 ? void 0 : i18n.defaultLocale) {
204
232
  const rootPath = basePath ? (0, pathe_1.join)(netlifyConfig.build.publish, basePath) : netlifyConfig.build.publish;
205
233
  // Copy the default locale into the root
@@ -80,6 +80,8 @@ const generateFunctions = async ({ INTERNAL_FUNCTIONS_SRC, PUBLISH_DIR, PACKAGE_
80
80
  await (0, fs_extra_1.copyFile)((0, pathe_1.join)(__dirname, '..', '..', 'lib', 'templates', 'server.js'), (0, pathe_1.join)(functionsDir, functionName, 'server.js'));
81
81
  await (0, fs_extra_1.copyFile)((0, pathe_1.join)(__dirname, '..', '..', 'lib', 'templates', 'requireHooks.js'), (0, pathe_1.join)(functionsDir, functionName, 'requireHooks.js'));
82
82
  await (0, fs_extra_1.copyFile)((0, pathe_1.join)(__dirname, '..', '..', 'lib', 'templates', 'handlerUtils.js'), (0, pathe_1.join)(functionsDir, functionName, 'handlerUtils.js'));
83
+ await (0, fs_extra_1.copyFile)((0, pathe_1.join)(__dirname, '..', '..', 'lib', 'templates', 'blob.js'), (0, pathe_1.join)(functionsDir, functionName, 'blob.js'));
84
+ await (0, fs_extra_1.copyFile)((0, pathe_1.join)(__dirname, '..', '..', 'lib', 'templates', 'blobStorage.js'), (0, pathe_1.join)(functionsDir, functionName, 'blobStorage.js'));
83
85
  await (0, functionsMetaData_1.writeFunctionConfiguration)({ functionName, functionTitle, functionsDir });
84
86
  const nfInternalFiles = await (0, tiny_glob_1.default)((0, pathe_1.join)(functionsDir, functionName, '**'));
85
87
  const lambda = ssrLambdas.find((l) => l.functionName === functionName);
@@ -257,6 +259,7 @@ const getSSRDependencies = async (publish) => {
257
259
  }),
258
260
  (0, pathe_1.join)(publish, '**', '*.html'),
259
261
  (0, pathe_1.join)(publish, 'static-manifest.json'),
262
+ (0, pathe_1.join)(publish, 'blobs-manifest.json'),
260
263
  ];
261
264
  };
262
265
  const getSSRLambdas = async (publish) => {
package/lib/index.js CHANGED
@@ -19,6 +19,7 @@ const functions_1 = require("./helpers/functions");
19
19
  const redirects_1 = require("./helpers/redirects");
20
20
  const utils_1 = require("./helpers/utils");
21
21
  const verification_1 = require("./helpers/verification");
22
+ const blobStorage_1 = require("./templates/blobStorage");
22
23
  const plugin = {
23
24
  async onPreBuild({ constants, netlifyConfig, utils: { build: { failBuild }, cache, }, }) {
24
25
  var _a;
@@ -108,7 +109,17 @@ const plugin = {
108
109
  });
109
110
  await (0, files_1.movePublicFiles)({ appDir, outdir, publish, basePath });
110
111
  if (!(0, destr_1.default)(process.env.SERVE_STATIC_FILES_FROM_ORIGIN)) {
111
- await (0, files_1.moveStaticPages)({ target, netlifyConfig, i18n, basePath });
112
+ const { NETLIFY_API_HOST, NETLIFY_API_TOKEN, SITE_ID } = constants;
113
+ const testBlobStorage = new blobStorage_1.Blobs({
114
+ authentication: {
115
+ apiURL: `https://${NETLIFY_API_HOST}`,
116
+ token: NETLIFY_API_TOKEN,
117
+ },
118
+ context: `deploy:${process.env.DEPLOY_ID}`,
119
+ siteID: SITE_ID,
120
+ });
121
+ const netliBlob = (await (0, blobStorage_1.isBlobStorageAvailable)(testBlobStorage)) ? testBlobStorage : undefined;
122
+ await (0, files_1.moveStaticPages)({ target, netlifyConfig, nextConfig: { basePath, i18n }, netliBlob });
112
123
  }
113
124
  await (0, redirects_1.generateStaticRedirects)({
114
125
  netlifyConfig,
@@ -0,0 +1,341 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ // src/templates/netliblob.mts
19
+ var netliblob_exports = {};
20
+ __export(netliblob_exports, {
21
+ Blobs: () => Blobs
22
+ });
23
+ module.exports = __toCommonJS(netliblob_exports);
24
+ // ../../node_modules/@netlify/blobs/dist/src/main.js
25
+ var import_node_fs = require("fs");
26
+ var import_promises = require("fs/promises");
27
+ var import_node_stream = require("stream");
28
+ var AbortError = class extends Error {
29
+ constructor(message) {
30
+ super();
31
+ this.name = "AbortError";
32
+ this.message = message;
33
+ }
34
+ };
35
+ var getDOMException = (errorMessage) => globalThis.DOMException === void 0 ? new AbortError(errorMessage) : new DOMException(errorMessage);
36
+ var getAbortedReason = (signal) => {
37
+ const reason = signal.reason === void 0 ? getDOMException("This operation was aborted.") : signal.reason;
38
+ return reason instanceof Error ? reason : getDOMException(reason);
39
+ };
40
+ async function pMap(iterable, mapper, { concurrency = Number.POSITIVE_INFINITY, stopOnError = true, signal } = {}) {
41
+ return new Promise((resolve, reject_) => {
42
+ if (iterable[Symbol.iterator] === void 0 && iterable[Symbol.asyncIterator] === void 0) {
43
+ throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
44
+ }
45
+ if (typeof mapper !== "function") {
46
+ throw new TypeError("Mapper function is required");
47
+ }
48
+ if (!((Number.isSafeInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency >= 1)) {
49
+ throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`);
50
+ }
51
+ const result = [];
52
+ const errors = [];
53
+ const skippedIndexesMap = /* @__PURE__ */ new Map();
54
+ let isRejected = false;
55
+ let isResolved = false;
56
+ let isIterableDone = false;
57
+ let resolvingCount = 0;
58
+ let currentIndex = 0;
59
+ const iterator = iterable[Symbol.iterator] === void 0 ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
60
+ const reject = (reason) => {
61
+ isRejected = true;
62
+ isResolved = true;
63
+ reject_(reason);
64
+ };
65
+ if (signal) {
66
+ if (signal.aborted) {
67
+ reject(getAbortedReason(signal));
68
+ }
69
+ signal.addEventListener("abort", () => {
70
+ reject(getAbortedReason(signal));
71
+ });
72
+ }
73
+ const next = async () => {
74
+ if (isResolved) {
75
+ return;
76
+ }
77
+ const nextItem = await iterator.next();
78
+ const index = currentIndex;
79
+ currentIndex++;
80
+ if (nextItem.done) {
81
+ isIterableDone = true;
82
+ if (resolvingCount === 0 && !isResolved) {
83
+ if (!stopOnError && errors.length > 0) {
84
+ reject(new AggregateError(errors));
85
+ return;
86
+ }
87
+ isResolved = true;
88
+ if (skippedIndexesMap.size === 0) {
89
+ resolve(result);
90
+ return;
91
+ }
92
+ const pureResult = [];
93
+ for (const [index2, value] of result.entries()) {
94
+ if (skippedIndexesMap.get(index2) === pMapSkip) {
95
+ continue;
96
+ }
97
+ pureResult.push(value);
98
+ }
99
+ resolve(pureResult);
100
+ }
101
+ return;
102
+ }
103
+ resolvingCount++;
104
+ (async () => {
105
+ try {
106
+ const element = await nextItem.value;
107
+ if (isResolved) {
108
+ return;
109
+ }
110
+ const value = await mapper(element, index);
111
+ if (value === pMapSkip) {
112
+ skippedIndexesMap.set(index, value);
113
+ }
114
+ result[index] = value;
115
+ resolvingCount--;
116
+ await next();
117
+ }
118
+ catch (error) {
119
+ if (stopOnError) {
120
+ reject(error);
121
+ }
122
+ else {
123
+ errors.push(error);
124
+ resolvingCount--;
125
+ try {
126
+ await next();
127
+ }
128
+ catch (error2) {
129
+ reject(error2);
130
+ }
131
+ }
132
+ }
133
+ })();
134
+ };
135
+ (async () => {
136
+ for (let index = 0; index < concurrency; index++) {
137
+ try {
138
+ await next();
139
+ }
140
+ catch (error) {
141
+ reject(error);
142
+ break;
143
+ }
144
+ if (isIterableDone || isRejected) {
145
+ break;
146
+ }
147
+ }
148
+ })();
149
+ });
150
+ }
151
+ var pMapSkip = Symbol("skip");
152
+ var DEFAULT_RETRY_DELAY = 5e3;
153
+ var MIN_RETRY_DELAY = 1e3;
154
+ var MAX_RETRY = 5;
155
+ var RATE_LIMIT_HEADER = "X-RateLimit-Reset";
156
+ var fetchAndRetry = async (fetcher, url, options, attemptsLeft = MAX_RETRY) => {
157
+ try {
158
+ const res = await fetcher(url, options);
159
+ if (attemptsLeft > 0 && (res.status === 429 || res.status >= 500)) {
160
+ const delay = getDelay(res.headers.get(RATE_LIMIT_HEADER));
161
+ await sleep(delay);
162
+ return fetchAndRetry(fetcher, url, options, attemptsLeft - 1);
163
+ }
164
+ return res;
165
+ }
166
+ catch (error) {
167
+ if (attemptsLeft === 0) {
168
+ throw error;
169
+ }
170
+ const delay = getDelay();
171
+ await sleep(delay);
172
+ return fetchAndRetry(fetcher, url, options, attemptsLeft - 1);
173
+ }
174
+ };
175
+ var getDelay = (rateLimitReset) => {
176
+ if (!rateLimitReset) {
177
+ return DEFAULT_RETRY_DELAY;
178
+ }
179
+ return Math.max(Number(rateLimitReset) * 1e3 - Date.now(), MIN_RETRY_DELAY);
180
+ };
181
+ var sleep = (ms) => new Promise((resolve) => {
182
+ setTimeout(resolve, ms);
183
+ });
184
+ var EXPIRY_HEADER = "x-nf-expires-at";
185
+ var Blobs = class _Blobs {
186
+ constructor({ authentication, context, fetcher, siteID }) {
187
+ var _a;
188
+ this.context = context !== null && context !== void 0 ? context : "production";
189
+ this.fetcher = fetcher !== null && fetcher !== void 0 ? fetcher : globalThis.fetch;
190
+ this.siteID = siteID;
191
+ if ("contextURL" in authentication) {
192
+ this.authentication = authentication;
193
+ }
194
+ else {
195
+ this.authentication = {
196
+ apiURL: (_a = authentication.apiURL) !== null && _a !== void 0 ? _a : "https://api.netlify.com",
197
+ token: authentication.token
198
+ };
199
+ }
200
+ if (fetcher) {
201
+ this.fetcher = fetcher;
202
+ }
203
+ else if (globalThis.fetch) {
204
+ this.fetcher = globalThis.fetch;
205
+ }
206
+ else {
207
+ throw new Error("You must specify a fetch-compatible `fetcher` parameter when `fetch` is not available globally");
208
+ }
209
+ }
210
+ async getFinalRequest(key, method) {
211
+ const encodedKey = encodeURIComponent(key);
212
+ if ("contextURL" in this.authentication) {
213
+ return {
214
+ headers: {
215
+ authorization: `Bearer ${this.authentication.token}`
216
+ },
217
+ url: `${this.authentication.contextURL}/${this.siteID}/${this.context}/${encodedKey}`
218
+ };
219
+ }
220
+ const apiURL = `${this.authentication.apiURL}/api/v1/sites/${this.siteID}/blobs/${encodedKey}?context=${this.context}`;
221
+ const headers = { authorization: `Bearer ${this.authentication.token}` };
222
+ const res = await this.fetcher(apiURL, { headers, method });
223
+ if (res.status !== 200) {
224
+ throw new Error(`${method} operation has failed: API returned a ${res.status} response`);
225
+ }
226
+ const { url } = await res.json();
227
+ return {
228
+ url
229
+ };
230
+ }
231
+ static getExpirationHeaders(expiration) {
232
+ if (typeof expiration === "number") {
233
+ return {
234
+ [EXPIRY_HEADER]: (Date.now() + expiration).toString()
235
+ };
236
+ }
237
+ if (expiration instanceof Date) {
238
+ return {
239
+ [EXPIRY_HEADER]: expiration.getTime().toString()
240
+ };
241
+ }
242
+ if (expiration === void 0) {
243
+ return {};
244
+ }
245
+ throw new TypeError(`'expiration' value must be a number or a Date, ${typeof expiration} found.`);
246
+ }
247
+ isConfigured() {
248
+ var _a;
249
+ return Boolean((_a = this.authentication) === null || _a === void 0 ? void 0 : _a.token) && Boolean(this.siteID);
250
+ }
251
+ async makeStoreRequest(key, method, extraHeaders, body) {
252
+ if (!this.isConfigured()) {
253
+ throw new Error("The blob store is unavailable because it's missing required configuration properties");
254
+ }
255
+ const { headers: baseHeaders = {}, url } = await this.getFinalRequest(key, method);
256
+ const headers = {
257
+ ...baseHeaders,
258
+ ...extraHeaders
259
+ };
260
+ if (method === "put") {
261
+ headers["cache-control"] = "max-age=0, stale-while-revalidate=60";
262
+ }
263
+ const options = {
264
+ body,
265
+ headers,
266
+ method
267
+ };
268
+ if (body instanceof ReadableStream) {
269
+ options.duplex = "half";
270
+ }
271
+ const res = await fetchAndRetry(this.fetcher, url, options);
272
+ if (res.status === 404 && method === "get") {
273
+ return null;
274
+ }
275
+ if (res.status !== 200) {
276
+ throw new Error(`${method} operation has failed: store returned a ${res.status} response`);
277
+ }
278
+ return res;
279
+ }
280
+ async delete(key) {
281
+ await this.makeStoreRequest(key, "delete");
282
+ }
283
+ async get(key, options) {
284
+ const { type } = options !== null && options !== void 0 ? options : {};
285
+ const res = await this.makeStoreRequest(key, "get");
286
+ const expiration = res === null || res === void 0 ? void 0 : res.headers.get(EXPIRY_HEADER);
287
+ if (typeof expiration === "string") {
288
+ const expirationTS = Number.parseInt(expiration);
289
+ if (!Number.isNaN(expirationTS) && expirationTS <= Date.now()) {
290
+ return null;
291
+ }
292
+ }
293
+ if (res === null) {
294
+ return res;
295
+ }
296
+ if (type === void 0 || type === "text") {
297
+ return res.text();
298
+ }
299
+ if (type === "arrayBuffer") {
300
+ return res.arrayBuffer();
301
+ }
302
+ if (type === "blob") {
303
+ return res.blob();
304
+ }
305
+ if (type === "json") {
306
+ return res.json();
307
+ }
308
+ if (type === "stream") {
309
+ return res.body;
310
+ }
311
+ throw new Error(`Invalid 'type' property: ${type}. Expected: arrayBuffer, blob, json, stream, or text.`);
312
+ }
313
+ async set(key, data, { expiration } = {}) {
314
+ const headers = _Blobs.getExpirationHeaders(expiration);
315
+ await this.makeStoreRequest(key, "put", headers, data);
316
+ }
317
+ async setFile(key, path, { expiration } = {}) {
318
+ const { size } = await (0, import_promises.stat)(path);
319
+ const file = import_node_stream.Readable.toWeb((0, import_node_fs.createReadStream)(path));
320
+ const headers = {
321
+ ..._Blobs.getExpirationHeaders(expiration),
322
+ "content-length": size.toString()
323
+ };
324
+ await this.makeStoreRequest(key, "put", headers, file);
325
+ }
326
+ setFiles(files, { concurrency = 5 } = {}) {
327
+ return pMap(files, ({ key, path, ...options }) => this.setFile(key, path, options), { concurrency });
328
+ }
329
+ async setJSON(key, data, { expiration } = {}) {
330
+ const payload = JSON.stringify(data);
331
+ const headers = {
332
+ ..._Blobs.getExpirationHeaders(expiration),
333
+ "content-type": "application/json"
334
+ };
335
+ await this.makeStoreRequest(key, "put", headers, payload);
336
+ }
337
+ };
338
+ // Annotate the CommonJS export names for ESM import in node:
339
+ 0 && (module.exports = {
340
+ Blobs
341
+ });
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Blobs = exports.getNormalizedBlobKey = exports.getBlobInit = exports.setBlobInit = exports.isBlobStorageAvailable = void 0;
4
+ const buffer_1 = require("buffer");
5
+ const blob_1 = require("./blob");
6
+ const Blobs = blob_1.Blobs;
7
+ exports.Blobs = Blobs;
8
+ const isBlobStorageAvailable = async (netliBlob) => {
9
+ try {
10
+ // request a key that is not present. If it returns `null` then the blob storage is available
11
+ // if it throws it's not available.
12
+ await netliBlob.get('any-key');
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ };
19
+ exports.isBlobStorageAvailable = isBlobStorageAvailable;
20
+ let blobInit;
21
+ const setBlobInit = (init) => {
22
+ blobInit = init;
23
+ };
24
+ exports.setBlobInit = setBlobInit;
25
+ const getBlobInit = () => blobInit;
26
+ exports.getBlobInit = getBlobInit;
27
+ /**
28
+ * @netlify/blobs ATM has some limitation to keys, so we need to normalize it for now (they will be resolved so we will be able to remove this code)
29
+ */
30
+ const getNormalizedBlobKey = (key) => buffer_1.Buffer.from(key).toString('base64url');
31
+ exports.getNormalizedBlobKey = getNormalizedBlobKey;
@@ -4,18 +4,20 @@ exports.getHandler = void 0;
4
4
  // Aliasing like this means the editor may be able to syntax-highlight the string
5
5
  const outdent_1 = require("outdent");
6
6
  /* eslint-disable @typescript-eslint/no-var-requires */
7
+ const { Buffer } = require('buffer');
7
8
  const { promises } = require('fs');
8
9
  const { Server } = require('http');
9
10
  const path = require('path');
10
11
  // eslint-disable-next-line n/prefer-global/url, n/prefer-global/url-search-params
11
12
  const { URLSearchParams, URL } = require('url');
12
13
  const { Bridge } = require('@vercel/node-bridge/bridge');
13
- const { augmentFsModule, getMaxAge, getMultiValueHeaders, getPrefetchResponse, normalizePath, } = require('./handlerUtils');
14
+ const { setBlobInit } = require('./blobStorage');
15
+ const { augmentFsModule, getMaxAge, getMultiValueHeaders, getPrefetchResponse, normalizePath } = require('./handlerUtils');
14
16
  const { overrideRequireHooks, applyRequireHooks } = require('./requireHooks');
15
17
  const { getNetlifyNextServer } = require('./server');
16
18
  // We return a function and then call `toString()` on it to serialise it as the launcher function
17
19
  // eslint-disable-next-line max-lines-per-function
18
- const makeHandler = ({ conf, app, pageRoot, NextServer, staticManifest = [], mode = 'ssr' }) => {
20
+ const makeHandler = ({ conf, app, pageRoot, NextServer, staticManifest = [], blobsManifest = new Set(), mode = 'ssr', }) => {
19
21
  var _a;
20
22
  // Change working directory into the site root, unless using Nx, which moves the
21
23
  // dist directory and handles this itself
@@ -42,7 +44,7 @@ const makeHandler = ({ conf, app, pageRoot, NextServer, staticManifest = [], mod
42
44
  }
43
45
  // Set during the request as it needs to get it from the request URL. Defaults to the URL env var
44
46
  let base = process.env.URL;
45
- augmentFsModule({ promises, staticManifest, pageRoot, getBase: () => base });
47
+ augmentFsModule({ promises, staticManifest, blobsManifest, pageRoot, getBase: () => base });
46
48
  // We memoize this because it can be shared between requests, but don't instantiate it until
47
49
  // the first request because we need the host and port.
48
50
  let bridge;
@@ -77,7 +79,7 @@ const makeHandler = ({ conf, app, pageRoot, NextServer, staticManifest = [], mod
77
79
  return bridge;
78
80
  };
79
81
  return async function handler(event, context) {
80
- var _a, _b, _c;
82
+ var _a, _b, _c, _d, _e;
81
83
  let requestMode = mode;
82
84
  const prefetchResponse = getPrefetchResponse(event, mode);
83
85
  if (prefetchResponse) {
@@ -96,6 +98,18 @@ const makeHandler = ({ conf, app, pageRoot, NextServer, staticManifest = [], mod
96
98
  // 'x-next-just-first-accept-language' header is escape hatch to be able to hit this code for tests (both automated and manual)
97
99
  event.headers['accept-language'] = event.headers['accept-language'].replace(/\s*,.*$/, '');
98
100
  }
101
+ if ((_b = (_a = context === null || context === void 0 ? void 0 : context.clientContext) === null || _a === void 0 ? void 0 : _a.custom) === null || _b === void 0 ? void 0 : _b.blobs) {
102
+ const rawData = Buffer.from(context.clientContext.custom.blobs, 'base64');
103
+ const data = JSON.parse(rawData.toString('ascii'));
104
+ setBlobInit({
105
+ authentication: {
106
+ contextURL: data.url,
107
+ token: data.token,
108
+ },
109
+ context: `deploy:${event.headers['x-nf-deploy-id']}`,
110
+ siteID: event.headers['x-nf-site-id'],
111
+ });
112
+ }
99
113
  const { headers, ...result } = await getBridge(event, context).launcher(event, context);
100
114
  // Convert all headers to multiValueHeaders
101
115
  const multiValueHeaders = getMultiValueHeaders(headers);
@@ -106,12 +120,12 @@ const makeHandler = ({ conf, app, pageRoot, NextServer, staticManifest = [], mod
106
120
  };
107
121
  console.log('Next server response:', JSON.stringify(response, null, 2));
108
122
  }
109
- if ((_b = (_a = multiValueHeaders['set-cookie']) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.includes('__prerender_bypass')) {
123
+ if ((_d = (_c = multiValueHeaders['set-cookie']) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.includes('__prerender_bypass')) {
110
124
  delete multiValueHeaders.etag;
111
125
  multiValueHeaders['cache-control'] = ['no-cache'];
112
126
  }
113
127
  // Sending SWR headers causes undefined behaviour with the Netlify CDN
114
- const cacheHeader = (_c = multiValueHeaders['cache-control']) === null || _c === void 0 ? void 0 : _c[0];
128
+ const cacheHeader = (_e = multiValueHeaders['cache-control']) === null || _e === void 0 ? void 0 : _e[0];
115
129
  if (cacheHeader === null || cacheHeader === void 0 ? void 0 : cacheHeader.includes('stale-while-revalidate')) {
116
130
  if (requestMode === 'odb') {
117
131
  const ttl = getMaxAge(cacheHeader);
@@ -153,8 +167,10 @@ const getHandler = ({ isODB = false, publishDir = '../../../.next', appDir = '..
153
167
 
154
168
  process.env.NODE_ENV = 'production';
155
169
 
170
+ const { Buffer } = require('buffer')
156
171
  const { Server } = require("http");
157
172
  const { promises } = require("fs");
173
+ const { setBlobInit } = require('./blobStorage')
158
174
  // We copy the file here rather than requiring from the node module
159
175
  const { Bridge } = require("./bridge");
160
176
  const { augmentFsModule, getMaxAge, getMultiValueHeaders, getPrefetchResponse, normalizePath } = require('./handlerUtils')
@@ -167,10 +183,14 @@ const getHandler = ({ isODB = false, publishDir = '../../../.next', appDir = '..
167
183
  try {
168
184
  staticManifest = require("${publishDir}/static-manifest.json")
169
185
  } catch {}
186
+ let blobsManifest
187
+ try {
188
+ blobsManifest = new Set(require("${publishDir}/blobs-manifest.json"))
189
+ } catch {}
170
190
  const path = require("path");
171
191
  const pageRoot = path.resolve(path.join(__dirname, "${publishDir}", "server"));
172
192
  exports.handler = ${isODB
173
- ? `builder((${makeHandler.toString()})({ conf: config, app: "${appDir}", pageRoot, NextServer, staticManifest, mode: 'odb' }));`
174
- : `(${makeHandler.toString()})({ conf: config, app: "${appDir}", pageRoot, NextServer, staticManifest, mode: 'ssr' });`}
193
+ ? `builder((${makeHandler.toString()})({ conf: config, app: "${appDir}", pageRoot, NextServer, staticManifest, blobsManifest, mode: 'odb' }));`
194
+ : `(${makeHandler.toString()})({ conf: config, app: "${appDir}", pageRoot, NextServer, staticManifest, blobsManifest, mode: 'ssr' });`}
175
195
  `;
176
196
  exports.getHandler = getHandler;