@netlify/plugin-nextjs 4.30.3-als.0 → 4.30.4-ipx-layer.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/helpers/edge.js
CHANGED
|
@@ -36,18 +36,12 @@ const preamble = /* js */ `
|
|
|
36
36
|
import {
|
|
37
37
|
decode as _base64Decode,
|
|
38
38
|
} from "https://deno.land/std@0.159.0/encoding/base64.ts";
|
|
39
|
-
|
|
40
|
-
import { AsyncLocalStorage } from "https://raw.githubusercontent.com/crowlKats/deno_std/asynclocalstorage/node/async_hooks.ts";
|
|
41
|
-
|
|
42
39
|
// Deno defines "window", but naughty libraries think this means it's a browser
|
|
43
40
|
delete globalThis.window
|
|
44
41
|
globalThis.process = { env: {...Deno.env.toObject(), NEXT_RUNTIME: 'edge', 'NEXT_PRIVATE_MINIMAL_MODE': '1' } }
|
|
45
42
|
globalThis.EdgeRuntime = "netlify-edge"
|
|
46
43
|
let _ENTRIES = {}
|
|
47
44
|
|
|
48
|
-
// Next.js expects this as a global
|
|
49
|
-
globalThis.AsyncLocalStorage = AsyncLocalStorage
|
|
50
|
-
|
|
51
45
|
// Next.js uses this extension to the Headers API implemented by Cloudflare workerd
|
|
52
46
|
if(!('getAll' in Headers.prototype)) {
|
|
53
47
|
Headers.prototype.getAll = function getAll(name) {
|
|
@@ -240,6 +234,7 @@ const writeEdgeFunctions = async ({ netlifyConfig, routesManifest, }) => {
|
|
|
240
234
|
var _a;
|
|
241
235
|
const manifest = {
|
|
242
236
|
functions: [],
|
|
237
|
+
layers: [],
|
|
243
238
|
version: 1,
|
|
244
239
|
};
|
|
245
240
|
const edgeFunctionRoot = (0, path_1.resolve)('.netlify', 'edge-functions');
|
|
@@ -262,7 +257,11 @@ const writeEdgeFunctions = async ({ netlifyConfig, routesManifest, }) => {
|
|
|
262
257
|
manifest.functions.push({
|
|
263
258
|
function: 'ipx',
|
|
264
259
|
name: 'next/image handler',
|
|
265
|
-
path: '/_next/image
|
|
260
|
+
path: nextConfig.images.path || '/_next/image',
|
|
261
|
+
});
|
|
262
|
+
manifest.layers.push({
|
|
263
|
+
name: 'https://ipx-edge-function-layer.netlify.app/mod.ts',
|
|
264
|
+
flag: 'ipx-edge-function-layer-url',
|
|
266
265
|
});
|
|
267
266
|
}
|
|
268
267
|
if (!(0, destr_1.default)(process.env.NEXT_DISABLE_NETLIFY_EDGE)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/plugin-nextjs",
|
|
3
|
-
"version": "4.30.
|
|
3
|
+
"version": "4.30.4-ipx-layer.0",
|
|
4
4
|
"description": "Run Next.js seamlessly on Netlify",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@types/jest": "^27.4.1",
|
|
42
42
|
"@types/merge-stream": "^1.1.2",
|
|
43
43
|
"@types/node": "^17.0.25",
|
|
44
|
-
"next": "^13.
|
|
44
|
+
"next": "^13.0.7",
|
|
45
45
|
"npm-run-all": "^4.1.5",
|
|
46
46
|
"typescript": "^4.6.3"
|
|
47
47
|
},
|
|
@@ -1,73 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { Context } from 'https://edge.netlify.com'
|
|
3
|
-
// Available at build time
|
|
4
|
-
import imageconfig from './imageconfig.json' assert { type: 'json' }
|
|
5
|
-
|
|
6
|
-
const defaultFormat = 'webp'
|
|
7
|
-
|
|
8
|
-
interface ImageConfig extends Record<string, unknown> {
|
|
9
|
-
formats?: string[]
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Checks if a URL param is numeric
|
|
13
|
-
const isNumeric = (value: string | null) => Number(value).toString() === value
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Implement content negotiation for images
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
// deno-lint-ignore require-await
|
|
20
|
-
const handler = async (req: Request, context: Context) => {
|
|
21
|
-
const { searchParams } = new URL(req.url)
|
|
22
|
-
const accept = new Accepts(req.headers)
|
|
23
|
-
const { formats = [defaultFormat] } = imageconfig as ImageConfig
|
|
24
|
-
if (formats.length === 0) {
|
|
25
|
-
formats.push(defaultFormat)
|
|
26
|
-
}
|
|
27
|
-
let type = accept.types(formats) || defaultFormat
|
|
28
|
-
if (Array.isArray(type)) {
|
|
29
|
-
type = type[0]
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const source = searchParams.get('url')
|
|
33
|
-
const width = searchParams.get('w')
|
|
34
|
-
const quality = searchParams.get('q') ?? '75'
|
|
1
|
+
import { getHandler } from 'https://ipx-edge-function-layer.netlify.app/mod.ts'
|
|
35
2
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (!source) {
|
|
39
|
-
errors.push('Missing "url" parameter')
|
|
40
|
-
} else if (!source.startsWith('http') && !source.startsWith('/')) {
|
|
41
|
-
errors.push('The "url" parameter must be a valid URL or path')
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (!width) {
|
|
45
|
-
errors.push('Missing "w" parameter')
|
|
46
|
-
} else if (!isNumeric(width)) {
|
|
47
|
-
errors.push('Invalid "w" parameter')
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (!isNumeric(quality)) {
|
|
51
|
-
errors.push('Invalid "q" parameter')
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (!source || errors.length > 0) {
|
|
55
|
-
return new Response(`Invalid request: \n${errors.join('\n')}`, {
|
|
56
|
-
status: 400,
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const modifiers = [`w_${width}`, `q_${quality}`]
|
|
61
|
-
|
|
62
|
-
if (type) {
|
|
63
|
-
if (type.includes('/')) {
|
|
64
|
-
// If this is a mimetype, strip "image/"
|
|
65
|
-
type = type.split('/')[1]
|
|
66
|
-
}
|
|
67
|
-
modifiers.push(`f_${type}`)
|
|
68
|
-
}
|
|
69
|
-
const target = `/_ipx/${modifiers.join(',')}/${encodeURIComponent(source)}`
|
|
70
|
-
return context.rewrite(target)
|
|
71
|
-
}
|
|
3
|
+
import imageconfig from './imageconfig.json' assert { type: 'json' }
|
|
72
4
|
|
|
73
|
-
export default
|
|
5
|
+
export default getHandler({ formats: imageconfig?.formats })
|
|
@@ -42,6 +42,7 @@ export type Rewrite = {
|
|
|
42
42
|
basePath?: false
|
|
43
43
|
locale?: false
|
|
44
44
|
has?: RouteHas[]
|
|
45
|
+
missing?: RouteHas[]
|
|
45
46
|
regex: string
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -51,6 +52,7 @@ export type Header = {
|
|
|
51
52
|
locale?: false
|
|
52
53
|
headers: Array<{ key: string; value: string }>
|
|
53
54
|
has?: RouteHas[]
|
|
55
|
+
missing?: RouteHas[]
|
|
54
56
|
regex: string
|
|
55
57
|
}
|
|
56
58
|
export type Redirect = {
|
|
@@ -59,6 +61,7 @@ export type Redirect = {
|
|
|
59
61
|
basePath?: false
|
|
60
62
|
locale?: false
|
|
61
63
|
has?: RouteHas[]
|
|
64
|
+
missing?: RouteHas[]
|
|
62
65
|
statusCode?: number
|
|
63
66
|
permanent?: boolean
|
|
64
67
|
regex: string
|
|
@@ -138,11 +141,16 @@ export function parseUrl(url: string): ParsedUrl {
|
|
|
138
141
|
|
|
139
142
|
// prepare-destination.ts
|
|
140
143
|
// Changed to use WHATWG Fetch Request instead of IncomingMessage
|
|
141
|
-
export function matchHas(
|
|
144
|
+
export function matchHas(
|
|
145
|
+
req: Pick<Request, 'headers' | 'url'>,
|
|
146
|
+
query: Params,
|
|
147
|
+
has: RouteHas[] = [],
|
|
148
|
+
missing: RouteHas[] = [],
|
|
149
|
+
): false | Params {
|
|
142
150
|
const params: Params = {}
|
|
143
151
|
const cookies = getCookies(req.headers)
|
|
144
152
|
const url = new URL(req.url)
|
|
145
|
-
const
|
|
153
|
+
const hasMatch = (hasItem: RouteHas) => {
|
|
146
154
|
let value: undefined | string | null
|
|
147
155
|
let key = hasItem.key
|
|
148
156
|
|
|
@@ -189,7 +197,9 @@ export function matchHas(req: Pick<Request, 'headers' | 'url'>, has: RouteHas[],
|
|
|
189
197
|
}
|
|
190
198
|
}
|
|
191
199
|
return false
|
|
192
|
-
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const allMatch = has.every((item) => hasMatch(item)) && !missing.some((item) => hasMatch(item))
|
|
193
203
|
|
|
194
204
|
if (allMatch) {
|
|
195
205
|
return params
|
|
@@ -371,6 +381,7 @@ export interface MiddlewareMatcher {
|
|
|
371
381
|
regexp: string
|
|
372
382
|
locale?: false
|
|
373
383
|
has?: RouteHas[]
|
|
384
|
+
missing?: RouteHas[]
|
|
374
385
|
}
|
|
375
386
|
|
|
376
387
|
export function getMiddlewareRouteMatcher(matchers: MiddlewareMatcher[]): MiddlewareRouteMatch {
|
|
@@ -381,8 +392,8 @@ export function getMiddlewareRouteMatcher(matchers: MiddlewareMatcher[]): Middle
|
|
|
381
392
|
continue
|
|
382
393
|
}
|
|
383
394
|
|
|
384
|
-
if (matcher.has) {
|
|
385
|
-
const hasParams = matchHas(req, matcher.has,
|
|
395
|
+
if (matcher.has || matcher.missing) {
|
|
396
|
+
const hasParams = matchHas(req, query, matcher.has, matcher.missing)
|
|
386
397
|
if (!hasParams) {
|
|
387
398
|
continue
|
|
388
399
|
}
|