diff options
author | 2025-02-06 15:07:22 +0000 | |
---|---|---|
committer | 2025-02-06 15:07:22 +0000 | |
commit | db32b913bfaae405dae2146b11ed6b0754f6c883 (patch) | |
tree | 5b2a4037e67d9d86acb1eb836ee5d07d0fc5d83f | |
parent | bba875a16c6d9c1c0ccd3956a52dc9d942918013 (diff) | |
parent | d15d1831e1f53af2dcf63568bb47fa3cfab1359b (diff) | |
download | astro-db32b913bfaae405dae2146b11ed6b0754f6c883.tar.gz astro-db32b913bfaae405dae2146b11ed6b0754f6c883.tar.zst astro-db32b913bfaae405dae2146b11ed6b0754f6c883.zip |
Merge pull request #13146 from withastro/move-netlify
chore: move netlify adapter to core
67 files changed, 3462 insertions, 26 deletions
diff --git a/package.json b/package.json index 051830499..aadc2eb9c 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,8 @@ "test:e2e:match": "cd packages/astro && pnpm playwright install chromium firefox && pnpm run test:e2e:match", "test:e2e:hosts": "turbo run test:hosted", "benchmark": "astro-benchmark", - "lint": "biome lint && eslint . --report-unused-disable-directives", - "lint:ci": "biome ci --formatter-enabled=false --organize-imports-enabled=false --reporter=github && eslint . --report-unused-disable-directives", + "lint": "biome lint && eslint . --report-unused-disable-directives-severity=warn", + "lint:ci": "biome ci --formatter-enabled=false --organize-imports-enabled=false --reporter=github && eslint . --report-unused-disable-directives-severity=warn", "lint:fix": "biome lint --write --unsafe", "publint": "pnpm -r --filter=astro --filter=create-astro --filter=\"@astrojs/*\" --no-bail exec publint", "version": "changeset version && node ./scripts/deps/update-example-versions.js && pnpm install --no-frozen-lockfile && pnpm run format", diff --git a/packages/integrations/netlify/CHANGELOG.md b/packages/integrations/netlify/CHANGELOG.md new file mode 100644 index 000000000..e5e84d3e8 --- /dev/null +++ b/packages/integrations/netlify/CHANGELOG.md @@ -0,0 +1,1272 @@ +# @astrojs/netlify + +## 6.1.0 + +### Minor Changes + +- [#496](https://github.com/withastro/adapters/pull/496) [`4b5cd22`](https://github.com/withastro/adapters/commit/4b5cd2268e8ed5e720772f50241b299762ea1eb8) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Stabilizes `astro:env` secrets support + +### Patch Changes + +- [#454](https://github.com/withastro/adapters/pull/454) [`83cedad`](https://github.com/withastro/adapters/commit/83cedad780bf7a23ae9f6ca0c44a7b7f1c1767e1) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - Improves Astro 5 support + +- [#501](https://github.com/withastro/adapters/pull/501) [`012b31d`](https://github.com/withastro/adapters/commit/012b31d98ce87c1199eb38b7aba2a28b7c1cf8cc) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Refactor of the redirects logic + +## 6.0.1 + +### Patch Changes + +- [#481](https://github.com/withastro/adapters/pull/481) [`9d98b8a`](https://github.com/withastro/adapters/commit/9d98b8a19efdd5c7483cce70b732208093bf82b2) Thanks [@ascorbic](https://github.com/ascorbic)! - Fixes an error where edge middleware would incorrectly assign locals + +- [#488](https://github.com/withastro/adapters/pull/488) [`f3739be`](https://github.com/withastro/adapters/commit/f3739bef812aa9659ff9bdd10ba9046ac716a3d5) Thanks [@ascorbic](https://github.com/ascorbic)! - Correctly pass Netlify context in edge middleware + +## 6.0.0 + +### Major Changes + +- [#367](https://github.com/withastro/adapters/pull/367) [`e02b54a`](https://github.com/withastro/adapters/commit/e02b54ad864ea25cb972f6196496b5aee36a47a3) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - Removed support for the Squoosh image service. As the underlying library `libsquoosh` is no longer maintained, and the image service sees very little usage we have decided to remove it from Astro. + + Our recommendation is to use the base Sharp image service, which is more powerful, faster, and more actively maintained. + + ```diff + - import { squooshImageService } from "astro/config"; + import { defineConfig } from "astro/config"; + + export default defineConfig({ + - image: { + - service: squooshImageService() + - } + }); + ``` + + If you are using this service, and cannot migrate to the base Sharp image service, a third-party extraction of the previous service is available here: https://github.com/Princesseuh/astro-image-service-squoosh + +- [#367](https://github.com/withastro/adapters/pull/367) [`e02b54a`](https://github.com/withastro/adapters/commit/e02b54ad864ea25cb972f6196496b5aee36a47a3) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - Deprecates the `functionPerRoute` option + + This option is now deprecated, and will be removed entirely in Astro v5.0. We suggest removing this option from your configuration as soon as you are able to: + + ```diff + import { defineConfig } from 'astro/config'; + import vercel from '@astrojs/vercel/serverless'; + + export default defineConfig({ + // ... + output: 'server', + adapter: vercel({ + - functionPerRoute: true, + }), + }); + ``` + +- [#375](https://github.com/withastro/adapters/pull/375) [`e7881f7`](https://github.com/withastro/adapters/commit/e7881f7928c6ca62d43c763033f9ed065a907f3b) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updates internal code to works with Astro 5 changes to hybrid rendering. No changes are necessary to your project, apart from using Astro 5 + +- [#397](https://github.com/withastro/adapters/pull/397) [`776a266`](https://github.com/withastro/adapters/commit/776a26670cf483e37ec0e6eba27a0bde09db0146) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Welcome to the Astro 5 beta! This release has no changes from the latest alpha of this package, but it does bring us one step closer to the final, stable release. + + Starting from this release, no breaking changes will be introduced unless absolutely necessary. + + To learn how to upgrade, check out the [Astro v5.0 upgrade guide in our beta docs site](https://5-0-0-beta.docs.astro.build/en/guides/upgrade-to/v5/). + +- [#451](https://github.com/withastro/adapters/pull/451) [`f248546`](https://github.com/withastro/adapters/commit/f24854669a2a3da79d8bf1e89b0b54063df0668c) Thanks [@ematipico](https://github.com/ematipico)! - Updates esbuild dependency to v0.24.0 + +- [#392](https://github.com/withastro/adapters/pull/392) [`3a49eb7`](https://github.com/withastro/adapters/commit/3a49eb7802c44212ccfab06034b7dc5f2b060e94) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updates internal code for Astro 5 changes. No changes is required to your project, apart from using Astro 5 + +### Minor Changes + +- [#385](https://github.com/withastro/adapters/pull/385) [`bb725b7`](https://github.com/withastro/adapters/commit/bb725b7a430a01a3cd197e3e84381be4fa0c945c) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Cleans up `astro:env` support + +## 6.0.0-beta.1 + +### Major Changes + +- [`f248546`](https://github.com/withastro/adapters/commit/f24854669a2a3da79d8bf1e89b0b54063df0668c) Thanks [@bluwy](https://github.com/bluwy)! - Updates esbuild dependency to v0.24.0 + +## 6.0.0-beta.0 + +### Major Changes + +- [#367](https://github.com/withastro/adapters/pull/367) [`e02b54a`](https://github.com/withastro/adapters/commit/e02b54ad864ea25cb972f6196496b5aee36a47a3) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - Removed support for the Squoosh image service. As the underlying library `libsquoosh` is no longer maintained, and the image service sees very little usage we have decided to remove it from Astro. + + Our recommendation is to use the base Sharp image service, which is more powerful, faster, and more actively maintained. + + ```diff + - import { squooshImageService } from "astro/config"; + import { defineConfig } from "astro/config"; + + export default defineConfig({ + - image: { + - service: squooshImageService() + - } + }); + ``` + + If you are using this service, and cannot migrate to the base Sharp image service, a third-party extraction of the previous service is available here: https://github.com/Princesseuh/astro-image-service-squoosh + +- [#367](https://github.com/withastro/adapters/pull/367) [`e02b54a`](https://github.com/withastro/adapters/commit/e02b54ad864ea25cb972f6196496b5aee36a47a3) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - Deprecates the `functionPerRoute` option + + This option is now deprecated, and will be removed entirely in Astro v5.0. We suggest removing this option from your configuration as soon as you are able to: + + ```diff + import { defineConfig } from 'astro/config'; + import vercel from '@astrojs/vercel/serverless'; + + export default defineConfig({ + // ... + output: 'server', + adapter: vercel({ + - functionPerRoute: true, + }), + }); + ``` + +- [#375](https://github.com/withastro/adapters/pull/375) [`e7881f7`](https://github.com/withastro/adapters/commit/e7881f7928c6ca62d43c763033f9ed065a907f3b) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updates internal code to works with Astro 5 changes to hybrid rendering. No changes are necessary to your project, apart from using Astro 5 + +- [#397](https://github.com/withastro/adapters/pull/397) [`776a266`](https://github.com/withastro/adapters/commit/776a26670cf483e37ec0e6eba27a0bde09db0146) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Welcome to the Astro 5 beta! This release has no changes from the latest alpha of this package, but it does bring us one step closer to the final, stable release. + + Starting from this release, no breaking changes will be introduced unless absolutely necessary. + + To learn how to upgrade, check out the [Astro v5.0 upgrade guide in our beta docs site](https://5-0-0-beta.docs.astro.build/en/guides/upgrade-to/v5/). + +- [#392](https://github.com/withastro/adapters/pull/392) [`3a49eb7`](https://github.com/withastro/adapters/commit/3a49eb7802c44212ccfab06034b7dc5f2b060e94) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updates internal code for Astro 5 changes. No changes is required to your project, apart from using Astro 5 + +### Minor Changes + +- [#385](https://github.com/withastro/adapters/pull/385) [`bb725b7`](https://github.com/withastro/adapters/commit/bb725b7a430a01a3cd197e3e84381be4fa0c945c) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Cleans up `astro:env` support + +## 5.5.4 + +### Patch Changes + +- [#413](https://github.com/withastro/adapters/pull/413) [`1b18e67`](https://github.com/withastro/adapters/commit/1b18e671a689b67bde20fdc7fb8cf1d6283e4ec9) Thanks [@ascorbic](https://github.com/ascorbic)! - Fixes `context.rewrite` in edge middleware + +## 5.5.3 + +### Patch Changes + +- [#388](https://github.com/withastro/adapters/pull/388) [`3f280f1`](https://github.com/withastro/adapters/commit/3f280f113ce768b1c27a2e3cfb36cbc4c43bafa7) Thanks [@hrishikesh-k](https://github.com/hrishikesh-k)! - Allows `-` in hostnames for Netlify Image CDN RegEx + +## 5.5.2 + +### Patch Changes + +- [#381](https://github.com/withastro/adapters/pull/381) [`46fbb26`](https://github.com/withastro/adapters/commit/46fbb26175ab09d12f95dba63cfe76bdcc25ef59) Thanks [@matthewp](https://github.com/matthewp)! - Prevent crawling for dependencies outside of the workspace root + +## 5.5.1 + +### Patch Changes + +- [#350](https://github.com/withastro/adapters/pull/350) [`2248bc7`](https://github.com/withastro/adapters/commit/2248bc7edcbe37e4e75f573f88a200c2ba5afbae) Thanks [@matthewp](https://github.com/matthewp)! - Apply polyfills immediately on function execution + + This moves up when the polyfills are applied so that they are present before Astro runs, preventing a race condition that can cause `crypto` to not be defined early enough in Node 18. + +## 5.5.0 + +### Minor Changes + +- [#326](https://github.com/withastro/adapters/pull/326) [`6dd65a0`](https://github.com/withastro/adapters/commit/6dd65a04c2afea941da34a1a1ce7b991f0768615) Thanks [@ascorbic](https://github.com/ascorbic)! - Sets immutable cache headers for static assets + +## 5.4.0 + +### Minor Changes + +- [#315](https://github.com/withastro/adapters/pull/315) [`a45eb36`](https://github.com/withastro/adapters/commit/a45eb365c609bbc1b9ca480c0e49da9cced682aa) Thanks [@eduardoboucas](https://github.com/eduardoboucas)! - Refactors the adapter to use the Netlify Frameworks API + +### Patch Changes + +- [#286](https://github.com/withastro/adapters/pull/286) [`e2ecf64`](https://github.com/withastro/adapters/commit/e2ecf646f9eefb64c23012598501d8de69dca285) Thanks [@theoephraim](https://github.com/theoephraim)! - Allows support for `node:` prefixed imports if using the Adapter with `edgeMiddleware: true` + +## 5.3.5 + +### Patch Changes + +- [#316](https://github.com/withastro/adapters/pull/316) [`d81806a`](https://github.com/withastro/adapters/commit/d81806a94a9bb5242b38c75bc173c17075fd3a41) Thanks [@ascorbic](https://github.com/ascorbic)! - Fixes a regression where edge middleware tried to bundle node builtins + +## 5.3.4 + +### Patch Changes + +- [#313](https://github.com/withastro/adapters/pull/313) [`55a3e1a`](https://github.com/withastro/adapters/commit/55a3e1a4356c87f86ae60990a87c6a055f217efb) Thanks [@ascorbic](https://github.com/ascorbic)! - Fixes an issue where files were not included in the SSR function when built in a monorepo + +## 5.3.3 + +### Patch Changes + +- [#296](https://github.com/withastro/adapters/pull/296) [`8a00cad`](https://github.com/withastro/adapters/commit/8a00cad52a94ba75feab3b42e702896f0bc8872e) Thanks [@ascorbic](https://github.com/ascorbic)! - Improves performance for serverless function builds by not bundling dependencies + +## 5.3.2 + +### Patch Changes + +- [#293](https://github.com/withastro/adapters/pull/293) [`ee840fa`](https://github.com/withastro/adapters/commit/ee840fa52ce86c2409e5199fb10d600285fb95ae) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Fixes `astro:env` getSecret compatibility + +## 5.3.1 + +### Patch Changes + +- [#282](https://github.com/withastro/adapters/pull/282) [`65337f3`](https://github.com/withastro/adapters/commit/65337f3aa67a1f2a40ea8c20a6fcc462e8cbfe94) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - Fixes backwards compatibility with Astro <= 4.9 + +## 5.3.0 + +### Minor Changes + +- [#275](https://github.com/withastro/adapters/pull/275) [`4a28bf6`](https://github.com/withastro/adapters/commit/4a28bf6cac7bd7e455551a91e40792f0737e87da) Thanks [@florian-lefebvre](https://github.com/florian-lefebvre)! - Adds support for experimental `astro:env` released in Astro 4.10 + +## 5.2.1 + +### Patch Changes + +- [#255](https://github.com/withastro/adapters/pull/255) [`3fa962d`](https://github.com/withastro/adapters/commit/3fa962db8f4437df9f1bba5b5ff8ea7b280a6924) Thanks [@ascorbic](https://github.com/ascorbic)! - Fixes an issue with edge middleware where `process.env` was not defined, by using a polyfill to shim it + +## 5.2.0 + +### Minor Changes + +- [#187](https://github.com/withastro/adapters/pull/187) [`79ebfa4c9e2f84309edb35481ad9cd1f3c7e5eb4`](https://github.com/withastro/adapters/commit/79ebfa4c9e2f84309edb35481ad9cd1f3c7e5eb4) Thanks [@ascorbic](https://github.com/ascorbic)! - Adds support for `image.remotePatterns` and `images.domains` with Netlify Image CDN + +## 5.1.3 + +### Patch Changes + +- [#163](https://github.com/withastro/adapters/pull/163) [`bc9ee99c7333ae29e4d4184059c09650330fd0d9`](https://github.com/withastro/adapters/commit/bc9ee99c7333ae29e4d4184059c09650330fd0d9) Thanks [@OiYouYeahYou](https://github.com/OiYouYeahYou)! - Fixes an issue where some astro CLI commands failed with `crypto is not defined` on Astro 4.4.0 and earlier. + +## 5.1.2 + +### Patch Changes + +- [#160](https://github.com/withastro/adapters/pull/160) [`994985547c2d2bc8c66b76f996257e68f8187a14`](https://github.com/withastro/adapters/commit/994985547c2d2bc8c66b76f996257e68f8187a14) Thanks [@lilnasy](https://github.com/lilnasy)! - Fixes an issue where enabling `edgeMiddleware` failed to bundle a dependency (`cssesc`) introduced in Astro 4.2.5. + +## 5.1.1 + +### Patch Changes + +- [#162](https://github.com/withastro/adapters/pull/162) [`07217c07e89d4596b464d05c4873e7039aa616f4`](https://github.com/withastro/adapters/commit/07217c07e89d4596b464d05c4873e7039aa616f4) Thanks [@Skn0tt](https://github.com/Skn0tt)! - Fixes bug where prerendered 404 pages were served as `text/plain` instead of `text/html` for hybrid/server apps, leading to browsers displaying source code instead of rendering it + +## 5.1.0 + +### Minor Changes + +- [#152](https://github.com/withastro/adapters/pull/152) [`816bdc42e0665904e418dd0137bd6a7c8c74307f`](https://github.com/withastro/adapters/commit/816bdc42e0665904e418dd0137bd6a7c8c74307f) Thanks [@lilnasy](https://github.com/lilnasy)! - Implements verification for edge middleware. This is a security measure to ensure that your serverless functions are only ever called by your edge middleware and not by a third party. + + When `edgeMiddleware` is enabled, the serverless function will now respond with `403 Forbidden` for requests that are not verified to have come from the generated edge middleware. No user action is necessary. + +## 5.0.1 + +### Patch Changes + +- [#143](https://github.com/withastro/adapters/pull/143) [`06bae52f26d1df1368581aa859f332141db00c1b`](https://github.com/withastro/adapters/commit/06bae52f26d1df1368581aa859f332141db00c1b) Thanks [@Skn0tt](https://github.com/Skn0tt)! - Fixes a bug in the Netlify Adapter where prerendered 404.astro pages weren't shown on hybrid/server deployments. + +## 5.0.0 + +### Major Changes + +- [#130](https://github.com/withastro/adapters/pull/130) [`2b5aaa4cfeda4bc7f1bf8db6210162c495866a95`](https://github.com/withastro/adapters/commit/2b5aaa4cfeda4bc7f1bf8db6210162c495866a95) Thanks [@asdfjkalsdfla](https://github.com/asdfjkalsdfla)! - Updates the internals of the integration to support Astro 4.0. See this [upstream pull request](https://github.com/withastro/astro/pull/9199) for additional details. **Warning:** Make sure to upgrade your Astro version to `>4.2` as previous versions are no longer supported. + +## 4.1.1 + +### Patch Changes + +- [#127](https://github.com/withastro/adapters/pull/127) [`36434f0c631cb963c748a11679cf7a96cd605d8e`](https://github.com/withastro/adapters/commit/36434f0c631cb963c748a11679cf7a96cd605d8e) Thanks [@Skn0tt](https://github.com/Skn0tt)! - Updates the behavior of the `cacheOnDemandPages` setting to only cache GET/HEAD requests by default + +## 4.1.0 + +### Minor Changes + +- [#120](https://github.com/withastro/adapters/pull/120) [`cf39b9d`](https://github.com/withastro/adapters/commit/cf39b9ddb3c3f7db563c67ac9a6e88857862b694) Thanks [@Skn0tt](https://github.com/Skn0tt)! - Adds opt-out option for Image CDN. + +## 4.0.2 + +### Patch Changes + +- [#117](https://github.com/withastro/adapters/pull/117) [`89f7c01`](https://github.com/withastro/adapters/commit/89f7c017e2190c288d257560d1cb2cf8cca8f2cb) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - Updates Netlify README.md + +## 4.0.1 + +### Patch Changes + +- [#105](https://github.com/withastro/adapters/pull/105) [`755058d`](https://github.com/withastro/adapters/commit/755058d447478c4a390bf86e8c83cb3a25b7cb28) Thanks [@Skn0tt](https://github.com/Skn0tt)! - fix crash when reading package.json version field + +## 4.0.0 + +### Major Changes + +- [#84](https://github.com/withastro/adapters/pull/84) [`ca64544`](https://github.com/withastro/adapters/commit/ca645447402316963bcc1181292baea58b8e3bff) Thanks [@Skn0tt](https://github.com/Skn0tt)! - # Netlify Adapter v4 simplifies static + SSR deployments + + This update is a complete overhaul of the Netlify adapter. + It simplifies the user-facing config, and resolves a number of bugs along the way. + + Here's what changes: + + ## Netlify Context is automatically available via Locals + + In v3, you could use `netlify-edge-middleware.ts` to inject data from the Netlify context into your Astro locals. + In v4, this file is no longer needed because the Netlify context is automatically made available via `Astro.locals.netlify.context`. + You can use this context to access information about the user (like geolocation or IP address), your Netlify site (like deploy ID) or the request (like its request ID or the CDN region it's served from). + + **Action Required:** + Remove the `netlify-edge-middleware.ts` or `netlify-edge-middleware.js` file. + In your codebase, change all usage of locals injected through that file to use `Astro.locals.netlify.context` instead. + + ### Image CDN + + v4 of this adapter integrates your Astro site with Netlify [Image CDN](https://docs.netlify.com/image-cdn/overview/). + This allows transforming images on-the-fly without impacting build times. + It's implemented using an [Astro Image Service](https://docs.astro.build/en/reference/image-service-reference/), and enabled by default. + + ## Replacement for On-Demand Builders + + On-Demand Builders (ODB) allows SSR-Rendered pages to be cached using a Time to Live (TTL) strategy. + While the Netlify platform continues to support existing pages with ODBs, we now recommend using the much more powerful + [Fine-Grained Cache Control](https://www.netlify.com/blog/swr-and-fine-grained-cache-control) going forward. + + In v3, you could deploy your SSR-Rendered Astro pages to ODBs by enabling the `builders` config option, + and then specifying the TTL on a per-page basis. + In v4, a new `cacheOnDemandPages` option replaces this config option. Take a look at the README to learn more about this. + + **Action Required:** + Replace the `builders` config option with `cacheOnDemandPages`. + + ```diff lang="ts" + // astro.config.mjs + export default defineConfig({ + // ... + adapter: netlify({ + - builders: true + + cacheOnDemandPages: true + }), + }); + ``` + + ## `functionPerRoute` was removed + + In v3, the `functionPerRoute` option allowed the SSR routes to be split up into multiple Netlify Functions. + This reduced the bundle sizes of each individual function, with the intention of speeding up code parsing, and therefore the time of cold starts. + In practice, this benefit is often nullified by the increase in number of cold starts - more handlers means fewer requests per handler, means more cold starts. + + In v4, support for this deployment mode was removed. + + **Action Required:** + Remove the `functionPerRoute` field from your config. + + ## `binaryMediaTypes` was removed + + `binaryMediaTypes` was a workaround required for some Astro endpoints, because v3 deployed those as "old" Netlify Functions (now referred to as ["Lambda Compatibility Mode"](https://docs.netlify.com/functions/lambda-compatibility)). + v4 uses the new [Netlify Functions 2.0](https://www.netlify.com/blog/introducing-netlify-functions-2-0/), which simply doesn't need this workaround anymore - so we're removing it 🎉 + + **Action Required:** + Remove the `binaryMediaTypes` field from your config. + +## 3.1.1 + +### Patch Changes + +- [#100](https://github.com/withastro/adapters/pull/100) [`1195955`](https://github.com/withastro/adapters/commit/11959551105aa1776eb58a015e0694960f128537) Thanks [@Jinksi](https://github.com/Jinksi)! - Fixes a typo for the peerDependency range in package.json, which prevents upgrade to Astro 4.0. + +## 3.1.0 + +### Minor Changes + +- [#96](https://github.com/withastro/adapters/pull/96) [`f1df277`](https://github.com/withastro/adapters/commit/f1df27740b5c185e28ad73a810bb5dad6bb1e8cd) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - Fixes an issue where this package could not be installed alongside Astro 4.0. + +## 3.0.4 + +### Patch Changes + +- [#51](https://github.com/withastro/adapters/pull/51) [`acf4c82`](https://github.com/withastro/adapters/commit/acf4c824f8e066d25d94ddf59a486083586567c4) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - Updates dependencies + +## 3.0.3 + +### Patch Changes + +- [#21](https://github.com/withastro/adapters/pull/21) [`09d2504`](https://github.com/withastro/adapters/commit/09d25043125250e65ccb59549f527d5d876c3a06) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - Updates repository information + +## 3.0.2 + +### Patch Changes + +- [#8661](https://github.com/withastro/astro/pull/8661) [`008f7647c`](https://github.com/withastro/astro/commit/008f7647c4788207aab55ab12c734bd80e6df9c5) Thanks [@Skn0tt](https://github.com/Skn0tt)! - fix build failures because of CJS builds and top-level await + +- Updated dependencies [[`69fbf95b2`](https://github.com/withastro/astro/commit/69fbf95b22c0fb0d8e7e5fef9ec61e26cac9767f)]: + - astro@3.1.4 + - @astrojs/underscore-redirects@0.3.0 + +## 3.0.1 + +### Patch Changes + +- [#8346](https://github.com/withastro/astro/pull/8346) [`b74dacdb6`](https://github.com/withastro/astro/commit/b74dacdb6a49755f979f15091355f06bd6bd64bf) Thanks [@delucis](https://github.com/delucis)! - Update README + +- Updated dependencies [[`c5633434f`](https://github.com/withastro/astro/commit/c5633434f02cc477ee8da380e22efaccfa55d459), [`405ad9501`](https://github.com/withastro/astro/commit/405ad950173dadddc519cf1c2e7f2523bf5326a8), [`6b1e79814`](https://github.com/withastro/astro/commit/6b1e7981469d30aa4c3658487abed6ffea94797f)]: + - astro@3.0.7 + - @astrojs/underscore-redirects@0.3.0 + +## 3.0.0 + +### Major Changes + +- [#8188](https://github.com/withastro/astro/pull/8188) [`d0679a666`](https://github.com/withastro/astro/commit/d0679a666f37da0fca396d42b9b32bbb25d29312) Thanks [@ematipico](https://github.com/ematipico)! - Remove support for Node 16. The lowest supported version by Astro and all integrations is now v18.14.1. As a reminder, Node 16 will be deprecated on the 11th September 2023. + +- [#8179](https://github.com/withastro/astro/pull/8179) [`6011d52d3`](https://github.com/withastro/astro/commit/6011d52d38e43c3e3d52bc3bc41a60e36061b7b7) Thanks [@matthewp](https://github.com/matthewp)! - Astro 3.0 Release Candidate + +- [#8188](https://github.com/withastro/astro/pull/8188) [`7511a4980`](https://github.com/withastro/astro/commit/7511a4980fd36536464c317de33a5190427f430a) Thanks [@ematipico](https://github.com/ematipico)! - When using an adapter that supports neither Squoosh or Sharp, Astro will now automatically use an image service that does not support processing, but still provides the other benefits of `astro:assets` such as enforcing `alt`, no CLS etc to users + +- [#8188](https://github.com/withastro/astro/pull/8188) [`148e61d24`](https://github.com/withastro/astro/commit/148e61d2492456811f8a3c8daaab1c3429a2ffdc) Thanks [@ematipico](https://github.com/ematipico)! - Reduced the amount of polyfills provided by Astro. Astro will no longer provide (no-op) polyfills for several web apis such as HTMLElement, Image or Document. If you need access to those APIs on the server, we recommend using more proper polyfills available on npm. + +- [#8029](https://github.com/withastro/astro/pull/8029) [`2ee418e06`](https://github.com/withastro/astro/commit/2ee418e06ab1f7855dee0078afbad0b06de3b183) Thanks [@matthewp](https://github.com/matthewp)! - Remove the Netlify Edge adapter + + `@astrojs/netlify/functions` now supports Edge middleware, so a separate adapter for Edge itself (deploying your entire app to the edge) is no longer necessary. Please update your Astro config to reflect this change: + + ```diff + // astro.config.mjs + import { defineConfig } from 'astro/config'; + - import netlify from '@astrojs/netlify/edge'; + + import netlify from '@astrojs/netlify/functions'; + + export default defineConfig({ + output: 'server', + adapter: netlify({ + + edgeMiddleware: true + }), + }); + ``` + + This adapter had several known limitations and compatibility issues that prevented many people from using it in production. To reduce maintenance costs and because we have a better story with Serveless + Edge Middleware, we are removing the Edge adapter. + +### Minor Changes + +- [#8188](https://github.com/withastro/astro/pull/8188) [`cd2d7e769`](https://github.com/withastro/astro/commit/cd2d7e76981ef9b9013453aa2629838e1e9fd422) Thanks [@ematipico](https://github.com/ematipico)! - Introduced the concept of feature map. A feature map is a list of features that are built-in in Astro, and an Adapter + can tell Astro if it can support it. + + ```ts + import { AstroIntegration } from './astro'; + + function myIntegration(): AstroIntegration { + return { + name: 'astro-awesome-list', + // new feature map + supportedAstroFeatures: { + hybridOutput: 'experimental', + staticOutput: 'stable', + serverOutput: 'stable', + assets: { + supportKind: 'stable', + isSharpCompatible: false, + isSquooshCompatible: false, + }, + }, + }; + } + ``` + +- [#8188](https://github.com/withastro/astro/pull/8188) [`80f1494cd`](https://github.com/withastro/astro/commit/80f1494cdaf72e58a420adb4f7c712d4089e1923) Thanks [@ematipico](https://github.com/ematipico)! - The `build.split` and `build.excludeMiddleware` configuration options are deprecated and have been replaced by options in the adapter config. + + If your config includes the `build.excludeMiddleware` option, replace it with `edgeMiddleware` in your adapter options: + + ```diff + import { defineConfig } from "astro/config"; + import netlify from "@astrojs/netlify/functions"; + + export default defineConfig({ + build: { + - excludeMiddleware: true + }, + adapter: netlify({ + + edgeMiddleware: true + }), + }); + ``` + + If your config includes the `build.split` option, replace it with `functionPerRoute` in your adapter options: + + ```diff + import { defineConfig } from "astro/config"; + import netlify from "@astrojs/netlify/functions"; + + export default defineConfig({ + build: { + - split: true + }, + adapter: netlify({ + + functionPerRoute: true + }), + }); + ``` + +### Patch Changes + +- Updated dependencies [[`d0679a666`](https://github.com/withastro/astro/commit/d0679a666f37da0fca396d42b9b32bbb25d29312), [`db39206cb`](https://github.com/withastro/astro/commit/db39206cbb85b034859ac416179f141184bb2bff), [`adf9fccfd`](https://github.com/withastro/astro/commit/adf9fccfdda107c2224558f1c2e6a77847ac0a8a), [`0c7b42dc6`](https://github.com/withastro/astro/commit/0c7b42dc6780e687e416137539f55a3a427d1d10), [`46c4c0e05`](https://github.com/withastro/astro/commit/46c4c0e053f830585b9ef229ce1c259df00a80f8), [`364d861bd`](https://github.com/withastro/astro/commit/364d861bd527b8511968e2837728148f090bedef), [`2484dc408`](https://github.com/withastro/astro/commit/2484dc4080e5cd84b9a53648a1de426d7c907be2), [`81545197a`](https://github.com/withastro/astro/commit/81545197a32fd015d763fc386c8b67e0e08b7393), [`6011d52d3`](https://github.com/withastro/astro/commit/6011d52d38e43c3e3d52bc3bc41a60e36061b7b7), [`c2c71d90c`](https://github.com/withastro/astro/commit/c2c71d90c264a2524f99e0373ab59015f23ad4b1), [`cd2d7e769`](https://github.com/withastro/astro/commit/cd2d7e76981ef9b9013453aa2629838e1e9fd422), [`80f1494cd`](https://github.com/withastro/astro/commit/80f1494cdaf72e58a420adb4f7c712d4089e1923), [`e45f30293`](https://github.com/withastro/astro/commit/e45f3029340db718b6ed7e91b5d14f5cf14cd71d), [`c0de7a7b0`](https://github.com/withastro/astro/commit/c0de7a7b0f042cd49cbea4f4ac1b2ab6f9fef644), [`65c354969`](https://github.com/withastro/astro/commit/65c354969e6fe0ef6d622e8f4c545e2f717ce8c6), [`3c3100851`](https://github.com/withastro/astro/commit/3c31008519ce68b5b1b1cb23b71fbe0a2d506882), [`34cb20021`](https://github.com/withastro/astro/commit/34cb2002161ba88df6bcb72fecfd12ed867c134b), [`a824863ab`](https://github.com/withastro/astro/commit/a824863ab1c451f4068eac54f28dd240573e1cba), [`44f7a2872`](https://github.com/withastro/astro/commit/44f7a28728c56c04ac377b6e917329f324874043), [`1048aca55`](https://github.com/withastro/astro/commit/1048aca550769415e528016e42b358ffbfd44b61), [`be6bbd2c8`](https://github.com/withastro/astro/commit/be6bbd2c86b9bf5268e765bb937dda00ff15781a), [`9e021a91c`](https://github.com/withastro/astro/commit/9e021a91c57d10809f588dd47968fc0e7f8b4d5c), [`7511a4980`](https://github.com/withastro/astro/commit/7511a4980fd36536464c317de33a5190427f430a), [`c37632a20`](https://github.com/withastro/astro/commit/c37632a20d06164fb97a4c2fc48df6d960398832), [`acf652fc1`](https://github.com/withastro/astro/commit/acf652fc1d5db166231e87e22d0d50444f5556d8), [`42785c7b7`](https://github.com/withastro/astro/commit/42785c7b784b151e6d582570e5d74482129e8eb8), [`8450379db`](https://github.com/withastro/astro/commit/8450379db854fb1eaa9f38f21d65db240bc616cd), [`dbc97b121`](https://github.com/withastro/astro/commit/dbc97b121f42583728f1cdfdbf14575fda943f5b), [`7d2f311d4`](https://github.com/withastro/astro/commit/7d2f311d428e3d1c8c13b9bf2a708d6435713fc2), [`2540feedb`](https://github.com/withastro/astro/commit/2540feedb06785d5a20eecc3668849f147d778d4), [`ea7ff5177`](https://github.com/withastro/astro/commit/ea7ff5177dbcd7b2508cb1eef1b22b8ee1f47079), [`68efd4a8b`](https://github.com/withastro/astro/commit/68efd4a8b29f248397667801465b3152dc98e9a7), [`7bd1b86f8`](https://github.com/withastro/astro/commit/7bd1b86f85c06fdde0a1ed9146d01bac69990671), [`036388f66`](https://github.com/withastro/astro/commit/036388f66dab68ad54b895ed86f9176958dd83c8), [`519a1c4e8`](https://github.com/withastro/astro/commit/519a1c4e8407c7abcb8d879b67a9f4b960652cae), [`1f58a7a1b`](https://github.com/withastro/astro/commit/1f58a7a1bea6888868b689dac94801d554319b02), [`2ae9d37f0`](https://github.com/withastro/astro/commit/2ae9d37f0a9cb21ab288d3c30aecb6d84db87788), [`a8f35777e`](https://github.com/withastro/astro/commit/a8f35777e7e322068a4e2f520c2c9e43ade19e58), [`70f34f5a3`](https://github.com/withastro/astro/commit/70f34f5a355f42526ee9e5355f3de8e510002ea2), [`5208a3c8f`](https://github.com/withastro/astro/commit/5208a3c8fefcec7694857fb344af351f4631fc34), [`84af8ed9d`](https://github.com/withastro/astro/commit/84af8ed9d1e6401c6ebc9c60fe8cddb44d5044b0), [`f003e7364`](https://github.com/withastro/astro/commit/f003e7364317cafdb8589913b26b28e928dd07c9), [`ffc9e2d3d`](https://github.com/withastro/astro/commit/ffc9e2d3de46049bf3d82140ef018f524fb03187), [`732111cdc`](https://github.com/withastro/astro/commit/732111cdce441639db31f40f621df48442d00969), [`0f637c71e`](https://github.com/withastro/astro/commit/0f637c71e511cb4c51712128d217a26c8eee4d40), [`33b8910cf`](https://github.com/withastro/astro/commit/33b8910cfdce5713891c50a84a0a8fe926311710), [`8a5b0c1f3`](https://github.com/withastro/astro/commit/8a5b0c1f3a4be6bb62db66ec70144109ff5b4c59), [`148e61d24`](https://github.com/withastro/astro/commit/148e61d2492456811f8a3c8daaab1c3429a2ffdc), [`e79e3779d`](https://github.com/withastro/astro/commit/e79e3779df0ad35253abcdb931d622847d9adb12), [`632579dc2`](https://github.com/withastro/astro/commit/632579dc2094cc342929261c89e689f0dd358284), [`3674584e0`](https://github.com/withastro/astro/commit/3674584e02b161a698b429ceb66723918fdc56ac), [`1db4e92c1`](https://github.com/withastro/astro/commit/1db4e92c12ed73681217f5cefd39f2f47542f961), [`e7f872e91`](https://github.com/withastro/astro/commit/e7f872e91e852b901cf221a5151077dec64305bf), [`16f09dfff`](https://github.com/withastro/astro/commit/16f09dfff7722fda99dd0412e3006a7a39c80829), [`4477bb41c`](https://github.com/withastro/astro/commit/4477bb41c8ed688785c545731ef5b184b629f4e5), [`55c10d1d5`](https://github.com/withastro/astro/commit/55c10d1d564e805efc3c1a7c48e0d9a1cdf0c7ed), [`3e834293d`](https://github.com/withastro/astro/commit/3e834293d47ab2761a7aa013916e8371871efb7f), [`96beb883a`](https://github.com/withastro/astro/commit/96beb883ad87f8bbf5b2f57e14a743763d2a6f58), [`997a0db8a`](https://github.com/withastro/astro/commit/997a0db8a4e3851edd69384cf5eadbb969e1d547), [`80f1494cd`](https://github.com/withastro/astro/commit/80f1494cdaf72e58a420adb4f7c712d4089e1923), [`0f0625504`](https://github.com/withastro/astro/commit/0f0625504145f18cba7dc6cf20291cb2abddc5a9), [`e1ae56e72`](https://github.com/withastro/astro/commit/e1ae56e724d0f83db1230359e06cd6bc26f5fa26), [`f32d093a2`](https://github.com/withastro/astro/commit/f32d093a280faafff024228c12bb438156ec34d7), [`f01eb585e`](https://github.com/withastro/astro/commit/f01eb585e7c972d940761309b1595f682b6922d2), [`b76c166bd`](https://github.com/withastro/astro/commit/b76c166bdd8e28683f62806aef968d1e0c3b06d9), [`a87cbe400`](https://github.com/withastro/astro/commit/a87cbe400314341d5f72abf86ea264e6b47c091f), [`866ed4098`](https://github.com/withastro/astro/commit/866ed4098edffb052239cdb26e076cf8db61b1d9), [`767eb6866`](https://github.com/withastro/astro/commit/767eb68666eb777965baa0d6ade20bbafecf95bf), [`32669cd47`](https://github.com/withastro/astro/commit/32669cd47555e9c7433c3998a2b6e624dfb2d8e9)]: + - astro@3.0.0 + - @astrojs/underscore-redirects@0.3.0 + +## 3.0.0-rc.2 + +### Major Changes + +- [#8179](https://github.com/withastro/astro/pull/8179) [`6011d52d3`](https://github.com/withastro/astro/commit/6011d52d38e43c3e3d52bc3bc41a60e36061b7b7) Thanks [@matthewp](https://github.com/matthewp)! - Astro 3.0 Release Candidate + +### Patch Changes + +- Updated dependencies [[`adf9fccfd`](https://github.com/withastro/astro/commit/adf9fccfdda107c2224558f1c2e6a77847ac0a8a), [`582132328`](https://github.com/withastro/astro/commit/5821323285646aee7ff9194a505f708028e4db57), [`81545197a`](https://github.com/withastro/astro/commit/81545197a32fd015d763fc386c8b67e0e08b7393), [`6011d52d3`](https://github.com/withastro/astro/commit/6011d52d38e43c3e3d52bc3bc41a60e36061b7b7), [`be6bbd2c8`](https://github.com/withastro/astro/commit/be6bbd2c86b9bf5268e765bb937dda00ff15781a), [`42785c7b7`](https://github.com/withastro/astro/commit/42785c7b784b151e6d582570e5d74482129e8eb8), [`95120efbe`](https://github.com/withastro/astro/commit/95120efbe817163663492181cbeb225849354493), [`2ae9d37f0`](https://github.com/withastro/astro/commit/2ae9d37f0a9cb21ab288d3c30aecb6d84db87788), [`f003e7364`](https://github.com/withastro/astro/commit/f003e7364317cafdb8589913b26b28e928dd07c9), [`732111cdc`](https://github.com/withastro/astro/commit/732111cdce441639db31f40f621df48442d00969), [`33b8910cf`](https://github.com/withastro/astro/commit/33b8910cfdce5713891c50a84a0a8fe926311710), [`e79e3779d`](https://github.com/withastro/astro/commit/e79e3779df0ad35253abcdb931d622847d9adb12), [`179796405`](https://github.com/withastro/astro/commit/179796405e053b559d83f84507e5a465861a029a), [`a87cbe400`](https://github.com/withastro/astro/commit/a87cbe400314341d5f72abf86ea264e6b47c091f), [`767eb6866`](https://github.com/withastro/astro/commit/767eb68666eb777965baa0d6ade20bbafecf95bf)]: + - astro@3.0.0-rc.5 + - @astrojs/underscore-redirects@0.3.0-rc.1 + +## 3.0.0-beta.1 + +### Major Changes + +- [#8029](https://github.com/withastro/astro/pull/8029) [`2ee418e06`](https://github.com/withastro/astro/commit/2ee418e06ab1f7855dee0078afbad0b06de3b183) Thanks [@matthewp](https://github.com/matthewp)! - Remove the Netlify Edge adapter + + `@astrojs/netlify/functions` now supports Edge middleware, so a separate adapter for Edge itself (deploying your entire app to the edge) is no longer necessary. Please update your Astro config to reflect this change: + + ```diff + // astro.config.mjs + import { defineConfig } from 'astro/config'; + - import netlify from '@astrojs/netlify/edge'; + + import netlify from '@astrojs/netlify/functions'; + + export default defineConfig({ + output: 'server', + adapter: netlify({ + + edgeMiddleware: true + }), + }); + ``` + + This adapter had several known limitations and compatibility issues that prevented many people from using it in production. To reduce maintenance costs and because we have a better story with Serveless + Edge Middleware, we are removing the Edge adapter. + +### Patch Changes + +- Updated dependencies [[`65c354969`](https://github.com/withastro/astro/commit/65c354969e6fe0ef6d622e8f4c545e2f717ce8c6), [`3c3100851`](https://github.com/withastro/astro/commit/3c31008519ce68b5b1b1cb23b71fbe0a2d506882), [`34cb20021`](https://github.com/withastro/astro/commit/34cb2002161ba88df6bcb72fecfd12ed867c134b), [`7bd1b86f8`](https://github.com/withastro/astro/commit/7bd1b86f85c06fdde0a1ed9146d01bac69990671), [`519a1c4e8`](https://github.com/withastro/astro/commit/519a1c4e8407c7abcb8d879b67a9f4b960652cae), [`70f34f5a3`](https://github.com/withastro/astro/commit/70f34f5a355f42526ee9e5355f3de8e510002ea2), [`0f637c71e`](https://github.com/withastro/astro/commit/0f637c71e511cb4c51712128d217a26c8eee4d40), [`866ed4098`](https://github.com/withastro/astro/commit/866ed4098edffb052239cdb26e076cf8db61b1d9), [`5b1e39ef6`](https://github.com/withastro/astro/commit/5b1e39ef6ec6dcebea96584f95d9530bd9aa715d)]: + - astro@3.0.0-beta.1 + - @astrojs/underscore-redirects@0.3.0-beta.0 + +## 3.0.0-beta.0 + +### Major Changes + +- [`1eae2e3f7`](https://github.com/withastro/astro/commit/1eae2e3f7d693c9dfe91c8ccfbe606d32bf2fb81) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Remove support for Node 16. The lowest supported version by Astro and all integrations is now v18.14.1. As a reminder, Node 16 will be deprecated on the 11th September 2023. + +- [`c022a4217`](https://github.com/withastro/astro/commit/c022a4217a805d223c1494e9eda4e48bbf810388) Thanks [@Princesseuh](https://github.com/Princesseuh)! - When using an adapter that supports neither Squoosh or Sharp, Astro will now automatically use an image service that does not support processing, but still provides the other benefits of `astro:assets` such as enforcing `alt`, no CLS etc to users + +- [`3dc1ca2fa`](https://github.com/withastro/astro/commit/3dc1ca2fac8d9965cc5085a5d09e72ed87b4281a) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Reduced the amount of polyfills provided by Astro. Astro will no longer provide (no-op) polyfills for several web apis such as HTMLElement, Image or Document. If you need access to those APIs on the server, we recommend using more proper polyfills available on npm. + +### Minor Changes + +- [`9b4f70a62`](https://github.com/withastro/astro/commit/9b4f70a629f55e461759ba46f68af7097a2e9215) Thanks [@ematipico](https://github.com/ematipico)! - Introduced the concept of feature map. A feature map is a list of features that are built-in in Astro, and an Adapter + can tell Astro if it can support it. + + ```ts + import { AstroIntegration } from './astro'; + + function myIntegration(): AstroIntegration { + return { + name: 'astro-awesome-list', + // new feature map + supportedAstroFeatures: { + hybridOutput: 'experimental', + staticOutput: 'stable', + serverOutput: 'stable', + assets: { + supportKind: 'stable', + isSharpCompatible: false, + isSquooshCompatible: false, + }, + }, + }; + } + ``` + +- [`3fdf509b2`](https://github.com/withastro/astro/commit/3fdf509b2731a9b2f972d89291e57cf78d62c769) Thanks [@ematipico](https://github.com/ematipico)! - The `build.split` and `build.excludeMiddleware` configuration options are deprecated and have been replaced by options in the adapter config. + + If your config includes the `build.excludeMiddleware` option, replace it with `edgeMiddleware` in your adapter options: + + ```diff + import { defineConfig } from "astro/config"; + import netlify from "@astrojs/netlify/functions"; + + export default defineConfig({ + build: { + - excludeMiddleware: true + }, + adapter: netlify({ + + edgeMiddleware: true + }), + }); + ``` + + If your config includes the `build.split` option, replace it with `functionPerRoute` in your adapter options: + + ```diff + import { defineConfig } from "astro/config"; + import netlify from "@astrojs/netlify/functions"; + + export default defineConfig({ + build: { + - split: true + }, + adapter: netlify({ + + functionPerRoute: true + }), + }); + ``` + +### Patch Changes + +- Updated dependencies [[`1eae2e3f7`](https://github.com/withastro/astro/commit/1eae2e3f7d693c9dfe91c8ccfbe606d32bf2fb81), [`76ddef19c`](https://github.com/withastro/astro/commit/76ddef19ccab6e5f7d3a5740cd41acf10e334b38), [`9b4f70a62`](https://github.com/withastro/astro/commit/9b4f70a629f55e461759ba46f68af7097a2e9215), [`3fdf509b2`](https://github.com/withastro/astro/commit/3fdf509b2731a9b2f972d89291e57cf78d62c769), [`2f951cd40`](https://github.com/withastro/astro/commit/2f951cd403dfcc2c3ca6aae618ae3e1409516e32), [`c022a4217`](https://github.com/withastro/astro/commit/c022a4217a805d223c1494e9eda4e48bbf810388), [`67becaa58`](https://github.com/withastro/astro/commit/67becaa580b8f787df58de66b7008b7098f1209c), [`bc37331d8`](https://github.com/withastro/astro/commit/bc37331d8154e3e95a8df9131e4e014e78a7a9e7), [`dfc2d93e3`](https://github.com/withastro/astro/commit/dfc2d93e3c645995379358fabbdfa9aab99f43d8), [`3dc1ca2fa`](https://github.com/withastro/astro/commit/3dc1ca2fac8d9965cc5085a5d09e72ed87b4281a), [`1be84dfee`](https://github.com/withastro/astro/commit/1be84dfee3ce8e6f5cc624f99aec4e980f6fde37), [`35f01df79`](https://github.com/withastro/astro/commit/35f01df797d23315f2bee2fc3fd795adb0559c58), [`3fdf509b2`](https://github.com/withastro/astro/commit/3fdf509b2731a9b2f972d89291e57cf78d62c769), [`78de801f2`](https://github.com/withastro/astro/commit/78de801f21fd4ca1653950027d953bf08614566b), [`59d6e569f`](https://github.com/withastro/astro/commit/59d6e569f63e175c97e82e94aa7974febfb76f7c), [`7723c4cc9`](https://github.com/withastro/astro/commit/7723c4cc93298c2e6530e55da7afda048f22cf81), [`fb5cd6b56`](https://github.com/withastro/astro/commit/fb5cd6b56dc27a71366ed5e1ab8bfe9b8f96bac5), [`631b9c410`](https://github.com/withastro/astro/commit/631b9c410d5d66fa384674027ba95d69ebb5063f)]: + - astro@3.0.0-beta.0 + - @astrojs/underscore-redirects@0.3.0-beta.0 + +## 2.6.0 + +### Minor Changes + +- [#7975](https://github.com/withastro/astro/pull/7975) [`f974c95a2`](https://github.com/withastro/astro/commit/f974c95a27ccbf91adbc66f6f1433f4cf11be33e) Thanks [@lilnasy](https://github.com/lilnasy)! - If you are using Netlify's On-demand Builders, you can now specify how long your pages should remain cached. By default, all pages will be rendered on first visit and reused on every subsequent visit until a redeploy. To set a custom revalidation time, call the `runtime.setBuildersTtl()` local in either your frontmatter or middleware. + + ```astro + --- + import Layout from '../components/Layout.astro'; + + if (import.meta.env.PROD) { + // revalidates every 45 seconds + Astro.locals.runtime.setBuildersTtl(45); + } + --- + + <Layout title="Astro on Netlify"> + {new Date(Date.now())} + </Layout> + ``` + +### Patch Changes + +- Updated dependencies [[`1b8d30209`](https://github.com/withastro/astro/commit/1b8d3020990130dabfaaf753db73a32c6e0c896a), [`405913cdf`](https://github.com/withastro/astro/commit/405913cdf20b26407aa351c090f0a0859a4e6f54), [`87d4b1843`](https://github.com/withastro/astro/commit/87d4b18437c7565c48cad4bea81831c2a244ebb8), [`c23377caa`](https://github.com/withastro/astro/commit/c23377caafbc75deb91c33b9678c1b6868ad40ea), [`86bee2812`](https://github.com/withastro/astro/commit/86bee2812185df6e14025e5962a335f51853587b)]: + - astro@2.10.6 + +## 2.5.2 + +### Patch Changes + +- [#7862](https://github.com/withastro/astro/pull/7862) [`1859960d0`](https://github.com/withastro/astro/commit/1859960d0443cc6638569408282544f37e0a90ae) Thanks [@Yan-Thomas](https://github.com/Yan-Thomas)! - Fix README GitHub search link + +- [#7754](https://github.com/withastro/astro/pull/7754) [`298dbb89f`](https://github.com/withastro/astro/commit/298dbb89f2963a547370b6e65cafd2650fdb1b27) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Improve `404` behavior for `serverless` and `edge` + +- Updated dependencies [[`298dbb89f`](https://github.com/withastro/astro/commit/298dbb89f2963a547370b6e65cafd2650fdb1b27), [`9e2203847`](https://github.com/withastro/astro/commit/9e22038472c8be05ed7a72620534b88324dce793), [`5c5da8d2f`](https://github.com/withastro/astro/commit/5c5da8d2fbb37830f3ee81830d4c9afcd2c1a3e3), [`0b8375fe8`](https://github.com/withastro/astro/commit/0b8375fe82a15bfff3f517f98de6454adb2779f1), [`89d015db6`](https://github.com/withastro/astro/commit/89d015db6ce4d15b5b1140f0eb6bfbef187d6ad7), [`ebf7ebbf7`](https://github.com/withastro/astro/commit/ebf7ebbf7ae767625d736fad327954cfb853837e)]: + - astro@2.9.7 + +## 2.5.1 + +### Patch Changes + +- [#7805](https://github.com/withastro/astro/pull/7805) [`42a21b5da`](https://github.com/withastro/astro/commit/42a21b5da631948da4495062a6ef30fbb91abd05) Thanks [@matthewp](https://github.com/matthewp)! - Prevent building .html file redirects in hybrid mode + +- Updated dependencies [[`31c4031ba`](https://github.com/withastro/astro/commit/31c4031ba7aea132a861f2465f38a83741f0cd05), [`5161cf919`](https://github.com/withastro/astro/commit/5161cf919c81bd3681af221def0abab7d25abec0), [`59b556232`](https://github.com/withastro/astro/commit/59b556232696d3aba3c2263ea104cd9922085fd2), [`267487e63`](https://github.com/withastro/astro/commit/267487e63ea0a4cfcb771c667a088afb16c62ba6), [`b063a2d8a`](https://github.com/withastro/astro/commit/b063a2d8aeaed18550d148511bfb68f9ba3cdb09), [`d5f526b33`](https://github.com/withastro/astro/commit/d5f526b3397cf24aa06353de2de91b2ba08cd4eb), [`7dbcbc86b`](https://github.com/withastro/astro/commit/7dbcbc86b3bd7e5458570906745364c9399d1a46)]: + - astro@2.9.4 + +## 2.5.0 + +### Minor Changes + +- [#7700](https://github.com/withastro/astro/pull/7700) [`a77741d25`](https://github.com/withastro/astro/commit/a77741d25e5d923461026003aba81869833863d4) Thanks [@delucis](https://github.com/delucis)! - When a project uses the new `build.excludeMiddleware` Astro config option, the `@astrojs/netlify/functions` adapter will bundle your middleware to run in a [Netlify Edge Function](https://docs.netlify.com/edge-functions/overview/). + + See the [Netlify adapter documentation](https://docs.astro.build/en/guides/integrations-guide/netlify/#run-middleware-in-edge-functions) for more details. + +### Patch Changes + +- Updated dependencies [[`72bbfac97`](https://github.com/withastro/astro/commit/72bbfac976c2965a523eea88ff0543e64d848d80), [`d401866f9`](https://github.com/withastro/astro/commit/d401866f93bfe25a50c171bc54b2b1ee0f483cc9), [`4f6b5ae2b`](https://github.com/withastro/astro/commit/4f6b5ae2ba8eb162e03f25cbd600a905d434f529), [`06c255716`](https://github.com/withastro/astro/commit/06c255716ae8e922fb9d4ffa5595cbb34146fff6)]: + - astro@2.8.5 + +## 2.4.0 + +### Minor Changes + +- [#7615](https://github.com/withastro/astro/pull/7615) [`f21357b69`](https://github.com/withastro/astro/commit/f21357b69d94fe8d81f267efddb182d1a3cc678a) Thanks [@ematipico](https://github.com/ematipico)! - The Netlify adapter builds to a single function by default. Astro 2.7 added support for splitting your build into separate entry points per page. If you use this configuration, the Netlify adapter will generate a separate function for each page. This can help reduce the size of each function so they are only bundling code used on that page. + + ```js + // astro.config.mjs + import { defineConfig } from 'astro/config'; + import netlify from '@astrojs/netlify/functions'; + + export default defineConfig({ + output: 'server', + adapter: netlify(), + build: { + split: true, + }, + }); + ``` + +### Patch Changes + +- Updated dependencies [[`f21357b69`](https://github.com/withastro/astro/commit/f21357b69d94fe8d81f267efddb182d1a3cc678a), [`86e19c7cf`](https://github.com/withastro/astro/commit/86e19c7cf8696e065c1ccdc2eb841ad0a2b61ede)]: + - @astrojs/underscore-redirects@0.2.0 + - astro@2.8.2 + +## 2.3.0 + +### Minor Changes + +- [#7067](https://github.com/withastro/astro/pull/7067) [`57f8d14c0`](https://github.com/withastro/astro/commit/57f8d14c027c30919363e12c664ccff4ed64d0fc) Thanks [@matthewp](https://github.com/matthewp)! - Support for experimental redirects + + This adds support for the redirects RFC in the Netlify adapter, including a new `@astrojs/netlify/static` adapter for static sites. + + No changes are necessary when using SSR. Simply use configured redirects and the adapter will update your `_redirects` file. + +### Patch Changes + +- [#7260](https://github.com/withastro/astro/pull/7260) [`39403c32f`](https://github.com/withastro/astro/commit/39403c32faea58399c61d3344b770f195be60d5b) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Unflags support for `output: 'hybrid'` mode, which enables pre-rendering by default. The additional `experimental.hybridOutput` flag can be safely removed from your configuration. + +- Updated dependencies [[`57f8d14c0`](https://github.com/withastro/astro/commit/57f8d14c027c30919363e12c664ccff4ed64d0fc), [`414eb19d2`](https://github.com/withastro/astro/commit/414eb19d2fcb55758f9d053076773b11b62f4c97), [`a7e2b37ff`](https://github.com/withastro/astro/commit/a7e2b37ff73871c46895c615846a86a539f45330), [`dd1a6b6c9`](https://github.com/withastro/astro/commit/dd1a6b6c941aeb7af934bd12db22412af262f5a1), [`d72cfa7ca`](https://github.com/withastro/astro/commit/d72cfa7cad758192163712ceb269405659fd14bc), [`144813f73`](https://github.com/withastro/astro/commit/144813f7308dcb9de64ebe3f0f2c6cba9ad81eb1), [`b5213654b`](https://github.com/withastro/astro/commit/b5213654b1b7f3ba573a48d3be688b2bdde7870f), [`e3b8c6296`](https://github.com/withastro/astro/commit/e3b8c62969d680d1915a122c610d281d6711aa63), [`890a2bc98`](https://github.com/withastro/astro/commit/890a2bc9891a2449ab99b01b65468f6dddba6b12), [`39403c32f`](https://github.com/withastro/astro/commit/39403c32faea58399c61d3344b770f195be60d5b), [`101f03209`](https://github.com/withastro/astro/commit/101f032098148b3daaac8d46ff1e535b79232e43)]: + - astro@2.6.0 + +## 2.2.3 + +### Patch Changes + +- [#6991](https://github.com/withastro/astro/pull/6991) [`719002ca5`](https://github.com/withastro/astro/commit/719002ca5b128744fb4316d4a52c5dcd46a42759) Thanks [@MoustaphaDev](https://github.com/MoustaphaDev)! - Enable experimental support for hybrid SSR with pre-rendering enabled by default + + **astro.config.mjs** + + ```js + import { defineConfig } from 'astro/config'; + export defaultdefineConfig({ + output: 'hybrid', + experimental: { + hybridOutput: true, + }, + }) + ``` + + Then add `export const prerender = false` to any page or endpoint you want to opt-out of pre-rendering. + + **src/pages/contact.astro** + + ```astro + --- + export const prerender = false; + + if (Astro.request.method === 'POST') { + // handle form submission + } + --- + + <form method="POST"> + <input type="text" name="name" /> + <input type="email" name="email" /> + <button type="submit">Submit</button> + </form> + ``` + +- [#7104](https://github.com/withastro/astro/pull/7104) [`826e02890`](https://github.com/withastro/astro/commit/826e0289005f645b902375b98d5549c6a95ccafa) Thanks [@bluwy](https://github.com/bluwy)! - Specify `"files"` field to only publish necessary files + +- Updated dependencies [[`4516d7b22`](https://github.com/withastro/astro/commit/4516d7b22c5979cde4537f196b53ae2826ba9561), [`e186ecc5e`](https://github.com/withastro/astro/commit/e186ecc5e292de8c6a2c441a2d588512c0813068), [`c6d7ebefd`](https://github.com/withastro/astro/commit/c6d7ebefdd554a9ef29cfeb426ac55cab80d6473), [`914c439bc`](https://github.com/withastro/astro/commit/914c439bccee9fec002c6d92beaa501c398e62ac), [`e9fc2c221`](https://github.com/withastro/astro/commit/e9fc2c2213036d47cd30a47a6cdad5633481a0f8), [`075eee08f`](https://github.com/withastro/astro/commit/075eee08f2e2b0baea008b97f3523f2cb937ee44), [`719002ca5`](https://github.com/withastro/astro/commit/719002ca5b128744fb4316d4a52c5dcd46a42759), [`fc52681ba`](https://github.com/withastro/astro/commit/fc52681ba2f8fe8bcd92eeedf3c6a52fd86a390e), [`fb84622af`](https://github.com/withastro/astro/commit/fb84622af04f795de8d17f24192de105f70fe910), [`cada10a46`](https://github.com/withastro/astro/commit/cada10a466f81f8edb0aa664f9cffdb6b5b8f307), [`cd410c5eb`](https://github.com/withastro/astro/commit/cd410c5eb71f825259279c27c4c39d0ad282c3f0), [`73ec6f6c1`](https://github.com/withastro/astro/commit/73ec6f6c16cadb71dafe9f664f0debde072c3173), [`410428672`](https://github.com/withastro/astro/commit/410428672ed97bba7ca0b3352c1a7ee564921462), [`763ff2d1e`](https://github.com/withastro/astro/commit/763ff2d1e44f54b899d7c65386f1b4b877c95737), [`c1669c001`](https://github.com/withastro/astro/commit/c1669c0011eecfe65a459d727848c18c189a54ca), [`3d525efc9`](https://github.com/withastro/astro/commit/3d525efc95cfb2deb5d9e04856d02965d66901c9)]: + - astro@2.5.0 + +## 2.2.2 + +### Patch Changes + +- [#6793](https://github.com/withastro/astro/pull/6793) [`1e3873c04`](https://github.com/withastro/astro/commit/1e3873c04abab6c498c93abc06828ecd235569d4) Thanks [@andremralves](https://github.com/andremralves)! - fix: no edge functions deployed to netlify + +## 2.2.1 + +### Patch Changes + +- [#6651](https://github.com/withastro/astro/pull/6651) [`416ceb973`](https://github.com/withastro/astro/commit/416ceb9730ce604cd3f73c22200907d9b9978073) Thanks [@matthewp](https://github.com/matthewp)! - Use Deno API to set Astro.clientAddress in Netlify Edge + +- Updated dependencies [[`72fed684a`](https://github.com/withastro/astro/commit/72fed684a35f00d80c69bcf6e8af297fed0294fe), [`45bff6fcc`](https://github.com/withastro/astro/commit/45bff6fccb3f5c71ff24c1ceb48cd532196c90f6), [`52d7a4a01`](https://github.com/withastro/astro/commit/52d7a4a011a3bb722b522fffd88c5fe9a519a196), [`9e88e0f23`](https://github.com/withastro/astro/commit/9e88e0f23c5913c07f7e3e96fa0555219ef710dc), [`fa84f1a7d`](https://github.com/withastro/astro/commit/fa84f1a7d2c290479c75199f16e8de489036d7ea), [`a98f6f418`](https://github.com/withastro/astro/commit/a98f6f418c92261a06ef79624a8c86e288c21eab), [`7f74326b7`](https://github.com/withastro/astro/commit/7f74326b762bfc174ebe8e37ae03733563e4214f)]: + - astro@2.2.1 + +## 2.2.0 + +### Minor Changes + +- [#6213](https://github.com/withastro/astro/pull/6213) [`afbbc4d5b`](https://github.com/withastro/astro/commit/afbbc4d5bfafc1779bac00b41c2a1cb1c90f2808) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updated compilation settings to disable downlevelling for Node 14 + +### Patch Changes + +- Updated dependencies [[`fec583909`](https://github.com/withastro/astro/commit/fec583909ab62829dc0c1600e2387979365f2b94), [`b087b83fe`](https://github.com/withastro/astro/commit/b087b83fe266c431fe34a07d5c2293cc4ab011c6), [`694918a56`](https://github.com/withastro/astro/commit/694918a56b01104831296be0c25456135a63c784), [`a20610609`](https://github.com/withastro/astro/commit/a20610609863ae3b48afe96819b8f11ae4f414d5), [`a4a74ab70`](https://github.com/withastro/astro/commit/a4a74ab70cd2aa0d812a1f6b202c4e240a8913bf), [`75921b3cd`](https://github.com/withastro/astro/commit/75921b3cd916d439f6392c487c21532fde35ed13), [`afbbc4d5b`](https://github.com/withastro/astro/commit/afbbc4d5bfafc1779bac00b41c2a1cb1c90f2808)]: + - astro@2.1.0 + - @astrojs/webapi@2.1.0 + +## 2.1.3 + +### Patch Changes + +- [#6323](https://github.com/withastro/astro/pull/6323) [`5e26bc891`](https://github.com/withastro/astro/commit/5e26bc891cbebb3598acfa760c135a25c548d624) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updated Undici to 5.20.0. This fixes a security issue and handling of cookies in certain cases in dev + +- [#6317](https://github.com/withastro/astro/pull/6317) [`2eb73cb9d`](https://github.com/withastro/astro/commit/2eb73cb9d1c982df5f8788ddacd634645643c5c6) Thanks [@bluwy](https://github.com/bluwy)! - Use .mjs extension when building to support CJS environments + +- Updated dependencies [[`5e26bc891`](https://github.com/withastro/astro/commit/5e26bc891cbebb3598acfa760c135a25c548d624), [`a156ecbb7`](https://github.com/withastro/astro/commit/a156ecbb7f4df6a46124a9a12eb712f9163db2ed), [`ccd72e6bb`](https://github.com/withastro/astro/commit/ccd72e6bb41e570d42b1b158e8124c8e04a1943d), [`504c7bacb`](https://github.com/withastro/astro/commit/504c7bacb8c1f2308a31e6c412825ba34983ba33), [`63dda6ded`](https://github.com/withastro/astro/commit/63dda6dedd4c6ea1d5ce72e9cf3fe5f88339a927), [`f91a7f376`](https://github.com/withastro/astro/commit/f91a7f376c223f18b4d8fbed81f95f6bea1cef8d)]: + - astro@2.0.15 + +## 2.1.2 + +### Patch Changes + +- [#6117](https://github.com/withastro/astro/pull/6117) [`32abe49bd`](https://github.com/withastro/astro/commit/32abe49bd073417b480b1b990f432a837c12eb6f) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Fix polyfills not being available in certain cases + +- Updated dependencies [[`f6fc662c3`](https://github.com/withastro/astro/commit/f6fc662c3c59d164584c6287a930fcd1c9086ee6), [`592386b75`](https://github.com/withastro/astro/commit/592386b75541f3b7f7d95c631f86024b7e2d314d), [`1b591a143`](https://github.com/withastro/astro/commit/1b591a1431b44eacd239ed8f76809916cabca1db), [`bf8d7366a`](https://github.com/withastro/astro/commit/bf8d7366acb57e1b21181cc40fff55a821d8119e), [`ec38a8921`](https://github.com/withastro/astro/commit/ec38a8921f02a275949abcababe1b8afdf8184a2), [`f20a85b64`](https://github.com/withastro/astro/commit/f20a85b642994f240d8c94260fc55ffa1fd14294), [`9f22ac3d0`](https://github.com/withastro/astro/commit/9f22ac3d097ef2cb3b2bbe5343b8a8a49d83425d), [`cee70f5c6`](https://github.com/withastro/astro/commit/cee70f5c6ac9b0d2edc1f8a6f8f5043605576026), [`ac7fb04d6`](https://github.com/withastro/astro/commit/ac7fb04d6b162f28a337918138d5737e2c0fffad), [`d1f5611fe`](https://github.com/withastro/astro/commit/d1f5611febfd020cca4078c71bafe599015edd16), [`2189170be`](https://github.com/withastro/astro/commit/2189170be523f74f244e84ccab22c655219773ce), [`32abe49bd`](https://github.com/withastro/astro/commit/32abe49bd073417b480b1b990f432a837c12eb6f)]: + - astro@2.0.7 + +## 2.1.1 + +### Patch Changes + +- [#6090](https://github.com/withastro/astro/pull/6090) [`97a97196f`](https://github.com/withastro/astro/commit/97a97196fc4d2dd8ced838ddbca17a587cfa0957) Thanks [@matthewp](https://github.com/matthewp)! - Fix Netlify Function regression + +## 2.1.0 + +### Minor Changes + +- [#5874](https://github.com/withastro/astro/pull/5874) [`1c230f103`](https://github.com/withastro/astro/commit/1c230f10373ec392b6cdcd5c196ae932f89033aa) Thanks [@juanmiguelguerrero](https://github.com/juanmiguelguerrero)! - Add `builders` config option for Netlify On-demand Builders. + +### Patch Changes + +- Updated dependencies [[`b4432cd6b`](https://github.com/withastro/astro/commit/b4432cd6b65bad685a99fe15867710b0663c13b2), [`98a4a914b`](https://github.com/withastro/astro/commit/98a4a914bc47f3da2764b3bdc01577d25fe2e261), [`071e1dee7`](https://github.com/withastro/astro/commit/071e1dee7e1943be67d1ded39a9af1b7a2aafd02), [`322e059d0`](https://github.com/withastro/astro/commit/322e059d0da9ab0d6a546a111fabda755bd5f1b6), [`b994f6f35`](https://github.com/withastro/astro/commit/b994f6f35e29b2d93ff8ddc281a69c0af3cc3edf), [`12c68343c`](https://github.com/withastro/astro/commit/12c68343c0aa891037d39d3c9b9378b004be6642)]: + - astro@2.0.3 + +## 2.0.0 + +### Major Changes + +- [#5584](https://github.com/withastro/astro/pull/5584) [`9963c6e4d`](https://github.com/withastro/astro/commit/9963c6e4d50c392c3d1ac4492237020f15ccb1de) & [#5842](https://github.com/withastro/astro/pull/5842) [`c4b0cb8bf`](https://github.com/withastro/astro/commit/c4b0cb8bf2b41887d9106440bb2e70d421a5f481) Thanks [@wulinsheng123](https://github.com/wulinsheng123) and [@natemoo-re](https://github.com/natemoo-re)! - **Breaking Change**: client assets are built to an `_astro` directory in the build output directory. Previously these were built to various locations, including `assets/`, `chunks/` and the root of build output. + + You can control this location with the new `build` configuration option named `assets`. + +- [#5707](https://github.com/withastro/astro/pull/5707) [`5eba34fcc`](https://github.com/withastro/astro/commit/5eba34fcc663def20bdf6e0daad02a6a5472776b) Thanks [@bluwy](https://github.com/bluwy)! - Remove `astro:build:start` backwards compatibility code + +- [#5806](https://github.com/withastro/astro/pull/5806) [`7572f7402`](https://github.com/withastro/astro/commit/7572f7402238da37de748be58d678fedaf863b53) Thanks [@matthewp](https://github.com/matthewp)! - Make astro a peerDependency of integrations + + This marks `astro` as a peerDependency of several packages that are already getting `major` version bumps. This is so we can more properly track the dependency between them and what version of Astro they are being used with. + +### Patch Changes + +- [#5768](https://github.com/withastro/astro/pull/5768) [`2f6745019`](https://github.com/withastro/astro/commit/2f6745019ac25785032ac3659c2433b6e224f383) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Fix set-cookies not working in certain cases when using Node 18+ + +- [#5904](https://github.com/withastro/astro/pull/5904) [`f5adbd6b5`](https://github.com/withastro/astro/commit/f5adbd6b55ca13a7523dff2cfc5dccdab9980fa7) Thanks [@matthewp](https://github.com/matthewp)! - Support prerender in \_redirects + +- [#5885](https://github.com/withastro/astro/pull/5885) [`8f1ae06e5`](https://github.com/withastro/astro/commit/8f1ae06e58f37c7d9e3b9076268b6e91546bdc07) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fix issue with prerendered pages when using `edge-functions` adapter + +- Updated dependencies [[`93e633922`](https://github.com/withastro/astro/commit/93e633922c2e449df3bb2357b3683af1d3c0e07b), [`16dc36a87`](https://github.com/withastro/astro/commit/16dc36a870df47a4151a8ed2d91d0bd1bb812458), [`01f3f463b`](https://github.com/withastro/astro/commit/01f3f463bf2918b310d130a9fabbf3ee21d14029), [`e2019be6f`](https://github.com/withastro/astro/commit/e2019be6ffa46fa33d92cfd346f9ecbe51bb7144), [`05caf445d`](https://github.com/withastro/astro/commit/05caf445d4d2728f1010aeb2179a9e756c2fd17d), [`49ab4f231`](https://github.com/withastro/astro/commit/49ab4f231c23b34891c3ee86f4b92bf8d6d267a3), [`a342a486c`](https://github.com/withastro/astro/commit/a342a486c2831461e24e6c2f1ca8a9d3e15477b6), [`8fb28648f`](https://github.com/withastro/astro/commit/8fb28648f66629741cb976bfe34ccd9d8f55661e), [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a), [`c2180746b`](https://github.com/withastro/astro/commit/c2180746b4f6d9ef1b6f86924f21f52cc6ab4e63), [`ae8a012a7`](https://github.com/withastro/astro/commit/ae8a012a7b6884a03c50494332ee37b4505c2c3b), [`cf2de5422`](https://github.com/withastro/astro/commit/cf2de5422c26bfdea4c75f76e57b57299ded3e3a), [`ce5c5dbd4`](https://github.com/withastro/astro/commit/ce5c5dbd46afbe738b03600758bf5c35113de522), [`ec09bb664`](https://github.com/withastro/astro/commit/ec09bb6642064dbd7d2f3369afb090363ae18de2), [`665a2c222`](https://github.com/withastro/astro/commit/665a2c2225e42881f5a9550599e8f3fc1deea0b4), [`259a539d7`](https://github.com/withastro/astro/commit/259a539d7d70c783330c797794b15716921629cf), [`f7aa1ec25`](https://github.com/withastro/astro/commit/f7aa1ec25d1584f7abd421903fbef66b1c050e2a), [`4987d6f44`](https://github.com/withastro/astro/commit/4987d6f44cfd0d81d88f21f5c380503403dc1e6a), [`304823811`](https://github.com/withastro/astro/commit/304823811eddd8e72aa1d8e2d39b40ab5cda3565), [`302e0ef8f`](https://github.com/withastro/astro/commit/302e0ef8f5d5232e3348afe680e599f3e537b5c5), [`55cea0a9d`](https://github.com/withastro/astro/commit/55cea0a9d8c8df91a46590fc04a9ac28089b3432), [`dd56c1941`](https://github.com/withastro/astro/commit/dd56c19411b126439b8bc42d681b6fa8c06e8c61), [`9963c6e4d`](https://github.com/withastro/astro/commit/9963c6e4d50c392c3d1ac4492237020f15ccb1de), [`46ecd5de3`](https://github.com/withastro/astro/commit/46ecd5de34df619e2ee73ccea39a57acd37bc0b8), [`be901dc98`](https://github.com/withastro/astro/commit/be901dc98c4a7f6b5536540aa8f7ba5108e939a0), [`f6cf92b48`](https://github.com/withastro/astro/commit/f6cf92b48317a19a3840ad781b77d6d3cae143bb), [`e818cc046`](https://github.com/withastro/astro/commit/e818cc0466a942919ea3c41585e231c8c80cb3d0), [`8c100a6fe`](https://github.com/withastro/astro/commit/8c100a6fe6cc652c3799d1622e12c2c969f30510), [`116d8835c`](https://github.com/withastro/astro/commit/116d8835ca9e78f8b5e477ee5a3d737b69f80706), [`840412128`](https://github.com/withastro/astro/commit/840412128b00a04515156e92c314a929d6b94f6d), [`1f49cddf9`](https://github.com/withastro/astro/commit/1f49cddf9e9ffc651efc171b2cbde9fbe9e8709d), [`7325df412`](https://github.com/withastro/astro/commit/7325df412107fc0e65cd45c1b568fb686708f723), [`16c7d0bfd`](https://github.com/withastro/astro/commit/16c7d0bfd49d2b9bfae45385f506bcd642f9444a), [`c55fbcb8e`](https://github.com/withastro/astro/commit/c55fbcb8edca1fe118a44f68c9f9436a4719d171), [`a9c292026`](https://github.com/withastro/astro/commit/a9c2920264e36cc5dc05f4adc1912187979edb0d), [`2a5786419`](https://github.com/withastro/astro/commit/2a5786419599b8674473c699300172b9aacbae2e), [`4a1cabfe6`](https://github.com/withastro/astro/commit/4a1cabfe6b9ef8a6fbbcc0727a0dc6fa300cedaa), [`a8d3e7924`](https://github.com/withastro/astro/commit/a8d3e79246605d252dcddad159e358e2d79bd624), [`fa8c131f8`](https://github.com/withastro/astro/commit/fa8c131f88ef67d14c62f1c00c97ed74d43a80ac), [`64b8082e7`](https://github.com/withastro/astro/commit/64b8082e776b832f1433ed288e6f7888adb626d0), [`c4b0cb8bf`](https://github.com/withastro/astro/commit/c4b0cb8bf2b41887d9106440bb2e70d421a5f481), [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a), [`23dc9ea96`](https://github.com/withastro/astro/commit/23dc9ea96a10343852d965efd41fe6665294f1fb), [`63a6ceb38`](https://github.com/withastro/astro/commit/63a6ceb38d88331451dca64d0034c7c58e3d26f1), [`a3a7fc929`](https://github.com/withastro/astro/commit/a3a7fc9298e6d88abb4b7bee1e58f05fa9558cf1), [`52209ca2a`](https://github.com/withastro/astro/commit/52209ca2ad72a30854947dcb3a90ab4db0ac0a6f), [`5fd9208d4`](https://github.com/withastro/astro/commit/5fd9208d447f5ab8909a2188b6c2491a0debd49d), [`5eba34fcc`](https://github.com/withastro/astro/commit/5eba34fcc663def20bdf6e0daad02a6a5472776b), [`899214298`](https://github.com/withastro/astro/commit/899214298cee5f0c975c7245e623c649e1842d73), [`3a00ecb3e`](https://github.com/withastro/astro/commit/3a00ecb3eb4bc44be758c064f2bde6e247e8a593), [`5eba34fcc`](https://github.com/withastro/astro/commit/5eba34fcc663def20bdf6e0daad02a6a5472776b), [`2303f9514`](https://github.com/withastro/astro/commit/2303f95142aa740c99213a098f82b99dd37d74a0), [`1ca81c16b`](https://github.com/withastro/astro/commit/1ca81c16b8b66236e092e6eb6ec3f73f5668421c), [`b66d7195c`](https://github.com/withastro/astro/commit/b66d7195c17a55ea0931bc3744888bd4f5f01ce6)]: + - astro@2.0.0 + - @astrojs/webapi@2.0.0 + +## 2.0.0-beta.4 + +### Patch Changes + +- [#5904](https://github.com/withastro/astro/pull/5904) [`f5adbd6b5`](https://github.com/withastro/astro/commit/f5adbd6b55ca13a7523dff2cfc5dccdab9980fa7) Thanks [@matthewp](https://github.com/matthewp)! - Support prerender in \_redirects + +- Updated dependencies [[`4987d6f44`](https://github.com/withastro/astro/commit/4987d6f44cfd0d81d88f21f5c380503403dc1e6a), [`304823811`](https://github.com/withastro/astro/commit/304823811eddd8e72aa1d8e2d39b40ab5cda3565), [`46ecd5de3`](https://github.com/withastro/astro/commit/46ecd5de34df619e2ee73ccea39a57acd37bc0b8), [`7325df412`](https://github.com/withastro/astro/commit/7325df412107fc0e65cd45c1b568fb686708f723), [`a8d3e7924`](https://github.com/withastro/astro/commit/a8d3e79246605d252dcddad159e358e2d79bd624), [`5fd9208d4`](https://github.com/withastro/astro/commit/5fd9208d447f5ab8909a2188b6c2491a0debd49d)]: + - astro@2.0.0-beta.4 + - @astrojs/webapi@2.0.0-beta.1 + +## 2.0.0-beta.3 + +### Patch Changes + +- [#5885](https://github.com/withastro/astro/pull/5885) [`8f1ae06e5`](https://github.com/withastro/astro/commit/8f1ae06e58f37c7d9e3b9076268b6e91546bdc07) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fix issue with prerendered pages when using `edge-functions` adapter + +- Updated dependencies [[`16dc36a87`](https://github.com/withastro/astro/commit/16dc36a870df47a4151a8ed2d91d0bd1bb812458), [`05caf445d`](https://github.com/withastro/astro/commit/05caf445d4d2728f1010aeb2179a9e756c2fd17d), [`a342a486c`](https://github.com/withastro/astro/commit/a342a486c2831461e24e6c2f1ca8a9d3e15477b6), [`ce5c5dbd4`](https://github.com/withastro/astro/commit/ce5c5dbd46afbe738b03600758bf5c35113de522), [`be901dc98`](https://github.com/withastro/astro/commit/be901dc98c4a7f6b5536540aa8f7ba5108e939a0), [`e818cc046`](https://github.com/withastro/astro/commit/e818cc0466a942919ea3c41585e231c8c80cb3d0), [`8c100a6fe`](https://github.com/withastro/astro/commit/8c100a6fe6cc652c3799d1622e12c2c969f30510), [`64b8082e7`](https://github.com/withastro/astro/commit/64b8082e776b832f1433ed288e6f7888adb626d0), [`899214298`](https://github.com/withastro/astro/commit/899214298cee5f0c975c7245e623c649e1842d73), [`3a00ecb3e`](https://github.com/withastro/astro/commit/3a00ecb3eb4bc44be758c064f2bde6e247e8a593), [`1ca81c16b`](https://github.com/withastro/astro/commit/1ca81c16b8b66236e092e6eb6ec3f73f5668421c), [`b66d7195c`](https://github.com/withastro/astro/commit/b66d7195c17a55ea0931bc3744888bd4f5f01ce6)]: + - astro@2.0.0-beta.3 + +## 2.0.0-beta.2 + +### Major Changes + +- [#5842](https://github.com/withastro/astro/pull/5842) [`c4b0cb8bf`](https://github.com/withastro/astro/commit/c4b0cb8bf2b41887d9106440bb2e70d421a5f481) Thanks [@natemoo-re](https://github.com/natemoo-re)! - **Breaking Change**: client assets are built to an `_astro` directory in the build output directory. Previously these were built to various locations, including `assets/`, `chunks/` and the root of build output. + + You can control this location with the new `build` configuration option named `assets`. + +- [#5806](https://github.com/withastro/astro/pull/5806) [`7572f7402`](https://github.com/withastro/astro/commit/7572f7402238da37de748be58d678fedaf863b53) Thanks [@matthewp](https://github.com/matthewp)! - Make astro a peerDependency of integrations + + This marks `astro` as a peerDependency of several packages that are already getting `major` version bumps. This is so we can more properly track the dependency between them and what version of Astro they are being used with. + +### Patch Changes + +- Updated dependencies [[`01f3f463b`](https://github.com/withastro/astro/commit/01f3f463bf2918b310d130a9fabbf3ee21d14029), [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a), [`c2180746b`](https://github.com/withastro/astro/commit/c2180746b4f6d9ef1b6f86924f21f52cc6ab4e63), [`ae8a012a7`](https://github.com/withastro/astro/commit/ae8a012a7b6884a03c50494332ee37b4505c2c3b), [`cf2de5422`](https://github.com/withastro/astro/commit/cf2de5422c26bfdea4c75f76e57b57299ded3e3a), [`ec09bb664`](https://github.com/withastro/astro/commit/ec09bb6642064dbd7d2f3369afb090363ae18de2), [`665a2c222`](https://github.com/withastro/astro/commit/665a2c2225e42881f5a9550599e8f3fc1deea0b4), [`f7aa1ec25`](https://github.com/withastro/astro/commit/f7aa1ec25d1584f7abd421903fbef66b1c050e2a), [`302e0ef8f`](https://github.com/withastro/astro/commit/302e0ef8f5d5232e3348afe680e599f3e537b5c5), [`840412128`](https://github.com/withastro/astro/commit/840412128b00a04515156e92c314a929d6b94f6d), [`1f49cddf9`](https://github.com/withastro/astro/commit/1f49cddf9e9ffc651efc171b2cbde9fbe9e8709d), [`c55fbcb8e`](https://github.com/withastro/astro/commit/c55fbcb8edca1fe118a44f68c9f9436a4719d171), [`4a1cabfe6`](https://github.com/withastro/astro/commit/4a1cabfe6b9ef8a6fbbcc0727a0dc6fa300cedaa), [`c4b0cb8bf`](https://github.com/withastro/astro/commit/c4b0cb8bf2b41887d9106440bb2e70d421a5f481), [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a), [`23dc9ea96`](https://github.com/withastro/astro/commit/23dc9ea96a10343852d965efd41fe6665294f1fb), [`63a6ceb38`](https://github.com/withastro/astro/commit/63a6ceb38d88331451dca64d0034c7c58e3d26f1), [`52209ca2a`](https://github.com/withastro/astro/commit/52209ca2ad72a30854947dcb3a90ab4db0ac0a6f), [`2303f9514`](https://github.com/withastro/astro/commit/2303f95142aa740c99213a098f82b99dd37d74a0)]: + - astro@2.0.0-beta.2 + - @astrojs/webapi@2.0.0-beta.0 + +## 2.0.0-beta.1 + +### Patch Changes + +- [#5768](https://github.com/withastro/astro/pull/5768) [`2f6745019`](https://github.com/withastro/astro/commit/2f6745019ac25785032ac3659c2433b6e224f383) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Fix set-cookies not working in certain cases when using Node 18+ + +## 2.0.0-beta.0 + +### Major Changes + +- [#5707](https://github.com/withastro/astro/pull/5707) [`5eba34fcc`](https://github.com/withastro/astro/commit/5eba34fcc663def20bdf6e0daad02a6a5472776b) Thanks [@bluwy](https://github.com/bluwy)! - Remove `astro:build:start` backwards compatibility code + +## 1.3.0 + +### Minor Changes + +- [#5297](https://github.com/withastro/astro/pull/5297) [`d2960984c`](https://github.com/withastro/astro/commit/d2960984c59af7b60a3ea472c6c58fb00534a8e6) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Introduces the **experimental** Prerender API. + + > **Note** + > This API is not yet stable and is subject to possible breaking changes! + + - Deploy an Astro server without sacrificing the speed or cacheability of static HTML. + - The Prerender API allows you to statically prerender specific `pages/` at build time. + + **Usage** + + - First, run `astro build --experimental-prerender` or enable `experimental: { prerender: true }` in your `astro.config.mjs` file. + - Then, include `export const prerender = true` in any file in the `pages/` directory that you wish to prerender. + +## 1.2.2 + +### Patch Changes + +- [#5534](https://github.com/withastro/astro/pull/5534) [`fabd9124b`](https://github.com/withastro/astro/commit/fabd9124bd3e654e885054f30e9c0d01eabf0470) Thanks [@bluwy](https://github.com/bluwy)! - Update esbuild dependency + +## 1.2.1 + +### Patch Changes + +- [#5301](https://github.com/withastro/astro/pull/5301) [`a79a37cad`](https://github.com/withastro/astro/commit/a79a37cad549b21f91599ff86899e456d9dcc7df) Thanks [@bluwy](https://github.com/bluwy)! - Fix environment variables usage in edge functions + +## 1.2.0 + +### Minor Changes + +- [#5056](https://github.com/withastro/astro/pull/5056) [`e55af8a23`](https://github.com/withastro/astro/commit/e55af8a23233b6335f45b7a04b9d026990fb616c) Thanks [@matthewp](https://github.com/matthewp)! - # New build configuration + + The ability to customize SSR build configuration more granularly is now available in Astro. You can now customize the output folder for `server` (the server code for SSR), `client` (your client-side JavaScript and assets), and `serverEntry` (the name of the entrypoint server module). Here are the defaults: + + ```js + import { defineConfig } from 'astro/config'; + + export default defineConfig({ + output: 'server', + build: { + server: './dist/server/', + client: './dist/client/', + serverEntry: 'entry.mjs', + }, + }); + ``` + + These new configuration options are only supported in SSR mode and are ignored when building to SSG (a static site). + + ## Integration hook change + + The integration hook `astro:build:start` includes a param `buildConfig` which includes all of these same options. You can continue to use this param in Astro 1.x, but it is deprecated in favor of the new `build.config` options. All of the built-in adapters have been updated to the new format. If you have an integration that depends on this param we suggest upgrading to do this instead: + + ```js + export default function myIntegration() { + return { + name: 'my-integration', + hooks: { + 'astro:config:setup': ({ updateConfig }) => { + updateConfig({ + build: { + server: '...', + }, + }); + }, + }, + }; + } + ``` + +## 1.1.0 + +### Minor Changes + +- [#4876](https://github.com/withastro/astro/pull/4876) [`d3091f89e`](https://github.com/withastro/astro/commit/d3091f89e92fcfe1ad48daca74055d54b1c853a3) Thanks [@matthewp](https://github.com/matthewp)! - Adds the Astro.cookies API + + `Astro.cookies` is a new API for manipulating cookies in Astro components and API routes. + + In Astro components, the new `Astro.cookies` object is a map-like object that allows you to get, set, delete, and check for a cookie's existence (`has`): + + ```astro + --- + type Prefs = { + darkMode: boolean; + }; + + Astro.cookies.set<Prefs>( + 'prefs', + { darkMode: true }, + { + expires: '1 month', + } + ); + + const prefs = Astro.cookies.get<Prefs>('prefs').json(); + --- + + <body data-theme={prefs.darkMode ? 'dark' : 'light'}></body> + ``` + + Once you've set a cookie with Astro.cookies it will automatically be included in the outgoing response. + + This API is also available with the same functionality in API routes: + + ```js + export function post({ cookies }) { + cookies.set('loggedIn', false); + + return new Response(null, { + status: 302, + headers: { + Location: '/login', + }, + }); + } + ``` + + See [the RFC](https://github.com/withastro/rfcs/blob/main/proposals/0025-cookie-management.md) to learn more. + +### Patch Changes + +- [#4842](https://github.com/withastro/astro/pull/4842) [`812658ad2`](https://github.com/withastro/astro/commit/812658ad2ab3732a99e35c4fd903e302e723db46) Thanks [@bluwy](https://github.com/bluwy)! - Add missing dependencies, support strict dependency installation (e.g. pnpm) + +## 1.0.4 + +### Patch Changes + +- [#4820](https://github.com/withastro/astro/pull/4820) [`9bfbd63f0`](https://github.com/withastro/astro/commit/9bfbd63f05d21b51f7fd726fc4c16949919529a0) Thanks [@matthewp](https://github.com/matthewp)! - Fix processing of images in Netlify Functions + +## 1.0.3 + +### Patch Changes + +- [#4722](https://github.com/withastro/astro/pull/4722) [`4bc70f354`](https://github.com/withastro/astro/commit/4bc70f3545ab950da306de9c5417a08a7532fa28) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix route validation failures on Netlify Edge + +## 1.0.2 + +### Patch Changes + +- [#4558](https://github.com/withastro/astro/pull/4558) [`742966456`](https://github.com/withastro/astro/commit/7429664566f05ecebf6d57906f950627e62e690c) Thanks [@tony-sull](https://github.com/tony-sull)! - Adding the `withastro` keyword to include the adapters on the [Integrations Catalog](https://astro.build/integrations) + +## 1.0.1 + +### Patch Changes + +- [#4274](https://github.com/withastro/astro/pull/4274) [`d3d09a2c9`](https://github.com/withastro/astro/commit/d3d09a2c9f1af4dc467783c8bf4a71800924d129) Thanks [@matthewp](https://github.com/matthewp)! - Adds 404 routing logic to Netlify redirects file + +## 1.0.0 + +### Major Changes + +- [`04ad44563`](https://github.com/withastro/astro/commit/04ad445632c67bdd60c1704e1e0dcbcaa27b9308) - > Astro v1.0 is out! Read the [official announcement post](https://astro.build/blog/astro-1/). + + **No breaking changes**. This package is now officially stable and compatible with `astro@1.0.0`! + +### Patch Changes + +- Updated dependencies [[`04ad44563`](https://github.com/withastro/astro/commit/04ad445632c67bdd60c1704e1e0dcbcaa27b9308)]: + - @astrojs/webapi@1.0.0 + +## 0.5.0 + +### Minor Changes + +- [#4015](https://github.com/withastro/astro/pull/4015) [`6fd161d76`](https://github.com/withastro/astro/commit/6fd161d7691cbf9d3ffa4646e46059dfd0940010) Thanks [@matthewp](https://github.com/matthewp)! - New `output` configuration option + + This change introduces a new "output target" configuration option (`output`). Setting the output target lets you decide the format of your final build, either: + + - `"static"` (default): A static site. Your final build will be a collection of static assets (HTML, CSS, JS) that you can deploy to any static site host. + - `"server"`: A dynamic server application. Your final build will be an application that will run in a hosted server environment, generating HTML dynamically for different requests. + + If `output` is omitted from your config, the default value `"static"` will be used. + + When using the `"server"` output target, you must also include a runtime adapter via the `adapter` configuration. An adapter will _adapt_ your final build to run on the deployed platform of your choice (Netlify, Vercel, Node.js, Deno, etc). + + To migrate: No action is required for most users. If you currently define an `adapter`, you will need to also add `output: 'server'` to your config file to make it explicit that you are building a server. Here is an example of what that change would look like for someone deploying to Netlify: + + ```diff + import { defineConfig } from 'astro/config'; + import netlify from '@astrojs/netlify/functions'; + + export default defineConfig({ + adapter: netlify(), + + output: 'server', + }); + ``` + +* [#4018](https://github.com/withastro/astro/pull/4018) [`0cc6ede36`](https://github.com/withastro/astro/commit/0cc6ede362996b9faba57481a790d6eb7fba2045) Thanks [@okikio](https://github.com/okikio)! - Support for 404 and 500 pages in SSR + +- [#3973](https://github.com/withastro/astro/pull/3973) [`5a23483ef`](https://github.com/withastro/astro/commit/5a23483efb3ba614b05a00064f84415620605204) Thanks [@matthewp](https://github.com/matthewp)! - Adds support for Astro.clientAddress + + The new `Astro.clientAddress` property allows you to get the IP address of the requested user. + + ```astro + + ``` + + This property is only available when building for SSR, and only if the adapter you are using supports providing the IP address. If you attempt to access the property in a SSG app it will throw an error. + +## 0.4.10 + +### Patch Changes + +- [#3885](https://github.com/withastro/astro/pull/3885) [`bf5d1cc1e`](https://github.com/withastro/astro/commit/bf5d1cc1e71da38a14658c615e9481f2145cc6e7) Thanks [@delucis](https://github.com/delucis)! - Integration README fixes + +## 0.4.9 + +### Patch Changes + +- [#3865](https://github.com/withastro/astro/pull/3865) [`1f9e4857`](https://github.com/withastro/astro/commit/1f9e4857ff2b2cb7db89d619618cdf546cd3b3dc) Thanks [@delucis](https://github.com/delucis)! - Small README fixes + +* [#3854](https://github.com/withastro/astro/pull/3854) [`b012ee55`](https://github.com/withastro/astro/commit/b012ee55b107dea0730286263b27d83e530fad5d) Thanks [@bholmesdev](https://github.com/bholmesdev)! - [astro add] Support adapters and third party packages + +## 0.4.8 + +### Patch Changes + +- [#3677](https://github.com/withastro/astro/pull/3677) [`8045c8ad`](https://github.com/withastro/astro/commit/8045c8ade16fe4306448b7f98a4560ef0557d378) Thanks [@Jutanium](https://github.com/Jutanium)! - Update READMEs + +## 0.4.7 + +### Patch Changes + +- [#3734](https://github.com/withastro/astro/pull/3734) [`4acd245d`](https://github.com/withastro/astro/commit/4acd245d8f59871eb9c0083ae1a0fe7aa70c84f5) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix: append shim to top of built file to avoid "can't read process of undefined" issues + +## 0.4.6 + +### Patch Changes + +- [#3673](https://github.com/withastro/astro/pull/3673) [`ba5ad785`](https://github.com/withastro/astro/commit/ba5ad7855c4252e10e76b41b88fd4c74b4b7295b) Thanks [@hippotastic](https://github.com/hippotastic)! - Fix react dependencies to improve test reliability + +## 0.4.5 + +### Patch Changes + +- [#3612](https://github.com/withastro/astro/pull/3612) [`fca58cfd`](https://github.com/withastro/astro/commit/fca58cfd91b68501ec82350ab023170b208d8ce7) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix: "vpath" import error when building for netlify edge + +## 0.4.4 + +### Patch Changes + +- [#3592](https://github.com/withastro/astro/pull/3592) [`0ddcef20`](https://github.com/withastro/astro/commit/0ddcef2043e3c2f65aaeec7a969c374c053e22f3) Thanks [@tony-sull](https://github.com/tony-sull)! - Adds support for base64 encoded responses in Netlify Functions + +## 0.4.3 + +### Patch Changes + +- [#3535](https://github.com/withastro/astro/pull/3535) [`f3ab822e`](https://github.com/withastro/astro/commit/f3ab822e328725c3905b0adad9889ad37653c24a) Thanks [@matthewp](https://github.com/matthewp)! - Fixes Netlify Edge Function and Astro.glob + +## 0.4.2 + +### Patch Changes + +- [#3503](https://github.com/withastro/astro/pull/3503) [`207f58d1`](https://github.com/withastro/astro/commit/207f58d1715ac024cc7c81b76e26aa49fca5173f) Thanks [@williamtetlow](https://github.com/williamtetlow)! - Alias `from 'astro'` imports to `'@astro/types'` + Update Deno and Netlify integrations to handle vite.resolves.alias as an array + +## 0.4.1 + +### Patch Changes + +- Updated dependencies [[`4de53ecc`](https://github.com/withastro/astro/commit/4de53eccef346bed843b491b7ab93987d7d85655)]: + - @astrojs/webapi@0.12.0 + +## 0.4.0 + +### Minor Changes + +- [#3381](https://github.com/withastro/astro/pull/3381) [`43d92227`](https://github.com/withastro/astro/commit/43d922277afaeca9c90364fbf0b19477fd2c6566) Thanks [@sarahetter](https://github.com/sarahetter)! - Updating out directories for Netlify Functions + +* [#3377](https://github.com/withastro/astro/pull/3377) [`e1294c42`](https://github.com/withastro/astro/commit/e1294c422b3d3e98ccc745fe95d5672c9a17fe1f) Thanks [@sarahetter](https://github.com/sarahetter)! - Change out directories on dist and serverEntry + +## 0.3.4 + +### Patch Changes + +- [#3342](https://github.com/withastro/astro/pull/3342) [`352fc316`](https://github.com/withastro/astro/commit/352fc3166fe3b3d3da3feff621394b20eacb9cc3) Thanks [@thepassle](https://github.com/thepassle)! - create redirects file for netlify edge adapter + +## 0.3.3 + +### Patch Changes + +- [#3170](https://github.com/withastro/astro/pull/3170) [`19667c45`](https://github.com/withastro/astro/commit/19667c45f318ec13cdc2b51016f3fa3487b2a32d) Thanks [@matthewp](https://github.com/matthewp)! - Netlify Edge: Forward requests for static assets + +## 0.3.2 + +### Patch Changes + +- [#3160](https://github.com/withastro/astro/pull/3160) [`ae9ac5cb`](https://github.com/withastro/astro/commit/ae9ac5cbdceba0687d83d56d9d5f80479ab88710) Thanks [@matthewp](https://github.com/matthewp)! - Allows using React.lazy, Suspense in SSR and with hydration + +## 0.3.1 + +### Patch Changes + +- [#3150](https://github.com/withastro/astro/pull/3150) [`05cf1a50`](https://github.com/withastro/astro/commit/05cf1a506702f06ed48cd26cbe5ca108839ff0e6) Thanks [@matthewp](https://github.com/matthewp)! - Outputs manifest.json in correct folder for Netlify Edge Functions + +## 0.3.0 + +### Minor Changes + +- [#3148](https://github.com/withastro/astro/pull/3148) [`4cf54c60`](https://github.com/withastro/astro/commit/4cf54c60aa63bd614b242da0602790015005673d) Thanks [@matthewp](https://github.com/matthewp)! - Adds support for Netlify Edge Functions + +## 0.2.3 + +### Patch Changes + +- [#3092](https://github.com/withastro/astro/pull/3092) [`a5caf08e`](https://github.com/withastro/astro/commit/a5caf08e2494e9f779baa6b288d277490dd436b8) Thanks [@matthewp](https://github.com/matthewp)! - Fixes setting multiple cookies with the Netlify adapter + +## 0.2.2 + +### Patch Changes + +- [#3079](https://github.com/withastro/astro/pull/3079) [`9f248b05`](https://github.com/withastro/astro/commit/9f248b0563828db0e01e685aac177eaf8107906e) Thanks [@hippotastic](https://github.com/hippotastic)! - Make Netlify adapter actually append redirects + +## 0.2.1 + +### Patch Changes + +- [`815d62f1`](https://github.com/withastro/astro/commit/815d62f151a36fef7d09590d4962ca71bda61b32) Thanks [@FredKSchott](https://github.com/FredKSchott)! - no changes. + +## 0.2.0 + +### Minor Changes + +- [`732ea388`](https://github.com/withastro/astro/commit/732ea3881e216f0e6de3642c549afd019d32409f) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Improve the Netlify adapter: + + 1. Remove `site` config requirement + 2. Fix an issue where query params were being stripped + 3. Pass the event body to the request object + +### Patch Changes + +- [#2996](https://github.com/withastro/astro/pull/2996) [`77aa3a5c`](https://github.com/withastro/astro/commit/77aa3a5c504c5f51ed1c4d2c8abc4997397deec2) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add human-readable error when a site is not provided in your astro.config + +* [#3011](https://github.com/withastro/astro/pull/3011) [`c6f8bce7`](https://github.com/withastro/astro/commit/c6f8bce7c35cc4fd450fe1b6cc8297a81e413b8e) Thanks [@matthewp](https://github.com/matthewp)! - Fixes dynamic routes in the Netlify adapter + +## 0.1.1-beta.1 + +### Patch Changes + +- [#3011](https://github.com/withastro/astro/pull/3011) [`c6f8bce7`](https://github.com/withastro/astro/commit/c6f8bce7c35cc4fd450fe1b6cc8297a81e413b8e) Thanks [@matthewp](https://github.com/matthewp)! - Fixes dynamic routes in the Netlify adapter + +## 0.1.1-beta.0 + +### Patch Changes + +- [#2996](https://github.com/withastro/astro/pull/2996) [`77aa3a5c`](https://github.com/withastro/astro/commit/77aa3a5c504c5f51ed1c4d2c8abc4997397deec2) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add human-readable error when a site is not provided in your astro.config + +## 0.1.0 + +### Minor Changes + +- [`e425f896`](https://github.com/withastro/astro/commit/e425f896b668d98033ad3b998b50c1f28bc7f6ee) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Update config options to respect [RFC0019](https://github.com/withastro/rfcs/blob/main/proposals/0019-config-finalization.md) + +## 0.0.2 + +### Patch Changes + +- [#2879](https://github.com/withastro/astro/pull/2879) [`80034c6c`](https://github.com/withastro/astro/commit/80034c6cbc89761618847e6df43fd49560a05aa9) Thanks [@matthewp](https://github.com/matthewp)! - Netlify Adapter + + This change adds a Netlify adapter that uses Netlify Functions. You can use it like so: + + ```js + import { defineConfig } from 'astro/config'; + import netlify from '@astrojs/netlify/functions'; + + export default defineConfig({ + adapter: netlify(), + }); + ``` diff --git a/packages/integrations/netlify/README.md b/packages/integrations/netlify/README.md index 4ed3ee77b..137b1ea66 100644 --- a/packages/integrations/netlify/README.md +++ b/packages/integrations/netlify/README.md @@ -1,3 +1,38 @@ # @astrojs/netlify -The Netlify adapter package has moved. Please see [the new repository for the Netlify adapter](https://github.com/withastro/adapters/tree/main/packages/netlify). +This adapter allows Astro to deploy your [`hybrid` or `server` rendered site](https://docs.astro.build/en/core-concepts/rendering-modes/#on-demand-rendered) to [Netlify](https://www.netlify.com/). + +## Documentation + +Read the [`@astrojs/netlify` docs][docs] + +## Support + +- Get help in the [Astro Discord][discord]. Post questions in our `#support` forum, or visit our dedicated `#dev` channel to discuss current development and more! + +- Check our [Astro Integration Documentation][astro-integration] for more on integrations. + +- Submit bug reports and feature requests as [GitHub issues][issues]. + +## Contributing + +This package is maintained by Astro's Core team. You're welcome to submit an issue or PR! These links will help you get started: + +- [Contributor Manual][contributing] +- [Code of Conduct][coc] +- [Community Guide][community] + +## License + +MIT + +Copyright (c) 2023–present [Astro][astro] + +[astro]: https://astro.build/ +[docs]: https://docs.astro.build/en/guides/integrations-guide/netlify/ +[contributing]: https://github.com/withastro/astro/blob/main/CONTRIBUTING.md +[coc]: https://github.com/withastro/.github/blob/main/CODE_OF_CONDUCT.md +[community]: https://github.com/withastro/.github/blob/main/COMMUNITY_GUIDE.md +[discord]: https://astro.build/chat/ +[issues]: https://github.com/withastro/adapter/issues +[astro-integration]: https://docs.astro.build/en/guides/integrations-guide/ diff --git a/packages/integrations/netlify/package.json b/packages/integrations/netlify/package.json index 4b54bb6c0..1eba7a91a 100644 --- a/packages/integrations/netlify/package.json +++ b/packages/integrations/netlify/package.json @@ -1,8 +1,59 @@ { "name": "@astrojs/netlify", - "version": "0.0.0", - "private": true, + "description": "Deploy your site to Netlify", + "version": "6.1.0", "type": "module", - "keywords": [], - "dont_remove": "This is a placeholder for the sake of the docs smoke test" + "types": "./dist/index.d.ts", + "author": "withastro", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/withastro/adapters.git", + "directory": "packages/netlify" + }, + "keywords": ["withastro", "astro-adapter"], + "bugs": "https://github.com/withastro/adapters/issues", + "homepage": "https://docs.astro.build/en/guides/integrations-guide/netlify/", + "exports": { + ".": "./dist/index.js", + "./static": "./dist/static.js", + "./functions": "./dist/functions.js", + "./ssr-function.js": "./dist/ssr-function.js", + "./image-service.js": "./dist/image-service.js", + "./package.json": "./package.json" + }, + "files": ["dist"], + "scripts": { + "build": "astro-scripts build \"src/**/*.ts\" && tsc", + "test": "pnpm run test-fn && pnpm run test-static", + "test-fn": "astro-scripts test \"test/functions/*.test.js\"", + "test-static": "astro-scripts test \"test/static/*.test.js\"", + "test:hosted": "astro-scripts test \"test/hosted/*.test.js\"" + }, + "dependencies": { + "@astrojs/internal-helpers": "0.5.1", + "@astrojs/underscore-redirects": "^0.6.0", + "@netlify/functions": "^2.8.0", + "@vercel/nft": "^0.29.0", + "esbuild": "^0.24.0", + "vite": "^6.0.7" + }, + "peerDependencies": { + "astro": "^5.0.0" + }, + "devDependencies": { + "@netlify/edge-functions": "^2.11.1", + "@netlify/edge-handler-types": "^0.34.1", + "@types/node": "^22.10.6", + "astro": "^5.1.6", + "astro-scripts": "workspace:*", + "cheerio": "1.0.0", + "execa": "^8.0.1", + "fast-glob": "^3.3.3", + "strip-ansi": "^7.1.0", + "typescript": "^5.7.3" + }, + "astro": { + "external": true + } } diff --git a/packages/integrations/netlify/src/functions.ts b/packages/integrations/netlify/src/functions.ts new file mode 100644 index 000000000..58428fec0 --- /dev/null +++ b/packages/integrations/netlify/src/functions.ts @@ -0,0 +1,9 @@ +import type { AstroIntegration } from 'astro'; +import netlifyIntegration, { type NetlifyIntegrationConfig } from './index.js'; + +export default function functionsIntegration(config: NetlifyIntegrationConfig): AstroIntegration { + console.warn( + 'The @astrojs/netlify/functions import is deprecated and will be removed in a future release. Please use @astrojs/netlify instead.' + ); + return netlifyIntegration(config); +} diff --git a/packages/integrations/netlify/src/image-service.ts b/packages/integrations/netlify/src/image-service.ts new file mode 100644 index 000000000..afdcc3917 --- /dev/null +++ b/packages/integrations/netlify/src/image-service.ts @@ -0,0 +1,57 @@ +import type { ExternalImageService, ImageMetadata } from 'astro'; +import { baseService } from 'astro/assets'; +import { AstroError } from 'astro/errors'; + +const SUPPORTED_FORMATS = ['avif', 'jpg', 'png', 'webp']; +const QUALITY_NAMES: Record<string, number> = { low: 25, mid: 50, high: 90, max: 100 }; + +export function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata { + return typeof src === 'object'; +} + +function removeLeadingForwardSlash(path: string) { + return path.startsWith('/') ? path.substring(1) : path; +} + +const service: ExternalImageService = { + getURL(options) { + const query = new URLSearchParams(); + + const fileSrc = isESMImportedImage(options.src) + ? removeLeadingForwardSlash(options.src.src) + : options.src; + + query.set('url', fileSrc); + + if (options.format) query.set('fm', options.format); + if (options.width) query.set('w', `${options.width}`); + if (options.height) query.set('h', `${options.height}`); + if (options.quality) query.set('q', `${options.quality}`); + + return `/.netlify/images?${query}`; + }, + getHTMLAttributes: baseService.getHTMLAttributes, + getSrcSet: baseService.getSrcSet, + validateOptions(options) { + if (options.format && !SUPPORTED_FORMATS.includes(options.format)) { + throw new AstroError( + `Unsupported image format "${options.format}"`, + `Use one of ${SUPPORTED_FORMATS.join(', ')} instead.` + ); + } + + if (options.quality) { + options.quality = + typeof options.quality === 'string' ? QUALITY_NAMES[options.quality] : options.quality; + if (options.quality < 1 || options.quality > 100) { + throw new AstroError( + `Invalid quality for picture "${options.src}"`, + 'Quality needs to be between 1 and 100.' + ); + } + } + return options; + }, +}; + +export default service; diff --git a/packages/integrations/netlify/src/index.ts b/packages/integrations/netlify/src/index.ts new file mode 100644 index 000000000..2c0fde008 --- /dev/null +++ b/packages/integrations/netlify/src/index.ts @@ -0,0 +1,539 @@ +import { randomUUID } from 'node:crypto'; +import { appendFile, mkdir, readFile, writeFile } from 'node:fs/promises'; +import type { IncomingMessage } from 'node:http'; +import { fileURLToPath } from 'node:url'; +import { emptyDir } from '@astrojs/internal-helpers/fs'; +import { createRedirectsFromAstroRoutes } from '@astrojs/underscore-redirects'; +import type { Context } from '@netlify/functions'; +import type { + AstroConfig, + AstroIntegration, + AstroIntegrationLogger, + HookParameters, + IntegrationResolvedRoute, +} from 'astro'; +import { build } from 'esbuild'; +import { copyDependenciesToFunction } from './lib/nft.js'; +import type { Args } from './ssr-function.js'; + +const { version: packageVersion } = JSON.parse( + await readFile(new URL('../package.json', import.meta.url), 'utf8') +); + +export interface NetlifyLocals { + netlify: { + context: Context; + }; +} + +type RemotePattern = AstroConfig['image']['remotePatterns'][number]; + +/** + * Convert a remote pattern object to a regex string + */ +export function remotePatternToRegex( + pattern: RemotePattern, + logger: AstroIntegrationLogger +): string | undefined { + let { protocol, hostname, port, pathname } = pattern; + + let regexStr = ''; + + if (protocol) { + regexStr += `${protocol}://`; + } else { + // Default to matching any protocol + regexStr += '[a-z]+://'; + } + + if (hostname) { + if (hostname.startsWith('**.')) { + // match any number of subdomains + regexStr += '([a-z0-9-]+\\.)*'; + hostname = hostname.substring(3); + } else if (hostname.startsWith('*.')) { + // match one subdomain + regexStr += '([a-z0-9-]+\\.)?'; + hostname = hostname.substring(2); // Remove '*.' from the beginning + } + // Escape dots in the hostname + regexStr += hostname.replace(/\./g, '\\.'); + } else { + regexStr += '[a-z0-9.-]+'; + } + + if (port) { + regexStr += `:${port}`; + } else { + // Default to matching any port + regexStr += '(:[0-9]+)?'; + } + + if (pathname) { + if (pathname.endsWith('/**')) { + // Match any path. + regexStr += `(\\${pathname.replace('/**', '')}.*)`; + } + if (pathname.endsWith('/*')) { + // Match one level of path + regexStr += `(\\${pathname.replace('/*', '')}\/[^/?#]+)\/?`; + } else { + // Exact match + regexStr += `(\\${pathname})`; + } + } else { + // Default to matching any path + regexStr += '(\\/[^?#]*)?'; + } + if (!regexStr.endsWith('.*)')) { + // Match query, but only if it's not already matched by the pathname + regexStr += '([?][^#]*)?'; + } + try { + new RegExp(regexStr); + } catch (e) { + logger.warn( + `Could not generate a valid regex from the remotePattern "${JSON.stringify( + pattern + )}". Please check the syntax.` + ); + return undefined; + } + return regexStr; +} + +async function writeNetlifyFrameworkConfig(config: AstroConfig, logger: AstroIntegrationLogger) { + const remoteImages: Array<string> = []; + // Domains get a simple regex match + remoteImages.push( + ...config.image.domains.map((domain) => `https?:\/\/${domain.replaceAll('.', '\\.')}\/.*`) + ); + // Remote patterns need to be converted to regexes + remoteImages.push( + ...config.image.remotePatterns + .map((pattern) => remotePatternToRegex(pattern, logger)) + .filter(Boolean as unknown as (pattern?: string) => pattern is string) + ); + + const headers = config.build.assetsPrefix + ? undefined + : [ + { + for: `${config.base}${config.base.endsWith('/') ? '' : '/'}${config.build.assets}/*`, + values: { + 'Cache-Control': 'public, max-age=31536000, immutable', + }, + }, + ]; + + // See https://docs.netlify.com/image-cdn/create-integration/ + const deployConfigDir = new URL('.netlify/v1/', config.root); + await mkdir(deployConfigDir, { recursive: true }); + await writeFile( + new URL('./config.json', deployConfigDir), + JSON.stringify({ + images: { remote_images: remoteImages }, + headers, + }) + ); +} + +export interface NetlifyIntegrationConfig { + /** + * If enabled, On-Demand-Rendered pages are cached for up to a year. + * This is useful for pages that are not updated often, like a blog post, + * but that you have too many of to pre-render at build time. + * + * You can override this behavior on a per-page basis + * by setting the `Cache-Control`, `CDN-Cache-Control` or `Netlify-CDN-Cache-Control` header + * from within the Page: + * + * ```astro + * // src/pages/cached-clock.astro + * Astro.response.headers.set('CDN-Cache-Control', "public, max-age=45, must-revalidate"); + * --- + * <p>{Date.now()}</p> + * ``` + */ + cacheOnDemandPages?: boolean; + + /** + * If disabled, Middleware is applied to prerendered pages at build-time, and to on-demand-rendered pages at runtime. + * Only disable when your Middleware does not need to run on prerendered pages. + * If you use Middleware to implement authentication, redirects or similar things, you should should likely enabled it. + * + * If enabled, Astro Middleware is deployed as an Edge Function and applies to all routes. + * Caveat: Locals set in Middleware are not applied to prerendered pages, because they've been rendered at build-time and are served from the CDN. + * + * @default {false} + */ + edgeMiddleware?: boolean; + + /** + * If enabled, Netlify Image CDN is used for image optimization. + * This transforms images on-the-fly without impacting build times. + * + * If disabled, Astro's built-in image optimization is run at build-time instead. + * + * @default {true} + */ + imageCDN?: boolean; +} + +export default function netlifyIntegration( + integrationConfig?: NetlifyIntegrationConfig +): AstroIntegration { + const isRunningInNetlify = Boolean( + process.env.NETLIFY || process.env.NETLIFY_LOCAL || process.env.NETLIFY_DEV + ); + + let _config: AstroConfig; + let outDir: URL; + let rootDir: URL; + let astroMiddlewareEntryPoint: URL | undefined = undefined; + // Secret used to verify that the caller is the astro-generated edge middleware and not a third-party + const middlewareSecret = randomUUID(); + + let finalBuildOutput: HookParameters<'astro:config:done'>['buildOutput']; + + const TRACE_CACHE = {}; + + const ssrBuildDir = () => new URL('./.netlify/build/', rootDir); + const ssrOutputDir = () => new URL('./.netlify/v1/functions/ssr/', rootDir); + const middlewareOutputDir = () => new URL('.netlify/v1/edge-functions/middleware/', rootDir); + + const cleanFunctions = async () => + await Promise.all([ + emptyDir(middlewareOutputDir()), + emptyDir(ssrOutputDir()), + emptyDir(ssrBuildDir()), + ]); + + async function writeRedirects( + routes: IntegrationResolvedRoute[], + dir: URL, + buildOutput: HookParameters<'astro:config:done'>['buildOutput'], + assets: HookParameters<'astro:build:done'>['assets'] + ) { + // all other routes are handled by SSR + const staticRedirects = routes.filter( + (route) => route.type === 'redirect' && (route.redirect || route.redirectRoute) + ); + + // this is needed to support redirects to dynamic routes + // on static. not sure why this is needed, but it works. + for (const { pattern, redirectRoute } of staticRedirects) { + const distURL = assets.get(pattern); + if (!distURL && redirectRoute) { + const redirectDistURL = assets.get(redirectRoute.pattern); + if (redirectDistURL) { + assets.set(pattern, redirectDistURL); + } + } + } + + const fallback = finalBuildOutput === 'static' ? '/.netlify/static' : '/.netlify/functions/ssr'; + const redirects = createRedirectsFromAstroRoutes({ + config: _config, + dir, + routeToDynamicTargetMap: new Map(staticRedirects.map((route) => [route, fallback])), + buildOutput, + assets, + }); + + if (!redirects.empty()) { + await appendFile(new URL('_redirects', outDir), `\n${redirects.print()}\n`); + } + } + + async function writeSSRFunction({ + notFoundContent, + logger, + root, + }: { + notFoundContent?: string; + logger: AstroIntegrationLogger; + root: URL; + }) { + const entry = new URL('./entry.mjs', ssrBuildDir()); + + const { handler } = await copyDependenciesToFunction( + { + entry, + outDir: ssrOutputDir(), + includeFiles: [], + excludeFiles: [], + logger, + root, + }, + TRACE_CACHE + ); + + await writeFile( + new URL('./ssr.mjs', ssrOutputDir()), + ` + import createSSRHandler from './${handler}'; + export default createSSRHandler(${JSON.stringify({ + cacheOnDemandPages: Boolean(integrationConfig?.cacheOnDemandPages), + notFoundContent, + })}); + export const config = { + includedFiles: ['**/*'], + name: 'Astro SSR', + nodeBundler: 'none', + generator: '@astrojs/netlify@${packageVersion}', + path: '/*', + preferStatic: true, + }; + ` + ); + } + + async function writeMiddleware(entrypoint: URL) { + await mkdir(middlewareOutputDir(), { recursive: true }); + await writeFile( + new URL('./entry.mjs', middlewareOutputDir()), + /* ts */ ` + import { onRequest } from "${fileURLToPath(entrypoint).replaceAll('\\', '/')}"; + import { createContext, trySerializeLocals } from 'astro/middleware'; + + export default async (request, context) => { + const ctx = createContext({ + request, + params: {}, + locals: { netlify: { context } } + }); + // https://docs.netlify.com/edge-functions/api/#return-a-rewrite + ctx.rewrite = (target) => { + if(target instanceof Request) { + // We can only mutate headers, so if anything else is different, we need to fetch + // the target URL instead. + if(target.method !== request.method || target.body || target.url.origin !== request.url.origin) { + return fetch(target); + } + // We can't replace the headers object, so we need to delete all headers and set them again + request.headers.forEach((_value, key) => { + request.headers.delete(key); + }); + target.headers.forEach((value, key) => { + request.headers.set(key, value); + }); + return new URL(target.url); + } + return new URL(target, request.url); + }; + const next = () => { + const { netlify, ...otherLocals } = ctx.locals; + request.headers.set("x-astro-locals", trySerializeLocals(otherLocals)); + request.headers.set("x-astro-middleware-secret", "${middlewareSecret}"); + return context.next(); + }; + + return onRequest(ctx, next); + } + + export const config = { + name: "Astro Middleware", + generator: "@astrojs/netlify@${packageVersion}", + path: "/*", excludedPath: ["/_astro/*", "/.netlify/images/*"] + }; + ` + ); + + // taking over bundling, because Netlify bundling trips over NPM modules + await build({ + entryPoints: [fileURLToPath(new URL('./entry.mjs', middlewareOutputDir()))], + // allow `node:` prefixed imports, which are valid in netlify's deno edge runtime + plugins: [ + { + name: 'allowNodePrefixedImports', + setup(puglinBuild) { + puglinBuild.onResolve({ filter: /^node:.*$/ }, (args) => ({ + path: args.path, + external: true, + })); + }, + }, + ], + target: 'es2022', + platform: 'neutral', + mainFields: ['module', 'main'], + outfile: fileURLToPath(new URL('./middleware.mjs', middlewareOutputDir())), + allowOverwrite: true, + format: 'esm', + bundle: true, + minify: false, + external: ['sharp'], + banner: { + // Import Deno polyfill for `process.env` at the top of the file + js: 'import process from "node:process";', + }, + }); + } + + function getLocalDevNetlifyContext(req: IncomingMessage): Context { + const isHttps = req.headers['x-forwarded-proto'] === 'https'; + const parseBase64JSON = <T = unknown>(header: string): T | undefined => { + if (typeof req.headers[header] === 'string') { + try { + return JSON.parse(Buffer.from(req.headers[header] as string, 'base64').toString('utf8')); + } catch {} + } + }; + + const context: Context = { + account: parseBase64JSON('x-nf-account-info') ?? { + id: 'mock-netlify-account-id', + }, + // TODO: this has type conflicts with @netlify/functions ^2.8.1 + // @ts-expect-error: this has type conflicts with @netlify/functions ^2.8.1 + deploy: { + id: + typeof req.headers['x-nf-deploy-id'] === 'string' + ? req.headers['x-nf-deploy-id'] + : 'mock-netlify-deploy-id', + }, + site: parseBase64JSON('x-nf-site-info') ?? { + id: 'mock-netlify-site-id', + name: 'mock-netlify-site.netlify.app', + url: `${isHttps ? 'https' : 'http'}://localhost:${isRunningInNetlify ? 8888 : 4321}`, + }, + geo: parseBase64JSON('x-nf-geo') ?? { + city: 'Mock City', + country: { code: 'mock', name: 'Mock Country' }, + subdivision: { code: 'SD', name: 'Mock Subdivision' }, + timezone: 'UTC', + longitude: 0, + latitude: 0, + }, + ip: + typeof req.headers['x-nf-client-connection-ip'] === 'string' + ? req.headers['x-nf-client-connection-ip'] + : (req.socket.remoteAddress ?? '127.0.0.1'), + server: { + region: 'local-dev', + }, + requestId: + typeof req.headers['x-nf-request-id'] === 'string' + ? req.headers['x-nf-request-id'] + : 'mock-netlify-request-id', + get cookies(): never { + throw new Error('Please use Astro.cookies instead.'); + }, + // @ts-expect-error This is not currently included in the public Netlify types + flags: undefined, + json: (input) => Response.json(input), + log: console.info, + next: () => { + throw new Error('`context.next` is not implemented for serverless functions'); + }, + get params(): never { + throw new Error("context.params don't contain any usable content in Astro."); + }, + rewrite() { + throw new Error('context.rewrite is not available in Astro.'); + }, + }; + + return context; + } + + let routes: IntegrationResolvedRoute[]; + + return { + name: '@astrojs/netlify', + hooks: { + 'astro:config:setup': async ({ config, updateConfig }) => { + rootDir = config.root; + await cleanFunctions(); + + outDir = new URL('./dist/', rootDir); + + const enableImageCDN = isRunningInNetlify && (integrationConfig?.imageCDN ?? true); + + updateConfig({ + outDir, + build: { + redirects: false, + client: outDir, + server: ssrBuildDir(), + }, + vite: { + server: { + watch: { + ignored: [fileURLToPath(new URL('./.netlify/**', rootDir))], + }, + }, + }, + image: { + service: { + entrypoint: enableImageCDN ? '@astrojs/netlify/image-service.js' : undefined, + }, + }, + }); + }, + 'astro:routes:resolved': (params) => { + routes = params.routes; + }, + 'astro:config:done': async ({ config, setAdapter, logger, buildOutput }) => { + rootDir = config.root; + _config = config; + + finalBuildOutput = buildOutput; + + await writeNetlifyFrameworkConfig(config, logger); + + const edgeMiddleware = integrationConfig?.edgeMiddleware ?? false; + + setAdapter({ + name: '@astrojs/netlify', + serverEntrypoint: '@astrojs/netlify/ssr-function.js', + exports: ['default'], + adapterFeatures: { + edgeMiddleware, + }, + args: { middlewareSecret } satisfies Args, + supportedAstroFeatures: { + hybridOutput: 'stable', + staticOutput: 'stable', + serverOutput: 'stable', + sharpImageService: 'stable', + envGetSecret: 'stable', + }, + }); + }, + 'astro:build:ssr': async ({ middlewareEntryPoint }) => { + astroMiddlewareEntryPoint = middlewareEntryPoint; + }, + 'astro:build:done': async ({ assets, dir, logger }) => { + await writeRedirects(routes, dir, finalBuildOutput, assets); + logger.info('Emitted _redirects'); + + if (finalBuildOutput !== 'static') { + let notFoundContent = undefined; + try { + notFoundContent = await readFile(new URL('./404.html', dir), 'utf8'); + } catch {} + await writeSSRFunction({ notFoundContent, logger, root: _config.root }); + logger.info('Generated SSR Function'); + } + if (astroMiddlewareEntryPoint) { + await writeMiddleware(astroMiddlewareEntryPoint); + logger.info('Generated Middleware Edge Function'); + } + }, + + // local dev + 'astro:server:setup': async ({ server }) => { + server.middlewares.use((req, _res, next) => { + const locals = Symbol.for('astro.locals'); + Reflect.set(req, locals, { + ...Reflect.get(req, locals), + netlify: { context: getLocalDevNetlifyContext(req) }, + }); + next(); + }); + }, + }, + }; +} diff --git a/packages/integrations/netlify/src/lib/nft.ts b/packages/integrations/netlify/src/lib/nft.ts new file mode 100644 index 000000000..c0584fd92 --- /dev/null +++ b/packages/integrations/netlify/src/lib/nft.ts @@ -0,0 +1,83 @@ +import { posix, relative, sep } from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; +import { copyFilesToFolder } from '@astrojs/internal-helpers/fs'; +import { appendForwardSlash } from '@astrojs/internal-helpers/path'; +import type { AstroIntegrationLogger } from 'astro'; +import { searchForWorkspaceRoot } from 'vite'; + +// Based on the equivalent function in `@astrojs/vercel` +export async function copyDependenciesToFunction( + { + entry, + outDir, + includeFiles, + excludeFiles, + logger, + root, + }: { + entry: URL; + outDir: URL; + includeFiles: URL[]; + excludeFiles: URL[]; + logger: AstroIntegrationLogger; + root: URL; + }, + // we want to pass the caching by reference, and not by value + cache: object +): Promise<{ handler: string }> { + const entryPath = fileURLToPath(entry); + logger.info(`Bundling function ${relative(fileURLToPath(outDir), entryPath)}`); + + // Set the base to the workspace root + const base = pathToFileURL(appendForwardSlash(searchForWorkspaceRoot(fileURLToPath(root)))); + + // The Vite bundle includes an import to `@vercel/nft` for some reason, + // and that trips up `@vercel/nft` itself during the adapter build. Using a + // dynamic import helps prevent the issue. + // TODO: investigate why + const { nodeFileTrace } = await import('@vercel/nft'); + const result = await nodeFileTrace([entryPath], { + base: fileURLToPath(base), + cache, + }); + + for (const error of result.warnings) { + if (error.message.startsWith('Failed to resolve dependency')) { + const [, module, file] = + /Cannot find module '(.+?)' loaded from (.+)/.exec(error.message) || []; + + // The import(astroRemark) sometimes fails to resolve, but it's not a problem + if (module === '@astrojs/') continue; + + // Sharp is always external and won't be able to be resolved, but that's also not a problem + if (module === 'sharp') continue; + + if (entryPath === file) { + logger.debug( + `The module "${module}" couldn't be resolved. This may not be a problem, but it's worth checking.` + ); + } else { + logger.debug( + `The module "${module}" inside the file "${file}" couldn't be resolved. This may not be a problem, but it's worth checking.` + ); + } + } + // parse errors are likely not js and can safely be ignored, + // such as this html file in "main" meant for nw instead of node: + // https://github.com/vercel/nft/issues/311 + else if (!error.message.startsWith('Failed to parse')) { + throw error; + } + } + + const commonAncestor = await copyFilesToFolder( + [...result.fileList].map((file) => new URL(file, base)).concat(includeFiles), + outDir, + excludeFiles + ); + + return { + // serverEntry location inside the outDir, converted to posix + handler: relative(commonAncestor, entryPath).split(sep).join(posix.sep), + }; +} diff --git a/packages/integrations/netlify/src/polyfill.ts b/packages/integrations/netlify/src/polyfill.ts new file mode 100644 index 000000000..dc00f45d7 --- /dev/null +++ b/packages/integrations/netlify/src/polyfill.ts @@ -0,0 +1,3 @@ +import { applyPolyfills } from 'astro/app/node'; + +applyPolyfills(); diff --git a/packages/integrations/netlify/src/ssr-function.ts b/packages/integrations/netlify/src/ssr-function.ts new file mode 100644 index 000000000..5ea2e97f1 --- /dev/null +++ b/packages/integrations/netlify/src/ssr-function.ts @@ -0,0 +1,78 @@ +// Keep at the top +import './polyfill.js'; + +import type { Context } from '@netlify/functions'; +import type { SSRManifest } from 'astro'; +import { App } from 'astro/app'; +import { setGetEnv } from 'astro/env/setup'; + +setGetEnv((key) => process.env[key]); + +export interface Args { + middlewareSecret: string; +} + +const clientAddressSymbol = Symbol.for('astro.clientAddress'); + +export const createExports = (manifest: SSRManifest, { middlewareSecret }: Args) => { + const app = new App(manifest); + + function createHandler(integrationConfig: { + cacheOnDemandPages: boolean; + notFoundContent?: string; + }) { + return async function handler(request: Request, context: Context) { + const routeData = app.match(request); + if (!routeData && typeof integrationConfig.notFoundContent !== 'undefined') { + return new Response(integrationConfig.notFoundContent, { + status: 404, + headers: { 'Content-Type': 'text/html; charset=utf-8' }, + }); + } + + Reflect.set(request, clientAddressSymbol, context.ip); + let locals: Record<string, unknown> = {}; + + const astroLocalsHeader = request.headers.get('x-astro-locals'); + const middlewareSecretHeader = request.headers.get('x-astro-middleware-secret'); + if (astroLocalsHeader) { + if (middlewareSecretHeader !== middlewareSecret) { + return new Response('Forbidden', { status: 403 }); + } + // hide the secret from the rest of user and library code + request.headers.delete('x-astro-middleware-secret'); + locals = JSON.parse(astroLocalsHeader); + } + + locals.netlify = { context }; + + const response = await app.render(request, { routeData, locals }); + + if (app.setCookieHeaders) { + for (const setCookieHeader of app.setCookieHeaders(response)) { + response.headers.append('Set-Cookie', setCookieHeader); + } + } + + if (integrationConfig.cacheOnDemandPages) { + const isCacheableMethod = ['GET', 'HEAD'].includes(request.method); + + // any user-provided Cache-Control headers take precedence + const hasCacheControl = [ + 'Cache-Control', + 'CDN-Cache-Control', + 'Netlify-CDN-Cache-Control', + ].some((header) => response.headers.has(header)); + + if (isCacheableMethod && !hasCacheControl) { + // caches this page for up to a year + response.headers.append('CDN-Cache-Control', 'public, max-age=31536000, must-revalidate'); + } + } + + return response; + }; + } + + return { default: createHandler }; +}; diff --git a/packages/integrations/netlify/src/static.ts b/packages/integrations/netlify/src/static.ts new file mode 100644 index 000000000..1c809ef8f --- /dev/null +++ b/packages/integrations/netlify/src/static.ts @@ -0,0 +1,8 @@ +import netlifyIntegration from './index.js'; + +export default function staticIntegration() { + console.warn( + 'The @astrojs/netlify/static import is deprecated and will be removed in a future release. Please use @astrojs/netlify instead.' + ); + return netlifyIntegration(); +} diff --git a/packages/integrations/netlify/test/functions/cookies.test.js b/packages/integrations/netlify/test/functions/cookies.test.js new file mode 100644 index 000000000..9d2565d91 --- /dev/null +++ b/packages/integrations/netlify/test/functions/cookies.test.js @@ -0,0 +1,53 @@ +import * as assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture } from '../../../../astro/test/test-utils.js'; + +describe( + 'Cookies', + () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ root: new URL('./fixtures/cookies/', import.meta.url) }); + await fixture.build(); + }); + + it('Can set multiple', async () => { + const entryURL = new URL( + './fixtures/cookies/.netlify/v1/functions/ssr/ssr.mjs', + import.meta.url + ); + const { default: handler } = await import(entryURL); + const resp = await handler( + new Request('http://example.com/login', { method: 'POST', body: '{}' }), + {} + ); + assert.equal(resp.status, 301); + assert.equal(resp.headers.get('location'), '/'); + assert.deepEqual(resp.headers.getSetCookie(), ['foo=foo; HttpOnly', 'bar=bar; HttpOnly']); + }); + + it('renders dynamic 404 page', async () => { + const entryURL = new URL( + './fixtures/cookies/.netlify/v1/functions/ssr/ssr.mjs', + import.meta.url + ); + const { default: handler } = await import(entryURL); + const resp = await handler( + new Request('http://example.com/nonexistant-page', { + headers: { + 'x-test': 'bar', + }, + }), + {} + ); + assert.equal(resp.status, 404); + const text = await resp.text(); + assert.equal(text.includes('This is my custom 404 page'), true); + assert.equal(text.includes('x-test: bar'), true); + }); + }, + { + timeout: 120000, + } +); diff --git a/packages/integrations/netlify/test/functions/edge-middleware.test.js b/packages/integrations/netlify/test/functions/edge-middleware.test.js new file mode 100644 index 000000000..683ec3b01 --- /dev/null +++ b/packages/integrations/netlify/test/functions/edge-middleware.test.js @@ -0,0 +1,66 @@ +import * as assert from 'node:assert/strict'; +import { after, before, describe, it } from 'node:test'; +import { loadFixture } from '../../../../astro/test/test-utils.js'; + +describe( + 'Middleware', + () => { + const root = new URL('./fixtures/middleware/', import.meta.url); + + describe('edgeMiddleware: false', () => { + let fixture; + before(async () => { + process.env.EDGE_MIDDLEWARE = 'false'; + fixture = await loadFixture({ root }); + await fixture.build(); + }); + + it('emits no edge function', async () => { + assert.equal( + fixture.pathExists('../.netlify/v1/edge-functions/middleware/middleware.mjs'), + false + ); + }); + + it('applies middleware to static files at build-time', async () => { + // prerendered page has middleware applied at build time + const prerenderedPage = await fixture.readFile('prerender/index.html'); + assert.equal(prerenderedPage.includes('<title>Middleware</title>'), true); + }); + + after(async () => { + process.env.EDGE_MIDDLEWARE = undefined; + await fixture.clean(); + }); + }); + + describe('edgeMiddleware: true', () => { + let fixture; + before(async () => { + process.env.EDGE_MIDDLEWARE = 'true'; + fixture = await loadFixture({ root }); + await fixture.build(); + }); + + it('emits an edge function', async () => { + const contents = await fixture.readFile( + '../.netlify/v1/edge-functions/middleware/middleware.mjs' + ); + assert.equal(contents.includes('"Hello world"'), false); + }); + + it.skip('does not apply middleware during prerendering', async () => { + const prerenderedPage = await fixture.readFile('prerender/index.html'); + assert.equal(prerenderedPage.includes('<title></title>'), true); + }); + + after(async () => { + process.env.EDGE_MIDDLEWARE = undefined; + await fixture.clean(); + }); + }); + }, + { + timeout: 120000, + } +); diff --git a/packages/integrations/netlify/test/functions/fixtures/.gitignore b/packages/integrations/netlify/test/functions/fixtures/.gitignore new file mode 100644 index 000000000..916f60644 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/.gitignore @@ -0,0 +1 @@ +**/netlify diff --git a/packages/integrations/netlify/test/functions/fixtures/cookies/.astro/types.d.ts b/packages/integrations/netlify/test/functions/fixtures/cookies/.astro/types.d.ts new file mode 100644 index 000000000..03d7cc43f --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/cookies/.astro/types.d.ts @@ -0,0 +1,2 @@ +/// <reference types="astro/client" /> +/// <reference path="content.d.ts" />
\ No newline at end of file diff --git a/packages/integrations/netlify/test/functions/fixtures/cookies/astro.config.mjs b/packages/integrations/netlify/test/functions/fixtures/cookies/astro.config.mjs new file mode 100644 index 000000000..033024c1a --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/cookies/astro.config.mjs @@ -0,0 +1,11 @@ +import netlify from '@astrojs/netlify'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + output: 'server', + adapter: netlify(), + site: `http://example.com`, + security: { + checkOrigin: false + } +});
\ No newline at end of file diff --git a/packages/integrations/netlify/test/functions/fixtures/cookies/package.json b/packages/integrations/netlify/test/functions/fixtures/cookies/package.json new file mode 100644 index 000000000..14257a558 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/cookies/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/netlify-cookies", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/netlify": "workspace:" + } +} diff --git a/packages/integrations/netlify/test/functions/fixtures/cookies/src/env.d.ts b/packages/integrations/netlify/test/functions/fixtures/cookies/src/env.d.ts new file mode 100644 index 000000000..9bc5cb41c --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/cookies/src/env.d.ts @@ -0,0 +1 @@ +/// <reference path="../.astro/types.d.ts" />
\ No newline at end of file diff --git a/packages/integrations/netlify/test/functions/fixtures/cookies/src/pages/404.astro b/packages/integrations/netlify/test/functions/fixtures/cookies/src/pages/404.astro new file mode 100644 index 000000000..9049fa0fb --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/cookies/src/pages/404.astro @@ -0,0 +1,7 @@ +--- +export const prerender = false +const header = Astro.request.headers.get("x-test") +--- + +<p>This is my custom 404 page</p> +<p>x-test: {header}</p>
\ No newline at end of file diff --git a/packages/integrations/netlify/test/functions/fixtures/cookies/src/pages/index.astro b/packages/integrations/netlify/test/functions/fixtures/cookies/src/pages/index.astro new file mode 100644 index 000000000..53e029f04 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/cookies/src/pages/index.astro @@ -0,0 +1,6 @@ +<html> +<head><title>Testing</title></head> +<body> + <h1>Testing</h1> +</body> +</html> diff --git a/packages/integrations/netlify/test/functions/fixtures/cookies/src/pages/login.js b/packages/integrations/netlify/test/functions/fixtures/cookies/src/pages/login.js new file mode 100644 index 000000000..3f1fe17b5 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/cookies/src/pages/login.js @@ -0,0 +1,12 @@ + +export function POST() { + const headers = new Headers(); + headers.append('Set-Cookie', `foo=foo; HttpOnly`); + headers.append('Set-Cookie', `bar=bar; HttpOnly`); + headers.append('Location', '/'); + + return new Response('', { + status: 301, + headers, + }); +} diff --git a/packages/integrations/netlify/test/functions/fixtures/middleware/.astro/types.d.ts b/packages/integrations/netlify/test/functions/fixtures/middleware/.astro/types.d.ts new file mode 100644 index 000000000..03d7cc43f --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/middleware/.astro/types.d.ts @@ -0,0 +1,2 @@ +/// <reference types="astro/client" /> +/// <reference path="content.d.ts" />
\ No newline at end of file diff --git a/packages/integrations/netlify/test/functions/fixtures/middleware/astro.config.mjs b/packages/integrations/netlify/test/functions/fixtures/middleware/astro.config.mjs new file mode 100644 index 000000000..0da6bf580 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/middleware/astro.config.mjs @@ -0,0 +1,19 @@ +import netlify from '@astrojs/netlify'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + output: 'server', + adapter: netlify({ + edgeMiddleware: process.env.EDGE_MIDDLEWARE === 'true', + imageCDN: process.env.DISABLE_IMAGE_CDN ? false : undefined, + }), + image: { + remotePatterns: [{ + protocol: 'https', + hostname: '*.example.org', + pathname: '/images/*', + }], + domains: ['example.net', 'secret.example.edu'], + }, + site: `http://example.com`, +});
\ No newline at end of file diff --git a/packages/integrations/netlify/test/functions/fixtures/middleware/package.json b/packages/integrations/netlify/test/functions/fixtures/middleware/package.json new file mode 100644 index 000000000..ddc811223 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/middleware/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/netlify-middleware-without-handler-file", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/netlify": "workspace:", + "sharp": "^0.33.5" + } +} diff --git a/packages/integrations/netlify/test/functions/fixtures/middleware/src/astronaut.jpg b/packages/integrations/netlify/test/functions/fixtures/middleware/src/astronaut.jpg Binary files differnew file mode 100644 index 000000000..d3326bcc7 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/middleware/src/astronaut.jpg diff --git a/packages/integrations/netlify/test/functions/fixtures/middleware/src/env.d.ts b/packages/integrations/netlify/test/functions/fixtures/middleware/src/env.d.ts new file mode 100644 index 000000000..9bc5cb41c --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/middleware/src/env.d.ts @@ -0,0 +1 @@ +/// <reference path="../.astro/types.d.ts" />
\ No newline at end of file diff --git a/packages/integrations/netlify/test/functions/fixtures/middleware/src/middleware.ts b/packages/integrations/netlify/test/functions/fixtures/middleware/src/middleware.ts new file mode 100644 index 000000000..9790b8755 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/middleware/src/middleware.ts @@ -0,0 +1,8 @@ +import https from 'node:https'; + +export const onRequest = (context, next) => { + context.locals.title = 'Middleware'; + context.locals.nodePrefixedImportExists = !!https; + + return next(); +}; diff --git a/packages/integrations/netlify/test/functions/fixtures/middleware/src/pages/astronaut.astro b/packages/integrations/netlify/test/functions/fixtures/middleware/src/pages/astronaut.astro new file mode 100644 index 000000000..b3da724c3 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/middleware/src/pages/astronaut.astro @@ -0,0 +1,9 @@ +--- +import { Image } from 'astro:assets'; +import astronautImage from "../astronaut.jpg" + +export const prerender = true; +--- + +<Image src={astronautImage} alt="an astronaut floating in space" /> + diff --git a/packages/integrations/netlify/test/functions/fixtures/middleware/src/pages/index.astro b/packages/integrations/netlify/test/functions/fixtures/middleware/src/pages/index.astro new file mode 100644 index 000000000..d97f70698 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/middleware/src/pages/index.astro @@ -0,0 +1,12 @@ +--- +const title = Astro.locals.title; +--- + +<html> +<head> + <title>{title}</title> +</head> +<body> +<h1>{title}</h1> +</body> +</html> diff --git a/packages/integrations/netlify/test/functions/fixtures/middleware/src/pages/prerender.astro b/packages/integrations/netlify/test/functions/fixtures/middleware/src/pages/prerender.astro new file mode 100644 index 000000000..f0314c053 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/middleware/src/pages/prerender.astro @@ -0,0 +1,13 @@ +--- +export const prerender = true; +const title = Astro.locals.title; +--- + +<html> +<head> + <title>{title}</title> +</head> +<body> +<h1>{title}</h1> +</body> +</html> diff --git a/packages/integrations/netlify/test/functions/fixtures/redirects/.astro/types.d.ts b/packages/integrations/netlify/test/functions/fixtures/redirects/.astro/types.d.ts new file mode 100644 index 000000000..03d7cc43f --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/redirects/.astro/types.d.ts @@ -0,0 +1,2 @@ +/// <reference types="astro/client" /> +/// <reference path="content.d.ts" />
\ No newline at end of file diff --git a/packages/integrations/netlify/test/functions/fixtures/redirects/astro.config.mjs b/packages/integrations/netlify/test/functions/fixtures/redirects/astro.config.mjs new file mode 100644 index 000000000..55613bd91 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/redirects/astro.config.mjs @@ -0,0 +1,11 @@ +import netlify from '@astrojs/netlify'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + output: 'static', + adapter: netlify(), + site: `http://example.com`, + redirects: { + '/other': '/', + }, +}); diff --git a/packages/integrations/netlify/test/functions/fixtures/redirects/package.json b/packages/integrations/netlify/test/functions/fixtures/redirects/package.json new file mode 100644 index 000000000..9970a81de --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/redirects/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/netlify-redirects", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/netlify": "workspace:" + } +} diff --git a/packages/integrations/netlify/test/functions/fixtures/redirects/src/env.d.ts b/packages/integrations/netlify/test/functions/fixtures/redirects/src/env.d.ts new file mode 100644 index 000000000..9bc5cb41c --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/redirects/src/env.d.ts @@ -0,0 +1 @@ +/// <reference path="../.astro/types.d.ts" />
\ No newline at end of file diff --git a/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/404.astro b/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/404.astro new file mode 100644 index 000000000..b9e3eda13 --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/404.astro @@ -0,0 +1,5 @@ +--- +export const prerender = true +--- + +<p>This is my static 404 page</p>
\ No newline at end of file diff --git a/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/index.astro b/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/index.astro new file mode 100644 index 000000000..41f740c4c --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/index.astro @@ -0,0 +1,9 @@ +--- +export const prerender = false; +--- +<html> +<head><title>Testing</title></head> +<body> + <h1>Testing</h1> +</body> +</html> diff --git a/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/nope.astro b/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/nope.astro new file mode 100644 index 000000000..f48d767ee --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/nope.astro @@ -0,0 +1,3 @@ +--- +return Astro.redirect('/'); +--- diff --git a/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/team/articles/[...slug].astro b/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/team/articles/[...slug].astro new file mode 100644 index 000000000..996cd989e --- /dev/null +++ b/packages/integrations/netlify/test/functions/fixtures/redirects/src/pages/team/articles/[...slug].astro @@ -0,0 +1,27 @@ +--- +export const prerender = false; + +export const getStaticPaths = (async () => { + const posts = [ + { slug: 'one', data: {draft: false, title: 'One'} }, + { slug: 'two', data: {draft: false, title: 'Two'} } + ]; + return posts.map((post) => { + return { + params: { slug: post.slug }, + props: { draft: post.data.draft, title: post.data.title }, + }; + }); +}) + +const { slug } = Astro.params; +const { title } = Astro.props; +--- +<html> + <head> + <title>{ title }</title> + </head> + <body> + <h1>{ title }</h1> + </body> +</html> diff --git a/packages/integrations/netlify/test/functions/image-cdn.test.js b/packages/integrations/netlify/test/functions/image-cdn.test.js new file mode 100644 index 000000000..45b41e4de --- /dev/null +++ b/packages/integrations/netlify/test/functions/image-cdn.test.js @@ -0,0 +1,139 @@ +import * as assert from 'node:assert/strict'; +import { after, before, describe, it } from 'node:test'; +import { remotePatternToRegex } from '@astrojs/netlify'; +import { loadFixture } from '../../../../astro/test/test-utils.js'; + +describe( + 'Image CDN', + () => { + const root = new URL('./fixtures/middleware/', import.meta.url); + + describe('when running outside of netlify', () => { + it('does not enable Image CDN', async () => { + const fixture = await loadFixture({ root }); + await fixture.build(); + + const astronautPage = await fixture.readFile('astronaut/index.html'); + assert.equal(astronautPage.includes(`src="/_astro/astronaut.`), true); + }); + }); + + describe('when running inside of netlify', () => { + after(() => { + process.env.NETLIFY = undefined; + process.env.DISABLE_IMAGE_CDN = undefined; + }); + + it('enables Netlify Image CDN', async () => { + process.env.NETLIFY = 'true'; + const fixture = await loadFixture({ root }); + await fixture.build(); + + const astronautPage = await fixture.readFile('astronaut/index.html'); + assert.equal(astronautPage.includes(`src="/.netlify/image`), true); + }); + + it('respects image CDN opt-out', async () => { + process.env.NETLIFY = 'true'; + process.env.DISABLE_IMAGE_CDN = 'true'; + const fixture = await loadFixture({ root }); + await fixture.build(); + + const astronautPage = await fixture.readFile('astronaut/index.html'); + assert.equal(astronautPage.includes(`src="/_astro/astronaut.`), true); + }); + }); + + describe('remote image config', () => { + let regexes; + + before(async () => { + const fixture = await loadFixture({ root }); + await fixture.build(); + + const config = await fixture.readFile('../.netlify/v1/config.json'); + if (config) { + regexes = JSON.parse(config).images.remote_images.map((pattern) => new RegExp(pattern)); + } + }); + + it('generates remote image config patterns', async () => { + assert.equal(regexes?.length, 3); + }); + + it('generates correct config for domains', async () => { + const domain = regexes[0]; + assert.equal(domain.test('https://example.net/image.jpg'), true); + assert.equal( + domain.test('https://www.example.net/image.jpg'), + false, + 'subdomain should not match' + ); + assert.equal(domain.test('http://example.net/image.jpg'), true, 'http should match'); + assert.equal( + domain.test('https://example.net/subdomain/image.jpg'), + true, + 'subpath should match' + ); + const subdomain = regexes[1]; + assert.equal( + subdomain.test('https://secret.example.edu/image.jpg'), + true, + 'should match subdomains' + ); + assert.equal( + subdomain.test('https://secretxexample.edu/image.jpg'), + false, + 'should not use dots in domains as wildcards' + ); + }); + + it('generates correct config for remotePatterns', async () => { + const patterns = regexes[2]; + assert.equal( + patterns.test('https://example.org/images/1.jpg'), + true, + 'should match domain' + ); + assert.equal( + patterns.test('https://www.example.org/images/2.jpg'), + true, + 'www subdomain should match' + ); + assert.equal( + patterns.test('https://www.subdomain.example.org/images/2.jpg'), + false, + 'second level subdomain should not match' + ); + assert.equal( + patterns.test('https://example.org/not-images/2.jpg'), + false, + 'wrong path should not match' + ); + }); + + it('warns when remotepatterns generates an invalid regex', async (t) => { + const logger = { + warn: t.mock.fn(), + }; + const regex = remotePatternToRegex( + { + hostname: '*.examp[le.org', + pathname: '/images/*', + }, + logger + ); + assert.strictEqual(regex, undefined); + const calls = logger.warn.mock.calls; + assert.strictEqual(calls.length, 1); + assert.equal( + calls[0].arguments[0], + 'Could not generate a valid regex from the remotePattern "{"hostname":"*.examp[le.org","pathname":"/images/*"}". Please check the syntax.' + ); + }); + }); + }, + { + timeout: 120000, + } +); diff --git a/packages/integrations/netlify/test/functions/redirects.test.js b/packages/integrations/netlify/test/functions/redirects.test.js new file mode 100644 index 000000000..ac77056c4 --- /dev/null +++ b/packages/integrations/netlify/test/functions/redirects.test.js @@ -0,0 +1,69 @@ +import * as assert from 'node:assert/strict'; +import { createServer } from 'node:http'; +import { before, describe, it } from 'node:test'; +import { loadFixture } from '../../../../astro/test/test-utils.js'; + +describe( + 'SSR - Redirects', + () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ root: new URL('./fixtures/redirects/', import.meta.url) }); + await fixture.build(); + }); + + it('Creates a redirects file', async () => { + const redirects = await fixture.readFile('./_redirects'); + const parts = redirects.split(/\s+/); + assert.deepEqual(parts, ['', '/other', '/', '301', '']); + // Snapshots are not supported in Node.js test yet (https://github.com/nodejs/node/issues/48260) + assert.equal(redirects, '\n/other / 301\n'); + }); + + it('Does not create .html files', async () => { + let hasErrored = false; + try { + await fixture.readFile('/other/index.html'); + } catch { + hasErrored = true; + } + assert.equal(hasErrored, true, 'this file should not exist'); + }); + + it('renders static 404 page', async () => { + const entryURL = new URL( + './fixtures/redirects/.netlify/v1/functions/ssr/ssr.mjs', + import.meta.url + ); + const { default: handler } = await import(entryURL); + const resp = await handler(new Request('http://example.com/nonexistant-page'), {}); + assert.equal(resp.status, 404); + assert.equal(resp.headers.get('content-type'), 'text/html; charset=utf-8'); + const text = await resp.text(); + assert.equal(text.includes('This is my static 404 page'), true); + }); + + it('does not pass through 404 request', async () => { + let testServerCalls = 0; + const testServer = createServer((req, res) => { + testServerCalls++; + res.writeHead(200); + res.end(); + }); + testServer.listen(5678); + const entryURL = new URL( + './fixtures/redirects/.netlify/v1/functions/ssr/ssr.mjs', + import.meta.url + ); + const { default: handler } = await import(entryURL); + const resp = await handler(new Request('http://localhost:5678/nonexistant-page'), {}); + assert.equal(resp.status, 404); + assert.equal(testServerCalls, 0); + testServer.close(); + }); + }, + { + timeout: 120000, + } +); diff --git a/packages/integrations/netlify/test/hosted/README.md b/packages/integrations/netlify/test/hosted/README.md new file mode 100644 index 000000000..8c1814844 --- /dev/null +++ b/packages/integrations/netlify/test/hosted/README.md @@ -0,0 +1,3 @@ +The tests in this folder are done directly on a deployed Netlify website (hosted at https://curious-boba-495d6d.netlify.app) and are not run by the test suite. They instead run every week through a GitHub action. + +The purpose of those tests is to make sure that everything works as expected while deployed. In a way, they're as E2E as it gets. diff --git a/packages/integrations/netlify/test/hosted/hosted-astro-project/astro.config.mjs b/packages/integrations/netlify/test/hosted/hosted-astro-project/astro.config.mjs new file mode 100644 index 000000000..94cc00f7b --- /dev/null +++ b/packages/integrations/netlify/test/hosted/hosted-astro-project/astro.config.mjs @@ -0,0 +1,19 @@ +import netlify from '@astrojs/netlify'; +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig({ + output: 'server', + adapter: netlify({ + edgeMiddleware: true, + }), + image: { + remotePatterns: [ + { + protocol: 'https', + hostname: 'images.unsplash.com', + pathname: '/photo-1567674867291-b2595ac53ab4', + }, + ], + }, +}); diff --git a/packages/integrations/netlify/test/hosted/hosted-astro-project/netlify.toml b/packages/integrations/netlify/test/hosted/hosted-astro-project/netlify.toml new file mode 100644 index 000000000..55c8404ee --- /dev/null +++ b/packages/integrations/netlify/test/hosted/hosted-astro-project/netlify.toml @@ -0,0 +1,3 @@ +[build] +command = "pnpm run --filter @test/netlify-hosted-astro-project... build" +publish = "/packages/netlify/test/hosted/hosted-astro-project/dist" diff --git a/packages/integrations/netlify/test/hosted/hosted-astro-project/package.json b/packages/integrations/netlify/test/hosted/hosted-astro-project/package.json new file mode 100644 index 000000000..69914a8db --- /dev/null +++ b/packages/integrations/netlify/test/hosted/hosted-astro-project/package.json @@ -0,0 +1,12 @@ +{ + "name": "@test/netlify-hosted-astro-project", + "version": "0.0.0", + "private": true, + "scripts": { + "build": "astro build" + }, + "dependencies": { + "@astrojs/netlify": "workspace:*", + "astro": "^5.1.6" + } +} diff --git a/packages/integrations/netlify/test/hosted/hosted-astro-project/src/assets/penguin.png b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/assets/penguin.png Binary files differnew file mode 100644 index 000000000..218acde5b --- /dev/null +++ b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/assets/penguin.png diff --git a/packages/integrations/netlify/test/hosted/hosted-astro-project/src/env.d.ts b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/env.d.ts new file mode 100644 index 000000000..f7cbe9c1d --- /dev/null +++ b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/env.d.ts @@ -0,0 +1 @@ +/// <reference types="astro/client-image" /> diff --git a/packages/integrations/netlify/test/hosted/hosted-astro-project/src/middleware.ts b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/middleware.ts new file mode 100644 index 000000000..1112a3566 --- /dev/null +++ b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/middleware.ts @@ -0,0 +1,11 @@ +import https from 'node:https'; + +export const onRequest = (context, next) => { + console.info(context.netlify); + context.locals.middleware = context?.locals?.netlify?.context?.geo?.country?.code ?? null; + context.locals.runtime = 'Deno' in globalThis ? 'Deno' : 'Node'; + context.locals.title = 'Middleware'; + context.locals.nodePrefixedImportExists = !!https; + + return next(); +}; diff --git a/packages/integrations/netlify/test/hosted/hosted-astro-project/src/pages/country.astro b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/pages/country.astro new file mode 100644 index 000000000..cad7116d6 --- /dev/null +++ b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/pages/country.astro @@ -0,0 +1,7 @@ +--- +const country = Astro.locals.middleware; +--- + +<h1>{country}</h1> +<h3>{country ? 'has context' : 'no context'}</h3> +<h2>{Astro.locals.runtime}</h2> diff --git a/packages/integrations/netlify/test/hosted/hosted-astro-project/src/pages/index.astro b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/pages/index.astro new file mode 100644 index 000000000..7d2cfcdc3 --- /dev/null +++ b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/pages/index.astro @@ -0,0 +1,13 @@ +--- +import { Image } from 'astro:assets'; +import penguin from '../assets/penguin.png'; +--- + +<Image src={penguin} width={300} alt="" /> + +<Image + src="https://images.unsplash.com/photo-1567674867291-b2595ac53ab4" + width={300} + height={400} + alt="Astro" +/> diff --git a/packages/integrations/netlify/test/hosted/hosted-astro-project/src/pages/time.astro b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/pages/time.astro new file mode 100644 index 000000000..873b5c720 --- /dev/null +++ b/packages/integrations/netlify/test/hosted/hosted-astro-project/src/pages/time.astro @@ -0,0 +1,5 @@ +--- +const currentTime = new Date().getTime(); +--- + +{currentTime} diff --git a/packages/integrations/netlify/test/hosted/hosted.test.js b/packages/integrations/netlify/test/hosted/hosted.test.js new file mode 100644 index 000000000..b8562ce82 --- /dev/null +++ b/packages/integrations/netlify/test/hosted/hosted.test.js @@ -0,0 +1,29 @@ +import * as assert from 'node:assert/strict'; +import { describe, it } from 'node:test'; + +const NETLIFY_TEST_URL = 'https://curious-boba-495d6d.netlify.app'; + +describe('Hosted Netlify Tests', () => { + it('Image endpoint works', async () => { + const image = await fetch( + `${NETLIFY_TEST_URL}/_image?href=%2F_astro%2Fpenguin.e9c64733.png&w=300&f=webp` + ); + + assert.equal(image.status, 200); + }); + + it('passes context from edge middleware', async () => { + const response = await fetch(`${NETLIFY_TEST_URL}/country`); + const body = await response.text(); + assert.match(body, /has context/); + assert.match(body, /Deno/); + }); + + it('Server returns fresh content', async () => { + const responseOne = await fetch(`${NETLIFY_TEST_URL}/time`).then((res) => res.text()); + + const responseTwo = await fetch(`${NETLIFY_TEST_URL}/time`).then((res) => res.text()); + + assert.notEqual(responseOne.body, responseTwo.body); + }); +}); diff --git a/packages/integrations/netlify/test/static/fixtures/redirects/.astro/types.d.ts b/packages/integrations/netlify/test/static/fixtures/redirects/.astro/types.d.ts new file mode 100644 index 000000000..03d7cc43f --- /dev/null +++ b/packages/integrations/netlify/test/static/fixtures/redirects/.astro/types.d.ts @@ -0,0 +1,2 @@ +/// <reference types="astro/client" /> +/// <reference path="content.d.ts" />
\ No newline at end of file diff --git a/packages/integrations/netlify/test/static/fixtures/redirects/astro.config.mjs b/packages/integrations/netlify/test/static/fixtures/redirects/astro.config.mjs new file mode 100644 index 000000000..ce441d8b1 --- /dev/null +++ b/packages/integrations/netlify/test/static/fixtures/redirects/astro.config.mjs @@ -0,0 +1,16 @@ +import netlify from '@astrojs/netlify'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + output: 'static', + adapter: netlify(), + site: "http://example.com", + redirects: { + '/other': '/', + '/two': { + status: 302, + destination: '/', + }, + '/blog/[...slug]': '/team/articles/[...slug]', + }, +}); diff --git a/packages/integrations/netlify/test/static/fixtures/redirects/package.json b/packages/integrations/netlify/test/static/fixtures/redirects/package.json new file mode 100644 index 000000000..3e543bf35 --- /dev/null +++ b/packages/integrations/netlify/test/static/fixtures/redirects/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/netlify-static-redirects", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/netlify": "workspace:" + } +} diff --git a/packages/integrations/netlify/test/static/fixtures/redirects/src/env.d.ts b/packages/integrations/netlify/test/static/fixtures/redirects/src/env.d.ts new file mode 100644 index 000000000..9bc5cb41c --- /dev/null +++ b/packages/integrations/netlify/test/static/fixtures/redirects/src/env.d.ts @@ -0,0 +1 @@ +/// <reference path="../.astro/types.d.ts" />
\ No newline at end of file diff --git a/packages/integrations/netlify/test/static/fixtures/redirects/src/pages/index.astro b/packages/integrations/netlify/test/static/fixtures/redirects/src/pages/index.astro new file mode 100644 index 000000000..53e029f04 --- /dev/null +++ b/packages/integrations/netlify/test/static/fixtures/redirects/src/pages/index.astro @@ -0,0 +1,6 @@ +<html> +<head><title>Testing</title></head> +<body> + <h1>Testing</h1> +</body> +</html> diff --git a/packages/integrations/netlify/test/static/fixtures/redirects/src/pages/nope.astro b/packages/integrations/netlify/test/static/fixtures/redirects/src/pages/nope.astro new file mode 100644 index 000000000..f48d767ee --- /dev/null +++ b/packages/integrations/netlify/test/static/fixtures/redirects/src/pages/nope.astro @@ -0,0 +1,3 @@ +--- +return Astro.redirect('/'); +--- diff --git a/packages/integrations/netlify/test/static/fixtures/redirects/src/pages/team/articles/[...slug].astro b/packages/integrations/netlify/test/static/fixtures/redirects/src/pages/team/articles/[...slug].astro new file mode 100644 index 000000000..716d3bd5d --- /dev/null +++ b/packages/integrations/netlify/test/static/fixtures/redirects/src/pages/team/articles/[...slug].astro @@ -0,0 +1,25 @@ +--- +export const getStaticPaths = (async () => { + const posts = [ + { slug: 'one', data: {draft: false, title: 'One'} }, + { slug: 'two', data: {draft: false, title: 'Two'} } + ]; + return posts.map((post) => { + return { + params: { slug: post.slug }, + props: { draft: post.data.draft, title: post.data.title }, + }; + }); +}) + +const { slug } = Astro.params; +const { title } = Astro.props; +--- +<html> + <head> + <title>{ title }</title> + </head> + <body> + <h1>{ title }</h1> + </body> +</html> diff --git a/packages/integrations/netlify/test/static/headers.test.js b/packages/integrations/netlify/test/static/headers.test.js new file mode 100644 index 000000000..5c1400098 --- /dev/null +++ b/packages/integrations/netlify/test/static/headers.test.js @@ -0,0 +1,25 @@ +import * as assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture } from '../../../../astro/test/test-utils.js'; + +describe('SSG - headers', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ root: new URL('./fixtures/redirects/', import.meta.url) }); + await fixture.build(); + }); + + it('Generates headers for static assets', async () => { + const config = await fixture.readFile('../.netlify/v1/config.json'); + const headers = JSON.parse(config).headers; + assert.deepEqual(headers, [ + { + for: '/_astro/*', + values: { + 'Cache-Control': 'public, max-age=31536000, immutable', + }, + }, + ]); + }); +}); diff --git a/packages/integrations/netlify/test/static/redirects.test.js b/packages/integrations/netlify/test/static/redirects.test.js new file mode 100644 index 000000000..cab954831 --- /dev/null +++ b/packages/integrations/netlify/test/static/redirects.test.js @@ -0,0 +1,34 @@ +import * as assert from 'node:assert/strict'; +import { before, describe, it } from 'node:test'; +import { loadFixture } from '../../../../astro/test/test-utils.js'; + +describe('SSG - Redirects', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ root: new URL('./fixtures/redirects/', import.meta.url) }); + await fixture.build(); + }); + + it('Creates a redirects file', async () => { + const redirects = await fixture.readFile('./_redirects'); + const parts = redirects.split(/\s+/); + assert.deepEqual(parts, [ + '', + + '/two', + '/', + '302', + + '/other', + '/', + '301', + + '/blog/*', + '/team/articles/*/index.html', + '301', + + '', + ]); + }); +}); diff --git a/packages/integrations/netlify/test/test-utils.js b/packages/integrations/netlify/test/test-utils.js new file mode 100644 index 000000000..7c012e86a --- /dev/null +++ b/packages/integrations/netlify/test/test-utils.js @@ -0,0 +1,12 @@ +import { execa } from 'execa'; + +/** Returns a process running the Astro CLI. */ +export function cli(/** @type {string[]} */ ...args) { + const spawned = execa('npx', ['astro', ...args], { + env: { ASTRO_TELEMETRY_DISABLED: true }, + }); + + spawned.stdout.setEncoding('utf8'); + + return spawned; +} diff --git a/packages/integrations/netlify/tsconfig.json b/packages/integrations/netlify/tsconfig.json new file mode 100644 index 000000000..1504b4b6d --- /dev/null +++ b/packages/integrations/netlify/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../../tsconfig.base.json", + "include": ["src"], + "compilerOptions": { + "outDir": "./dist" + } +} diff --git a/packages/integrations/node/test/node-middleware.test.js b/packages/integrations/node/test/node-middleware.test.js index 8bc0b2777..57d3ba434 100644 --- a/packages/integrations/node/test/node-middleware.test.js +++ b/packages/integrations/node/test/node-middleware.test.js @@ -31,7 +31,7 @@ describe('behavior from middleware, standalone', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -72,7 +72,7 @@ describe('behavior from middleware, middleware', () => { after(async () => { server.close(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); diff --git a/packages/integrations/node/test/prerender.test.js b/packages/integrations/node/test/prerender.test.js index 71137b76a..4912f2290 100644 --- a/packages/integrations/node/test/prerender.test.js +++ b/packages/integrations/node/test/prerender.test.js @@ -34,7 +34,7 @@ describe('Prerendering', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -106,7 +106,7 @@ describe('Prerendering', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -179,7 +179,7 @@ describe('Prerendering', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -220,7 +220,7 @@ describe('Prerendering', () => { after(async () => { await devServer.stop(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -271,7 +271,7 @@ describe('Hybrid rendering', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -341,7 +341,7 @@ describe('Hybrid rendering', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -403,7 +403,7 @@ describe('Hybrid rendering', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); diff --git a/packages/integrations/node/test/test-utils.js b/packages/integrations/node/test/test-utils.js index 4f273756c..53b1a690c 100644 --- a/packages/integrations/node/test/test-utils.js +++ b/packages/integrations/node/test/test-utils.js @@ -45,7 +45,6 @@ export function toPromise(res) { const write = res.write; res.write = function (data, encoding) { if (ArrayBuffer.isView(data) && !Buffer.isBuffer(data)) { - // biome-ignore lint/style/noParameterAssign: <explanation> data = Buffer.from(data.buffer); } return write.call(this, data, encoding); diff --git a/packages/integrations/node/test/trailing-slash.test.js b/packages/integrations/node/test/trailing-slash.test.js index 2a73efa75..b1ef3c970 100644 --- a/packages/integrations/node/test/trailing-slash.test.js +++ b/packages/integrations/node/test/trailing-slash.test.js @@ -36,7 +36,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -104,7 +104,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -175,7 +175,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -236,7 +236,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -300,7 +300,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); @@ -379,7 +379,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); - // biome-ignore lint/performance/noDelete: <explanation> + delete process.env.PRERENDER; }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86eda9d02..6deb6c7a2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4995,7 +4995,93 @@ importers: specifier: workspace:* version: link:../../../../../astro - packages/integrations/netlify: {} + packages/integrations/netlify: + dependencies: + '@astrojs/internal-helpers': + specifier: 0.5.1 + version: link:../../internal-helpers + '@astrojs/underscore-redirects': + specifier: ^0.6.0 + version: link:../../underscore-redirects + '@netlify/functions': + specifier: ^2.8.0 + version: 2.8.2 + '@vercel/nft': + specifier: ^0.29.0 + version: 0.29.1(rollup@4.34.2) + esbuild: + specifier: ^0.24.0 + version: 0.24.2 + vite: + specifier: ^6.0.7 + version: 6.0.11(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.1)(sass@1.83.4)(yaml@2.5.1) + devDependencies: + '@netlify/edge-functions': + specifier: ^2.11.1 + version: 2.11.1 + '@netlify/edge-handler-types': + specifier: ^0.34.1 + version: 0.34.1 + '@types/node': + specifier: ^22.10.6 + version: 22.13.1 + astro: + specifier: ^5.1.6 + version: link:../../astro + astro-scripts: + specifier: workspace:* + version: link:../../../scripts + cheerio: + specifier: 1.0.0 + version: 1.0.0 + execa: + specifier: ^8.0.1 + version: 8.0.1 + fast-glob: + specifier: ^3.3.3 + version: 3.3.3 + strip-ansi: + specifier: ^7.1.0 + version: 7.1.0 + typescript: + specifier: ^5.7.3 + version: 5.7.3 + + packages/integrations/netlify/test/functions/fixtures/cookies: + dependencies: + '@astrojs/netlify': + specifier: 'workspace:' + version: link:../../../.. + + packages/integrations/netlify/test/functions/fixtures/middleware: + dependencies: + '@astrojs/netlify': + specifier: 'workspace:' + version: link:../../../.. + sharp: + specifier: ^0.33.5 + version: 0.33.5 + + packages/integrations/netlify/test/functions/fixtures/redirects: + dependencies: + '@astrojs/netlify': + specifier: 'workspace:' + version: link:../../../.. + + packages/integrations/netlify/test/hosted/hosted-astro-project: + dependencies: + '@astrojs/netlify': + specifier: workspace:* + version: link:../../.. + astro: + specifier: ^5.1.6 + version: link:../../../../../astro + + packages/integrations/netlify/test/static/fixtures/redirects: + dependencies: + '@astrojs/netlify': + specifier: 'workspace:' + version: link:../../../.. packages/integrations/node: dependencies: @@ -6432,6 +6518,9 @@ packages: '@emnapi/runtime@1.1.1': resolution: {integrity: sha512-3bfqkzuR1KLx57nZfjr2NLnFOobvyS0aTszaEGCGqmYMVDRaGvgIZbjGSV/MHSSmLgQ/b9JFHQ5xm5WRZYd+XQ==} + '@emnapi/runtime@1.3.1': + resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} + '@esbuild/aix-ppc64@0.24.2': resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} engines: {node: '>=18'} @@ -6648,117 +6737,226 @@ packages: cpu: [arm64] os: [darwin] + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + '@img/sharp-darwin-x64@0.33.3': resolution: {integrity: sha512-2QeSl7QDK9ru//YBT4sQkoq7L0EAJZA3rtV+v9p8xTKl4U1bUqTIaCnoC7Ctx2kCjQgwFXDasOtPTCT8eCTXvw==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [darwin] + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + '@img/sharp-libvips-darwin-arm64@1.0.2': resolution: {integrity: sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==} engines: {macos: '>=11', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [darwin] + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + '@img/sharp-libvips-darwin-x64@1.0.2': resolution: {integrity: sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==} engines: {macos: '>=10.13', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [darwin] + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + '@img/sharp-libvips-linux-arm64@1.0.2': resolution: {integrity: sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==} engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + '@img/sharp-libvips-linux-arm@1.0.2': resolution: {integrity: sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==} engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm] os: [linux] + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + '@img/sharp-libvips-linux-s390x@1.0.2': resolution: {integrity: sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==} engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [s390x] os: [linux] + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + cpu: [s390x] + os: [linux] + '@img/sharp-libvips-linux-x64@1.0.2': resolution: {integrity: sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==} engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + '@img/sharp-libvips-linuxmusl-arm64@1.0.2': resolution: {integrity: sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==} engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + cpu: [arm64] + os: [linux] + '@img/sharp-libvips-linuxmusl-x64@1.0.2': resolution: {integrity: sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==} engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + cpu: [x64] + os: [linux] + '@img/sharp-linux-arm64@0.33.3': resolution: {integrity: sha512-Zf+sF1jHZJKA6Gor9hoYG2ljr4wo9cY4twaxgFDvlG0Xz9V7sinsPp8pFd1XtlhTzYo0IhDbl3rK7P6MzHpnYA==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + '@img/sharp-linux-arm@0.33.3': resolution: {integrity: sha512-Q7Ee3fFSC9P7vUSqVEF0zccJsZ8GiiCJYGWDdhEjdlOeS9/jdkyJ6sUSPj+bL8VuOYFSbofrW0t/86ceVhx32w==} engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm] os: [linux] + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + '@img/sharp-linux-s390x@0.33.3': resolution: {integrity: sha512-vFk441DKRFepjhTEH20oBlFrHcLjPfI8B0pMIxGm3+yilKyYeHEVvrZhYFdqIseSclIqbQ3SnZMwEMWonY5XFA==} engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [s390x] os: [linux] + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + '@img/sharp-linux-x64@0.33.3': resolution: {integrity: sha512-Q4I++herIJxJi+qmbySd072oDPRkCg/SClLEIDh5IL9h1zjhqjv82H0Seupd+q2m0yOfD+/fJnjSoDFtKiHu2g==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + '@img/sharp-linuxmusl-arm64@0.33.3': resolution: {integrity: sha512-qnDccehRDXadhM9PM5hLvcPRYqyFCBN31kq+ErBSZtZlsAc1U4Z85xf/RXv1qolkdu+ibw64fUDaRdktxTNP9A==} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + '@img/sharp-linuxmusl-x64@0.33.3': resolution: {integrity: sha512-Jhchim8kHWIU/GZ+9poHMWRcefeaxFIs9EBqf9KtcC14Ojk6qua7ghKiPs0sbeLbLj/2IGBtDcxHyjCdYWkk2w==} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + '@img/sharp-wasm32@0.33.3': resolution: {integrity: sha512-68zivsdJ0koE96stdUfM+gmyaK/NcoSZK5dV5CAjES0FUXS9lchYt8LAB5rTbM7nlWtxaU/2GON0HVN6/ZYJAQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [wasm32] + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + '@img/sharp-win32-ia32@0.33.3': resolution: {integrity: sha512-CyimAduT2whQD8ER4Ux7exKrtfoaUiVr7HG0zZvO0XTFn2idUWljjxv58GxNTkFb8/J9Ub9AqITGkJD6ZginxQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [ia32] os: [win32] + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + '@img/sharp-win32-x64@0.33.3': resolution: {integrity: sha512-viT4fUIDKnli3IfOephGnolMzhz5VaTvDRkYqtZxOMIoMQ4MrAziO7pT1nVnOt2FAm7qW5aa+CCc13aEY6Le0g==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [win32] + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -6844,6 +7042,11 @@ packages: '@manypkg/get-packages@1.1.3': resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + '@mapbox/node-pre-gyp@2.0.0': + resolution: {integrity: sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg==} + engines: {node: '>=18'} + hasBin: true + '@markdoc/markdoc@0.4.0': resolution: {integrity: sha512-fSh4P3Y4E7oaKYc2oNzSIJVPDto7SMzAuQN1Iyx53UxzleA6QzRdNWRxmiPqtVDaDi5dELd2yICoG91csrGrAw==} engines: {node: '>=14.7.0'} @@ -6873,6 +7076,24 @@ packages: resolution: {integrity: sha512-9hIbusvAZjSGBJ42OyFC2AxsEph1LuKQahMWFcPGEIsOqIYHhMRkYA7wSUMhH7naydjNmllpcp3pJLOK4RhFaQ==} engines: {node: ^14.16.0 || >=16.0.0} + '@netlify/edge-functions@2.11.1': + resolution: {integrity: sha512-pyQOTZ8a+ge5lZlE+H/UAHyuqQqtL5gE0pXrHT9mOykr3YQqnkB2hZMtx12odatZ87gHg4EA+UPyMZUbLfnXvw==} + + '@netlify/edge-handler-types@0.34.1': + resolution: {integrity: sha512-YTwn8cw89M4lRTmoUhl9s8ljSGMDt7FOIsxsrx7YrRz/RZlbh4Yuh4RU13DDafDRBEVuRbjGo93cnN621ZfBjA==} + + '@netlify/functions@2.8.2': + resolution: {integrity: sha512-DeoAQh8LuNPvBE4qsKlezjKj0PyXDryOFJfJKo3Z1qZLKzQ21sT314KQKPVjfvw6knqijj+IO+0kHXy/TJiqNA==} + engines: {node: '>=14.0.0'} + + '@netlify/node-cookies@0.1.0': + resolution: {integrity: sha512-OAs1xG+FfLX0LoRASpqzVntVV/RpYkgpI0VrUnw2u0Q1qiZUzcPffxRK8HF3gc4GjuhG5ahOEMJ9bswBiZPq0g==} + engines: {node: ^14.16.0 || >=16.0.0} + + '@netlify/serverless-functions-api@1.26.1': + resolution: {integrity: sha512-q3L9i3HoNfz0SGpTIS4zTcKBbRkxzCRpd169eyiTuk3IwcPC3/85mzLHranlKo2b+HYT0gu37YxGB45aD8A3Tw==} + engines: {node: '>=18.0.0'} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -7487,6 +7708,11 @@ packages: '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + '@vercel/nft@0.29.1': + resolution: {integrity: sha512-6239JJM1V9b3OjvZIjbe+47/hGxMr44FEzlbTErrqzebCaoKAHK+yvahn3gdNacybDUbTxVF8Zuh0vqaeM8aKQ==} + engines: {node: '>=18'} + hasBin: true + '@vitejs/plugin-react@4.3.4': resolution: {integrity: sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==} engines: {node: ^14.18.0 || >=16.0.0} @@ -7627,10 +7853,19 @@ packages: '@webcomponents/template-shadowroot@0.2.1': resolution: {integrity: sha512-fXL/vIUakyZL62hyvUh+EMwbVoTc0hksublmRz6ai6et8znHkJa6gtqMUZo1oc7dIz46exHSIImml9QTdknMHg==} + abbrev@3.0.0: + resolution: {integrity: sha512-+/kfrslGQ7TNV2ecmQwMJj/B65g5KVq1/L3SGVZ3tCYGqlzFuFCGBZJtMP99wH3NpEUyAjn0zPdPUg0D+DwrOA==} + engines: {node: ^18.17.0 || >=20.5.0} + accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -7650,6 +7885,10 @@ packages: resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} engines: {node: '>= 14'} + agent-base@7.1.3: + resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} + engines: {node: '>= 14'} + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -7743,6 +7982,9 @@ packages: resolution: {integrity: sha512-cWMaNwUJnf37C/S5TfCkk/15MwbPRwVYALA2jtjkbHjCmAPiDXyNJy2q3p1KAZzDLHAWyarUWSujUoHR4pEgrA==} engines: {node: '>= 14'} + async-sema@3.1.1: + resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -7805,6 +8047,9 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + bindings@1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + birpc@0.2.19: resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==} @@ -7931,6 +8176,10 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -8631,6 +8880,9 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -8725,6 +8977,9 @@ packages: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -8781,6 +9036,10 @@ packages: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -8934,6 +9193,10 @@ packages: resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} engines: {node: '>= 14'} + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + human-id@1.0.2: resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} @@ -8977,6 +9240,10 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -9631,6 +9898,10 @@ packages: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} + minizlib@3.0.1: + resolution: {integrity: sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==} + engines: {node: '>= 18'} + mitt@3.0.1: resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} @@ -9642,6 +9913,11 @@ packages: engines: {node: '>=10'} hasBin: true + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -9738,6 +10014,11 @@ packages: node-releases@2.0.18: resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + nopt@8.1.0: + resolution: {integrity: sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -9783,6 +10064,9 @@ packages: resolution: {integrity: sha512-y1HRYy8s/RlcBvDUwKXSmkODMdx4KSuIvloCnQYJ2LdBBC1asY4HtfhXwe3UWknLakATZDnbzht2Ijw3M1EqFg==} engines: {node: '>=9.4.0 || ^8.9.4'} + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} @@ -9920,6 +10204,10 @@ packages: resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -10503,6 +10791,10 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} + hasBin: true + rollup@4.34.2: resolution: {integrity: sha512-sBDUoxZEaqLu9QeNalL8v3jw6WjPku4wfZGyTU7l7m1oC+rpRihXc/n/H+4148ZkGz5Xli8CHMns//fFGKvpIQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -10597,6 +10889,10 @@ packages: resolution: {integrity: sha512-vHUeXJU1UvlO/BNwTpT0x/r53WkLUVxrmb5JTgW92fdFCFk0ispLMAeu/jPO2vjkXM1fYUi3K7/qcLF47pwM1A==} engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0} + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -10853,6 +11149,10 @@ packages: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + tar@7.4.3: + resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} + engines: {node: '>=18'} + term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -11203,6 +11503,9 @@ packages: url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + urlpattern-polyfill@8.0.2: + resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==} + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -11558,6 +11861,9 @@ packages: resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} engines: {node: '>=18'} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.16.0: resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} engines: {node: '>=10.0.0'} @@ -11602,6 +11908,10 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + yaml-language-server@1.15.0: resolution: {integrity: sha512-N47AqBDCMQmh6mBLmI6oqxryHRzi33aPFPsJhYy3VTUGCdLHYjGh4FZzpUjRlphaADBBkDmnkM/++KNIOHi5Rw==} hasBin: true @@ -12506,6 +12816,11 @@ snapshots: tslib: 2.6.2 optional: true + '@emnapi/runtime@1.3.1': + dependencies: + tslib: 2.6.2 + optional: true + '@esbuild/aix-ppc64@0.24.2': optional: true @@ -12645,76 +12960,151 @@ snapshots: '@img/sharp-libvips-darwin-arm64': 1.0.2 optional: true + '@img/sharp-darwin-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + optional: true + '@img/sharp-darwin-x64@0.33.3': optionalDependencies: '@img/sharp-libvips-darwin-x64': 1.0.2 optional: true + '@img/sharp-darwin-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + optional: true + '@img/sharp-libvips-darwin-arm64@1.0.2': optional: true + '@img/sharp-libvips-darwin-arm64@1.0.4': + optional: true + '@img/sharp-libvips-darwin-x64@1.0.2': optional: true + '@img/sharp-libvips-darwin-x64@1.0.4': + optional: true + '@img/sharp-libvips-linux-arm64@1.0.2': optional: true + '@img/sharp-libvips-linux-arm64@1.0.4': + optional: true + '@img/sharp-libvips-linux-arm@1.0.2': optional: true + '@img/sharp-libvips-linux-arm@1.0.5': + optional: true + '@img/sharp-libvips-linux-s390x@1.0.2': optional: true + '@img/sharp-libvips-linux-s390x@1.0.4': + optional: true + '@img/sharp-libvips-linux-x64@1.0.2': optional: true + '@img/sharp-libvips-linux-x64@1.0.4': + optional: true + '@img/sharp-libvips-linuxmusl-arm64@1.0.2': optional: true + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + optional: true + '@img/sharp-libvips-linuxmusl-x64@1.0.2': optional: true + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + optional: true + '@img/sharp-linux-arm64@0.33.3': optionalDependencies: '@img/sharp-libvips-linux-arm64': 1.0.2 optional: true + '@img/sharp-linux-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + optional: true + '@img/sharp-linux-arm@0.33.3': optionalDependencies: '@img/sharp-libvips-linux-arm': 1.0.2 optional: true + '@img/sharp-linux-arm@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + optional: true + '@img/sharp-linux-s390x@0.33.3': optionalDependencies: '@img/sharp-libvips-linux-s390x': 1.0.2 optional: true + '@img/sharp-linux-s390x@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.4 + optional: true + '@img/sharp-linux-x64@0.33.3': optionalDependencies: '@img/sharp-libvips-linux-x64': 1.0.2 optional: true + '@img/sharp-linux-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + optional: true + '@img/sharp-linuxmusl-arm64@0.33.3': optionalDependencies: '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 optional: true + '@img/sharp-linuxmusl-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + optional: true + '@img/sharp-linuxmusl-x64@0.33.3': optionalDependencies: '@img/sharp-libvips-linuxmusl-x64': 1.0.2 optional: true + '@img/sharp-linuxmusl-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + optional: true + '@img/sharp-wasm32@0.33.3': dependencies: '@emnapi/runtime': 1.1.1 optional: true + '@img/sharp-wasm32@0.33.5': + dependencies: + '@emnapi/runtime': 1.3.1 + optional: true + '@img/sharp-win32-ia32@0.33.3': optional: true + '@img/sharp-win32-ia32@0.33.5': + optional: true + '@img/sharp-win32-x64@0.33.3': optional: true + '@img/sharp-win32-x64@0.33.5': + optional: true + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -12724,6 +13114,10 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 @@ -12821,6 +13215,19 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 + '@mapbox/node-pre-gyp@2.0.0': + dependencies: + consola: 3.2.3 + detect-libc: 2.0.3 + https-proxy-agent: 7.0.6 + node-fetch: 2.7.0 + nopt: 8.1.0 + semver: 7.7.1 + tar: 7.4.3 + transitivePeerDependencies: + - encoding + - supports-color + '@markdoc/markdoc@0.4.0(@types/react@18.3.18)(react@19.0.0)': optionalDependencies: '@types/markdown-it': 12.2.3 @@ -12866,6 +13273,23 @@ snapshots: '@netlify/blobs@8.1.0': {} + '@netlify/edge-functions@2.11.1': {} + + '@netlify/edge-handler-types@0.34.1': + dependencies: + web-streams-polyfill: 3.3.3 + + '@netlify/functions@2.8.2': + dependencies: + '@netlify/serverless-functions-api': 1.26.1 + + '@netlify/node-cookies@0.1.0': {} + + '@netlify/serverless-functions-api@1.26.1': + dependencies: + '@netlify/node-cookies': 0.1.0 + urlpattern-polyfill: 8.0.2 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -13331,7 +13755,7 @@ snapshots: '@types/sax@1.2.7': dependencies: - '@types/node': 18.19.50 + '@types/node': 22.13.1 '@types/semver@7.5.8': {} @@ -13356,7 +13780,7 @@ snapshots: '@types/ws@8.5.12': dependencies: - '@types/node': 18.19.50 + '@types/node': 22.13.1 '@types/xml2js@0.4.14': dependencies: @@ -13463,6 +13887,25 @@ snapshots: '@ungap/structured-clone@1.2.0': {} + '@vercel/nft@0.29.1(rollup@4.34.2)': + dependencies: + '@mapbox/node-pre-gyp': 2.0.0 + '@rollup/pluginutils': 5.1.4(rollup@4.34.2) + acorn: 8.14.0 + acorn-import-attributes: 1.9.5(acorn@8.14.0) + async-sema: 3.1.1 + bindings: 1.5.0 + estree-walker: 2.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + node-gyp-build: 4.8.2 + picomatch: 4.0.2 + resolve-from: 5.0.0 + transitivePeerDependencies: + - encoding + - rollup + - supports-color + '@vitejs/plugin-react@4.3.4(vite@6.0.11(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.1)(sass@1.83.4)(yaml@2.5.1))': dependencies: '@babel/core': 7.26.0 @@ -13697,11 +14140,17 @@ snapshots: '@webcomponents/template-shadowroot@0.2.1': {} + abbrev@3.0.0: {} + accepts@1.3.8: dependencies: mime-types: 2.1.35 negotiator: 0.6.3 + acorn-import-attributes@1.9.5(acorn@8.14.0): + dependencies: + acorn: 8.14.0 + acorn-jsx@5.3.2(acorn@8.14.0): dependencies: acorn: 8.14.0 @@ -13718,6 +14167,8 @@ snapshots: transitivePeerDependencies: - supports-color + agent-base@7.1.3: {} + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -13809,6 +14260,8 @@ snapshots: async-listen@3.0.1: {} + async-sema@3.1.1: {} + asynckit@0.4.0: {} autocannon@7.15.0: @@ -13895,6 +14348,10 @@ snapshots: binary-extensions@2.3.0: {} + bindings@1.5.0: + dependencies: + file-uri-to-path: 1.0.0 + birpc@0.2.19: {} body-parser@1.20.3: @@ -14052,6 +14509,8 @@ snapshots: chownr@2.0.0: {} + chownr@3.0.0: {} + ci-info@3.9.0: {} ci-info@4.1.0: {} @@ -14684,6 +15143,8 @@ snapshots: dependencies: flat-cache: 4.0.1 + file-uri-to-path@1.0.0: {} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -14784,6 +15245,8 @@ snapshots: dependencies: minipass: 3.3.6 + fs.realpath@1.0.0: {} + fsevents@2.3.2: optional: true @@ -14842,6 +15305,15 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + globals@11.12.0: {} globals@14.0.0: {} @@ -15128,6 +15600,13 @@ snapshots: transitivePeerDependencies: - supports-color + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + human-id@1.0.2: {} human-signals@5.0.0: {} @@ -15163,6 +15642,11 @@ snapshots: imurmurhash@0.1.4: {} + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + inherits@2.0.4: {} inline-style-parser@0.1.1: {} @@ -16061,12 +16545,19 @@ snapshots: minipass: 3.3.6 yallist: 4.0.0 + minizlib@3.0.1: + dependencies: + minipass: 7.1.2 + rimraf: 5.0.10 + mitt@3.0.1: {} mj-context-menu@0.6.1: {} mkdirp@1.0.4: {} + mkdirp@3.0.1: {} + mri@1.2.0: {} mrmime@2.0.0: {} @@ -16145,6 +16636,10 @@ snapshots: node-releases@2.0.18: {} + nopt@8.1.0: + dependencies: + abbrev: 3.0.0 + normalize-path@3.0.0: {} normalize-range@0.1.2: {} @@ -16182,6 +16677,10 @@ snapshots: on-net-listen@1.1.2: {} + once@1.4.0: + dependencies: + wrappy: 1.0.2 + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 @@ -16327,6 +16826,8 @@ snapshots: path-exists@5.0.0: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-key@4.0.0: {} @@ -17028,6 +17529,10 @@ snapshots: rfdc@1.4.1: {} + rimraf@5.0.10: + dependencies: + glob: 10.4.5 + rollup@4.34.2: dependencies: '@types/estree': 1.0.6 @@ -17185,6 +17690,32 @@ snapshots: '@img/sharp-win32-ia32': 0.33.3 '@img/sharp-win32-x64': 0.33.3 + sharp@0.33.5: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.7.1 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -17505,6 +18036,15 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 + tar@7.4.3: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.0.1 + mkdirp: 3.0.1 + yallist: 5.0.0 + term-size@2.2.1: {} terminal-link@3.0.0: @@ -17793,6 +18333,8 @@ snapshots: querystringify: 2.2.0 requires-port: 1.0.0 + urlpattern-polyfill@8.0.2: {} + util-deprecate@1.0.2: {} utils-merge@1.0.1: {} @@ -18172,6 +18714,8 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.1.0 + wrappy@1.0.2: {} + ws@8.16.0: {} xml-name-validator@5.0.0: {} @@ -18195,6 +18739,8 @@ snapshots: yallist@4.0.0: {} + yallist@5.0.0: {} + yaml-language-server@1.15.0: dependencies: ajv: 8.17.1 |