@netlify/plugin-nextjs 4.14.1 → 4.16.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.
@@ -229,6 +229,7 @@ const moveStaticPages = async ({ netlifyConfig, target, i18n, basePath, }) => {
229
229
  }
230
230
  };
231
231
  exports.moveStaticPages = moveStaticPages;
232
+ const PATCH_WARNING = `/* File patched by Netlify */`;
232
233
  /**
233
234
  * Attempt to patch a source file, preserving a backup
234
235
  */
@@ -237,7 +238,11 @@ const patchFile = async ({ file, replacements, }) => {
237
238
  console.warn('File was not found');
238
239
  return false;
239
240
  }
240
- const content = await (0, fs_extra_1.readFile)(file, 'utf8');
241
+ let content = await (0, fs_extra_1.readFile)(file, 'utf8');
242
+ // If the file has already been patched, patch the backed-up original instead
243
+ if (content.includes(PATCH_WARNING) && (0, fs_extra_1.existsSync)(`${file}.orig`)) {
244
+ content = await (0, fs_extra_1.readFile)(`${file}.orig`, 'utf8');
245
+ }
241
246
  const newContent = replacements.reduce((acc, [from, to]) => {
242
247
  if (acc.includes(to)) {
243
248
  console.log('Already patched. Skipping.');
@@ -250,7 +255,7 @@ const patchFile = async ({ file, replacements, }) => {
250
255
  return false;
251
256
  }
252
257
  await (0, fs_extra_1.writeFile)(`${file}.orig`, content);
253
- await (0, fs_extra_1.writeFile)(file, newContent);
258
+ await (0, fs_extra_1.writeFile)(file, `${newContent}\n${PATCH_WARNING}`);
254
259
  console.log('Done');
255
260
  return true;
256
261
  };
@@ -40,7 +40,7 @@ const generatePagesResolver = async ({ constants: { INTERNAL_FUNCTIONS_SRC, FUNC
40
40
  };
41
41
  exports.generatePagesResolver = generatePagesResolver;
42
42
  // Move our next/image function into the correct functions directory
43
- const setupImageFunction = async ({ constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC = constants_1.DEFAULT_FUNCTIONS_SRC }, imageconfig = {}, netlifyConfig, basePath, remotePatterns, }) => {
43
+ const setupImageFunction = async ({ constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIONS_SRC = constants_1.DEFAULT_FUNCTIONS_SRC }, imageconfig = {}, netlifyConfig, basePath, remotePatterns, responseHeaders, }) => {
44
44
  const functionsPath = INTERNAL_FUNCTIONS_SRC || FUNCTIONS_SRC;
45
45
  const functionName = `${constants_1.IMAGE_FUNCTION_NAME}.js`;
46
46
  const functionDirectory = (0, pathe_1.join)(functionsPath, constants_1.IMAGE_FUNCTION_NAME);
@@ -49,6 +49,7 @@ const setupImageFunction = async ({ constants: { INTERNAL_FUNCTIONS_SRC, FUNCTIO
49
49
  ...imageconfig,
50
50
  basePath: [basePath, constants_1.IMAGE_FUNCTION_NAME].join('/'),
51
51
  remotePatterns,
52
+ responseHeaders,
52
53
  });
53
54
  await (0, fs_extra_1.copyFile)((0, pathe_1.join)(__dirname, '..', '..', 'lib', 'templates', 'ipx.js'), (0, pathe_1.join)(functionDirectory, functionName));
54
55
  const imagePath = imageconfig.path || '/_next/image';
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.isNextAuthInstalled = exports.findModuleFromBase = exports.shouldSkip = exports.getPreviewRewrites = exports.getApiRewrites = exports.redirectsForNextRouteWithData = exports.redirectsForNextRoute = exports.isApiRoute = exports.routeToDataRoute = exports.netlifyRoutesForNextRouteWithData = exports.toNetlifyRoute = void 0;
6
+ exports.getCustomImageResponseHeaders = exports.isNextAuthInstalled = exports.findModuleFromBase = exports.shouldSkip = exports.getPreviewRewrites = exports.getApiRewrites = exports.redirectsForNextRouteWithData = exports.redirectsForNextRoute = exports.isApiRoute = exports.routeToDataRoute = exports.netlifyRoutesForNextRouteWithData = exports.toNetlifyRoute = void 0;
7
7
  const globby_1 = __importDefault(require("globby"));
8
8
  const pathe_1 = require("pathe");
9
9
  const constants_1 = require("../constants");
@@ -146,3 +146,12 @@ const isNextAuthInstalled = () => {
146
146
  }
147
147
  };
148
148
  exports.isNextAuthInstalled = isNextAuthInstalled;
149
+ const getCustomImageResponseHeaders = (headers) => {
150
+ const customImageResponseHeaders = headers.find((header) => { var _a; return (_a = header.for) === null || _a === void 0 ? void 0 : _a.startsWith('/_next/image/'); });
151
+ if (customImageResponseHeaders) {
152
+ return customImageResponseHeaders === null || customImageResponseHeaders === void 0 ? void 0 : customImageResponseHeaders.values;
153
+ }
154
+ return null;
155
+ };
156
+ exports.getCustomImageResponseHeaders = getCustomImageResponseHeaders;
157
+ /* eslint-enable max-lines */
package/lib/index.js CHANGED
@@ -80,6 +80,7 @@ const plugin = {
80
80
  netlifyConfig,
81
81
  basePath,
82
82
  remotePatterns: experimentalRemotePatterns,
83
+ responseHeaders: (0, utils_1.getCustomImageResponseHeaders)(netlifyConfig.headers),
83
84
  });
84
85
  await (0, redirects_1.generateRedirects)({
85
86
  netlifyConfig,
@@ -122,7 +123,6 @@ const plugin = {
122
123
  (0, config_1.generateCustomHeaders)(nextConfig, headers);
123
124
  (0, verification_1.warnForProblematicUserRewrites)({ basePath, redirects });
124
125
  (0, verification_1.warnForRootRedirects)({ appDir });
125
- await (0, files_1.unpatchNextFiles)(basePath);
126
126
  },
127
127
  };
128
128
  module.exports = plugin;
@@ -81,6 +81,13 @@ const makeHandler = (conf, app, pageRoot, staticManifest = [], mode = 'ssr') =>
81
81
  // Next expects to be able to parse the query from the URL
82
82
  const query = new URLSearchParams(event.queryStringParameters).toString();
83
83
  event.path = query ? `${event.path}?${query}` : event.path;
84
+ const graphToken = event.netlifyGraphToken;
85
+ if (graphToken && requestMode !== 'ssr') {
86
+ // Prefix with underscore to help us determine the origin of the token
87
+ // allows us to write better error messages
88
+ // eslint-disable-next-line no-underscore-dangle
89
+ process.env._NETLIFY_GRAPH_TOKEN = graphToken;
90
+ }
84
91
  const { headers, ...result } = await getBridge(event).launcher(event, context);
85
92
  // Convert all headers to multiValueHeaders
86
93
  const multiValueHeaders = getMultiValueHeaders(headers);
@@ -8,5 +8,6 @@ exports.handler = (0, ipx_1.createIPXHandler)({
8
8
  basePath: imageconfig_json_1.basePath,
9
9
  domains: imageconfig_json_1.domains,
10
10
  remotePatterns: imageconfig_json_1.remotePatterns,
11
+ responseHeaders: imageconfig_json_1.responseHeaders,
11
12
  });
12
13
  /* eslint-enable n/no-missing-import, import/no-unresolved, @typescript-eslint/ban-ts-comment */
package/package.json CHANGED
@@ -1,28 +1,16 @@
1
1
  {
2
2
  "name": "@netlify/plugin-nextjs",
3
- "version": "4.14.1",
3
+ "version": "4.16.0",
4
4
  "description": "Run Next.js seamlessly on Netlify",
5
5
  "main": "lib/index.js",
6
6
  "files": [
7
7
  "lib/**/*",
8
8
  "src/templates/edge/*",
9
- "manifest.yml",
10
- "middleware.js"
9
+ "manifest.yml"
11
10
  ],
12
- "typesVersions": {
13
- "*": {
14
- "middleware": [
15
- "dist-types/middleware"
16
- ]
17
- }
18
- },
19
- "exports": {
20
- ".": "./lib/index.js",
21
- "./middleware": "./lib/middleware/index.js"
22
- },
23
11
  "dependencies": {
24
- "@netlify/functions": "^1.0.0",
25
- "@netlify/ipx": "^1.1.3",
12
+ "@netlify/functions": "^1.1.0",
13
+ "@netlify/ipx": "^1.2.1",
26
14
  "@vercel/node-bridge": "^2.1.0",
27
15
  "chalk": "^4.1.2",
28
16
  "fs-extra": "^10.0.0",
@@ -40,7 +28,7 @@
40
28
  },
41
29
  "devDependencies": {
42
30
  "@delucis/if-env": "^1.1.2",
43
- "@netlify/build": "^27.8.1",
31
+ "@netlify/build": "^27.11.4",
44
32
  "@types/fs-extra": "^9.0.13",
45
33
  "@types/jest": "^27.4.1",
46
34
  "@types/node": "^17.0.25",
@@ -63,14 +51,13 @@
63
51
  },
64
52
  "repository": {
65
53
  "type": "git",
66
- "url": "git+https://github.com/netlify/netlify-plugin-nextjs.git"
54
+ "url": "git+https://github.com/netlify/next-runtime.git"
67
55
  },
68
- "author": "",
69
- "license": "ISC",
56
+ "license": "MIT",
70
57
  "bugs": {
71
- "url": "https://github.com/netlify/netlify-plugin-nextjs/issues"
58
+ "url": "https://github.com/netlify/next-runtime/issues"
72
59
  },
73
- "homepage": "https://github.com/netlify/netlify-plugin-nextjs#readme",
60
+ "homepage": "https://github.com/netlify/next-runtime#readme",
74
61
  "engines": {
75
62
  "node": ">=12.0.0"
76
63
  }
@@ -46,9 +46,6 @@ globalThis.NFRequestContextMap ||= new Map()
46
46
 
47
47
  const handler = async (req: Request, context: Context) => {
48
48
  const url = new URL(req.url)
49
- if (url.pathname.startsWith('/_next/static/')) {
50
- return
51
- }
52
49
 
53
50
  const geo = {
54
51
  country: context.geo.country?.code,
@@ -1,4 +0,0 @@
1
- "use strict";
2
- /* eslint-disable max-classes-per-file */
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- /* eslint-enable max-classes-per-file */
@@ -1,19 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./response"), exports);
18
- __exportStar(require("./request"), exports);
19
- __exportStar(require("./html-rewriter"), exports);
@@ -1,64 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MiddlewareRequest = void 0;
4
- const server_1 = require("next/server");
5
- const response_1 = require("./response");
6
- /**
7
- * Supercharge your Next middleware with Netlify Edge Functions
8
- */
9
- class MiddlewareRequest extends Request {
10
- constructor(nextRequest) {
11
- super(nextRequest);
12
- this.nextRequest = nextRequest;
13
- if (!('Deno' in globalThis)) {
14
- throw new Error('MiddlewareRequest only works in a Netlify Edge Function environment');
15
- }
16
- const requestId = nextRequest.headers.get('x-nf-request-id');
17
- if (!requestId) {
18
- throw new Error('Missing x-nf-request-id header');
19
- }
20
- const requestContext = globalThis.NFRequestContextMap.get(requestId);
21
- if (!requestContext) {
22
- throw new Error(`Could not find request context for request id ${requestId}`);
23
- }
24
- this.context = requestContext.context;
25
- this.originalRequest = requestContext.request;
26
- }
27
- // Add the headers to the original request, which will be passed to the origin
28
- applyHeaders() {
29
- this.headers.forEach((value, name) => {
30
- this.originalRequest.headers.set(name, value);
31
- });
32
- }
33
- async next() {
34
- this.applyHeaders();
35
- const response = await this.context.next();
36
- return new response_1.MiddlewareResponse(response);
37
- }
38
- rewrite(destination, init) {
39
- if (typeof destination === 'string' && destination.startsWith('/')) {
40
- destination = new URL(destination, this.url);
41
- }
42
- this.applyHeaders();
43
- return server_1.NextResponse.rewrite(destination, init);
44
- }
45
- get headers() {
46
- return this.nextRequest.headers;
47
- }
48
- get cookies() {
49
- return this.nextRequest.cookies;
50
- }
51
- get geo() {
52
- return this.nextRequest.geo;
53
- }
54
- get ip() {
55
- return this.nextRequest.ip;
56
- }
57
- get nextUrl() {
58
- return this.nextRequest.url;
59
- }
60
- get url() {
61
- return this.nextRequest.url.toString();
62
- }
63
- }
64
- exports.MiddlewareRequest = MiddlewareRequest;
@@ -1,90 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MiddlewareResponse = void 0;
4
- const server_1 = require("next/server");
5
- // A NextResponse that wraps the Netlify origin response
6
- // We can't pass it through directly, because Next disallows returning a response body
7
- class MiddlewareResponse extends server_1.NextResponse {
8
- constructor(originResponse) {
9
- super();
10
- this.originResponse = originResponse;
11
- // These are private in Node when compiling, but we access them in Deno at runtime
12
- Object.defineProperty(this, 'dataTransforms', {
13
- value: [],
14
- enumerable: false,
15
- writable: false,
16
- });
17
- Object.defineProperty(this, 'elementHandlers', {
18
- value: [],
19
- enumerable: false,
20
- writable: false,
21
- });
22
- }
23
- /**
24
- * Transform the page props before they are passed to the client.
25
- * This works for both HTML pages and JSON data
26
- */
27
- transformData(transform) {
28
- // The transforms are evaluated after the middleware is returned
29
- this.dataTransforms.push(transform);
30
- }
31
- /**
32
- * Rewrite the response HTML with the given selector and handlers
33
- */
34
- rewriteHTML(selector, handlers) {
35
- this.elementHandlers.push([selector, handlers]);
36
- }
37
- /**
38
- * Sets the value of a page prop.
39
- * @see transformData if you need more control
40
- */
41
- setPageProp(key, value) {
42
- this.transformData((props) => {
43
- props.pageProps || (props.pageProps = {});
44
- props.pageProps[key] = value;
45
- return props;
46
- });
47
- }
48
- /**
49
- * Replace the text of the given element. Takes either a string or a function
50
- * that is passed the original string and returns new new string.
51
- * @see rewriteHTML for more control
52
- */
53
- replaceText(selector, valueOrReplacer) {
54
- // If it's a string then our job is simpler, because we don't need to collect the current text
55
- if (typeof valueOrReplacer === 'string') {
56
- this.rewriteHTML(selector, {
57
- text(textChunk) {
58
- if (textChunk.lastInTextNode) {
59
- textChunk.replace(valueOrReplacer);
60
- }
61
- else {
62
- textChunk.remove();
63
- }
64
- },
65
- });
66
- }
67
- else {
68
- let text = '';
69
- this.rewriteHTML(selector, {
70
- text(textChunk) {
71
- text += textChunk.text;
72
- // We're finished, so we can replace the text
73
- if (textChunk.lastInTextNode) {
74
- textChunk.replace(valueOrReplacer(text));
75
- }
76
- else {
77
- // Remove the chunk, because we'll be adding it back later
78
- textChunk.remove();
79
- }
80
- },
81
- });
82
- }
83
- }
84
- get headers() {
85
- var _a;
86
- // If we have the origin response, we should use its headers
87
- return ((_a = this.originResponse) === null || _a === void 0 ? void 0 : _a.headers) || super.headers;
88
- }
89
- }
90
- exports.MiddlewareResponse = MiddlewareResponse;