From 0bc1401d224cea9c9fb3de14d91160cd7d7081a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Ara=C3=BAjo?= <4138302+paulo@users.noreply.github.com> Date: Fri, 29 Dec 2023 15:16:23 +0100 Subject: [PATCH 1/5] fix: include identity context data under custom netlify client context (#6277) --- src/lib/functions/server.ts | 38 +++++++++++++------ .../commands/dev/dev-miscellaneous.test.js | 30 +++++++++++++++ 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/lib/functions/server.ts b/src/lib/functions/server.ts index 05aefd9e9ff..de4ea543ef7 100644 --- a/src/lib/functions/server.ts +++ b/src/lib/functions/server.ts @@ -34,21 +34,35 @@ const buildClientContext = function (headers) { const parts = headers.authorization.split(' ') if (parts.length !== 2 || parts[0] !== 'Bearer') return + const identity = { + url: 'https://netlify-dev-locally-emulated-identity.netlify.com/.netlify/identity', + token: + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJuZXRsaWZ5IGRldiIsInRlc3REYXRhIjoiTkVUTElGWV9ERVZfTE9DQUxMWV9FTVVMQVRFRF9JREVOVElUWSJ9.2eSDqUOZAOBsx39FHFePjYj12k0LrxldvGnlvDu3GMI', + // you can decode this with https://jwt.io/ + // just says + // { + // "source": "netlify dev", + // "testData": "NETLIFY_DEV_LOCALLY_EMULATED_IDENTITY" + // } + } + + // This data is available on both the context root and under custom.netlify for retro-compatibility. + // In the future it will only be available in custom.netlify. + // @ts-expect-error + const user = jwtDecode(parts[1]) + + const netlifyContext = JSON.stringify({ + identity: identity, + user: user, + }) + try { return { - identity: { - url: 'https://netlify-dev-locally-emulated-identity.netlify.com/.netlify/identity', - token: - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJuZXRsaWZ5IGRldiIsInRlc3REYXRhIjoiTkVUTElGWV9ERVZfTE9DQUxMWV9FTVVMQVRFRF9JREVOVElUWSJ9.2eSDqUOZAOBsx39FHFePjYj12k0LrxldvGnlvDu3GMI', - // you can decode this with https://jwt.io/ - // just says - // { - // "source": "netlify dev", - // "testData": "NETLIFY_DEV_LOCALLY_EMULATED_IDENTITY" - // } + identity: identity, + user: user, + custom: { + netlify: Buffer.from(netlifyContext).toString('base64'), }, - // @ts-expect-error - user: jwtDecode(parts[1]), } } catch { // Ignore errors - bearer token is not a JWT, probably not intended for us diff --git a/tests/integration/commands/dev/dev-miscellaneous.test.js b/tests/integration/commands/dev/dev-miscellaneous.test.js index 56e2104346b..5b3e40440de 100644 --- a/tests/integration/commands/dev/dev-miscellaneous.test.js +++ b/tests/integration/commands/dev/dev-miscellaneous.test.js @@ -1,3 +1,4 @@ +import { Buffer } from 'buffer' import path from 'path' import { fileURLToPath } from 'url' @@ -151,6 +152,35 @@ describe.concurrent('commands/dev-miscellaneous', () => { }) }) + test('function clientContext.custom.netlify should be set', async (t) => { + await withSiteBuilder('site-with-function', async (builder) => { + await builder + .withNetlifyToml({ config: { functions: { directory: 'functions' } } }) + .withFunction({ + path: 'hello.js', + handler: async (_, context) => ({ + statusCode: 200, + body: JSON.stringify(context), + }), + }) + .buildAsync() + + await withDevServer({ cwd: builder.directory }, async (server) => { + const response = await fetch(`${server.url}/.netlify/functions/hello`, { + headers: { + Authorization: + 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJuZXRsaWZ5IGRldiIsInRlc3REYXRhIjoiTkVUTElGWV9ERVZfTE9DQUxMWV9FTVVMQVRFRF9JREVOVElUWSJ9.2eSDqUOZAOBsx39FHFePjYj12k0LrxldvGnlvDu3GMI', + }, + }).then((res) => res.json()) + + const netlifyContext = Buffer.from(response.clientContext.custom.netlify, 'base64').toString() + t.expect(JSON.parse(netlifyContext).identity.url).toEqual( + 'https://netlify-dev-locally-emulated-identity.netlify.com/.netlify/identity', + ) + }) + }) + }) + test('should enforce role based redirects with default secret and role path', async (t) => { await withSiteBuilder('site-with-default-role-based-redirects', async (builder) => { setupRoleBasedRedirectsSite(builder) From 8c1084ce4accef2369dc85d0f705526852603484 Mon Sep 17 00:00:00 2001 From: "token-generator-app[bot]" <82042599+token-generator-app[bot]@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:31:59 +0000 Subject: [PATCH 2/5] chore(main): release 17.10.2 (#6270) Co-authored-by: token-generator-app[bot] <82042599+token-generator-app[bot]@users.noreply.github.com> --- CHANGELOG.md | 9 +++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 277f62a51b5..1f429981aa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,15 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +## [17.10.2](https://github.com/netlify/cli/compare/v17.10.1...v17.10.2) (2023-12-29) + + +### Bug Fixes + +* clear `dist` directory before Dev for Nuxt ([#6242](https://github.com/netlify/cli/issues/6242)) ([6014df5](https://github.com/netlify/cli/commit/6014df5d6ec27948247d2835c3bb41e33d265c16)) +* don't show workspace selection if there is only one package ([#6271](https://github.com/netlify/cli/issues/6271)) ([5d6bcf3](https://github.com/netlify/cli/commit/5d6bcf3c8afdcd53f6f98c969c8abd3958a082be)) +* include identity context data under custom netlify client context ([#6277](https://github.com/netlify/cli/issues/6277)) ([0bc1401](https://github.com/netlify/cli/commit/0bc1401d224cea9c9fb3de14d91160cd7d7081a0)) + ## [17.10.1](https://github.com/netlify/cli/compare/v17.10.0...v17.10.1) (2023-12-08) diff --git a/package-lock.json b/package-lock.json index 23b7b13a90e..078235a378a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "netlify-cli", - "version": "17.10.1", + "version": "17.10.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "netlify-cli", - "version": "17.10.1", + "version": "17.10.2", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 8b1c0070923..48d002a4daf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "netlify-cli", "description": "Netlify command line tool", - "version": "17.10.1", + "version": "17.10.2", "author": "Netlify Inc.", "type": "module", "engines": { From d74c00d431a8cf2180364eb37459d4e037b863ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Tue, 2 Jan 2024 14:00:30 +0000 Subject: [PATCH 3/5] fix: support Blobs in unlinked sites (#6279) --- src/lib/blobs/blobs.ts | 2 +- src/lib/functions/server.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/blobs/blobs.ts b/src/lib/blobs/blobs.ts index 518b3e831fa..94e9bdf8f1a 100644 --- a/src/lib/blobs/blobs.ts +++ b/src/lib/blobs/blobs.ts @@ -28,7 +28,7 @@ const printLocalBlobsNotice = () => { } const startBlobsServer = async (debug: boolean, projectRoot: string, token: string) => { - const directory = path.resolve(projectRoot, getPathInProject(['blobs-serves'])) + const directory = path.resolve(projectRoot, getPathInProject(['blobs-serve'])) const server = new BlobsServer({ debug, directory, diff --git a/src/lib/functions/server.ts b/src/lib/functions/server.ts index de4ea543ef7..900fb25b132 100644 --- a/src/lib/functions/server.ts +++ b/src/lib/functions/server.ts @@ -157,7 +157,7 @@ export const createHandler = function (options) { 'client-ip': [remoteAddress], 'x-nf-client-connection-ip': [remoteAddress], 'x-nf-account-id': [options.accountId], - 'x-nf-site-id': [options?.siteInfo?.id] ?? 'unlinked', + 'x-nf-site-id': [options?.siteInfo?.id ?? 'unlinked'], [efHeaders.Geo]: Buffer.from(JSON.stringify(geoLocation)).toString('base64'), }).reduce((prev, [key, value]) => ({ ...prev, [key]: Array.isArray(value) ? value : [value] }), {}) const rawQuery = new URLSearchParams(requestQuery).toString() From 02e1069a81f508320ff5a48e3d68f490c50093af Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 2 Jan 2024 16:19:42 +0100 Subject: [PATCH 4/5] feat: detect internal functions created after dev server already started (#6257) * refactor: store projectDir as class member * fix: always scan for internal edge functions * refactor: add some types * fix: scan for declarations in deployconfig * refactor: some typescript * fix: always watch internal functions dir this has the side-effect that we're *always* starting the function server! * refactor: some cleanup now that we're always starting the functions server * chore: prettier * fix: read import map from deploy config at runtime * chore: remove unused code * chore: prettier * fix: check if import_map is defined * fix: deploying needs functions-internal folder even if empty * fix: functions server is now always started * chore: remove dangling console.error * chore: fix some more types * chore: fix some more types * fix: site root always exists * chore: more types * chore: mooore types * chore: moar types * fix: implement precedence for user functions before this commit, we were relying on the order of calling `scanDirectories` to set things up right. now that internal functions can be added during dev, we need to handle precedence more explicitly! * chore: prettier * fix: try removing clash in sitenames * chore: debug this schmu * fix: try awaiting the expectation * refactor: use build instead of deprecated buildAsync * chore: disable ssh * chore: prettier * fix: one more try * fix: this time I got you! * fix: root is not always defined * fix: make builderror type error --- package-lock.json | 1408 +++++++++++++---- package.json | 2 +- src/commands/deploy/deploy.ts | 14 +- src/commands/serve/serve.ts | 4 + src/lib/edge-functions/internal.ts | 54 - src/lib/edge-functions/proxy.ts | 35 +- src/lib/edge-functions/registry.ts | 66 +- src/lib/functions/netlify-function.ts | 9 +- src/lib/functions/registry.ts | 67 +- src/lib/functions/runtimes/index.ts | 62 +- src/lib/functions/server.ts | 3 +- src/utils/deploy/deploy-site.ts | 16 +- src/utils/detect-server-settings.ts | 121 +- src/utils/functions/functions.ts | 20 +- src/utils/types.d.ts | 5 +- .../integration-iscA.ts | 0 .../integration-iscB.ts | 0 .../integration-manifestA.ts | 0 .../integration-manifestB.ts | 0 .../integration-manifestC.ts | 0 .../manifest.json | 0 .../commands/dev/dev-miscellaneous.test.js | 78 +- .../integration/commands/dev/dev.zisi.test.js | 47 +- .../commands/dev/edge-functions.test.ts | 177 ++- .../functions-with-args.test.js | 46 +- tests/integration/utils/dev-server.ts | 2 +- tests/integration/utils/fixture.ts | 10 +- 27 files changed, 1469 insertions(+), 777 deletions(-) delete mode 100644 src/lib/edge-functions/internal.ts rename tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/{edge-functions => _edge-functions}/integration-iscA.ts (100%) rename tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/{edge-functions => _edge-functions}/integration-iscB.ts (100%) rename tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/{edge-functions => _edge-functions}/integration-manifestA.ts (100%) rename tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/{edge-functions => _edge-functions}/integration-manifestB.ts (100%) rename tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/{edge-functions => _edge-functions}/integration-manifestC.ts (100%) rename tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/{edge-functions => _edge-functions}/manifest.json (100%) diff --git a/package-lock.json b/package-lock.json index 078235a378a..c216374bcae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@netlify/build": "29.31.0", "@netlify/build-info": "7.11.3", "@netlify/config": "20.10.0", - "@netlify/edge-bundler": "10.1.3", + "@netlify/edge-bundler": "11.0.0", "@netlify/local-functions-proxy": "1.1.1", "@netlify/zip-it-and-ship-it": "9.28.1", "@octokit/rest": "19.0.13", @@ -2446,175 +2446,633 @@ "node": ">= 14" } }, - "node_modules/@netlify/build/node_modules/@opentelemetry/core": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.18.1.tgz", - "integrity": "sha512-kvnUqezHMhsQvdsnhnqTNfAJs3ox/isB0SVrM1dhVFw7SsB7TstuVa6fgWnN2GdPyilIFLUvvbTZoVRmx6eiRg==", - "dependencies": { - "@opentelemetry/semantic-conventions": "1.18.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.8.0" - } - }, - "node_modules/@netlify/build/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.18.1.tgz", - "integrity": "sha512-+NLGHr6VZwcgE/2lw8zDIufOCGnzsA5CbQIMleXZTrgkBd0TanCX+MiDYJ1TOS4KL/Tqk0nFRxawnaYr6pkZkA==", + "node_modules/@netlify/build/node_modules/@esbuild/android-arm": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.6.tgz", + "integrity": "sha512-muPzBqXJKCbMYoNbb1JpZh/ynl0xS6/+pLjrofcR3Nad82SbsCogYzUE6Aq9QT3cLP0jR/IVK/NHC9b90mSHtg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=14" + "node": ">=12" } }, - "node_modules/@netlify/build/node_modules/@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "node_modules/@netlify/build/node_modules/@esbuild/android-arm64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.6.tgz", + "integrity": "sha512-KQ/hbe9SJvIJ4sR+2PcZ41IBV+LPJyYp6V1K1P1xcMRup9iYsBoQn4MzE3mhMLOld27Au2eDcLlIREeKGUXpHQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "node": ">=12" } }, - "node_modules/@netlify/build/node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dependencies": { - "defer-to-connect": "^2.0.1" - }, + "node_modules/@netlify/build/node_modules/@esbuild/android-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.6.tgz", + "integrity": "sha512-VVJVZQ7p5BBOKoNxd0Ly3xUM78Y4DyOoFKdkdAe2m11jbh0LEU4bPles4e/72EMl4tapko8o915UalN/5zhspg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=14.16" + "node": ">=12" } }, - "node_modules/@netlify/build/node_modules/cacheable-lookup": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", - "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "node_modules/@netlify/build/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.6.tgz", + "integrity": "sha512-91LoRp/uZAKx6ESNspL3I46ypwzdqyDLXZH7x2QYCLgtnaU08+AXEbabY2yExIz03/am0DivsTtbdxzGejfXpA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14.16" + "node": ">=12" } }, - "node_modules/@netlify/build/node_modules/cacheable-request": { - "version": "10.2.14", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", - "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", - "dependencies": { - "@types/http-cache-semantics": "^4.0.2", - "get-stream": "^6.0.1", - "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.3", - "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", - "responselike": "^3.0.0" - }, + "node_modules/@netlify/build/node_modules/@esbuild/darwin-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.6.tgz", + "integrity": "sha512-QCGHw770ubjBU1J3ZkFJh671MFajGTYMZumPs9E/rqU52md6lIil97BR0CbPq6U+vTh3xnTNDHKRdR8ggHnmxQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14.16" + "node": ">=12" } }, - "node_modules/@netlify/build/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/@netlify/build/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "node_modules/@netlify/build/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.6.tgz", + "integrity": "sha512-J53d0jGsDcLzWk9d9SPmlyF+wzVxjXpOH7jVW5ae7PvrDst4kiAz6sX+E8btz0GB6oH12zC+aHRD945jdjF2Vg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], "engines": { "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@netlify/build/node_modules/execa": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", - "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^3.0.1", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, + "node_modules/@netlify/build/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.6.tgz", + "integrity": "sha512-hn9qvkjHSIB5Z9JgCCjED6YYVGCNpqB7dEGavBdG6EjBD8S/UcNUIlGcB35NCkMETkdYwfZSvD9VoDJX6VeUVA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">=12" } }, - "node_modules/@netlify/build/node_modules/figures": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", - "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", - "dependencies": { - "escape-string-regexp": "^5.0.0", - "is-unicode-supported": "^1.2.0" - }, + "node_modules/@netlify/build/node_modules/@esbuild/linux-arm": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.6.tgz", + "integrity": "sha512-G8IR5zFgpXad/Zp7gr7ZyTKyqZuThU6z1JjmRyN1vSF8j0bOlGzUwFSMTbctLAdd7QHpeyu0cRiuKrqK1ZTwvQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/@netlify/build/node_modules/got": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", - "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, + "node_modules/@netlify/build/node_modules/@esbuild/linux-arm64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.6.tgz", + "integrity": "sha512-HQCOrk9XlH3KngASLaBfHpcoYEGUt829A9MyxaI8RMkfRA8SakG6YQEITAuwmtzFdEu5GU4eyhKcpv27dFaOBg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" + "node": ">=12" } }, - "node_modules/@netlify/build/node_modules/http2-wrapper": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - }, + "node_modules/@netlify/build/node_modules/@esbuild/linux-ia32": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.6.tgz", + "integrity": "sha512-22eOR08zL/OXkmEhxOfshfOGo8P69k8oKHkwkDrUlcB12S/sw/+COM4PhAPT0cAYW/gpqY2uXp3TpjQVJitz7w==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10.19.0" + "node": ">=12" } }, - "node_modules/@netlify/build/node_modules/human-signals": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", - "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "node_modules/@netlify/build/node_modules/@esbuild/linux-loong64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.6.tgz", + "integrity": "sha512-82RvaYAh/SUJyjWA8jDpyZCHQjmEggL//sC7F3VKYcBMumQjUL3C5WDl/tJpEiKtt7XrWmgjaLkrk205zfvwTA==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12.20.0" + "node": ">=12" } }, - "node_modules/@netlify/build/node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "node_modules/@netlify/build/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.6.tgz", + "integrity": "sha512-8tvnwyYJpR618vboIv2l8tK2SuK/RqUIGMfMENkeDGo3hsEIrpGldMGYFcWxWeEILe5Fi72zoXLmhZ7PR23oQA==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@netlify/build/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.6.tgz", + "integrity": "sha512-Qt+D7xiPajxVNk5tQiEJwhmarNnLPdjXAoA5uWMpbfStZB0+YU6a3CtbWYSy+sgAsnyx4IGZjWsTzBzrvg/fMA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@netlify/build/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.6.tgz", + "integrity": "sha512-lxRdk0iJ9CWYDH1Wpnnnc640ajF4RmQ+w6oHFZmAIYu577meE9Ka/DCtpOrwr9McMY11ocbp4jirgGgCi7Ls/g==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@netlify/build/node_modules/@esbuild/linux-s390x": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.6.tgz", + "integrity": "sha512-MopyYV39vnfuykHanRWHGRcRC3AwU7b0QY4TI8ISLfAGfK+tMkXyFuyT1epw/lM0pflQlS53JoD22yN83DHZgA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@netlify/build/node_modules/@esbuild/linux-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.6.tgz", + "integrity": "sha512-UWcieaBzsN8WYbzFF5Jq7QULETPcQvlX7KL4xWGIB54OknXJjBO37sPqk7N82WU13JGWvmDzFBi1weVBajPovg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@netlify/build/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.6.tgz", + "integrity": "sha512-EpWiLX0fzvZn1wxtLxZrEW+oQED9Pwpnh+w4Ffv8ZLuMhUoqR9q9rL4+qHW8F4Mg5oQEKxAoT0G+8JYNqCiR6g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@netlify/build/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.6.tgz", + "integrity": "sha512-fFqTVEktM1PGs2sLKH4M5mhAVEzGpeZJuasAMRnvDZNCV0Cjvm1Hu35moL2vC0DOrAQjNTvj4zWrol/lwQ8Deg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@netlify/build/node_modules/@esbuild/sunos-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.6.tgz", + "integrity": "sha512-M+XIAnBpaNvaVAhbe3uBXtgWyWynSdlww/JNZws0FlMPSBy+EpatPXNIlKAdtbFVII9OpX91ZfMb17TU3JKTBA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@netlify/build/node_modules/@esbuild/win32-arm64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.6.tgz", + "integrity": "sha512-2DchFXn7vp/B6Tc2eKdTsLzE0ygqKkNUhUBCNtMx2Llk4POIVMUq5rUYjdcedFlGLeRe1uLCpVvCmE+G8XYybA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@netlify/build/node_modules/@esbuild/win32-ia32": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.6.tgz", + "integrity": "sha512-PBo/HPDQllyWdjwAVX+Gl2hH0dfBydL97BAH/grHKC8fubqp02aL4S63otZ25q3sBdINtOBbz1qTZQfXbP4VBg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@netlify/build/node_modules/@esbuild/win32-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.6.tgz", + "integrity": "sha512-OE7yIdbDif2kKfrGa+V0vx/B3FJv2L4KnIiLlvtibPyO9UkgO3rzYE0HhpREo2vmJ1Ixq1zwm9/0er+3VOSZJA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@netlify/build/node_modules/@netlify/edge-bundler": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/@netlify/edge-bundler/-/edge-bundler-10.1.3.tgz", + "integrity": "sha512-+cFFUrdbkhbtmpvQlRam4CmNguKBjte7usNXO1IxDmExeYxdwkDWWBCjOO4zd/D12TIC3HSJGJjT76GkF+RwTg==", + "dependencies": { + "@import-maps/resolve": "^1.0.1", + "@vercel/nft": "^0.24.3", + "ajv": "^8.11.2", + "ajv-errors": "^3.0.0", + "better-ajv-errors": "^1.2.0", + "common-path-prefix": "^3.0.0", + "env-paths": "^3.0.0", + "esbuild": "0.19.6", + "execa": "^6.0.0", + "find-up": "^6.3.0", + "get-package-name": "^2.2.0", + "get-port": "^6.1.2", + "is-path-inside": "^4.0.0", + "jsonc-parser": "^3.2.0", + "node-fetch": "^3.1.1", + "node-stream-zip": "^1.15.0", + "p-retry": "^5.1.1", + "p-wait-for": "^4.1.0", + "path-key": "^4.0.0", + "regexp-tree": "^0.1.24", + "semver": "^7.3.8", + "tmp-promise": "^3.0.3", + "urlpattern-polyfill": "8.0.2", + "uuid": "^9.0.0" + }, + "engines": { + "node": "^14.16.0 || >=16.0.0" + } + }, + "node_modules/@netlify/build/node_modules/@opentelemetry/core": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.18.1.tgz", + "integrity": "sha512-kvnUqezHMhsQvdsnhnqTNfAJs3ox/isB0SVrM1dhVFw7SsB7TstuVa6fgWnN2GdPyilIFLUvvbTZoVRmx6eiRg==", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.18.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.8.0" + } + }, + "node_modules/@netlify/build/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.18.1.tgz", + "integrity": "sha512-+NLGHr6VZwcgE/2lw8zDIufOCGnzsA5CbQIMleXZTrgkBd0TanCX+MiDYJ1TOS4KL/Tqk0nFRxawnaYr6pkZkA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@netlify/build/node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@netlify/build/node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@netlify/build/node_modules/@vercel/nft": { + "version": "0.24.4", + "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.24.4.tgz", + "integrity": "sha512-KjYAZty7boH5fi5udp6p+lNu6nawgs++pHW+3koErMgbRkkHuToGX/FwjN5clV1FcaM3udfd4zW/sUapkMgpZw==", + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.5", + "@rollup/pluginutils": "^4.0.0", + "acorn": "^8.6.0", + "async-sema": "^3.1.1", + "bindings": "^1.4.0", + "estree-walker": "2.0.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.2", + "node-gyp-build": "^4.2.2", + "resolve-from": "^5.0.0" + }, + "bin": { + "nft": "out/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@netlify/build/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@netlify/build/node_modules/ajv-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", + "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==", + "peerDependencies": { + "ajv": "^8.0.1" + } + }, + "node_modules/@netlify/build/node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@netlify/build/node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "dependencies": { + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@netlify/build/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@netlify/build/node_modules/esbuild": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.6.tgz", + "integrity": "sha512-Xl7dntjA2OEIvpr9j0DVxxnog2fyTGnyVoQXAMQI6eR3mf9zCQds7VIKUDCotDgE/p4ncTgeRqgX8t5d6oP4Gw==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.6", + "@esbuild/android-arm64": "0.19.6", + "@esbuild/android-x64": "0.19.6", + "@esbuild/darwin-arm64": "0.19.6", + "@esbuild/darwin-x64": "0.19.6", + "@esbuild/freebsd-arm64": "0.19.6", + "@esbuild/freebsd-x64": "0.19.6", + "@esbuild/linux-arm": "0.19.6", + "@esbuild/linux-arm64": "0.19.6", + "@esbuild/linux-ia32": "0.19.6", + "@esbuild/linux-loong64": "0.19.6", + "@esbuild/linux-mips64el": "0.19.6", + "@esbuild/linux-ppc64": "0.19.6", + "@esbuild/linux-riscv64": "0.19.6", + "@esbuild/linux-s390x": "0.19.6", + "@esbuild/linux-x64": "0.19.6", + "@esbuild/netbsd-x64": "0.19.6", + "@esbuild/openbsd-x64": "0.19.6", + "@esbuild/sunos-x64": "0.19.6", + "@esbuild/win32-arm64": "0.19.6", + "@esbuild/win32-ia32": "0.19.6", + "@esbuild/win32-x64": "0.19.6" + } + }, + "node_modules/@netlify/build/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@netlify/build/node_modules/execa": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@netlify/build/node_modules/figures": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", + "dependencies": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@netlify/build/node_modules/get-port": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.1.2.tgz", + "integrity": "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@netlify/build/node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/@netlify/build/node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/@netlify/build/node_modules/human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@netlify/build/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "engines": { "node": ">=12" @@ -2623,6 +3081,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@netlify/build/node_modules/is-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@netlify/build/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/@netlify/build/node_modules/lowercase-keys": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", @@ -2759,6 +3233,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@netlify/build/node_modules/p-timeout": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", + "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@netlify/build/node_modules/p-wait-for": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-4.1.0.tgz", + "integrity": "sha512-i8nE5q++9h8oaQHWltS1Tnnv4IoMDOlqN7C0KFG2OdbK0iFJIt6CROZ8wfBM+K4Pxqfnq4C4lkkpXqTEpB5DZw==", + "dependencies": { + "p-timeout": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@netlify/build/node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -3121,9 +3620,9 @@ } }, "node_modules/@netlify/edge-bundler": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/@netlify/edge-bundler/-/edge-bundler-10.1.3.tgz", - "integrity": "sha512-+cFFUrdbkhbtmpvQlRam4CmNguKBjte7usNXO1IxDmExeYxdwkDWWBCjOO4zd/D12TIC3HSJGJjT76GkF+RwTg==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@netlify/edge-bundler/-/edge-bundler-11.0.0.tgz", + "integrity": "sha512-DPFkzQmdZR/1a3jUaZMbxk79N6PEtqhxEvx6x5wISegqkeM9DPNe+PQIBFXpsAwIeb9MB1RU7vliT1hIRt8DBg==", "dependencies": { "@import-maps/resolve": "^1.0.1", "@vercel/nft": "^0.24.3", @@ -3132,7 +3631,7 @@ "better-ajv-errors": "^1.2.0", "common-path-prefix": "^3.0.0", "env-paths": "^3.0.0", - "esbuild": "0.19.6", + "esbuild": "0.19.9", "execa": "^6.0.0", "find-up": "^6.3.0", "get-package-name": "^2.2.0", @@ -3155,9 +3654,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/android-arm": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.6.tgz", - "integrity": "sha512-muPzBqXJKCbMYoNbb1JpZh/ynl0xS6/+pLjrofcR3Nad82SbsCogYzUE6Aq9QT3cLP0jR/IVK/NHC9b90mSHtg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.9.tgz", + "integrity": "sha512-jkYjjq7SdsWuNI6b5quymW0oC83NN5FdRPuCbs9HZ02mfVdAP8B8eeqLSYU3gb6OJEaY5CQabtTFbqBf26H3GA==", "cpu": [ "arm" ], @@ -3170,9 +3669,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/android-arm64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.6.tgz", - "integrity": "sha512-KQ/hbe9SJvIJ4sR+2PcZ41IBV+LPJyYp6V1K1P1xcMRup9iYsBoQn4MzE3mhMLOld27Au2eDcLlIREeKGUXpHQ==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.9.tgz", + "integrity": "sha512-q4cR+6ZD0938R19MyEW3jEsMzbb/1rulLXiNAJQADD/XYp7pT+rOS5JGxvpRW8dFDEfjW4wLgC/3FXIw4zYglQ==", "cpu": [ "arm64" ], @@ -3185,9 +3684,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/android-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.6.tgz", - "integrity": "sha512-VVJVZQ7p5BBOKoNxd0Ly3xUM78Y4DyOoFKdkdAe2m11jbh0LEU4bPles4e/72EMl4tapko8o915UalN/5zhspg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.9.tgz", + "integrity": "sha512-KOqoPntWAH6ZxDwx1D6mRntIgZh9KodzgNOy5Ebt9ghzffOk9X2c1sPwtM9P+0eXbefnDhqYfkh5PLP5ULtWFA==", "cpu": [ "x64" ], @@ -3200,9 +3699,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/darwin-arm64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.6.tgz", - "integrity": "sha512-91LoRp/uZAKx6ESNspL3I46ypwzdqyDLXZH7x2QYCLgtnaU08+AXEbabY2yExIz03/am0DivsTtbdxzGejfXpA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.9.tgz", + "integrity": "sha512-KBJ9S0AFyLVx2E5D8W0vExqRW01WqRtczUZ8NRu+Pi+87opZn5tL4Y0xT0mA4FtHctd0ZgwNoN639fUUGlNIWw==", "cpu": [ "arm64" ], @@ -3215,9 +3714,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/darwin-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.6.tgz", - "integrity": "sha512-QCGHw770ubjBU1J3ZkFJh671MFajGTYMZumPs9E/rqU52md6lIil97BR0CbPq6U+vTh3xnTNDHKRdR8ggHnmxQ==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.9.tgz", + "integrity": "sha512-vE0VotmNTQaTdX0Q9dOHmMTao6ObjyPm58CHZr1UK7qpNleQyxlFlNCaHsHx6Uqv86VgPmR4o2wdNq3dP1qyDQ==", "cpu": [ "x64" ], @@ -3230,9 +3729,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.6.tgz", - "integrity": "sha512-J53d0jGsDcLzWk9d9SPmlyF+wzVxjXpOH7jVW5ae7PvrDst4kiAz6sX+E8btz0GB6oH12zC+aHRD945jdjF2Vg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.9.tgz", + "integrity": "sha512-uFQyd/o1IjiEk3rUHSwUKkqZwqdvuD8GevWF065eqgYfexcVkxh+IJgwTaGZVu59XczZGcN/YMh9uF1fWD8j1g==", "cpu": [ "arm64" ], @@ -3245,9 +3744,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/freebsd-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.6.tgz", - "integrity": "sha512-hn9qvkjHSIB5Z9JgCCjED6YYVGCNpqB7dEGavBdG6EjBD8S/UcNUIlGcB35NCkMETkdYwfZSvD9VoDJX6VeUVA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.9.tgz", + "integrity": "sha512-WMLgWAtkdTbTu1AWacY7uoj/YtHthgqrqhf1OaEWnZb7PQgpt8eaA/F3LkV0E6K/Lc0cUr/uaVP/49iE4M4asA==", "cpu": [ "x64" ], @@ -3260,9 +3759,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/linux-arm": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.6.tgz", - "integrity": "sha512-G8IR5zFgpXad/Zp7gr7ZyTKyqZuThU6z1JjmRyN1vSF8j0bOlGzUwFSMTbctLAdd7QHpeyu0cRiuKrqK1ZTwvQ==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.9.tgz", + "integrity": "sha512-C/ChPohUYoyUaqn1h17m/6yt6OB14hbXvT8EgM1ZWaiiTYz7nWZR0SYmMnB5BzQA4GXl3BgBO1l8MYqL/He3qw==", "cpu": [ "arm" ], @@ -3275,9 +3774,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/linux-arm64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.6.tgz", - "integrity": "sha512-HQCOrk9XlH3KngASLaBfHpcoYEGUt829A9MyxaI8RMkfRA8SakG6YQEITAuwmtzFdEu5GU4eyhKcpv27dFaOBg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.9.tgz", + "integrity": "sha512-PiPblfe1BjK7WDAKR1Cr9O7VVPqVNpwFcPWgfn4xu0eMemzRp442hXyzF/fSwgrufI66FpHOEJk0yYdPInsmyQ==", "cpu": [ "arm64" ], @@ -3290,9 +3789,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/linux-ia32": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.6.tgz", - "integrity": "sha512-22eOR08zL/OXkmEhxOfshfOGo8P69k8oKHkwkDrUlcB12S/sw/+COM4PhAPT0cAYW/gpqY2uXp3TpjQVJitz7w==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.9.tgz", + "integrity": "sha512-f37i/0zE0MjDxijkPSQw1CO/7C27Eojqb+r3BbHVxMLkj8GCa78TrBZzvPyA/FNLUMzP3eyHCVkAopkKVja+6Q==", "cpu": [ "ia32" ], @@ -3305,9 +3804,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/linux-loong64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.6.tgz", - "integrity": "sha512-82RvaYAh/SUJyjWA8jDpyZCHQjmEggL//sC7F3VKYcBMumQjUL3C5WDl/tJpEiKtt7XrWmgjaLkrk205zfvwTA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.9.tgz", + "integrity": "sha512-t6mN147pUIf3t6wUt3FeumoOTPfmv9Cc6DQlsVBpB7eCpLOqQDyWBP1ymXn1lDw4fNUSb/gBcKAmvTP49oIkaA==", "cpu": [ "loong64" ], @@ -3320,9 +3819,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/linux-mips64el": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.6.tgz", - "integrity": "sha512-8tvnwyYJpR618vboIv2l8tK2SuK/RqUIGMfMENkeDGo3hsEIrpGldMGYFcWxWeEILe5Fi72zoXLmhZ7PR23oQA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.9.tgz", + "integrity": "sha512-jg9fujJTNTQBuDXdmAg1eeJUL4Jds7BklOTkkH80ZgQIoCTdQrDaHYgbFZyeTq8zbY+axgptncko3v9p5hLZtw==", "cpu": [ "mips64el" ], @@ -3335,9 +3834,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/linux-ppc64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.6.tgz", - "integrity": "sha512-Qt+D7xiPajxVNk5tQiEJwhmarNnLPdjXAoA5uWMpbfStZB0+YU6a3CtbWYSy+sgAsnyx4IGZjWsTzBzrvg/fMA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.9.tgz", + "integrity": "sha512-tkV0xUX0pUUgY4ha7z5BbDS85uI7ABw3V1d0RNTii7E9lbmV8Z37Pup2tsLV46SQWzjOeyDi1Q7Wx2+QM8WaCQ==", "cpu": [ "ppc64" ], @@ -3350,9 +3849,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/linux-riscv64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.6.tgz", - "integrity": "sha512-lxRdk0iJ9CWYDH1Wpnnnc640ajF4RmQ+w6oHFZmAIYu577meE9Ka/DCtpOrwr9McMY11ocbp4jirgGgCi7Ls/g==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.9.tgz", + "integrity": "sha512-DfLp8dj91cufgPZDXr9p3FoR++m3ZJ6uIXsXrIvJdOjXVREtXuQCjfMfvmc3LScAVmLjcfloyVtpn43D56JFHg==", "cpu": [ "riscv64" ], @@ -3365,9 +3864,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/linux-s390x": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.6.tgz", - "integrity": "sha512-MopyYV39vnfuykHanRWHGRcRC3AwU7b0QY4TI8ISLfAGfK+tMkXyFuyT1epw/lM0pflQlS53JoD22yN83DHZgA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.9.tgz", + "integrity": "sha512-zHbglfEdC88KMgCWpOl/zc6dDYJvWGLiUtmPRsr1OgCViu3z5GncvNVdf+6/56O2Ca8jUU+t1BW261V6kp8qdw==", "cpu": [ "s390x" ], @@ -3380,9 +3879,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/linux-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.6.tgz", - "integrity": "sha512-UWcieaBzsN8WYbzFF5Jq7QULETPcQvlX7KL4xWGIB54OknXJjBO37sPqk7N82WU13JGWvmDzFBi1weVBajPovg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.9.tgz", + "integrity": "sha512-JUjpystGFFmNrEHQnIVG8hKwvA2DN5o7RqiO1CVX8EN/F/gkCjkUMgVn6hzScpwnJtl2mPR6I9XV1oW8k9O+0A==", "cpu": [ "x64" ], @@ -3395,9 +3894,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/netbsd-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.6.tgz", - "integrity": "sha512-EpWiLX0fzvZn1wxtLxZrEW+oQED9Pwpnh+w4Ffv8ZLuMhUoqR9q9rL4+qHW8F4Mg5oQEKxAoT0G+8JYNqCiR6g==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.9.tgz", + "integrity": "sha512-GThgZPAwOBOsheA2RUlW5UeroRfESwMq/guy8uEe3wJlAOjpOXuSevLRd70NZ37ZrpO6RHGHgEHvPg1h3S1Jug==", "cpu": [ "x64" ], @@ -3410,9 +3909,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/openbsd-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.6.tgz", - "integrity": "sha512-fFqTVEktM1PGs2sLKH4M5mhAVEzGpeZJuasAMRnvDZNCV0Cjvm1Hu35moL2vC0DOrAQjNTvj4zWrol/lwQ8Deg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.9.tgz", + "integrity": "sha512-Ki6PlzppaFVbLnD8PtlVQfsYw4S9n3eQl87cqgeIw+O3sRr9IghpfSKY62mggdt1yCSZ8QWvTZ9jo9fjDSg9uw==", "cpu": [ "x64" ], @@ -3425,9 +3924,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/sunos-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.6.tgz", - "integrity": "sha512-M+XIAnBpaNvaVAhbe3uBXtgWyWynSdlww/JNZws0FlMPSBy+EpatPXNIlKAdtbFVII9OpX91ZfMb17TU3JKTBA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.9.tgz", + "integrity": "sha512-MLHj7k9hWh4y1ddkBpvRj2b9NCBhfgBt3VpWbHQnXRedVun/hC7sIyTGDGTfsGuXo4ebik2+3ShjcPbhtFwWDw==", "cpu": [ "x64" ], @@ -3440,9 +3939,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/win32-arm64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.6.tgz", - "integrity": "sha512-2DchFXn7vp/B6Tc2eKdTsLzE0ygqKkNUhUBCNtMx2Llk4POIVMUq5rUYjdcedFlGLeRe1uLCpVvCmE+G8XYybA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.9.tgz", + "integrity": "sha512-GQoa6OrQ8G08guMFgeXPH7yE/8Dt0IfOGWJSfSH4uafwdC7rWwrfE6P9N8AtPGIjUzdo2+7bN8Xo3qC578olhg==", "cpu": [ "arm64" ], @@ -3455,9 +3954,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/win32-ia32": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.6.tgz", - "integrity": "sha512-PBo/HPDQllyWdjwAVX+Gl2hH0dfBydL97BAH/grHKC8fubqp02aL4S63otZ25q3sBdINtOBbz1qTZQfXbP4VBg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.9.tgz", + "integrity": "sha512-UOozV7Ntykvr5tSOlGCrqU3NBr3d8JqPes0QWN2WOXfvkWVGRajC+Ym0/Wj88fUgecUCLDdJPDF0Nna2UK3Qtg==", "cpu": [ "ia32" ], @@ -3470,9 +3969,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/@esbuild/win32-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.6.tgz", - "integrity": "sha512-OE7yIdbDif2kKfrGa+V0vx/B3FJv2L4KnIiLlvtibPyO9UkgO3rzYE0HhpREo2vmJ1Ixq1zwm9/0er+3VOSZJA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.9.tgz", + "integrity": "sha512-oxoQgglOP7RH6iasDrhY+R/3cHrfwIDvRlT4CGChflq6twk8iENeVvMJjmvBb94Ik1Z+93iGO27err7w6l54GQ==", "cpu": [ "x64" ], @@ -3532,9 +4031,9 @@ } }, "node_modules/@netlify/edge-bundler/node_modules/esbuild": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.6.tgz", - "integrity": "sha512-Xl7dntjA2OEIvpr9j0DVxxnog2fyTGnyVoQXAMQI6eR3mf9zCQds7VIKUDCotDgE/p4ncTgeRqgX8t5d6oP4Gw==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.9.tgz", + "integrity": "sha512-U9CHtKSy+EpPsEBa+/A2gMs/h3ylBC0H0KSqIg7tpztHerLi6nrrcoUJAkNCEPumx8yJ+Byic4BVwHgRbN0TBg==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -3543,28 +4042,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.19.6", - "@esbuild/android-arm64": "0.19.6", - "@esbuild/android-x64": "0.19.6", - "@esbuild/darwin-arm64": "0.19.6", - "@esbuild/darwin-x64": "0.19.6", - "@esbuild/freebsd-arm64": "0.19.6", - "@esbuild/freebsd-x64": "0.19.6", - "@esbuild/linux-arm": "0.19.6", - "@esbuild/linux-arm64": "0.19.6", - "@esbuild/linux-ia32": "0.19.6", - "@esbuild/linux-loong64": "0.19.6", - "@esbuild/linux-mips64el": "0.19.6", - "@esbuild/linux-ppc64": "0.19.6", - "@esbuild/linux-riscv64": "0.19.6", - "@esbuild/linux-s390x": "0.19.6", - "@esbuild/linux-x64": "0.19.6", - "@esbuild/netbsd-x64": "0.19.6", - "@esbuild/openbsd-x64": "0.19.6", - "@esbuild/sunos-x64": "0.19.6", - "@esbuild/win32-arm64": "0.19.6", - "@esbuild/win32-ia32": "0.19.6", - "@esbuild/win32-x64": "0.19.6" + "@esbuild/android-arm": "0.19.9", + "@esbuild/android-arm64": "0.19.9", + "@esbuild/android-x64": "0.19.9", + "@esbuild/darwin-arm64": "0.19.9", + "@esbuild/darwin-x64": "0.19.9", + "@esbuild/freebsd-arm64": "0.19.9", + "@esbuild/freebsd-x64": "0.19.9", + "@esbuild/linux-arm": "0.19.9", + "@esbuild/linux-arm64": "0.19.9", + "@esbuild/linux-ia32": "0.19.9", + "@esbuild/linux-loong64": "0.19.9", + "@esbuild/linux-mips64el": "0.19.9", + "@esbuild/linux-ppc64": "0.19.9", + "@esbuild/linux-riscv64": "0.19.9", + "@esbuild/linux-s390x": "0.19.9", + "@esbuild/linux-x64": "0.19.9", + "@esbuild/netbsd-x64": "0.19.9", + "@esbuild/openbsd-x64": "0.19.9", + "@esbuild/sunos-x64": "0.19.9", + "@esbuild/win32-arm64": "0.19.9", + "@esbuild/win32-ia32": "0.19.9", + "@esbuild/win32-x64": "0.19.9" } }, "node_modules/@netlify/edge-bundler/node_modules/execa": { @@ -26513,6 +27012,169 @@ "yargs": "^17.6.0" }, "dependencies": { + "@esbuild/android-arm": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.6.tgz", + "integrity": "sha512-muPzBqXJKCbMYoNbb1JpZh/ynl0xS6/+pLjrofcR3Nad82SbsCogYzUE6Aq9QT3cLP0jR/IVK/NHC9b90mSHtg==", + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.6.tgz", + "integrity": "sha512-KQ/hbe9SJvIJ4sR+2PcZ41IBV+LPJyYp6V1K1P1xcMRup9iYsBoQn4MzE3mhMLOld27Au2eDcLlIREeKGUXpHQ==", + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.6.tgz", + "integrity": "sha512-VVJVZQ7p5BBOKoNxd0Ly3xUM78Y4DyOoFKdkdAe2m11jbh0LEU4bPles4e/72EMl4tapko8o915UalN/5zhspg==", + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.6.tgz", + "integrity": "sha512-91LoRp/uZAKx6ESNspL3I46ypwzdqyDLXZH7x2QYCLgtnaU08+AXEbabY2yExIz03/am0DivsTtbdxzGejfXpA==", + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.6.tgz", + "integrity": "sha512-QCGHw770ubjBU1J3ZkFJh671MFajGTYMZumPs9E/rqU52md6lIil97BR0CbPq6U+vTh3xnTNDHKRdR8ggHnmxQ==", + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.6.tgz", + "integrity": "sha512-J53d0jGsDcLzWk9d9SPmlyF+wzVxjXpOH7jVW5ae7PvrDst4kiAz6sX+E8btz0GB6oH12zC+aHRD945jdjF2Vg==", + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.6.tgz", + "integrity": "sha512-hn9qvkjHSIB5Z9JgCCjED6YYVGCNpqB7dEGavBdG6EjBD8S/UcNUIlGcB35NCkMETkdYwfZSvD9VoDJX6VeUVA==", + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.6.tgz", + "integrity": "sha512-G8IR5zFgpXad/Zp7gr7ZyTKyqZuThU6z1JjmRyN1vSF8j0bOlGzUwFSMTbctLAdd7QHpeyu0cRiuKrqK1ZTwvQ==", + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.6.tgz", + "integrity": "sha512-HQCOrk9XlH3KngASLaBfHpcoYEGUt829A9MyxaI8RMkfRA8SakG6YQEITAuwmtzFdEu5GU4eyhKcpv27dFaOBg==", + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.6.tgz", + "integrity": "sha512-22eOR08zL/OXkmEhxOfshfOGo8P69k8oKHkwkDrUlcB12S/sw/+COM4PhAPT0cAYW/gpqY2uXp3TpjQVJitz7w==", + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.6.tgz", + "integrity": "sha512-82RvaYAh/SUJyjWA8jDpyZCHQjmEggL//sC7F3VKYcBMumQjUL3C5WDl/tJpEiKtt7XrWmgjaLkrk205zfvwTA==", + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.6.tgz", + "integrity": "sha512-8tvnwyYJpR618vboIv2l8tK2SuK/RqUIGMfMENkeDGo3hsEIrpGldMGYFcWxWeEILe5Fi72zoXLmhZ7PR23oQA==", + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.6.tgz", + "integrity": "sha512-Qt+D7xiPajxVNk5tQiEJwhmarNnLPdjXAoA5uWMpbfStZB0+YU6a3CtbWYSy+sgAsnyx4IGZjWsTzBzrvg/fMA==", + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.6.tgz", + "integrity": "sha512-lxRdk0iJ9CWYDH1Wpnnnc640ajF4RmQ+w6oHFZmAIYu577meE9Ka/DCtpOrwr9McMY11ocbp4jirgGgCi7Ls/g==", + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.6.tgz", + "integrity": "sha512-MopyYV39vnfuykHanRWHGRcRC3AwU7b0QY4TI8ISLfAGfK+tMkXyFuyT1epw/lM0pflQlS53JoD22yN83DHZgA==", + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.6.tgz", + "integrity": "sha512-UWcieaBzsN8WYbzFF5Jq7QULETPcQvlX7KL4xWGIB54OknXJjBO37sPqk7N82WU13JGWvmDzFBi1weVBajPovg==", + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.6.tgz", + "integrity": "sha512-EpWiLX0fzvZn1wxtLxZrEW+oQED9Pwpnh+w4Ffv8ZLuMhUoqR9q9rL4+qHW8F4Mg5oQEKxAoT0G+8JYNqCiR6g==", + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.6.tgz", + "integrity": "sha512-fFqTVEktM1PGs2sLKH4M5mhAVEzGpeZJuasAMRnvDZNCV0Cjvm1Hu35moL2vC0DOrAQjNTvj4zWrol/lwQ8Deg==", + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.6.tgz", + "integrity": "sha512-M+XIAnBpaNvaVAhbe3uBXtgWyWynSdlww/JNZws0FlMPSBy+EpatPXNIlKAdtbFVII9OpX91ZfMb17TU3JKTBA==", + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.6.tgz", + "integrity": "sha512-2DchFXn7vp/B6Tc2eKdTsLzE0ygqKkNUhUBCNtMx2Llk4POIVMUq5rUYjdcedFlGLeRe1uLCpVvCmE+G8XYybA==", + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.6.tgz", + "integrity": "sha512-PBo/HPDQllyWdjwAVX+Gl2hH0dfBydL97BAH/grHKC8fubqp02aL4S63otZ25q3sBdINtOBbz1qTZQfXbP4VBg==", + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.6.tgz", + "integrity": "sha512-OE7yIdbDif2kKfrGa+V0vx/B3FJv2L4KnIiLlvtibPyO9UkgO3rzYE0HhpREo2vmJ1Ixq1zwm9/0er+3VOSZJA==", + "optional": true + }, + "@netlify/edge-bundler": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/@netlify/edge-bundler/-/edge-bundler-10.1.3.tgz", + "integrity": "sha512-+cFFUrdbkhbtmpvQlRam4CmNguKBjte7usNXO1IxDmExeYxdwkDWWBCjOO4zd/D12TIC3HSJGJjT76GkF+RwTg==", + "requires": { + "@import-maps/resolve": "^1.0.1", + "@vercel/nft": "^0.24.3", + "ajv": "^8.11.2", + "ajv-errors": "^3.0.0", + "better-ajv-errors": "^1.2.0", + "common-path-prefix": "^3.0.0", + "env-paths": "^3.0.0", + "esbuild": "0.19.6", + "execa": "^6.0.0", + "find-up": "^6.3.0", + "get-package-name": "^2.2.0", + "get-port": "^6.1.2", + "is-path-inside": "^4.0.0", + "jsonc-parser": "^3.2.0", + "node-fetch": "^3.1.1", + "node-stream-zip": "^1.15.0", + "p-retry": "^5.1.1", + "p-wait-for": "^4.1.0", + "path-key": "^4.0.0", + "regexp-tree": "^0.1.24", + "semver": "^7.3.8", + "tmp-promise": "^3.0.3", + "urlpattern-polyfill": "8.0.2", + "uuid": "^9.0.0" + } + }, "@opentelemetry/core": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.18.1.tgz", @@ -26539,6 +27201,41 @@ "defer-to-connect": "^2.0.1" } }, + "@vercel/nft": { + "version": "0.24.4", + "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.24.4.tgz", + "integrity": "sha512-KjYAZty7boH5fi5udp6p+lNu6nawgs++pHW+3koErMgbRkkHuToGX/FwjN5clV1FcaM3udfd4zW/sUapkMgpZw==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.5", + "@rollup/pluginutils": "^4.0.0", + "acorn": "^8.6.0", + "async-sema": "^3.1.1", + "bindings": "^1.4.0", + "estree-walker": "2.0.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.2", + "node-gyp-build": "^4.2.2", + "resolve-from": "^5.0.0" + } + }, + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", + "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==", + "requires": {} + }, "cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", @@ -26563,6 +27260,35 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, + "esbuild": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.6.tgz", + "integrity": "sha512-Xl7dntjA2OEIvpr9j0DVxxnog2fyTGnyVoQXAMQI6eR3mf9zCQds7VIKUDCotDgE/p4ncTgeRqgX8t5d6oP4Gw==", + "requires": { + "@esbuild/android-arm": "0.19.6", + "@esbuild/android-arm64": "0.19.6", + "@esbuild/android-x64": "0.19.6", + "@esbuild/darwin-arm64": "0.19.6", + "@esbuild/darwin-x64": "0.19.6", + "@esbuild/freebsd-arm64": "0.19.6", + "@esbuild/freebsd-x64": "0.19.6", + "@esbuild/linux-arm": "0.19.6", + "@esbuild/linux-arm64": "0.19.6", + "@esbuild/linux-ia32": "0.19.6", + "@esbuild/linux-loong64": "0.19.6", + "@esbuild/linux-mips64el": "0.19.6", + "@esbuild/linux-ppc64": "0.19.6", + "@esbuild/linux-riscv64": "0.19.6", + "@esbuild/linux-s390x": "0.19.6", + "@esbuild/linux-x64": "0.19.6", + "@esbuild/netbsd-x64": "0.19.6", + "@esbuild/openbsd-x64": "0.19.6", + "@esbuild/sunos-x64": "0.19.6", + "@esbuild/win32-arm64": "0.19.6", + "@esbuild/win32-ia32": "0.19.6", + "@esbuild/win32-x64": "0.19.6" + } + }, "escape-string-regexp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", @@ -26593,6 +27319,11 @@ "is-unicode-supported": "^1.2.0" } }, + "get-port": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.1.2.tgz", + "integrity": "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==" + }, "got": { "version": "12.6.1", "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", @@ -26630,6 +27361,16 @@ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==" }, + "is-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==" + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "lowercase-keys": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", @@ -26702,6 +27443,19 @@ "resolved": "https://registry.npmjs.org/p-map/-/p-map-6.0.0.tgz", "integrity": "sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==" }, + "p-timeout": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", + "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==" + }, + "p-wait-for": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-4.1.0.tgz", + "integrity": "sha512-i8nE5q++9h8oaQHWltS1Tnnv4IoMDOlqN7C0KFG2OdbK0iFJIt6CROZ8wfBM+K4Pxqfnq4C4lkkpXqTEpB5DZw==", + "requires": { + "p-timeout": "^5.0.0" + } + }, "path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -26980,9 +27734,9 @@ } }, "@netlify/edge-bundler": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/@netlify/edge-bundler/-/edge-bundler-10.1.3.tgz", - "integrity": "sha512-+cFFUrdbkhbtmpvQlRam4CmNguKBjte7usNXO1IxDmExeYxdwkDWWBCjOO4zd/D12TIC3HSJGJjT76GkF+RwTg==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@netlify/edge-bundler/-/edge-bundler-11.0.0.tgz", + "integrity": "sha512-DPFkzQmdZR/1a3jUaZMbxk79N6PEtqhxEvx6x5wISegqkeM9DPNe+PQIBFXpsAwIeb9MB1RU7vliT1hIRt8DBg==", "requires": { "@import-maps/resolve": "^1.0.1", "@vercel/nft": "^0.24.3", @@ -26991,7 +27745,7 @@ "better-ajv-errors": "^1.2.0", "common-path-prefix": "^3.0.0", "env-paths": "^3.0.0", - "esbuild": "0.19.6", + "esbuild": "0.19.9", "execa": "^6.0.0", "find-up": "^6.3.0", "get-package-name": "^2.2.0", @@ -27011,135 +27765,135 @@ }, "dependencies": { "@esbuild/android-arm": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.6.tgz", - "integrity": "sha512-muPzBqXJKCbMYoNbb1JpZh/ynl0xS6/+pLjrofcR3Nad82SbsCogYzUE6Aq9QT3cLP0jR/IVK/NHC9b90mSHtg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.9.tgz", + "integrity": "sha512-jkYjjq7SdsWuNI6b5quymW0oC83NN5FdRPuCbs9HZ02mfVdAP8B8eeqLSYU3gb6OJEaY5CQabtTFbqBf26H3GA==", "optional": true }, "@esbuild/android-arm64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.6.tgz", - "integrity": "sha512-KQ/hbe9SJvIJ4sR+2PcZ41IBV+LPJyYp6V1K1P1xcMRup9iYsBoQn4MzE3mhMLOld27Au2eDcLlIREeKGUXpHQ==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.9.tgz", + "integrity": "sha512-q4cR+6ZD0938R19MyEW3jEsMzbb/1rulLXiNAJQADD/XYp7pT+rOS5JGxvpRW8dFDEfjW4wLgC/3FXIw4zYglQ==", "optional": true }, "@esbuild/android-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.6.tgz", - "integrity": "sha512-VVJVZQ7p5BBOKoNxd0Ly3xUM78Y4DyOoFKdkdAe2m11jbh0LEU4bPles4e/72EMl4tapko8o915UalN/5zhspg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.9.tgz", + "integrity": "sha512-KOqoPntWAH6ZxDwx1D6mRntIgZh9KodzgNOy5Ebt9ghzffOk9X2c1sPwtM9P+0eXbefnDhqYfkh5PLP5ULtWFA==", "optional": true }, "@esbuild/darwin-arm64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.6.tgz", - "integrity": "sha512-91LoRp/uZAKx6ESNspL3I46ypwzdqyDLXZH7x2QYCLgtnaU08+AXEbabY2yExIz03/am0DivsTtbdxzGejfXpA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.9.tgz", + "integrity": "sha512-KBJ9S0AFyLVx2E5D8W0vExqRW01WqRtczUZ8NRu+Pi+87opZn5tL4Y0xT0mA4FtHctd0ZgwNoN639fUUGlNIWw==", "optional": true }, "@esbuild/darwin-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.6.tgz", - "integrity": "sha512-QCGHw770ubjBU1J3ZkFJh671MFajGTYMZumPs9E/rqU52md6lIil97BR0CbPq6U+vTh3xnTNDHKRdR8ggHnmxQ==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.9.tgz", + "integrity": "sha512-vE0VotmNTQaTdX0Q9dOHmMTao6ObjyPm58CHZr1UK7qpNleQyxlFlNCaHsHx6Uqv86VgPmR4o2wdNq3dP1qyDQ==", "optional": true }, "@esbuild/freebsd-arm64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.6.tgz", - "integrity": "sha512-J53d0jGsDcLzWk9d9SPmlyF+wzVxjXpOH7jVW5ae7PvrDst4kiAz6sX+E8btz0GB6oH12zC+aHRD945jdjF2Vg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.9.tgz", + "integrity": "sha512-uFQyd/o1IjiEk3rUHSwUKkqZwqdvuD8GevWF065eqgYfexcVkxh+IJgwTaGZVu59XczZGcN/YMh9uF1fWD8j1g==", "optional": true }, "@esbuild/freebsd-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.6.tgz", - "integrity": "sha512-hn9qvkjHSIB5Z9JgCCjED6YYVGCNpqB7dEGavBdG6EjBD8S/UcNUIlGcB35NCkMETkdYwfZSvD9VoDJX6VeUVA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.9.tgz", + "integrity": "sha512-WMLgWAtkdTbTu1AWacY7uoj/YtHthgqrqhf1OaEWnZb7PQgpt8eaA/F3LkV0E6K/Lc0cUr/uaVP/49iE4M4asA==", "optional": true }, "@esbuild/linux-arm": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.6.tgz", - "integrity": "sha512-G8IR5zFgpXad/Zp7gr7ZyTKyqZuThU6z1JjmRyN1vSF8j0bOlGzUwFSMTbctLAdd7QHpeyu0cRiuKrqK1ZTwvQ==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.9.tgz", + "integrity": "sha512-C/ChPohUYoyUaqn1h17m/6yt6OB14hbXvT8EgM1ZWaiiTYz7nWZR0SYmMnB5BzQA4GXl3BgBO1l8MYqL/He3qw==", "optional": true }, "@esbuild/linux-arm64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.6.tgz", - "integrity": "sha512-HQCOrk9XlH3KngASLaBfHpcoYEGUt829A9MyxaI8RMkfRA8SakG6YQEITAuwmtzFdEu5GU4eyhKcpv27dFaOBg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.9.tgz", + "integrity": "sha512-PiPblfe1BjK7WDAKR1Cr9O7VVPqVNpwFcPWgfn4xu0eMemzRp442hXyzF/fSwgrufI66FpHOEJk0yYdPInsmyQ==", "optional": true }, "@esbuild/linux-ia32": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.6.tgz", - "integrity": "sha512-22eOR08zL/OXkmEhxOfshfOGo8P69k8oKHkwkDrUlcB12S/sw/+COM4PhAPT0cAYW/gpqY2uXp3TpjQVJitz7w==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.9.tgz", + "integrity": "sha512-f37i/0zE0MjDxijkPSQw1CO/7C27Eojqb+r3BbHVxMLkj8GCa78TrBZzvPyA/FNLUMzP3eyHCVkAopkKVja+6Q==", "optional": true }, "@esbuild/linux-loong64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.6.tgz", - "integrity": "sha512-82RvaYAh/SUJyjWA8jDpyZCHQjmEggL//sC7F3VKYcBMumQjUL3C5WDl/tJpEiKtt7XrWmgjaLkrk205zfvwTA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.9.tgz", + "integrity": "sha512-t6mN147pUIf3t6wUt3FeumoOTPfmv9Cc6DQlsVBpB7eCpLOqQDyWBP1ymXn1lDw4fNUSb/gBcKAmvTP49oIkaA==", "optional": true }, "@esbuild/linux-mips64el": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.6.tgz", - "integrity": "sha512-8tvnwyYJpR618vboIv2l8tK2SuK/RqUIGMfMENkeDGo3hsEIrpGldMGYFcWxWeEILe5Fi72zoXLmhZ7PR23oQA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.9.tgz", + "integrity": "sha512-jg9fujJTNTQBuDXdmAg1eeJUL4Jds7BklOTkkH80ZgQIoCTdQrDaHYgbFZyeTq8zbY+axgptncko3v9p5hLZtw==", "optional": true }, "@esbuild/linux-ppc64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.6.tgz", - "integrity": "sha512-Qt+D7xiPajxVNk5tQiEJwhmarNnLPdjXAoA5uWMpbfStZB0+YU6a3CtbWYSy+sgAsnyx4IGZjWsTzBzrvg/fMA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.9.tgz", + "integrity": "sha512-tkV0xUX0pUUgY4ha7z5BbDS85uI7ABw3V1d0RNTii7E9lbmV8Z37Pup2tsLV46SQWzjOeyDi1Q7Wx2+QM8WaCQ==", "optional": true }, "@esbuild/linux-riscv64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.6.tgz", - "integrity": "sha512-lxRdk0iJ9CWYDH1Wpnnnc640ajF4RmQ+w6oHFZmAIYu577meE9Ka/DCtpOrwr9McMY11ocbp4jirgGgCi7Ls/g==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.9.tgz", + "integrity": "sha512-DfLp8dj91cufgPZDXr9p3FoR++m3ZJ6uIXsXrIvJdOjXVREtXuQCjfMfvmc3LScAVmLjcfloyVtpn43D56JFHg==", "optional": true }, "@esbuild/linux-s390x": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.6.tgz", - "integrity": "sha512-MopyYV39vnfuykHanRWHGRcRC3AwU7b0QY4TI8ISLfAGfK+tMkXyFuyT1epw/lM0pflQlS53JoD22yN83DHZgA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.9.tgz", + "integrity": "sha512-zHbglfEdC88KMgCWpOl/zc6dDYJvWGLiUtmPRsr1OgCViu3z5GncvNVdf+6/56O2Ca8jUU+t1BW261V6kp8qdw==", "optional": true }, "@esbuild/linux-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.6.tgz", - "integrity": "sha512-UWcieaBzsN8WYbzFF5Jq7QULETPcQvlX7KL4xWGIB54OknXJjBO37sPqk7N82WU13JGWvmDzFBi1weVBajPovg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.9.tgz", + "integrity": "sha512-JUjpystGFFmNrEHQnIVG8hKwvA2DN5o7RqiO1CVX8EN/F/gkCjkUMgVn6hzScpwnJtl2mPR6I9XV1oW8k9O+0A==", "optional": true }, "@esbuild/netbsd-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.6.tgz", - "integrity": "sha512-EpWiLX0fzvZn1wxtLxZrEW+oQED9Pwpnh+w4Ffv8ZLuMhUoqR9q9rL4+qHW8F4Mg5oQEKxAoT0G+8JYNqCiR6g==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.9.tgz", + "integrity": "sha512-GThgZPAwOBOsheA2RUlW5UeroRfESwMq/guy8uEe3wJlAOjpOXuSevLRd70NZ37ZrpO6RHGHgEHvPg1h3S1Jug==", "optional": true }, "@esbuild/openbsd-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.6.tgz", - "integrity": "sha512-fFqTVEktM1PGs2sLKH4M5mhAVEzGpeZJuasAMRnvDZNCV0Cjvm1Hu35moL2vC0DOrAQjNTvj4zWrol/lwQ8Deg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.9.tgz", + "integrity": "sha512-Ki6PlzppaFVbLnD8PtlVQfsYw4S9n3eQl87cqgeIw+O3sRr9IghpfSKY62mggdt1yCSZ8QWvTZ9jo9fjDSg9uw==", "optional": true }, "@esbuild/sunos-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.6.tgz", - "integrity": "sha512-M+XIAnBpaNvaVAhbe3uBXtgWyWynSdlww/JNZws0FlMPSBy+EpatPXNIlKAdtbFVII9OpX91ZfMb17TU3JKTBA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.9.tgz", + "integrity": "sha512-MLHj7k9hWh4y1ddkBpvRj2b9NCBhfgBt3VpWbHQnXRedVun/hC7sIyTGDGTfsGuXo4ebik2+3ShjcPbhtFwWDw==", "optional": true }, "@esbuild/win32-arm64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.6.tgz", - "integrity": "sha512-2DchFXn7vp/B6Tc2eKdTsLzE0ygqKkNUhUBCNtMx2Llk4POIVMUq5rUYjdcedFlGLeRe1uLCpVvCmE+G8XYybA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.9.tgz", + "integrity": "sha512-GQoa6OrQ8G08guMFgeXPH7yE/8Dt0IfOGWJSfSH4uafwdC7rWwrfE6P9N8AtPGIjUzdo2+7bN8Xo3qC578olhg==", "optional": true }, "@esbuild/win32-ia32": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.6.tgz", - "integrity": "sha512-PBo/HPDQllyWdjwAVX+Gl2hH0dfBydL97BAH/grHKC8fubqp02aL4S63otZ25q3sBdINtOBbz1qTZQfXbP4VBg==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.9.tgz", + "integrity": "sha512-UOozV7Ntykvr5tSOlGCrqU3NBr3d8JqPes0QWN2WOXfvkWVGRajC+Ym0/Wj88fUgecUCLDdJPDF0Nna2UK3Qtg==", "optional": true }, "@esbuild/win32-x64": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.6.tgz", - "integrity": "sha512-OE7yIdbDif2kKfrGa+V0vx/B3FJv2L4KnIiLlvtibPyO9UkgO3rzYE0HhpREo2vmJ1Ixq1zwm9/0er+3VOSZJA==", + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.9.tgz", + "integrity": "sha512-oxoQgglOP7RH6iasDrhY+R/3cHrfwIDvRlT4CGChflq6twk8iENeVvMJjmvBb94Ik1Z+93iGO27err7w6l54GQ==", "optional": true }, "@vercel/nft": { @@ -27178,32 +27932,32 @@ "requires": {} }, "esbuild": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.6.tgz", - "integrity": "sha512-Xl7dntjA2OEIvpr9j0DVxxnog2fyTGnyVoQXAMQI6eR3mf9zCQds7VIKUDCotDgE/p4ncTgeRqgX8t5d6oP4Gw==", - "requires": { - "@esbuild/android-arm": "0.19.6", - "@esbuild/android-arm64": "0.19.6", - "@esbuild/android-x64": "0.19.6", - "@esbuild/darwin-arm64": "0.19.6", - "@esbuild/darwin-x64": "0.19.6", - "@esbuild/freebsd-arm64": "0.19.6", - "@esbuild/freebsd-x64": "0.19.6", - "@esbuild/linux-arm": "0.19.6", - "@esbuild/linux-arm64": "0.19.6", - "@esbuild/linux-ia32": "0.19.6", - "@esbuild/linux-loong64": "0.19.6", - "@esbuild/linux-mips64el": "0.19.6", - "@esbuild/linux-ppc64": "0.19.6", - "@esbuild/linux-riscv64": "0.19.6", - "@esbuild/linux-s390x": "0.19.6", - "@esbuild/linux-x64": "0.19.6", - "@esbuild/netbsd-x64": "0.19.6", - "@esbuild/openbsd-x64": "0.19.6", - "@esbuild/sunos-x64": "0.19.6", - "@esbuild/win32-arm64": "0.19.6", - "@esbuild/win32-ia32": "0.19.6", - "@esbuild/win32-x64": "0.19.6" + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.9.tgz", + "integrity": "sha512-U9CHtKSy+EpPsEBa+/A2gMs/h3ylBC0H0KSqIg7tpztHerLi6nrrcoUJAkNCEPumx8yJ+Byic4BVwHgRbN0TBg==", + "requires": { + "@esbuild/android-arm": "0.19.9", + "@esbuild/android-arm64": "0.19.9", + "@esbuild/android-x64": "0.19.9", + "@esbuild/darwin-arm64": "0.19.9", + "@esbuild/darwin-x64": "0.19.9", + "@esbuild/freebsd-arm64": "0.19.9", + "@esbuild/freebsd-x64": "0.19.9", + "@esbuild/linux-arm": "0.19.9", + "@esbuild/linux-arm64": "0.19.9", + "@esbuild/linux-ia32": "0.19.9", + "@esbuild/linux-loong64": "0.19.9", + "@esbuild/linux-mips64el": "0.19.9", + "@esbuild/linux-ppc64": "0.19.9", + "@esbuild/linux-riscv64": "0.19.9", + "@esbuild/linux-s390x": "0.19.9", + "@esbuild/linux-x64": "0.19.9", + "@esbuild/netbsd-x64": "0.19.9", + "@esbuild/openbsd-x64": "0.19.9", + "@esbuild/sunos-x64": "0.19.9", + "@esbuild/win32-arm64": "0.19.9", + "@esbuild/win32-ia32": "0.19.9", + "@esbuild/win32-x64": "0.19.9" } }, "execa": { diff --git a/package.json b/package.json index 48d002a4daf..c19fecc382d 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "@netlify/build": "29.31.0", "@netlify/build-info": "7.11.3", "@netlify/config": "20.10.0", - "@netlify/edge-bundler": "10.1.3", + "@netlify/edge-bundler": "11.0.0", "@netlify/local-functions-proxy": "1.1.1", "@netlify/zip-it-and-ship-it": "9.28.1", "@octokit/rest": "19.0.13", diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index 1a5ab4f012e..f3ec4657316 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -411,7 +411,6 @@ const runDeploy = async ({ deployToProduction, // @ts-expect-error TS(7031) FIXME: Binding element 'functionsConfig' implicitly has a... Remove this comment to see the full error message functionsConfig, - // @ts-expect-error TS(7031) FIXME: Binding element 'functionsFolder' implicitly has a... Remove this comment to see the full error message functionsFolder, // @ts-expect-error TS(7031) FIXME: Binding element 'options' implicitly has an 'a... Remove this comment to see the full error message options, @@ -429,6 +428,8 @@ const runDeploy = async ({ skipFunctionsCache, // @ts-expect-error TS(7031) FIXME: Binding element 'title' implicitly has an 'any' ty... Remove this comment to see the full error message title, +}: { + functionsFolder?: string }) => { let results let deployId @@ -444,13 +445,14 @@ const runDeploy = async ({ results = await api.createSiteDeploy({ siteId, title, body: { draft, branch: alias } }) deployId = results.id - // @ts-expect-error TS(2345) FIXME: Argument of type '{ base: any; packagePath: any; }... Remove this comment to see the full error message - const internalFunctionsFolder = await getInternalFunctionsDir({ base: site.root, packagePath }) + const internalFunctionsFolder = await getInternalFunctionsDir({ base: site.root, packagePath, ensureExists: true }) // The order of the directories matter: zip-it-and-ship-it will prioritize // functions from the rightmost directories. In this case, we want user // functions to take precedence over internal functions. - const functionDirectories = [internalFunctionsFolder, functionsFolder].filter(Boolean) + const functionDirectories = [internalFunctionsFolder, functionsFolder].filter((folder): folder is string => + Boolean(folder), + ) const manifestPath = skipFunctionsCache ? null : await getFunctionsManifestPath({ base: site.root, packagePath }) const redirectsPath = `${deployFolder}/_redirects` @@ -475,11 +477,10 @@ const runDeploy = async ({ uploadDeployBlobs({ deployId, siteId, silent, options, cachedConfig: command.netlify.cachedConfig }) results = await deploySite(api, siteId, deployFolder, { + // @ts-expect-error FIXME config, - // @ts-expect-error TS(2322) FIXME: Type 'any[]' is not assignable to type 'never[]'. fnDir: functionDirectories, functionsConfig, - // @ts-expect-error TS(2322) FIXME: Type '(event: any) => void' is not assignable to t... Remove this comment to see the full error message statusCb: silent ? () => {} : deployProgressCb(), deployTimeout, syncFileLimit: SYNC_FILE_LIMIT, @@ -732,6 +733,7 @@ const prepAndRunDeploy = async ({ }) const results = await runDeploy({ + // @ts-expect-error FIXME alias, api, command, diff --git a/src/commands/serve/serve.ts b/src/commands/serve/serve.ts index d136d55c4bf..2c3a5c1095c 100644 --- a/src/commands/serve/serve.ts +++ b/src/commands/serve/serve.ts @@ -61,6 +61,10 @@ export const serve = async (options: OptionValues, command: BaseCommand) => { siteInfo, }) + if (!site.root) { + throw new Error('Site root not found') + } + // Ensure the internal functions directory exists so that the functions // server and registry are initialized, and any functions created by // Netlify Build are loaded. diff --git a/src/lib/edge-functions/internal.ts b/src/lib/edge-functions/internal.ts deleted file mode 100644 index 334f5c09b26..00000000000 --- a/src/lib/edge-functions/internal.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { readFile, stat } from 'fs/promises' -import { dirname, join, resolve } from 'path' - -import { getPathInProject } from '../settings.js' - -import { INTERNAL_EDGE_FUNCTIONS_FOLDER } from './consts.js' - -/** - * @param {string} workingDir - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message -export const getInternalFunctions = async (workingDir) => { - const path = join(workingDir, getPathInProject([INTERNAL_EDGE_FUNCTIONS_FOLDER])) - - try { - const stats = await stat(path) - - if (!stats.isDirectory()) { - throw new Error('Internal edge functions directory expected') - } - } catch { - return { - functions: [], - path: null, - } - } - - try { - const manifestPath = join(path, 'manifest.json') - // @ts-expect-error TS(2345) FIXME: Argument of type 'Buffer' is not assignable to par... Remove this comment to see the full error message - const manifest = JSON.parse(await readFile(manifestPath)) - - if (manifest.version !== 1) { - throw new Error('Unsupported manifest format') - } - - const data = { - functions: manifest.functions || [], - path, - } - - if (manifest.import_map) { - // @ts-expect-error TS(2339) FIXME: Property 'importMap' does not exist on type '{ fun... Remove this comment to see the full error message - data.importMap = resolve(dirname(manifestPath), manifest.import_map) - } - - return data - } catch { - return { - functions: [], - path, - } - } -} diff --git a/src/lib/edge-functions/proxy.ts b/src/lib/edge-functions/proxy.ts index 50dbbfe4f00..683bcdbee8d 100644 --- a/src/lib/edge-functions/proxy.ts +++ b/src/lib/edge-functions/proxy.ts @@ -1,5 +1,6 @@ import { Buffer } from 'buffer' import { rm } from 'fs/promises' +import type { IncomingMessage } from 'http' import { join, resolve } from 'path' import * as bundler from '@netlify/edge-bundler' @@ -13,7 +14,6 @@ import { startSpinner, stopSpinner } from '../spinner.js' import { getBootstrapURL } from './bootstrap.js' import { DIST_IMPORT_MAP_PATH, EDGE_FUNCTIONS_SERVE_FOLDER } from './consts.js' import { headers, getFeatureFlagsHeader, getInvocationMetadataHeader } from './headers.js' -import { getInternalFunctions } from './internal.js' import { EdgeFunctionsRegistry } from './registry.js' const headersSymbol = Symbol('Edge Functions Headers') @@ -134,12 +134,6 @@ export const initializeProxy = async ({ // @ts-expect-error TS(7031) FIXME: Binding element 'state' implicitly has an 'any' ty... Remove this comment to see the full error message state, }) => { - const { - functions: internalFunctions, - // @ts-expect-error TS(2339) FIXME: Property 'importMap' does not exist on type '{ fun... Remove this comment to see the full error message - importMap, - path: internalFunctionsPath, - } = await getInternalFunctions(projectDir) const userFunctionsPath = config.build.edge_functions const isolatePort = await getAvailablePort() const buildFeatureFlags = { @@ -159,19 +153,13 @@ export const initializeProxy = async ({ env: configEnv, featureFlags: buildFeatureFlags, getUpdatedConfig, - importMaps: [importMap].filter(Boolean), inspectSettings, - internalDirectory: internalFunctionsPath, - internalFunctions, port: isolatePort, projectDir, repositoryRoot, }) - const hasEdgeFunctions = userFunctionsPath !== undefined || internalFunctionsPath - - // @ts-expect-error TS(7006) FIXME: Parameter 'req' implicitly has an 'any' type. - return async (req) => { - if (req.headers[headers.Passthrough] !== undefined || !hasEdgeFunctions) { + return async (req: IncomingMessage & { [headersSymbol]: Record }) => { + if (req.headers[headers.Passthrough] !== undefined) { return } @@ -196,8 +184,8 @@ export const initializeProxy = async ({ await registry.initialize() - const url = new URL(req.url, `http://${LOCAL_HOST}:${mainPort}`) - const { functionNames, invocationMetadata } = registry.matchURLPath(url.pathname, req.method) + const url = new URL(req.url!, `http://${LOCAL_HOST}:${mainPort}`) + const { functionNames, invocationMetadata } = registry.matchURLPath(url.pathname, req.method!) if (functionNames.length === 0) { return @@ -240,14 +228,8 @@ const prepareServer = async ({ featureFlags, // @ts-expect-error TS(7031) FIXME: Binding element 'getUpdatedConfig' implicitly has ... Remove this comment to see the full error message getUpdatedConfig, - // @ts-expect-error TS(7031) FIXME: Binding element 'importMaps' implicitly has an 'an... Remove this comment to see the full error message - importMaps, // @ts-expect-error TS(7031) FIXME: Binding element 'inspectSettings' implicitly has a... Remove this comment to see the full error message inspectSettings, - // @ts-expect-error TS(7031) FIXME: Binding element 'internalDirectory' implicitly has... Remove this comment to see the full error message - internalDirectory, - // @ts-expect-error TS(7031) FIXME: Binding element 'internalFunctions' implicitly has... Remove this comment to see the full error message - internalFunctions, // @ts-expect-error TS(7031) FIXME: Binding element 'port' implicitly has an 'any' typ... Remove this comment to see the full error message port, // @ts-expect-error TS(7031) FIXME: Binding element 'projectDir' implicitly has an 'an... Remove this comment to see the full error message @@ -255,9 +237,6 @@ const prepareServer = async ({ // @ts-expect-error TS(7031) FIXME: Binding element 'repositoryRoot' implicitly has an... Remove this comment to see the full error message repositoryRoot, }) => { - // Merging internal with user-defined import maps. - const importMapPaths = [...importMaps, config.functions['*'].deno_import_map] - try { const distImportMapPath = getPathInProject([DIST_IMPORT_MAP_PATH]) const servePath = resolve(projectDir, getPathInProject([EDGE_FUNCTIONS_SERVE_FOLDER])) @@ -277,7 +256,6 @@ const prepareServer = async ({ )}. The file does not seem to have a function as the default export.`, formatImportError: (name) => `${NETLIFYDEVERR} ${chalk.red('Failed')} to run Edge Function ${chalk.yellow(name)}:`, - importMapPaths, inspectSettings, port, rootPath: repositoryRoot, @@ -291,8 +269,7 @@ const prepareServer = async ({ directories: [directory].filter(Boolean), env: configEnv, getUpdatedConfig, - internalDirectories: [internalDirectory].filter(Boolean), - internalFunctions, + importMapFromTOML: config.functions['*'].deno_import_map, projectDir, runIsolate, servePath, diff --git a/src/lib/edge-functions/registry.ts b/src/lib/edge-functions/registry.ts index 3144a49117a..ab26b017124 100644 --- a/src/lib/edge-functions/registry.ts +++ b/src/lib/edge-functions/registry.ts @@ -1,3 +1,5 @@ +import { readFile } from 'fs/promises' +import { join } from 'path' import { fileURLToPath } from 'url' import type { Declaration, EdgeFunction, FunctionConfig, Manifest, ModuleGraph } from '@netlify/edge-bundler' @@ -13,6 +15,9 @@ import { watchDebounced, isNodeError, } from '../../utils/command-helpers.js' +import { getPathInProject } from '../settings.js' + +import { INTERNAL_EDGE_FUNCTIONS_FOLDER } from './consts.js' // TODO: Replace with a proper type for the entire config object. interface Config { @@ -33,18 +38,19 @@ interface EdgeFunctionsRegistryOptions { directories: string[] env: Record getUpdatedConfig: () => Promise - internalDirectories: string[] - internalFunctions: Declaration[] projectDir: string runIsolate: RunIsolate servePath: string + importMapFromTOML?: string } export class EdgeFunctionsRegistry { private buildError: Error | null = null private bundler: typeof import('@netlify/edge-bundler') private configPath: string - private declarationsFromDeployConfig: Declaration[] + public importMapFromDeployConfig?: string + private importMapFromTOML?: string + private declarationsFromDeployConfig: Declaration[] = [] private declarationsFromTOML: Declaration[] private dependencyPaths = new Map() private directories: string[] @@ -53,13 +59,13 @@ export class EdgeFunctionsRegistry { private functionPaths = new Map() private getUpdatedConfig: () => Promise private initialScan: Promise - private internalDirectories: string[] private internalFunctions: EdgeFunction[] = [] private manifest: Manifest | null = null private routes: Route[] = [] private runIsolate: RunIsolate private servePath: string private userFunctions: EdgeFunction[] = [] + private projectDir: string constructor({ bundler, @@ -68,8 +74,7 @@ export class EdgeFunctionsRegistry { directories, env, getUpdatedConfig, - internalDirectories, - internalFunctions, + importMapFromTOML, projectDir, runIsolate, servePath, @@ -77,12 +82,12 @@ export class EdgeFunctionsRegistry { this.bundler = bundler this.configPath = configPath this.directories = directories - this.internalDirectories = internalDirectories this.getUpdatedConfig = getUpdatedConfig this.runIsolate = runIsolate this.servePath = servePath + this.projectDir = projectDir - this.declarationsFromDeployConfig = internalFunctions + this.importMapFromTOML = importMapFromTOML this.declarationsFromTOML = EdgeFunctionsRegistry.getDeclarationsFromTOML(config) this.env = EdgeFunctionsRegistry.getEnvironmentVariables(env) @@ -95,7 +100,7 @@ export class EdgeFunctionsRegistry { this.initialScan = this.doInitialScan() - this.setupWatchers(projectDir) + this.setupWatchers() } private async doInitialScan() { @@ -475,16 +480,47 @@ export class EdgeFunctionsRegistry { this.env, { getFunctionsConfig: true, + importMapPaths: [this.importMapFromTOML, this.importMapFromDeployConfig].filter(nonNullable), }, ) return { functionsConfig, graph, npmSpecifiersWithExtraneousFiles, success } } + private get internalDirectory() { + return join(this.projectDir, getPathInProject([INTERNAL_EDGE_FUNCTIONS_FOLDER])) + } + + private async readDeployConfig() { + const manifestPath = join(this.internalDirectory, 'manifest.json') + try { + const contents = await readFile(manifestPath, 'utf8') + const manifest = JSON.parse(contents) + return manifest + } catch {} + } + + private async scanForDeployConfig() { + const deployConfig = await this.readDeployConfig() + if (!deployConfig) { + return + } + + if (deployConfig.version !== 1) { + throw new Error('Unsupported manifest format') + } + + this.declarationsFromDeployConfig = deployConfig.functions + this.importMapFromDeployConfig = deployConfig.import_map + ? join(this.internalDirectory, deployConfig.import_map) + : undefined + } + private async scanForFunctions() { const [internalFunctions, userFunctions] = await Promise.all([ - this.bundler.find(this.internalDirectories), + this.bundler.find([this.internalDirectory]), this.bundler.find(this.directories), + this.scanForDeployConfig(), ]) const functions = [...internalFunctions, ...userFunctions] const newFunctions = functions.filter((func) => { @@ -508,7 +544,7 @@ export class EdgeFunctionsRegistry { return { all: functions, new: newFunctions, deleted: deletedFunctions } } - private async setupWatchers(projectDir: string) { + private async setupWatchers() { if (!this.configPath) { return } @@ -529,18 +565,18 @@ export class EdgeFunctionsRegistry { // directories, they might be importing files that are located in // parent directories. So we watch the entire project directory for // changes. - await this.setupWatcherForDirectory(projectDir) + await this.setupWatcherForDirectory() } - private async setupWatcherForDirectory(directory: string) { + private async setupWatcherForDirectory() { const ignored = [`${this.servePath}/**`] - const watcher = await watchDebounced(directory, { + const watcher = await watchDebounced(this.projectDir, { ignored, onAdd: () => this.checkForAddedOrDeletedFunctions(), onChange: (paths) => this.handleFileChange(paths), onUnlink: () => this.checkForAddedOrDeletedFunctions(), }) - this.directoryWatchers.set(directory, watcher) + this.directoryWatchers.set(this.projectDir, watcher) } } diff --git a/src/lib/functions/netlify-function.ts b/src/lib/functions/netlify-function.ts index f4f55501771..a202948156b 100644 --- a/src/lib/functions/netlify-function.ts +++ b/src/lib/functions/netlify-function.ts @@ -30,6 +30,7 @@ export default class NetlifyFunction { public readonly mainFile: string public readonly displayName: string public readonly schedule?: string + public readonly runtime: string private readonly directory: string private readonly projectRoot: string @@ -43,7 +44,7 @@ export default class NetlifyFunction { private buildQueue?: Promise<$FIXME> private buildData?: $FIXME - private buildError: unknown | null = null + public buildError: Error | null = null // List of the function's source files. This starts out as an empty set // and will get populated on every build. @@ -81,7 +82,6 @@ export default class NetlifyFunction { this.name = name this.displayName = displayName ?? name this.projectRoot = projectRoot - // @ts-expect-error TS(2339) FIXME: Property 'runtime' does not exist on type 'Netlify... Remove this comment to see the full error message this.runtime = runtime this.timeoutBackground = timeoutBackground this.timeoutSynchronous = timeoutSynchronous @@ -199,7 +199,9 @@ export default class NetlifyFunction { return { includedFiles, srcFilesDiff } } catch (error) { - this.buildError = error + if (error instanceof Error) { + this.buildError = error + } return { error } } @@ -228,7 +230,6 @@ export default class NetlifyFunction { await this.buildQueue if (this.buildError) { - // @ts-expect-error TS(2339) FIXME: Property 'buildError' does not exist on type 'Netl... Remove this comment to see the full error message return { result: null, error: { errorMessage: this.buildError.message } } } diff --git a/src/lib/functions/registry.ts b/src/lib/functions/registry.ts index 118399baa98..840a4a65a43 100644 --- a/src/lib/functions/registry.ts +++ b/src/lib/functions/registry.ts @@ -3,7 +3,7 @@ import { createRequire } from 'module' import { basename, extname, isAbsolute, join, resolve } from 'path' import { env } from 'process' -import { listFunctions } from '@netlify/zip-it-and-ship-it' +import { ListedFunction, listFunctions } from '@netlify/zip-it-and-ship-it' import extractZip from 'extract-zip' import { @@ -28,6 +28,9 @@ export const DEFAULT_FUNCTION_URL_EXPRESSION = /^\/.netlify\/(functions|builders const TYPES_PACKAGE = '@netlify/functions' const ZIP_EXTENSION = '.zip' +const isInternalFunction = (func: ListedFunction | NetlifyFunction) => + func.mainFile.includes(getPathInProject([INTERNAL_FUNCTIONS_FOLDER])) + /** * @typedef {"buildError" | "extracted" | "loaded" | "missing-types-package" | "reloaded" | "reloading" | "removed"} FunctionEvent */ @@ -200,7 +203,6 @@ export class FunctionsRegistry { : `refer to https://ntl.fyi/functions-runtime` const warning = `The function is using the legacy CommonJS format. To start using ES modules, ${action}.` - // @ts-expect-error TS(2322) FIXME: Type 'string' is not assignable to type 'never'. FunctionsRegistry.logEvent(event, { func, warnings: [warning] }) } else { FunctionsRegistry.logEvent(event, { func }) @@ -304,15 +306,11 @@ export class FunctionsRegistry { /** * Logs an event associated with functions. - * - * @param {FunctionEvent} event - * @param {object} data - * @param {NetlifyFunction} [data.func] - * @param {string[]} [data.warnings] - * @returns */ - // @ts-expect-error TS(7006) FIXME: Parameter 'event' implicitly has an 'any' type. - static logEvent(event, { func, warnings = [] }) { + static logEvent( + event: 'buildError' | 'extracted' | 'loaded' | 'missing-types-package' | 'reloaded' | 'reloading' | 'removed', + { func, warnings = [] }: { func: NetlifyFunction; warnings?: string[] }, + ) { let warningsText = '' if (warnings.length !== 0) { @@ -381,19 +379,14 @@ export class FunctionsRegistry { /** * Adds a function to the registry - * - * @param {string} name - * @param {NetlifyFunction} funcBeforeHook - * @param {boolean} [isReload] - * @returns */ - // @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type. - async registerFunction(name, funcBeforeHook, isReload = false) { + async registerFunction(name: string, funcBeforeHook: NetlifyFunction, isReload = false) { const { runtime } = funcBeforeHook // The `onRegister` hook allows runtimes to modify the function before it's // registered, or to prevent it from being registered altogether if the // hook returns `null`. + // @ts-expect-error FIXME const func = typeof runtime.onRegister === 'function' ? runtime.onRegister(funcBeforeHook) : funcBeforeHook if (func === null) { @@ -453,13 +446,9 @@ export class FunctionsRegistry { /** * A proxy to zip-it-and-ship-it's `listFunctions` method. It exists just so * that we can mock it in tests. - * @param {Parameters} args - * @returns */ - // @ts-expect-error TS(7019) FIXME: Rest parameter 'args' implicitly has an 'any[]' ty... Remove this comment to see the full error message // eslint-disable-next-line class-methods-use-this - async listFunctions(...args) { - // @ts-expect-error TS(2556) FIXME: A spread argument must either have a tuple type or... Remove this comment to see the full error message + async listFunctions(...args: Parameters) { return await listFunctions(...args) } @@ -467,20 +456,17 @@ export class FunctionsRegistry { * Takes a list of directories and scans for functions. It keeps tracks of * any functions in those directories that we've previously seen, and takes * care of registering and unregistering functions as they come and go. - * - * @param {string[]} relativeDirs */ - // @ts-expect-error TS(7006) FIXME: Parameter 'relativeDirs' implicitly has an 'any' t... Remove this comment to see the full error message - async scan(relativeDirs) { - // @ts-expect-error TS(7006) FIXME: Parameter 'dir' implicitly has an 'any' type. - const directories = relativeDirs.filter(Boolean).map((dir) => (isAbsolute(dir) ? dir : join(this.projectRoot, dir))) + async scan(relativeDirs: (string | undefined)[]) { + const directories = relativeDirs + .filter((dir): dir is string => Boolean(dir)) + .map((dir) => (isAbsolute(dir) ? dir : join(this.projectRoot, dir))) // check after filtering to filter out [undefined] for example if (directories.length === 0) { return } - // @ts-expect-error TS(7006) FIXME: Parameter 'path' implicitly has an 'any' type. await Promise.all(directories.map((path) => FunctionsRegistry.prepareDirectoryScan(path))) const functions = await this.listFunctions(directories, { @@ -492,11 +478,26 @@ export class FunctionsRegistry { config: this.config.functions, }) + // user-defined functions take precedence over internal functions, + // so we want to ignore any internal functions where there's a user-defined one with the same name + const ignoredFunctions = new Set( + functions + .filter( + (func) => + isInternalFunction(func) && + this.functions.has(func.name) && + !isInternalFunction(this.functions.get(func.name)!), + ) + .map((func) => func.name), + ) + // Before registering any functions, we look for any functions that were on // the previous list but are missing from the new one. We unregister them. const deletedFunctions = [...this.functions.values()].filter((oldFunc) => { const isFound = functions.some( - (newFunc) => newFunc.name === oldFunc.name && newFunc.mainFile === oldFunc.mainFile, + (newFunc) => + ignoredFunctions.has(newFunc.name) || + (newFunc.name === oldFunc.name && newFunc.mainFile === oldFunc.mainFile), ) return !isFound @@ -510,6 +511,10 @@ export class FunctionsRegistry { // where the last ones precede the previous ones. This is why // we reverse the array so we get the right functions precedence in the CLI. functions.reverse().map(async ({ displayName, mainFile, name, runtime: runtimeName }) => { + if (ignoredFunctions.has(name)) { + return + } + const runtime = runtimes[runtimeName] // If there is no matching runtime, it means this function is not yet @@ -527,7 +532,6 @@ export class FunctionsRegistry { blobsContext: this.blobsContext, // @ts-expect-error TS(2339) FIXME: Property 'config' does not exist on type 'Function... Remove this comment to see the full error message config: this.config, - // @ts-expect-error TS(7006) FIXME: Parameter 'directory' implicitly has an 'any' type... Remove this comment to see the full error message directory: directories.find((directory) => mainFile.startsWith(directory)), mainFile, name, @@ -564,7 +568,6 @@ export class FunctionsRegistry { FunctionsRegistry.logEvent('removed', { func }) }) - // @ts-expect-error TS(7006) FIXME: Parameter 'path' implicitly has an 'any' type. await Promise.all(directories.map((path) => this.setupDirectoryWatcher(path))) } diff --git a/src/lib/functions/runtimes/index.ts b/src/lib/functions/runtimes/index.ts index df4d51271c8..bd12080115e 100644 --- a/src/lib/functions/runtimes/index.ts +++ b/src/lib/functions/runtimes/index.ts @@ -1,45 +1,33 @@ import * as go from './go/index.js' import * as js from './js/index.js' import * as rust from './rust/index.js' -/* eslint-enable import/no-namespace */ -/** - * @callback BuildFunction - * @param {object} func - * @returns {Promise<{srcFiles: string[], buildPath?: string}>} - */ -/** - * @callback GetBuildFunction - * @param {{ config: object, context: object, errorExit: function, func: object, functionsDirectory: string, projectRoot: string }} params - * @returns {Promise} - */ +type BuildFunction = (func: object) => Promise<{ srcFiles: string[]; buildPath?: string }> +type GetBuildFunction = (params: { + config: object + context: object + // eslint-disable-next-line @typescript-eslint/ban-types + errorExit: Function + func: object + functionsDirectory: string + projectRoot: string +}) => Promise +type InvokeFunction = (params: { + context: object + event: object + func: object + timeout: number +}) => Promise<{ body: object; statusCode: number }> +type OnDirectoryScanFunction = (params: { directory: string }) => Promise +type OnRegisterFunction = (func: object) => Promise -/** - * @callback InvokeFunction - * @param {{ context: object, event: object, func: object, timeout: number }} params - * @returns {Promise<{ body: object, statusCode: number }>} - */ - -/** - * @callback OnDirectoryScanFunction - * @param {{ directory: string }} params - * @returns {Promise} - */ - -/** - * @callback OnRegisterFunction - * @param {object} func - * @returns {object|null} - */ - -/** - * @typedef {object} Runtime - * @property {GetBuildFunction} getBuildFunction - * @property {InvokeFunction} invokeFunction - * @property {OnDirectoryScanFunction} [onDirectoryScan] - * @property {OnRegisterFunction} [onRegister] - * @property {string} name - */ +export interface Runtime { + getBuildFunction: GetBuildFunction + invokeFunction: InvokeFunction + onDirectoryScan?: OnDirectoryScanFunction + onRegister?: OnRegisterFunction + name: string +} const runtimes = { [go.name]: go, diff --git a/src/lib/functions/server.ts b/src/lib/functions/server.ts index 900fb25b132..85b53a2a142 100644 --- a/src/lib/functions/server.ts +++ b/src/lib/functions/server.ts @@ -293,9 +293,8 @@ export const startFunctionsServer = async (options) => { siteUrl, timeouts, } = options - // @ts-expect-error TS(2345) FIXME: Argument of type '{ base: any; }' is not assignabl... Remove this comment to see the full error message const internalFunctionsDir = await getInternalFunctionsDir({ base: site.root }) - const functionsDirectories = [] + const functionsDirectories: string[] = [] let manifest // If the `loadDistFunctions` parameter is sent, the functions server will diff --git a/src/utils/deploy/deploy-site.ts b/src/utils/deploy/deploy-site.ts index c6010c8b655..32b0f5965c0 100644 --- a/src/utils/deploy/deploy-site.ts +++ b/src/utils/deploy/deploy-site.ts @@ -62,9 +62,18 @@ export const deploySite = async ( tmpDir = temporaryDirectory(), // @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message workingDir, + }: { + concurrentHash?: number + concurrentUpload?: number + deployTimeout?: number + draft?: boolean + maxRetry?: number + statusCb?: (status: { type: string; msg: string; phase: string }) => void + syncFileLimit?: number + tmpDir?: string + fnDir?: string[] } = {}, ) => { - // @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1. statusCb({ type: 'hashing', msg: `Hashing files...`, @@ -115,7 +124,6 @@ export const deploySite = async ( edgeFunctionsCount > 0 && 'edge functions', ]) - // @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1. statusCb({ type: 'hashing', msg: `Finished hashing ${stats}`, @@ -141,7 +149,6 @@ instead of manual deployment. For more information, visit https://ntl.fyi/cli-native-modules.`) } - // @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1. statusCb({ type: 'create-deploy', msg: 'CDN diffing files...', @@ -168,7 +175,6 @@ For more information, visit https://ntl.fyi/cli-native-modules.`) const { required: requiredFiles, required_functions: requiredFns } = deploy - // @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1. statusCb({ type: 'create-deploy', msg: `CDN requesting ${requiredFiles.length} files${ @@ -183,7 +189,6 @@ For more information, visit https://ntl.fyi/cli-native-modules.`) await uploadFiles(api, deployId, uploadList, { concurrentUpload, statusCb, maxRetry }) - // @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1. statusCb({ type: 'wait-for-deploy', msg: 'Waiting for deploy to go live...', @@ -191,7 +196,6 @@ For more information, visit https://ntl.fyi/cli-native-modules.`) }) deploy = await waitForDeploy(api, deployId, siteId, deployTimeout) - // @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1. statusCb({ type: 'wait-for-deploy', msg: draft ? 'Draft deploy is live!' : 'Deploy is live!', diff --git a/src/utils/detect-server-settings.ts b/src/utils/detect-server-settings.ts index c46d40e322e..07554431a58 100644 --- a/src/utils/detect-server-settings.ts +++ b/src/utils/detect-server-settings.ts @@ -12,25 +12,16 @@ import { type DevConfig } from '../commands/dev/types.js' import { detectFrameworkSettings } from './build-info.js' import { NETLIFYDEVWARN, chalk, log } from './command-helpers.js' import { acquirePort } from './dev.js' -import { getInternalFunctionsDir } from './functions/functions.js' import { getPluginsToAutoInstall } from './init/utils.js' import { BaseServerSettings, ServerSettings } from './types.js' -/** @param {string} str */ -// @ts-expect-error TS(7006) FIXME: Parameter 'str' implicitly has an 'any' type. -const formatProperty = (str) => chalk.magenta(`'${str}'`) -/** @param {string} str */ -// @ts-expect-error TS(7006) FIXME: Parameter 'str' implicitly has an 'any' type. -const formatValue = (str) => chalk.green(`'${str}'`) +const formatProperty = (str: string) => chalk.magenta(`'${str}'`) +const formatValue = (str: string) => chalk.green(`'${str}'`) -/** - * @param {object} options - * @param {string} options.keyFile - * @param {string} options.certFile - * @returns {Promise<{ key: string, cert: string, keyFilePath: string, certFilePath: string }>} - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const readHttpsSettings = async (options) => { +const readHttpsSettings = async (options: { + keyFile: string + certFile: string +}): Promise<{ key: string; cert: string; keyFilePath: string; certFilePath: string }> => { if (typeof options !== 'object' || !options.keyFile || !options.certFile) { throw new TypeError( `https options should be an object with ${formatProperty('keyFile')} and ${formatProperty( @@ -61,12 +52,8 @@ const readHttpsSettings = async (options) => { /** * Validates a property inside the devConfig to be of a given type - * @param {import('../commands/dev/types.js').DevConfig} devConfig The devConfig - * @param {keyof import('../commands/dev/types.js').DevConfig} property The property to validate - * @param {'string' | 'number'} type The type it should have */ -// @ts-expect-error TS(7006) FIXME: Parameter 'devConfig' implicitly has an 'any' type... Remove this comment to see the full error message -function validateProperty(devConfig, property, type) { +function validateProperty(devConfig: DevConfig, property: keyof DevConfig, type: 'string' | 'number') { if (devConfig[property] && typeof devConfig[property] !== type) { const formattedProperty = formatProperty(property) throw new TypeError( @@ -75,13 +62,7 @@ function validateProperty(devConfig, property, type) { } } -/** - * - * @param {object} config - * @param {import('../commands/dev/types.js').DevConfig} config.devConfig - */ -// @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message -const validateFrameworkConfig = ({ devConfig }) => { +const validateFrameworkConfig = ({ devConfig }: { devConfig: DevConfig }) => { validateProperty(devConfig, 'command', 'string') validateProperty(devConfig, 'port', 'number') validateProperty(devConfig, 'targetPort', 'number') @@ -95,13 +76,7 @@ const validateFrameworkConfig = ({ devConfig }) => { } } -/** - * @param {object} config - * @param {import('../commands/dev/types.js').DevConfig} config.devConfig - * @param {number=} config.detectedPort - */ -// @ts-expect-error TS(7031) FIXME: Binding element 'detectedPort' implicitly has an '... Remove this comment to see the full error message -const validateConfiguredPort = ({ detectedPort, devConfig }) => { +const validateConfiguredPort = ({ detectedPort, devConfig }: { detectedPort?: number; devConfig: DevConfig }) => { if (devConfig.port && devConfig.port === detectedPort) { const formattedPort = formatProperty('port') throw new Error( @@ -115,23 +90,15 @@ const DEFAULT_STATIC_PORT = 3999 /** * Logs a message that it was unable to determine the dist directory and falls back to the workingDir - * @param {string} workingDir */ -// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message -const getDefaultDist = (workingDir) => { +const getDefaultDist = (workingDir: string) => { log(`${NETLIFYDEVWARN} Unable to determine public folder to serve files from. Using current working directory`) log(`${NETLIFYDEVWARN} Setup a netlify.toml file with a [dev] section to specify your dev server settings.`) log(`${NETLIFYDEVWARN} See docs at: https://cli.netlify.com/netlify-dev#project-detection`) return workingDir } -/** - * @param {object} config - * @param {import('../commands/dev/types.js').DevConfig} config.devConfig - * @returns {Promise} - */ -// @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message -const getStaticServerPort = async ({ devConfig }) => { +const getStaticServerPort = async ({ devConfig }: { devConfig: DevConfig }): Promise => { const port = await acquirePort({ configuredPort: devConfig.staticServerPort, defaultPort: DEFAULT_STATIC_PORT, @@ -141,16 +108,15 @@ const getStaticServerPort = async ({ devConfig }) => { return port } -/** - * - * @param {object} config - * @param {import('../commands/dev/types.js').DevConfig} config.devConfig - * @param {import('commander').OptionValues} config.flags - * @param {string} config.workingDir - * @returns {Promise & {command?: string}>} - */ -// @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message -const handleStaticServer = async ({ devConfig, flags, workingDir }) => { +const handleStaticServer = async ({ + devConfig, + flags, + workingDir, +}: { + devConfig: DevConfig + flags: OptionValues + workingDir: string +}): Promise & { command?: string }> => { validateProperty(devConfig, 'staticServerPort', 'number') if (flags.dir) { @@ -203,21 +169,18 @@ const getSettingsFromDetectedSettings = (command: BaseCommand, settings?: Settin } } -/** - * @param {import('../commands/dev/types.js').DevConfig} devConfig - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'devConfig' implicitly has an 'any' type... Remove this comment to see the full error message -const hasCommandAndTargetPort = (devConfig) => devConfig.command && devConfig.targetPort +const hasCommandAndTargetPort = (devConfig: DevConfig) => devConfig.command && devConfig.targetPort /** * Creates settings for the custom framework - * @param {object} config - * @param {import('../commands/dev/types.js').DevConfig} config.devConfig - * @param {string} config.workingDir - * @returns {import('./types.js').BaseServerSettings} */ -// @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message -const handleCustomFramework = ({ devConfig, workingDir }) => { +const handleCustomFramework = ({ + devConfig, + workingDir, +}: { + devConfig: DevConfig + workingDir: string +}): BaseServerSettings => { if (!hasCommandAndTargetPort(devConfig)) { throw new Error( `${formatProperty('command')} and ${formatProperty('targetPort')} properties are required when ${formatProperty( @@ -236,28 +199,15 @@ const handleCustomFramework = ({ devConfig, workingDir }) => { /** * Merges the framework settings with the devConfig - * @param {object} config - * @param {import('../commands/dev/types.js').DevConfig} config.devConfig - * @param {string} config.workingDir - * @param {Partial=} config.frameworkSettings */ const mergeSettings = async ({ devConfig, frameworkSettings = {}, workingDir, }: { - devConfig: { command?: string; publish?: string; targetPort?: number; base?: string } + devConfig: DevConfig + frameworkSettings?: BaseServerSettings workingDir: string - frameworkSettings?: { - baseDirectory?: string - command?: string - dist?: string - env?: Record - framework?: string - frameworkPort?: number - pollingStrategies?: string[] - clearPublishDirectory?: boolean - } }) => { const command = devConfig.command || frameworkSettings.command const frameworkPort = devConfig.targetPort || frameworkSettings.frameworkPort @@ -353,9 +303,6 @@ const detectServerSettings = async ( }) // @ts-expect-error TS(2339) FIXME: Property 'functions' does not exist on type '{}'. const functionsDir = devConfig.functions || settings.functions - // @ts-expect-error TS(2345) FIXME: Argument of type '{ base: any; }' is not assignabl... Remove this comment to see the full error message - const internalFunctionsDir = await getInternalFunctionsDir({ base: command.workingDir }) - const shouldStartFunctionsServer = Boolean(functionsDir || internalFunctionsDir) return { ...settings, @@ -363,7 +310,7 @@ const detectServerSettings = async ( jwtSecret: devConfig.jwtSecret || 'secret', jwtRolePath: devConfig.jwtRolePath || 'app_metadata.authorization.roles', functions: functionsDir, - ...(shouldStartFunctionsServer && { functionsPort: await getPort({ port: devConfig.functionsPort || 0 }) }), + functionsPort: await getPort({ port: devConfig.functionsPort || 0 }), ...(devConfig.https && { https: await readHttpsSettings(devConfig.https) }), } } @@ -371,12 +318,9 @@ const detectServerSettings = async ( /** * Returns a copy of the provided config with any plugins provided by the * server settings - * @param {*} config - * @param {Partial} settings - * @returns {*} Modified config */ // @ts-expect-error TS(7006) FIXME: Parameter 'config' implicitly has an 'any' type. -export const getConfigWithPlugins = (config, settings) => { +export const getConfigWithPlugins = (config, settings: ServerSettings) => { if (!settings.plugins) { return config } @@ -389,7 +333,6 @@ export const getConfigWithPlugins = (config, settings) => { // @ts-expect-error TS(7006) FIXME: Parameter 'plugin' implicitly has an 'any' type. const existingPluginNames = new Set(existingPlugins.map((plugin) => plugin.package)) const newPlugins = settings.plugins - // @ts-expect-error TS(7006) FIXME: Parameter 'pluginName' implicitly has an 'any' typ... Remove this comment to see the full error message .map((pluginName) => { if (existingPluginNames.has(pluginName)) { return diff --git a/src/utils/functions/functions.ts b/src/utils/functions/functions.ts index 69650ee1dda..23ce9fc4836 100644 --- a/src/utils/functions/functions.ts +++ b/src/utils/functions/functions.ts @@ -44,21 +44,21 @@ export const getFunctionsServePath = ({ base, packagePath = '' }) => { /** * Retrieves the internal functions directory and creates it if ensureExists is provided - * @param {object} config - * @param {string} config.base - * @param {boolean=} config.ensureExists - * @param {string} config.packagePath - * @returns */ -// @ts-expect-error TS(7031) FIXME: Binding element 'base' implicitly has an 'any' typ... Remove this comment to see the full error message -export const getInternalFunctionsDir = async ({ base, ensureExists, packagePath = '' }) => { +export const getInternalFunctionsDir = async ({ + base, + ensureExists, + packagePath = '', +}: { + base: string + ensureExists?: boolean + packagePath?: string +}) => { const path = resolve(base, packagePath, getPathInProject([INTERNAL_FUNCTIONS_FOLDER])) if (ensureExists) { await fs.mkdir(path, { recursive: true }) } - const isDirectory = await isDirectoryAsync(path) - - return isDirectory ? path : null + return path } diff --git a/src/utils/types.d.ts b/src/utils/types.d.ts index d8bcef98bf9..9491106febd 100644 --- a/src/utils/types.d.ts +++ b/src/utils/types.d.ts @@ -33,6 +33,7 @@ export type BaseServerSettings = { env?: NodeJS.ProcessEnv pollingStrategies?: string[] plugins?: string[] + clearPublishDirectory?: boolean } export type ServerSettings = BaseServerSettings & { @@ -40,8 +41,10 @@ export type ServerSettings = BaseServerSettings & { jwtSecret: string /** default 'app_metadata.authorization.roles' */ jwtRolePath: string - /** The port where the functions are running on */ + /** The port where the dev server is running on */ port: number + /** The port where the functions are running on */ + functionsPort: number https?: { key: string; cert: string; keyFilePath: string; certFilePath: string } clearPublishDirectory?: boolean } diff --git a/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/integration-iscA.ts b/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/integration-iscA.ts similarity index 100% rename from tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/integration-iscA.ts rename to tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/integration-iscA.ts diff --git a/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/integration-iscB.ts b/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/integration-iscB.ts similarity index 100% rename from tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/integration-iscB.ts rename to tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/integration-iscB.ts diff --git a/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/integration-manifestA.ts b/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/integration-manifestA.ts similarity index 100% rename from tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/integration-manifestA.ts rename to tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/integration-manifestA.ts diff --git a/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/integration-manifestB.ts b/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/integration-manifestB.ts similarity index 100% rename from tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/integration-manifestB.ts rename to tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/integration-manifestB.ts diff --git a/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/integration-manifestC.ts b/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/integration-manifestC.ts similarity index 100% rename from tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/integration-manifestC.ts rename to tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/integration-manifestC.ts diff --git a/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/manifest.json b/tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/manifest.json similarity index 100% rename from tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/edge-functions/manifest.json rename to tests/integration/__fixtures__/dev-server-with-edge-functions/.netlify/_edge-functions/manifest.json diff --git a/tests/integration/commands/dev/dev-miscellaneous.test.js b/tests/integration/commands/dev/dev-miscellaneous.test.js index 5b3e40440de..d3a71f4bc83 100644 --- a/tests/integration/commands/dev/dev-miscellaneous.test.js +++ b/tests/integration/commands/dev/dev-miscellaneous.test.js @@ -926,7 +926,7 @@ describe.concurrent('commands/dev-miscellaneous', () => { }) }) - test.skip('should respect in-source configuration from internal edge functions', async (t) => { + test('should respect in-source configuration from internal edge functions', async (t) => { await withSiteBuilder('site-with-internal-edge-functions', async (builder) => { const publicDir = 'public' await builder @@ -937,16 +937,20 @@ describe.concurrent('commands/dev-miscellaneous', () => { }, }, }) - .withEdgeFunction({ - config: { path: '/internal-1' }, - handler: () => new Response('Hello from an internal function'), - internal: true, - name: 'internal', - }) - - await builder.buildAsync() + .build() await withDevServer({ cwd: builder.directory }, async ({ port, waitForLogMatching }) => { + // internal functions are cleared on startup, + // so we create them after the dev server is up and running + await builder + .withEdgeFunction({ + config: { path: '/internal-1' }, + handler: () => new Response('Hello from an internal function'), + internal: true, + name: 'internal', + }) + .build() + const res1 = await fetch(`http://localhost:${port}/internal-1`) t.expect(res1.status).toBe(200) @@ -979,7 +983,7 @@ describe.concurrent('commands/dev-miscellaneous', () => { }) }) - test.skip('Serves edge functions with import maps coming from the `functions.deno_import_map` config property and from the internal manifest', async (t) => { + test('Serves edge functions with import maps coming from the `functions.deno_import_map` config property and from the internal manifest', async (t) => { await withSiteBuilder('site-with-edge-functions-and-import-maps', async (builder) => { const internalEdgeFunctionsDir = path.join('.netlify', 'edge-functions') @@ -999,11 +1003,6 @@ describe.concurrent('commands/dev-miscellaneous', () => { handler: `import { greet } from "greeter"; export default async () => new Response(greet("Netlify"))`, name: 'greet', }) - .withEdgeFunction({ - handler: `import { yell } from "yeller"; export default async () => new Response(yell("Netlify"))`, - name: 'yell', - internal: true, - }) // User-defined import map .withContentFiles([ { @@ -1016,29 +1015,36 @@ describe.concurrent('commands/dev-miscellaneous', () => { path: 'import_map.json', }, ]) - // Internal import map - .withContentFiles([ - { - content: 'export const yell = (name: string) => name.toUpperCase()', - path: path.join(internalEdgeFunctionsDir, 'util', 'yeller.ts'), - }, - { - content: JSON.stringify({ - functions: [{ function: 'yell', path: '/yell' }], - import_map: 'import_map.json', - version: 1, - }), - path: path.join(internalEdgeFunctionsDir, 'manifest.json'), - }, - { - content: JSON.stringify({ imports: { yeller: './util/yeller.ts' } }), - path: path.join(internalEdgeFunctionsDir, 'import_map.json'), - }, - ]) - - await builder.buildAsync() + .build() await withDevServer({ cwd: builder.directory }, async ({ port }) => { + await builder + .withEdgeFunction({ + handler: `import { yell } from "yeller"; export default async () => new Response(yell("Netlify"))`, + name: 'yell', + internal: true, + }) + // Internal import map + .withContentFiles([ + { + content: 'export const yell = (name: string) => name.toUpperCase()', + path: path.join(internalEdgeFunctionsDir, 'util', 'yeller.ts'), + }, + { + content: JSON.stringify({ + functions: [{ function: 'yell', path: '/yell' }], + import_map: 'import_map.json', + version: 1, + }), + path: path.join(internalEdgeFunctionsDir, 'manifest.json'), + }, + { + content: JSON.stringify({ imports: { yeller: './util/yeller.ts' } }), + path: path.join(internalEdgeFunctionsDir, 'import_map.json'), + }, + ]) + .build() + const [res1, res2] = await Promise.all([ fetch(`http://localhost:${port}/greet`), fetch(`http://localhost:${port}/yell`), diff --git a/tests/integration/commands/dev/dev.zisi.test.js b/tests/integration/commands/dev/dev.zisi.test.js index 16730639afa..956dd455009 100644 --- a/tests/integration/commands/dev/dev.zisi.test.js +++ b/tests/integration/commands/dev/dev.zisi.test.js @@ -49,7 +49,7 @@ describe.concurrent.each(testMatrix)('withSiteBuilder with args: $args', ({ args body: JSON.stringify(event), }), }) - .buildAsync() + .build() await withDevServer({ cwd: builder.directory, args }, async (server) => { const [fromFunction, queryPassthrough, queryInRedirect, withParamMatching, functionWithSplat] = @@ -80,7 +80,7 @@ describe.concurrent.each(testMatrix)('withSiteBuilder with args: $args', ({ args }) test('Should not use the ZISI function bundler if not using esbuild', async (t) => { - await withSiteBuilder('site-with-esm-function', async (builder) => { + await withSiteBuilder('site-with-esm-function-and-no-esbuild', async (builder) => { builder.withNetlifyToml({ config: { functions: { directory: 'functions' } } }).withContentFile({ path: path.join('functions', 'esm-function', 'esm-function.js'), content: ` @@ -93,18 +93,17 @@ export async function handler(event, context) { `, }) - await builder.buildAsync() + await builder.build() - t.expect(() => - withDevServer({ cwd: builder.directory, args }, async (server) => - nodeFetch(`${server.url}/.netlify/functions/esm-function`).text(), - ), - ).rejects.toThrow() + await withDevServer({ cwd: builder.directory, args }, async (server) => { + const resp = await nodeFetch(`${server.url}/.netlify/functions/esm-function`) + t.expect(await resp.text()).toContain(`SyntaxError: Unexpected token 'export'`) + }) }) }) test('Should use the ZISI function bundler and serve ESM functions if using esbuild', async (t) => { - await withSiteBuilder('site-with-esm-function', async (builder) => { + await withSiteBuilder('site-with-esm-function-and-esbuild', async (builder) => { builder .withNetlifyToml({ config: { functions: { directory: 'functions', node_bundler: 'esbuild' } } }) .withContentFile({ @@ -119,7 +118,7 @@ export async function handler(event, context) { `, }) - await builder.buildAsync() + await builder.build() await withDevServer({ cwd: builder.directory, args }, async (server) => { const response = await nodeFetch(`${server.url}/.netlify/functions/esm-function`).then((res) => res.text()) @@ -129,7 +128,7 @@ export async function handler(event, context) { }) test('Should use the ZISI function bundler and serve TypeScript functions if using esbuild', async (t) => { - await withSiteBuilder('site-with-ts-function', async (builder) => { + await withSiteBuilder('site-with-ts-function-and-esbuild', async (builder) => { builder .withNetlifyToml({ config: { functions: { directory: 'functions', node_bundler: 'esbuild' } } }) .withContentFile({ @@ -149,7 +148,7 @@ export const handler = async function () { `, }) - await builder.buildAsync() + await builder.build() await withDevServer({ cwd: builder.directory, args }, async (server) => { const response = await nodeFetch(`${server.url}/.netlify/functions/ts-function`).then((res) => res.text()) @@ -159,7 +158,7 @@ export const handler = async function () { }) test('Should use the ZISI function bundler and serve TypeScript functions if not using esbuild', async (t) => { - await withSiteBuilder('site-with-ts-function', async (builder) => { + await withSiteBuilder('site-with-ts-function-and-no-esbuild', async (builder) => { builder.withNetlifyToml({ config: { functions: { directory: 'functions' } } }).withContentFile({ path: path.join('functions', 'ts-function', 'ts-function.ts'), content: ` @@ -177,7 +176,7 @@ export const handler = async function () { `, }) - await builder.buildAsync() + await builder.build() await withDevServer({ cwd: builder.directory, args }, async (server) => { const response = await nodeFetch(`${server.url}/.netlify/functions/ts-function`).then((res) => res.text()) @@ -242,7 +241,7 @@ export const handler = async function () { }, name: 'hello', }) - .buildAsync() + .build() await Promise.all([ copyFile(`${__dirname}/../../../../localhost.crt`, `${builder.directory}/localhost.crt`), @@ -301,7 +300,7 @@ export const handler = async function () { } }, }) - .buildAsync() + .build() const siteInfo = { account_slug: 'test-account', @@ -353,7 +352,7 @@ export const handler = async function () { path: 'hello.js', handler: async () => ({ statusCode: 200, body: 'Hello' }), }) - .buildAsync() + .build() await withDevServer({ cwd: builder.directory, args }, async (server) => { await curl(`${server.url}/.netlify/functions/hello`, [ @@ -383,7 +382,7 @@ export const handler = async function () { redirects: [{ from: '/*', to: '/index.html', status: 200 }], }, }) - .buildAsync() + .build() await withDevServer({ cwd: builder.directory, args }, async (server) => { const response = await nodeFetch(`${server.url}/${encodeURIComponent('范.txt')}`) @@ -406,7 +405,7 @@ export const handler = async function () { metadata: { builder_function: true }, }), }) - .buildAsync() + .build() await withDevServer({ cwd: builder.directory, args }, async (server) => { const response = await nodeFetch(`${server.url}/.netlify/functions/custom-headers`) @@ -427,7 +426,7 @@ export const handler = async function () { await builder .withContentFile({ path: 'static/special[test].txt', content: `special` }) .withRedirectsFile({ redirects: [{ from: '/_next/static/*', to: '/static/:splat', status: 200 }] }) - .buildAsync() + .build() await withDevServer({ cwd: builder.directory, args }, async (server) => { const [response1, response2] = await Promise.all([ @@ -440,9 +439,9 @@ export const handler = async function () { }) }) - test(`should not redirect POST request to functions server when it doesn't exists`, async (t) => { + test(`always redirects POST requests to functions server`, async (t) => { await withSiteBuilder('site-with-post-request', async (builder) => { - await builder.buildAsync() + await builder.build() await withDevServer({ cwd: builder.directory, args }, async (server) => { // an error is expected since we're sending a POST request to a static server @@ -455,8 +454,8 @@ export const handler = async function () { body: 'some=thing', }) - t.expect(error.status).toBe(405) - t.expect(await error.text()).toEqual('Method Not Allowed') + t.expect(error.status).toBe(404) + t.expect(await error.text()).toEqual('Function not found...') }) }) }) diff --git a/tests/integration/commands/dev/edge-functions.test.ts b/tests/integration/commands/dev/edge-functions.test.ts index 63f6b83cf3a..82e0995ae89 100644 --- a/tests/integration/commands/dev/edge-functions.test.ts +++ b/tests/integration/commands/dev/edge-functions.test.ts @@ -1,4 +1,6 @@ import process from 'process' +import { rename } from 'fs/promises' +import { join } from 'path' import execa from 'execa' import { describe, expect, expectTypeOf, test } from 'vitest' @@ -31,106 +33,117 @@ const routes = [ }, ] -const setup = async ({ fixture }) => { +const setup = async ({ fixture }: FixtureTestContext) => { await execa('npm', ['install'], { cwd: fixture.directory }) } +const recreateEdgeFunctions = async ({ fixture }: FixtureTestContext) => { + await rename( + join(fixture.directory, '.netlify', '_edge-functions'), + join(fixture.directory, '.netlify', 'edge-functions'), + ) +} + describe.skipIf(isWindows)('edge functions', () => { - setupFixtureTests('dev-server-with-edge-functions', { devServer: true, mockApi: { routes } }, () => { - test.skip('should run edge functions in correct order', async ({ devServer }) => { - const response = await fetch(`http://localhost:${devServer.port}/ordertest`) - const body = await response.text() + setupFixtureTests( + 'dev-server-with-edge-functions', + { devServer: true, mockApi: { routes }, setupAfterDev: recreateEdgeFunctions }, + () => { + test('should run edge functions in correct order', async ({ devServer }) => { + const response = await fetch(`http://localhost:${devServer.port}/ordertest`) + const body = await response.text() - expect(response.status).toBe(200) - expect(body).toMatchSnapshot() - }) + expect(response.status).toBe(200) + expect(body).toMatchSnapshot() + }) - test('should provide context properties', async ({ devServer }) => { - const response = await fetch(`http://localhost:${devServer.port}/context`) - - const { deploy, geo, ip, params, requestId, server, site } = await response.json() - expect(geo.city).toEqual('Mock City') - expect(geo.country.code).toEqual('DE') - expect(deploy).toEqual({ id: '0' }) - expectTypeOf(ip).toBeString() - expect(params).toEqual({}) - expectTypeOf(requestId).toBeString() - expect(server).toEqual({ region: 'local' }) - expect(site).toEqual({ id: 'foo', name: 'site-name', url: `http://localhost:${devServer.port}` }) - }) + test('should provide context properties', async ({ devServer }) => { + const response = await fetch(`http://localhost:${devServer.port}/context`) + + const { deploy, geo, ip, params, requestId, server, site } = await response.json() + expect(geo.city).toEqual('Mock City') + expect(geo.country.code).toEqual('DE') + expect(deploy).toEqual({ id: '0' }) + expectTypeOf(ip).toBeString() + expect(params).toEqual({}) + expectTypeOf(requestId).toBeString() + expect(server).toEqual({ region: 'local' }) + expect(site).toEqual({ id: 'foo', name: 'site-name', url: `http://localhost:${devServer.port}` }) + }) - test('should expose URL parameters', async ({ devServer }) => { - const response = await fetch(`http://localhost:${devServer.port}/categories/foo/products/bar`) + test('should expose URL parameters', async ({ devServer }) => { + const response = await fetch(`http://localhost:${devServer.port}/categories/foo/products/bar`) - const { params } = await response.json() - expect(params).toEqual({ - category: 'foo', - product: 'bar', + const { params } = await response.json() + expect(params).toEqual({ + category: 'foo', + product: 'bar', + }) }) - }) - test('should expose URL parameters to edge functions with `cache: "manual"`', async ({ - devServer, - }) => { - const response = await fetch(`http://localhost:${devServer.port}/categories-after-cache/foo/products/bar`) + test('should expose URL parameters to edge functions with `cache: "manual"`', async ({ + devServer, + }) => { + const response = await fetch(`http://localhost:${devServer.port}/categories-after-cache/foo/products/bar`) - const { params } = await response.json() - expect(params).toEqual({ - category: 'foo', - product: 'bar', + const { params } = await response.json() + expect(params).toEqual({ + category: 'foo', + product: 'bar', + }) }) - }) - test('should respect config.methods field', async ({ devServer }) => { - const responseGet = await fetch(`http://localhost:${devServer.port}/products/really-bad-product`, { - method: 'GET', - }) + test('should respect config.methods field', async ({ devServer }) => { + const responseGet = await fetch(`http://localhost:${devServer.port}/products/really-bad-product`, { + method: 'GET', + }) - expect(responseGet.status).toBe(404) + expect(responseGet.status).toBe(404) - const responseDelete = await fetch(`http://localhost:${devServer.port}/products/really-bad-product`, { - method: 'DELETE', - }) + const responseDelete = await fetch(`http://localhost:${devServer.port}/products/really-bad-product`, { + method: 'DELETE', + }) - expect(await responseDelete.text()).toEqual('Deleted item successfully: really-bad-product') - }) + expect(await responseDelete.text()).toEqual('Deleted item successfully: really-bad-product') + }) - test('should show an error page when an edge function has an uncaught exception', async ({ - devServer, - }) => { - const [plainTextResponse, htmlResponse] = await Promise.all([ - fetch(`http://localhost:${devServer.port}/uncaught-exception`, { - method: 'GET', - }), - fetch(`http://localhost:${devServer.port}/uncaught-exception`, { - method: 'GET', - headers: { - Accept: 'text/html', - }, - }), - ]) - - expect(plainTextResponse.status).toBe(500) - expect(await plainTextResponse.text()).toContain('ReferenceError: thisWillThrow is not defined') - - expect(await htmlResponse.text()).toContain( - '

An unhandled error in the function code triggered the following message:

', - ) - }) + test('should show an error page when an edge function has an uncaught exception', async ({ + devServer, + }) => { + const [plainTextResponse, htmlResponse] = await Promise.all([ + fetch(`http://localhost:${devServer.port}/uncaught-exception`, { + method: 'GET', + }), + fetch(`http://localhost:${devServer.port}/uncaught-exception`, { + method: 'GET', + headers: { + Accept: 'text/html', + }, + }), + ]) + + expect(plainTextResponse.status).toBe(500) + expect(await plainTextResponse.text()).toContain('ReferenceError: thisWillThrow is not defined') + + expect(await htmlResponse.text()).toContain( + '

An unhandled error in the function code triggered the following message:

', + ) + }) - test('should set the `URL`, `SITE_ID`, and `SITE_NAME` environment variables', async ({ - devServer, - }) => { - const body = (await fetch(`http://localhost:${devServer.port}/echo-env`).then((res) => res.json())) as Record< - string, - string - > - - expect(body.SITE_ID).toBe('foo') - expect(body.SITE_NAME).toBe('site-name') - expect(body.URL).toBe(`http://localhost:${devServer.port}`) - }) - }) + test('should set the `URL`, `SITE_ID`, and `SITE_NAME` environment variables', async ({ + devServer, + }) => { + const body = (await fetch(`http://localhost:${devServer.port}/echo-env`).then((res) => res.json())) as Record< + string, + string + > + + expect(body.SITE_ID).toBe('foo') + expect(body.SITE_NAME).toBe('site-name') + expect(body.URL).toBe(`http://localhost:${devServer.port}`) + }) + }, + ) setupFixtureTests('dev-server-with-edge-functions', { devServer: true, mockApi: { routes } }, () => { test('should not remove other edge functions on change', async ({ devServer, fixture }) => { diff --git a/tests/integration/commands/functions-with-args/functions-with-args.test.js b/tests/integration/commands/functions-with-args/functions-with-args.test.js index b6a19773078..c4dee08cf0b 100644 --- a/tests/integration/commands/functions-with-args/functions-with-args.test.js +++ b/tests/integration/commands/functions-with-args/functions-with-args.test.js @@ -482,7 +482,7 @@ exports.handler = async () => ({ }) }) - test.skip('Serves functions from the internal functions directory', async (t) => { + test('Serves functions from the internal functions directory', async (t) => { await withSiteBuilder('function-internal', async (builder) => { const bundlerConfig = args.includes('esbuild') ? { node_bundler: 'esbuild' } : {} @@ -494,17 +494,22 @@ exports.handler = async () => ({ ...bundlerConfig, }, }) - .withFunction({ - path: 'hello.js', - pathPrefix: '.netlify/functions-internal', - handler: async () => ({ - statusCode: 200, - body: 'Internal', - }), - }) - .buildAsync() + .build() await withDevServer({ cwd: builder.directory, args }, async ({ outputBuffer, port, waitForLogMatching }) => { + await builder + .withFunction({ + path: 'hello.js', + pathPrefix: '.netlify/functions-internal', + handler: async () => ({ + statusCode: 200, + body: 'Internal', + }), + }) + .build() + + await pause(WAIT_WRITE) + await tryAndLogOutput(async () => { t.expect(await fetch(`http://localhost:${port}/.netlify/functions/hello`).then((res) => res.text())).toEqual( 'Internal', @@ -552,17 +557,20 @@ exports.handler = async () => ({ body: 'User', }), }) - .withFunction({ - path: 'hello.js', - pathPrefix: '.netlify/functions-internal', - handler: async () => ({ - statusCode: 200, - body: 'Internal', - }), - }) - .buildAsync() + .build() await withDevServer({ cwd: builder.directory, args }, async ({ outputBuffer, port, waitForLogMatching }) => { + await builder + .withFunction({ + path: 'hello.js', + pathPrefix: '.netlify/functions-internal', + handler: async () => ({ + statusCode: 200, + body: 'Internal', + }), + }) + .build() + await tryAndLogOutput(async () => { t.expect(await fetch(`http://localhost:${port}/.netlify/functions/hello`).then((res) => res.text())).toEqual( 'User', diff --git a/tests/integration/utils/dev-server.ts b/tests/integration/utils/dev-server.ts index fdbaecdb9f0..f7d9c46ee98 100644 --- a/tests/integration/utils/dev-server.ts +++ b/tests/integration/utils/dev-server.ts @@ -22,7 +22,7 @@ export const getExecaOptions = ({ cwd, env }) => { } } -interface DevServer { +export interface DevServer { url: string host: string port: number diff --git a/tests/integration/utils/fixture.ts b/tests/integration/utils/fixture.ts index c3878b67c3b..a8480004ac9 100644 --- a/tests/integration/utils/fixture.ts +++ b/tests/integration/utils/fixture.ts @@ -7,7 +7,7 @@ import { temporaryDirectory } from 'tempy' import { afterAll, afterEach, beforeAll, beforeEach, describe } from 'vitest' import { callCli } from './call-cli.js' -import { startDevServer } from './dev-server.ts' +import { DevServer, startDevServer } from './dev-server.ts' import { MockApi, Route, getCLIOptions, startMockApi } from './mock-api-vitest.js' import { SiteBuilder } from './site-builder.ts' @@ -20,7 +20,7 @@ interface MockApiOptions { export interface FixtureTestContext { fixture: Fixture - devServer?: any + devServer?: DevServer mockApi?: MockApi } @@ -33,6 +33,10 @@ export interface FixtureOptions { * Executed after fixture setup, but before tests run */ setup?: LifecycleHook + /** + * Executed after fixture setup, after dev is started, but before tests run + */ + setupAfterDev?: LifecycleHook /** * Executed before fixture is cleaned up */ @@ -158,6 +162,8 @@ export async function setupFixtureTests( NETLIFY_AUTH_TOKEN: 'fake-token', }, }) + + await options.setupAfterDev?.({ fixture, mockApi, devServer }) } }, HOOK_TIMEOUT) From 013f7f56442336e2bef9ecef24409e59ec488886 Mon Sep 17 00:00:00 2001 From: "token-generator-app[bot]" <82042599+token-generator-app[bot]@users.noreply.github.com> Date: Tue, 2 Jan 2024 15:31:10 +0000 Subject: [PATCH 5/5] chore(main): release 17.11.0 (#6280) Co-authored-by: token-generator-app[bot] <82042599+token-generator-app[bot]@users.noreply.github.com> --- CHANGELOG.md | 12 ++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f429981aa9..99a2e81c6e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,18 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +## [17.11.0](https://github.com/netlify/cli/compare/v17.10.2...v17.11.0) (2024-01-02) + + +### Features + +* detect internal functions created after dev server already started ([#6257](https://github.com/netlify/cli/issues/6257)) ([02e1069](https://github.com/netlify/cli/commit/02e1069a81f508320ff5a48e3d68f490c50093af)) + + +### Bug Fixes + +* support Blobs in unlinked sites ([#6279](https://github.com/netlify/cli/issues/6279)) ([d74c00d](https://github.com/netlify/cli/commit/d74c00d431a8cf2180364eb37459d4e037b863ee)) + ## [17.10.2](https://github.com/netlify/cli/compare/v17.10.1...v17.10.2) (2023-12-29) diff --git a/package-lock.json b/package-lock.json index c216374bcae..0e3fb3b2a3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "netlify-cli", - "version": "17.10.2", + "version": "17.11.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "netlify-cli", - "version": "17.10.2", + "version": "17.11.0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index c19fecc382d..a4ee54cd70a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "netlify-cli", "description": "Netlify command line tool", - "version": "17.10.2", + "version": "17.11.0", "author": "Netlify Inc.", "type": "module", "engines": {