@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.
- package/lib/constants.js +1 -0
- package/lib/helpers/edge.js +1 -0
- package/lib/helpers/files.js +34 -6
- package/lib/helpers/functions.js +3 -0
- package/lib/index.js +12 -1
- package/lib/templates/blob.js +341 -0
- package/lib/templates/blobStorage.js +31 -0
- package/lib/templates/getHandler.js +28 -8
- package/lib/templates/handlerUtils.js +46 -26
- package/lib/templates/server.js +26 -3
- package/lib/templates/vendor.js +20 -0
- package/package.json +10 -5
- package/src/templates/edge/next-dev.js +3 -3
- package/src/templates/edge/shims.js +6 -6
- package/src/templates/edge-shared/next-utils.ts +3 -3
- package/src/templates/edge-shared/utils.ts +1 -1
- package/src/templates/vendor/deno.land/std@0.134.0/fmt/colors.ts +536 -0
- package/src/templates/vendor/deno.land/std@0.134.0/testing/_diff.ts +360 -0
- package/src/templates/vendor/deno.land/std@0.134.0/testing/asserts.ts +866 -0
- package/src/templates/vendor/deno.land/std@0.175.0/_util/asserts.ts +25 -0
- package/src/templates/vendor/deno.land/std@0.175.0/_util/os.ts +23 -0
- package/src/templates/vendor/deno.land/std@0.175.0/async/abortable.ts +149 -0
- package/src/templates/vendor/deno.land/std@0.175.0/async/deadline.ts +30 -0
- package/src/templates/vendor/deno.land/std@0.175.0/async/debounce.ts +79 -0
- package/src/templates/vendor/deno.land/std@0.175.0/async/deferred.ts +48 -0
- package/src/templates/vendor/deno.land/std@0.175.0/async/delay.ts +67 -0
- package/src/templates/vendor/deno.land/std@0.175.0/async/mod.ts +18 -0
- package/src/templates/vendor/deno.land/std@0.175.0/async/mux_async_iterator.ts +97 -0
- package/src/templates/vendor/deno.land/std@0.175.0/async/pool.ts +95 -0
- package/src/templates/vendor/deno.land/std@0.175.0/async/retry.ts +81 -0
- package/src/templates/vendor/deno.land/std@0.175.0/async/tee.ts +100 -0
- package/src/templates/vendor/deno.land/std@0.175.0/bytes/index_of_needle.ts +49 -0
- package/src/templates/vendor/deno.land/std@0.175.0/crypto/timing_safe_equal.ts +29 -0
- package/src/templates/vendor/deno.land/std@0.175.0/datetime/to_imf.ts +45 -0
- package/src/templates/vendor/deno.land/std@0.175.0/encoding/base64.ts +144 -0
- package/src/templates/vendor/deno.land/std@0.175.0/encoding/base64url.ts +70 -0
- package/src/templates/vendor/deno.land/std@0.175.0/flags/mod.ts +785 -0
- package/src/templates/vendor/deno.land/std@0.175.0/fmt/colors.ts +569 -0
- package/src/templates/vendor/deno.land/std@0.175.0/fmt/printf.ts +939 -0
- package/src/templates/vendor/deno.land/std@0.175.0/http/cookie.ts +403 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_core.ts +77 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_events.d.ts +848 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_events.mjs +1033 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_global.d.ts +66 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_next_tick.ts +173 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_process/exiting.ts +4 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_process/process.ts +131 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_process/stdio.mjs +7 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_process/streams.mjs +146 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_stream.d.ts +1488 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_stream.mjs +746 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_util/_util_callbackify.ts +129 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/_utils.ts +206 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/assert.ts +940 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/assertion_error.ts +579 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/async_hooks.ts +331 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/buffer.ts +13 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/events.ts +14 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/buffer.d.ts +2074 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/buffer.mjs +2607 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/crypto/_keys.ts +16 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/crypto/constants.ts +5 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/error_codes.ts +7 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/errors.ts +2867 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/fixed_queue.ts +123 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/hide_stack_frames.ts +16 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/net.ts +95 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/normalize_encoding.mjs +72 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/options.ts +45 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/primordials.mjs +30 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/process/per_thread.mjs +272 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/readline/callbacks.mjs +137 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/readline/utils.mjs +580 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/streams/destroy.mjs +320 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/streams/end-of-stream.mjs +229 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/streams/utils.mjs +242 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/util/comparisons.ts +669 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/util/debuglog.ts +118 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/util/inspect.mjs +2237 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/util/types.ts +113 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/util.mjs +143 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal/validators.mjs +317 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_libuv_winerror.ts +229 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_listen.ts +16 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_node.ts +18 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_timingSafeEqual.ts +12 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_utils.ts +86 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/_winerror.ts +16873 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/ares.ts +66 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/async_wrap.ts +152 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/buffer.ts +130 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/cares_wrap.ts +541 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/config.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/connection_wrap.ts +80 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/constants.ts +900 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/contextify.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/credentials.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/crypto.ts +14 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/errors.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/fs.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/fs_dir.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/fs_event_wrap.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/handle_wrap.ts +50 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/heap_utils.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/http_parser.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/icu.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/inspector.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/js_stream.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/messaging.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/mod.ts +108 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/module_wrap.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/native_module.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/natives.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/node_file.ts +84 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/node_options.ts +39 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/options.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/os.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/performance.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/pipe_wrap.ts +392 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/process_methods.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/report.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/serdes.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/signal_wrap.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/spawn_sync.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/stream_wrap.ts +354 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/string_decoder.ts +15 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/symbols.ts +27 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/task_queue.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/tcp_wrap.ts +488 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/timers.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/tls_wrap.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/trace_events.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/tty_wrap.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/types.ts +186 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/udp_wrap.ts +496 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/url.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/util.ts +126 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/uv.ts +437 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/v8.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/worker.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/internal_binding/zlib.ts +3 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/process.ts +705 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/stream.ts +37 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/string_decoder.ts +337 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/util/types.ts +4 -0
- package/src/templates/vendor/deno.land/std@0.175.0/node/util.ts +289 -0
- package/src/templates/vendor/deno.land/std@0.175.0/path/_constants.ts +49 -0
- package/src/templates/vendor/deno.land/std@0.175.0/path/_interface.ts +30 -0
- package/src/templates/vendor/deno.land/std@0.175.0/path/_util.ts +194 -0
- package/src/templates/vendor/deno.land/std@0.175.0/path/common.ts +40 -0
- package/src/templates/vendor/deno.land/std@0.175.0/path/glob.ts +418 -0
- package/src/templates/vendor/deno.land/std@0.175.0/path/mod.ts +53 -0
- package/src/templates/vendor/deno.land/std@0.175.0/path/posix.ts +487 -0
- package/src/templates/vendor/deno.land/std@0.175.0/path/separator.ts +7 -0
- package/src/templates/vendor/deno.land/std@0.175.0/path/win32.ts +962 -0
- package/src/templates/vendor/deno.land/std@0.175.0/streams/write_all.ts +64 -0
- package/src/templates/vendor/deno.land/std@0.175.0/testing/_diff.ts +440 -0
- package/src/templates/vendor/deno.land/std@0.175.0/testing/_format.ts +23 -0
- package/src/templates/vendor/deno.land/std@0.175.0/testing/asserts.ts +906 -0
- package/src/templates/vendor/deno.land/std@0.175.0/types.d.ts +89 -0
- package/src/templates/vendor/deno.land/x/html_rewriter@v0.1.0-pre.17/index.ts +133 -0
- package/src/templates/vendor/deno.land/x/html_rewriter@v0.1.0-pre.17/vendor/asyncify.js +112 -0
- package/src/templates/vendor/deno.land/x/html_rewriter@v0.1.0-pre.17/vendor/html_rewriter.d.ts +88 -0
- package/src/templates/vendor/deno.land/x/html_rewriter@v0.1.0-pre.17/vendor/html_rewriter.js +974 -0
- package/src/templates/vendor/deno.land/x/path_to_regexp@v6.2.1/index.ts +621 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/compiled/cookie.js +8 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/error.js +9 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/next-url.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/spec-extension/cookies.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/spec-extension/request.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/spec-extension/response.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/server/web/utils.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/get-hostname.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/i18n/detect-domain-locale.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/i18n/normalize-locale-path.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/add-locale.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/add-path-prefix.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/add-path-suffix.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/format-next-pathname-info.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/get-next-pathname-info.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/parse-path.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/path-has-prefix.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/remove-path-prefix.js +2 -0
- package/src/templates/vendor/esm.sh/v91/next@12.2.5/deno/dist/shared/lib/router/utils/remove-trailing-slash.js +2 -0
- package/src/templates/vendor/import_map.json +29 -0
- 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}`;
|
package/lib/helpers/edge.js
CHANGED
|
@@ -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'));
|
package/lib/helpers/files.js
CHANGED
|
@@ -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,
|
|
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
|
|
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
|
|
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
|
package/lib/helpers/functions.js
CHANGED
|
@@ -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
|
-
|
|
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 {
|
|
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 ((
|
|
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 = (
|
|
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;
|