diff --git a/.changeset/cool-birds-prove.md b/.changeset/cool-birds-prove.md new file mode 100644 index 000000000000..70c190b89273 --- /dev/null +++ b/.changeset/cool-birds-prove.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix missing styles for Markdoc files in development diff --git a/.changeset/early-students-taste.md b/.changeset/early-students-taste.md new file mode 100644 index 000000000000..3f068a0d250c --- /dev/null +++ b/.changeset/early-students-taste.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Remove `slash` package diff --git a/.changeset/flat-houses-brush.md b/.changeset/flat-houses-brush.md new file mode 100644 index 000000000000..4dfd4198aa3b --- /dev/null +++ b/.changeset/flat-houses-brush.md @@ -0,0 +1,5 @@ +--- +'@astrojs/svelte': minor +--- + +feat: support svelte 4 diff --git a/.changeset/flat-papayas-invite.md b/.changeset/flat-papayas-invite.md new file mode 100644 index 000000000000..c8b1193d7662 --- /dev/null +++ b/.changeset/flat-papayas-invite.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Allow astro to be installed underneath a folder with leading slashes diff --git a/.changeset/happy-stingrays-carry.md b/.changeset/happy-stingrays-carry.md new file mode 100644 index 000000000000..f63778dcf23b --- /dev/null +++ b/.changeset/happy-stingrays-carry.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Handle esbuild 0.18 changes diff --git a/.changeset/nervous-paws-knock.md b/.changeset/nervous-paws-knock.md new file mode 100644 index 000000000000..4051bd8c2c1d --- /dev/null +++ b/.changeset/nervous-paws-knock.md @@ -0,0 +1,5 @@ +--- +'@astrojs/vercel': patch +--- + +Fix redirects for root page when using `trailingSlash: "always"` diff --git a/.changeset/proud-vans-approve.md b/.changeset/proud-vans-approve.md deleted file mode 100644 index c58b5279957c..000000000000 --- a/.changeset/proud-vans-approve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'astro': patch ---- - -Fixed `RedirectConfig` type definition diff --git a/.changeset/rich-pumpkins-change.md b/.changeset/rich-pumpkins-change.md new file mode 100644 index 000000000000..1637bd11c2ff --- /dev/null +++ b/.changeset/rich-pumpkins-change.md @@ -0,0 +1,5 @@ +--- +'@astrojs/internal-helpers': patch +--- + +Add `slash` path utility diff --git a/.changeset/tiny-lemons-sit.md b/.changeset/tiny-lemons-sit.md new file mode 100644 index 000000000000..8e43429f7f42 --- /dev/null +++ b/.changeset/tiny-lemons-sit.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Prevent accidental inclusion of page CSS in dev mode diff --git a/.github/ISSUE_TEMPLATE/---01-bug-report.yml b/.github/ISSUE_TEMPLATE/---01-bug-report.yml index 32e636cce7c7..a9786522b28f 100644 --- a/.github/ISSUE_TEMPLATE/---01-bug-report.yml +++ b/.github/ISSUE_TEMPLATE/---01-bug-report.yml @@ -53,6 +53,13 @@ body: description: A clear and concise description of what the bug is. validations: required: true + - type: textarea + id: bug-expectation + attributes: + label: What's the expected result? + description: Describe what you expect to happen. + validations: + required: true - type: input id: bug-reproduction attributes: diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index e896bd2f2275..7774667cf6af 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -4,7 +4,7 @@ contact_links: url: https://github.com/withastro/docs about: File an issue or make an improvement to the docs website. - name: πŸ’‘ Ideas for New Features, Improvements and RFCs - url: https://github.com/withastro/rfcs/discussions + url: https://github.com/withastro/roadmap/discussions about: Propose and discuss future improvements to Astro - name: πŸ‘Ύ Chat url: https://astro.build/chat diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 970dc1d7c0d8..3c54ee2061e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ on: paths-ignore: - ".vscode/**" - "**/*.md" + - ".github/ISSUE_TEMPLATE/**" # Automatically cancel older in-progress jobs on the same branch concurrency: @@ -148,7 +149,7 @@ jobs: - name: Use Deno uses: denoland/setup-deno@v1 with: - deno-version: v1.26.1 + deno-version: v1.34.1 - name: Install dependencies run: pnpm install diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 3291ce16e6a4..6b1b0e4ad8bf 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -1,4 +1,4 @@ -name: "Format Code" +name: Format on: workflow_dispatch: @@ -7,33 +7,9 @@ on: - main jobs: - format: + prettier: if: github.repository_owner == 'withastro' - runs-on: ubuntu-latest - env: - NODE_OPTIONS: "--max_old_space_size=4096" - steps: - - name: Check out code using Git - uses: actions/checkout@v3 - with: - ref: ${{ github.head_ref }} - # Needs access to push to main - token: ${{ secrets.FREDKBOT_GITHUB_TOKEN }} - - name: Setup PNPM - uses: pnpm/action-setup@v2 - - name: Setup Node - uses: actions/setup-node@v3 - with: - node-version: 16 - cache: "pnpm" - - name: Install dependencies - run: pnpm install - - name: Format code - run: pnpm run format:ci - - name: Commit changes - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "[ci] format" - branch: ${{ github.head_ref }} - commit_user_name: fredkbot - commit_user_email: fred+astrobot@astro.build + uses: withastro/automation/.github/workflows/format.yml@main + with: + command: "format:ci" + secrets: inherit diff --git a/.github/workflows/issue.yml b/.github/workflows/issue.yml deleted file mode 100644 index cc370ea07ebf..000000000000 --- a/.github/workflows/issue.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Auto Assign Issues to Project - -on: - issues: - types: [opened] - -env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - -jobs: - auto_assign_issues: - runs-on: ubuntu-latest - name: Auto-assign new issues to projects - steps: - - name: Assign Bugs to the Bug Tracker - uses: srggrs/assign-one-project-github-action@1.3.1 - if: github.event.action == 'opened' && startsWith(github.event.issue.title, 'πŸ› BUG:') - with: - project: 'https://github.com/withastro/astro/projects/2' - column_name: 'Needs Triage' - - - name: Assign RFCs to the RFC Tracker - uses: srggrs/assign-one-project-github-action@1.3.1 - if: github.event.action == 'opened' && startsWith(github.event.issue.title, 'πŸ’‘ RFC:') - with: - project: 'https://github.com/withastro/astro/projects/3' - column_name: 'Discussing' - - - name: Assign RFCs to the Docs Tracker - uses: srggrs/assign-one-project-github-action@1.3.1 - if: github.event.action == 'opened' && startsWith(github.event.issue.title, 'πŸ“˜ DOC:') - with: - project: 'https://github.com/withastro/astro/projects/5' - column_name: 'TODO' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8f686c577411..2aa663727425 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,21 +18,11 @@ jobs: congrats: name: congratsbot if: ${{ github.repository_owner == 'withastro' }} - runs-on: ubuntu-latest - steps: - - id: setup - env: - MESSAGE: ${{ github.event.commits[0].message }} - run: | - TRIMMED=$(echo "$MESSAGE" | sed '1!d;q') - echo "::set-output name=COMMIT_MSG::${TRIMMED}" - - name: Send a Discord notification when a PR is merged - env: - DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_CONGRATS }} - # DISCORD_AVATAR: ${{ github.event.pull_request.user.avatar_url }} - uses: Ilshidur/action-discord@0.3.2 - with: - args: "**Merged!** ${{ github.event.commits[0].author.name }}: [`${{ steps.setup.outputs.COMMIT_MSG }}`]()" + uses: withastro/automation/.github/workflows/congratsbot.yml@main + with: + EMOJIS: 'πŸŽ‰,🎊,πŸ§‘β€πŸš€,πŸ₯³,πŸ™Œ,πŸš€,πŸ‘,<:houston_golden:1068575433647456447>,<:astrocoin:894990669515489301>,<:astro_pride:1085944201587458169>' + secrets: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_CONGRATS }} check_for_update: name: Check for Updates diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 027533ef6905..2a3bfd1948b7 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,4 +1,4 @@ -name: "Nightly" +name: Nightly on: schedule: @@ -7,76 +7,7 @@ on: workflow_dispatch: jobs: - stat: - # Temporarily disable since stat collection hasn't work for a while - if: false - runs-on: ubuntu-latest - steps: - - name: Check out code using Git - uses: actions/checkout@v3 - - - name: Setup PNPM - uses: pnpm/action-setup@v2 - - - name: Setup Node - uses: actions/setup-node@v3 - with: - node-version: 16 - cache: "pnpm" - - - name: Install dependencies - run: pnpm install - - - name: Collect stats - run: node scripts/stats/index.js - env: - # Needs access to collect stats from the GitHub API - GITHUB_TOKEN: ${{ secrets.FREDKBOT_GITHUB_TOKEN }} - - - name: Commit changes - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "[ci] collect stats" - branch: ${{ github.head_ref }} - # Needs access to push to main - token: ${{ secrets.FREDKBOT_GITHUB_TOKEN }} - lockfile: if: github.repository_owner == 'withastro' - runs-on: ubuntu-latest - steps: - - name: Check out code using Git - uses: actions/checkout@v3 - - - name: Setup PNPM - uses: pnpm/action-setup@v2 - - - name: Setup Node - uses: actions/setup-node@v3 - with: - node-version: 16 - cache: "pnpm" - - - name: Delete the existing pnpm-lock.yaml file - run: rm pnpm-lock.yaml - - # https://github.com/pnpm/pnpm/issues/6463 - - name: Update .npmrc to update packages to latest - run: echo "resolution-mode=highest" >> .npmrc - - - name: Create a fresh pnpm lockfile (no install) - run: pnpm install --lockfile-only - - - name: Create Pull Request - id: createpr - uses: peter-evans/create-pull-request@v5 - with: - branch: ci/lockfile - # Access token is needed to trigger CI on this PR - token: ${{ secrets.FREDKBOT_GITHUB_TOKEN }} - commit-message: "[ci] update lockfile" - add-paths: pnpm-lock.yaml - title: "[ci] update lockfile" - body: > - This PR is auto-generated by a nightly GitHub action. - It should automatically be merged if tests pass. + uses: withastro/automation/.github/workflows/lockfile.yml@main + secrets: inherit diff --git a/.prettierignore b/.prettierignore index e6c627f0c5f5..71dca9c3c4a5 100644 --- a/.prettierignore +++ b/.prettierignore @@ -12,14 +12,11 @@ packages/markdown/component/Markdown.astro **/fixtures **/vendor **/.vercel -examples/docs/**/*.md -examples/blog/**/*.md # Directories .github .changeset # Files -README.md packages/webapi/mod.d.ts pnpm-lock.yaml diff --git a/.prettierrc.js b/.prettierrc.cjs similarity index 61% rename from .prettierrc.js rename to .prettierrc.cjs index d43df33f5b7a..0909ba219d02 100644 --- a/.prettierrc.js +++ b/.prettierrc.cjs @@ -8,14 +8,6 @@ module.exports = { useTabs: true, plugins: ['./node_modules/prettier-plugin-astro'], overrides: [ - { - // Changesets run Prettier using our configuration, however it uses a very old version of Prettier that does - // not support our plugin and it ends up doing more harm than good. As such, we'll disable our plugin for changelogs - files: ['CHANGELOG.md'], - options: { - plugins: [], - }, - }, { files: ['.*', '*.json', '*.md', '*.toml', '*.yml'], options: { diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ff03da2868a5..25baacecb52e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,7 +11,7 @@ We welcome contributions of any size and skill level. As an open source project, ```shell node: "^>=16.12.0" -pnpm: "^8.2.0" +pnpm: "^8.6.2" # otherwise, your build will fail ``` diff --git a/README.md b/README.md index 934bceb9828e..31341cdd6ab6 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@

- ## Install The **recommended** way to install the latest version of Astro is by running the command below: @@ -23,9 +22,10 @@ You can also install Astro **manually** by running this command instead: npm install --save-dev astro ``` -Looking for help? Start with our [Getting Started](https://docs.astro.build/en/getting-started/) guide. +Looking for help? Start with our [Getting Started](https://docs.astro.build/en/getting-started/) guide. Looking for quick examples? [Open a starter project](https://astro.new/) right in your browser. + ## Documentation Visit our [official documentation](https://docs.astro.build/). @@ -33,9 +33,10 @@ Visit our [official documentation](https://docs.astro.build/). ## Support Having trouble? Get help in the official [Astro Discord](https://astro.build/chat). + ## Contributing -**New contributors welcome!** Check out our [Contributors Guide](CONTRIBUTING.md) for help getting started. +**New contributors welcome!** Check out our [Contributors Guide](CONTRIBUTING.md) for help getting started. Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll help you get your first contribution in no time! @@ -47,23 +48,23 @@ Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll | [create-astro](packages/create-astro) | [![create-astro version](https://img.shields.io/npm/v/create-astro.svg?label=%20)](packages/create-astro/CHANGELOG.md) | | [@astrojs/react](packages/integrations/react) | [![astro version](https://img.shields.io/npm/v/@astrojs/react.svg?label=%20)](packages/integrations/react/CHANGELOG.md) | | [@astrojs/preact](packages/integrations/preact) | [![astro version](https://img.shields.io/npm/v/@astrojs/preact.svg?label=%20)](packages/integrations/preact/CHANGELOG.md) | -| [@astrojs/solid-js](packages/integrations/solid) | [![astro version](https://img.shields.io/npm/v/@astrojs/solid-js.svg?label=%20)](packages/integrations/solid/CHANGELOG.md) | +| [@astrojs/solid-js](packages/integrations/solid) | [![astro version](https://img.shields.io/npm/v/@astrojs/solid-js.svg?label=%20)](packages/integrations/solid/CHANGELOG.md) | | [@astrojs/svelte](packages/integrations/svelte) | [![astro version](https://img.shields.io/npm/v/@astrojs/svelte.svg?label=%20)](packages/integrations/svelte/CHANGELOG.md) | | [@astrojs/vue](packages/integrations/vue) | [![astro version](https://img.shields.io/npm/v/@astrojs/vue.svg?label=%20)](packages/integrations/vue/CHANGELOG.md) | | [@astrojs/lit](packages/integrations/lit) | [![astro version](https://img.shields.io/npm/v/@astrojs/lit.svg?label=%20)](packages/integrations/lit/CHANGELOG.md) | | [@astrojs/deno](packages/integrations/deno) | [![astro version](https://img.shields.io/npm/v/@astrojs/deno.svg?label=%20)](packages/integrations/deno/CHANGELOG.md) | | [@astrojs/netlify](packages/integrations/netlify) | [![astro version](https://img.shields.io/npm/v/@astrojs/netlify.svg?label=%20)](packages/integrations/netlify/CHANGELOG.md) | -| [@astrojs/node](packages/integrations/node) | [![astro version](https://img.shields.io/npm/v/@astrojs/node.svg?label=%20)](packages/integrations/node/CHANGELOG.md) | +| [@astrojs/node](packages/integrations/node) | [![astro version](https://img.shields.io/npm/v/@astrojs/node.svg?label=%20)](packages/integrations/node/CHANGELOG.md) | | [@astrojs/vercel](packages/integrations/vercel) | [![astro version](https://img.shields.io/npm/v/@astrojs/vercel.svg?label=%20)](packages/integrations/vercel/CHANGELOG.md) | | [@astrojs/cloudflare](packages/integrations/cloudflare) | [![astro version](https://img.shields.io/npm/v/@astrojs/cloudflare.svg?label=%20)](packages/integrations/cloudflare/CHANGELOG.md) | | [@astrojs/partytown](packages/integrations/partytown) | [![astro version](https://img.shields.io/npm/v/@astrojs/partytown.svg?label=%20)](packages/integrations/partytown/CHANGELOG.md) | | [@astrojs/sitemap](packages/integrations/sitemap) | [![astro version](https://img.shields.io/npm/v/@astrojs/sitemap.svg?label=%20)](packages/integrations/sitemap/CHANGELOG.md) | | [@astrojs/tailwind](packages/integrations/tailwind) | [![astro version](https://img.shields.io/npm/v/@astrojs/tailwind.svg?label=%20)](packages/integrations/tailwind/CHANGELOG.md) | | [@astrojs/turbolinks](packages/integrations/turbolinks) | [![astro version](https://img.shields.io/npm/v/@astrojs/turbolinks.svg?label=%20)](packages/integrations/turbolinks/CHANGELOG.md) | -| [@astrojs/alpinejs](packages/integrations/alpinejs) | [![astro version](https://img.shields.io/npm/v/@astrojs/alpinejs.svg?label=%20)](packages/integrations/alpinejs/CHANGELOG.md) | -| [@astrojs/image](packages/integrations/image) | [![astro version](https://img.shields.io/npm/v/@astrojs/image.svg?label=%20)](packages/integrations/image/CHANGELOG.md) | -| [@astrojs/mdx](packages/integrations/mdx) | [![astro version](https://img.shields.io/npm/v/@astrojs/mdx.svg?label=%20)](packages/integrations/mdx/CHANGELOG.md) | -| [@astrojs/prefetch](packages/integrations/prefetch) | [![astro version](https://img.shields.io/npm/v/@astrojs/prefetch.svg?label=%20)](packages/integrations/prefetch/CHANGELOG.md) | +| [@astrojs/alpinejs](packages/integrations/alpinejs) | [![astro version](https://img.shields.io/npm/v/@astrojs/alpinejs.svg?label=%20)](packages/integrations/alpinejs/CHANGELOG.md) | +| [@astrojs/image](packages/integrations/image) | [![astro version](https://img.shields.io/npm/v/@astrojs/image.svg?label=%20)](packages/integrations/image/CHANGELOG.md) | +| [@astrojs/mdx](packages/integrations/mdx) | [![astro version](https://img.shields.io/npm/v/@astrojs/mdx.svg?label=%20)](packages/integrations/mdx/CHANGELOG.md) | +| [@astrojs/prefetch](packages/integrations/prefetch) | [![astro version](https://img.shields.io/npm/v/@astrojs/prefetch.svg?label=%20)](packages/integrations/prefetch/CHANGELOG.md) | [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6178/badge)](https://bestpractices.coreinfrastructure.org/projects/6178) @@ -71,10 +72,9 @@ Several official projects are maintained outside of this repo: | Project | Repository | | ------------------------------------------------------------------- | ----------------------------------------------------------------------- | -| [@astrojs/compiler](https://github.com/withastro/compiler) | [withastro/compiler](https://github.com/withastro/compiler) | +| [@astrojs/compiler](https://github.com/withastro/compiler) | [withastro/compiler](https://github.com/withastro/compiler) | | [Astro Language Tools](https://github.com/withastro/language-tools) | [withastro/language-tools](https://github.com/withastro/language-tools) | - ## Links - [License (MIT)](LICENSE) @@ -92,8 +92,7 @@ Astro is generously supported by Netlify, Storyblok, and several other amazing o

-[![Astro's sponsors.](https://astro.build/sponsors.png -"Astro's sponsors. +[![Astro's sponsors.](https://astro.build/sponsors.png "Astro's sponsors. Platinum sponsors: Netlify, storyblok, Vercel, Ship Shape, Google Chrome Gold sponsors: β€Ήdivβ€ΊRIOTS, DEEPGRAM, CloudCannon Sponsors: Monogram, Qoddi, Dimension")](https://github.com/sponsors/withastro) diff --git a/benchmark/package.json b/benchmark/package.json index 0edcbc905082..308ee1276082 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -11,11 +11,11 @@ "@astrojs/node": "workspace:*", "@benchmark/timer": "workspace:*", "astro": "workspace:*", - "autocannon": "^7.10.0", + "autocannon": "^7.11.0", "execa": "^6.1.0", "markdown-table": "^3.0.3", "mri": "^1.2.0", "port-authority": "^2.0.1", - "pretty-bytes": "^6.0.0" + "pretty-bytes": "^6.1.0" } } diff --git a/examples/basics/README.md b/examples/basics/README.md index 43c1d6d0cb51..75d44e0daef1 100644 --- a/examples/basics/README.md +++ b/examples/basics/README.md @@ -12,7 +12,6 @@ npm create astro@latest -- --template basics ![basics](https://user-images.githubusercontent.com/4677417/186188965-73453154-fdec-4d6b-9c34-cb35c248ae5b.png) - ## πŸš€ Project Structure Inside of your Astro project, you'll see the following folders and files: diff --git a/examples/basics/package.json b/examples/basics/package.json index faaed5dbae73..eafcb6ef697e 100644 --- a/examples/basics/package.json +++ b/examples/basics/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^2.5.6" + "astro": "^2.7.0" } } diff --git a/examples/blog/README.md b/examples/blog/README.md index 579d3244a0cd..33c8496b6569 100644 --- a/examples/blog/README.md +++ b/examples/blog/README.md @@ -10,7 +10,6 @@ npm create astro@latest -- --template blog > πŸ§‘β€πŸš€ **Seasoned astronaut?** Delete this file. Have fun! - ![blog](https://user-images.githubusercontent.com/4677417/186189140-4ef17aac-c3c9-4918-a8c2-ce86ba1bb394.png) Features: diff --git a/examples/blog/package.json b/examples/blog/package.json index 8aad8cdf1281..eb63d7e79bd8 100644 --- a/examples/blog/package.json +++ b/examples/blog/package.json @@ -11,9 +11,9 @@ "astro": "astro" }, "dependencies": { - "@astrojs/mdx": "^0.19.5", + "@astrojs/mdx": "^0.19.7", "@astrojs/rss": "^2.4.3", - "@astrojs/sitemap": "^1.3.2", - "astro": "^2.5.6" + "@astrojs/sitemap": "^1.3.3", + "astro": "^2.7.0" } } diff --git a/examples/blog/src/content/blog/first-post.md b/examples/blog/src/content/blog/first-post.md index 33b844032f78..eb5e250f8263 100644 --- a/examples/blog/src/content/blog/first-post.md +++ b/examples/blog/src/content/blog/first-post.md @@ -1,8 +1,8 @@ --- -title: "First post" -description: "Lorem ipsum dolor sit amet" -pubDate: "Jul 08 2022" -heroImage: "/placeholder-hero.jpg" +title: 'First post' +description: 'Lorem ipsum dolor sit amet' +pubDate: 'Jul 08 2022' +heroImage: '/placeholder-hero.jpg' --- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. diff --git a/examples/blog/src/content/blog/markdown-style-guide.md b/examples/blog/src/content/blog/markdown-style-guide.md index 242e862782cd..bb7bb2daabd6 100644 --- a/examples/blog/src/content/blog/markdown-style-guide.md +++ b/examples/blog/src/content/blog/markdown-style-guide.md @@ -1,8 +1,8 @@ --- -title: "Markdown Style Guide" -description: "Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro." -pubDate: "Jul 01 2022" -heroImage: "/placeholder-hero.jpg" +title: 'Markdown Style Guide' +description: 'Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.' +pubDate: 'Jul 01 2022' +heroImage: '/placeholder-hero.jpg' --- Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro. diff --git a/examples/blog/src/content/blog/second-post.md b/examples/blog/src/content/blog/second-post.md index 1bd5ee4658a4..b5a0679383c4 100644 --- a/examples/blog/src/content/blog/second-post.md +++ b/examples/blog/src/content/blog/second-post.md @@ -1,8 +1,8 @@ --- -title: "Second post" -description: "Lorem ipsum dolor sit amet" -pubDate: "Jul 22 2022" -heroImage: "/placeholder-hero.jpg" +title: 'Second post' +description: 'Lorem ipsum dolor sit amet' +pubDate: 'Jul 22 2022' +heroImage: '/placeholder-hero.jpg' --- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. diff --git a/examples/blog/src/content/blog/third-post.md b/examples/blog/src/content/blog/third-post.md index d7f1f24b0408..a2bc343bd7de 100644 --- a/examples/blog/src/content/blog/third-post.md +++ b/examples/blog/src/content/blog/third-post.md @@ -1,8 +1,8 @@ --- -title: "Third post" -description: "Lorem ipsum dolor sit amet" -pubDate: "Jul 15 2022" -heroImage: "/placeholder-hero.jpg" +title: 'Third post' +description: 'Lorem ipsum dolor sit amet' +pubDate: 'Jul 15 2022' +heroImage: '/placeholder-hero.jpg' --- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. diff --git a/examples/component/README.md b/examples/component/README.md index 00f1a04e51f4..c92a01a954f4 100644 --- a/examples/component/README.md +++ b/examples/component/README.md @@ -10,7 +10,6 @@ npm create astro@latest -- --template component [![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/non-html-pages) [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/component/devcontainer.json) - ## πŸš€ Project Structure Inside of your Astro project, you'll see the following folders and files: @@ -27,9 +26,10 @@ Inside of your Astro project, you'll see the following folders and files: The `index.ts` file is the "entry point" for your package. Export your components in `index.ts` to make them importable from your package. ## 🧞 Commands + All commands are run from the root of the project, from a terminal: -| Command | Action | -| :--------------------- | :----------------------------------------------- | -| `npm link` | Registers this package locally. Run `npm link my-component-library` in an Astro project to install your components -| `npm publish` | [Publishes](https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages#publishing-unscoped-public-packages) this package to NPM. Requires you to be [logged in](https://docs.npmjs.com/cli/v8/commands/npm-adduser) +| Command | Action | +| :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `npm link` | Registers this package locally. Run `npm link my-component-library` in an Astro project to install your components | +| `npm publish` | [Publishes](https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages#publishing-unscoped-public-packages) this package to NPM. Requires you to be [logged in](https://docs.npmjs.com/cli/v8/commands/npm-adduser) | diff --git a/examples/component/package.json b/examples/component/package.json index 0d91bd079839..d9aba504476d 100644 --- a/examples/component/package.json +++ b/examples/component/package.json @@ -15,7 +15,7 @@ ], "scripts": {}, "devDependencies": { - "astro": "^2.5.6" + "astro": "^2.7.0" }, "peerDependencies": { "astro": "^2.0.0-beta.0" diff --git a/examples/deno/README.md b/examples/deno/README.md index 0b1ea4c4bda7..98f7ee020622 100644 --- a/examples/deno/README.md +++ b/examples/deno/README.md @@ -12,7 +12,6 @@ npm create astro@latest -- --template deno ![basics](https://user-images.githubusercontent.com/4677417/186188965-73453154-fdec-4d6b-9c34-cb35c248ae5b.png) - ## πŸš€ Project Structure Inside of your Astro project, you'll see the following folders and files: diff --git a/examples/deno/package.json b/examples/deno/package.json index b267befb24d8..573260eaf0a4 100644 --- a/examples/deno/package.json +++ b/examples/deno/package.json @@ -10,9 +10,9 @@ "astro": "astro" }, "dependencies": { - "astro": "^2.5.6" + "astro": "^2.7.0" }, "devDependencies": { - "@astrojs/deno": "^4.1.1" + "@astrojs/deno": "^4.2.0" } } diff --git a/examples/framework-alpine/README.md b/examples/framework-alpine/README.md index 3bd88aa01ea8..9c61ea1b0f81 100644 --- a/examples/framework-alpine/README.md +++ b/examples/framework-alpine/README.md @@ -9,4 +9,3 @@ npm create astro@latest -- --template framework-alpine [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/framework-alpine/devcontainer.json) This example showcases Astro working with [AlpineJS](https://alpinejs.dev/). - diff --git a/examples/framework-alpine/package.json b/examples/framework-alpine/package.json index 6d686ba768ea..4e7b41a72430 100644 --- a/examples/framework-alpine/package.json +++ b/examples/framework-alpine/package.json @@ -13,7 +13,7 @@ "dependencies": { "@astrojs/alpinejs": "^0.2.2", "@types/alpinejs": "^3.7.1", - "alpinejs": "^3.12.0", - "astro": "^2.5.6" + "alpinejs": "^3.12.2", + "astro": "^2.7.0" } } diff --git a/examples/framework-lit/README.md b/examples/framework-lit/README.md index 830822fd4936..9afdb987cb03 100644 --- a/examples/framework-lit/README.md +++ b/examples/framework-lit/README.md @@ -8,4 +8,4 @@ npm create astro@latest -- --template framework-lit [![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/framework-lit) [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/framework-lit/devcontainer.json) -This example showcases Astro working with [Lit](https://lit.dev/). \ No newline at end of file +This example showcases Astro working with [Lit](https://lit.dev/). diff --git a/examples/framework-lit/package.json b/examples/framework-lit/package.json index aa176cac9008..e9a705e78e05 100644 --- a/examples/framework-lit/package.json +++ b/examples/framework-lit/package.json @@ -11,9 +11,9 @@ "astro": "astro" }, "dependencies": { - "@astrojs/lit": "^2.0.2", + "@astrojs/lit": "^2.1.0", "@webcomponents/template-shadowroot": "^0.2.1", - "astro": "^2.5.6", - "lit": "^2.7.4" + "astro": "^2.7.0", + "lit": "^2.7.5" } } diff --git a/examples/framework-multiple/package.json b/examples/framework-multiple/package.json index e5fb7b468df2..dcb8e76b6273 100644 --- a/examples/framework-multiple/package.json +++ b/examples/framework-multiple/package.json @@ -14,14 +14,14 @@ "@astrojs/preact": "^2.2.1", "@astrojs/react": "^2.2.1", "@astrojs/solid-js": "^2.2.0", - "@astrojs/svelte": "^2.2.0", + "@astrojs/svelte": "^3.0.0", "@astrojs/vue": "^2.2.1", - "astro": "^2.5.6", - "preact": "^10.13.2", + "astro": "^2.7.0", + "preact": "^10.15.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "solid-js": "^1.7.4", - "svelte": "^3.58.0", - "vue": "^3.2.47" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/examples/framework-preact/package.json b/examples/framework-preact/package.json index 5b9b5ca9926e..5a512e043630 100644 --- a/examples/framework-preact/package.json +++ b/examples/framework-preact/package.json @@ -13,7 +13,7 @@ "dependencies": { "@astrojs/preact": "^2.2.1", "@preact/signals": "^1.1.3", - "astro": "^2.5.6", - "preact": "^10.13.2" + "astro": "^2.7.0", + "preact": "^10.15.1" } } diff --git a/examples/framework-react/package.json b/examples/framework-react/package.json index b57022042c7e..a45551b6ec46 100644 --- a/examples/framework-react/package.json +++ b/examples/framework-react/package.json @@ -12,9 +12,9 @@ }, "dependencies": { "@astrojs/react": "^2.2.1", - "@types/react": "^18.2.5", - "@types/react-dom": "^18.2.3", - "astro": "^2.5.6", + "@types/react": "^18.2.13", + "@types/react-dom": "^18.2.6", + "astro": "^2.7.0", "react": "^18.2.0", "react-dom": "^18.2.0" } diff --git a/examples/framework-solid/package.json b/examples/framework-solid/package.json index f399110b840d..d08d534bf818 100644 --- a/examples/framework-solid/package.json +++ b/examples/framework-solid/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@astrojs/solid-js": "^2.2.0", - "astro": "^2.5.6", - "solid-js": "^1.7.4" + "astro": "^2.7.0", + "solid-js": "^1.7.6" } } diff --git a/examples/framework-svelte/package.json b/examples/framework-svelte/package.json index a3c348e62f30..2d23e527aec5 100644 --- a/examples/framework-svelte/package.json +++ b/examples/framework-svelte/package.json @@ -11,8 +11,8 @@ "astro": "astro" }, "dependencies": { - "@astrojs/svelte": "^2.2.0", - "astro": "^2.5.6", - "svelte": "^3.58.0" + "@astrojs/svelte": "^3.0.0", + "astro": "^2.7.0", + "svelte": "^3.59.1" } } diff --git a/examples/framework-vue/README.md b/examples/framework-vue/README.md index bc311c9dd413..07f94e1c3f54 100644 --- a/examples/framework-vue/README.md +++ b/examples/framework-vue/README.md @@ -9,4 +9,3 @@ npm create astro@latest -- --template framework-vue [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/framework-vue/devcontainer.json) This example showcases Astro working with [Vue](https://v3.vuejs.org/). - diff --git a/examples/framework-vue/package.json b/examples/framework-vue/package.json index f6ea660a6ac0..4cb61f3c3599 100644 --- a/examples/framework-vue/package.json +++ b/examples/framework-vue/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@astrojs/vue": "^2.2.1", - "astro": "^2.5.6", - "vue": "^3.2.47" + "astro": "^2.7.0", + "vue": "^3.3.4" } } diff --git a/examples/hackernews/package.json b/examples/hackernews/package.json index fb43330ae91b..27775a5f7c0c 100644 --- a/examples/hackernews/package.json +++ b/examples/hackernews/package.json @@ -11,7 +11,7 @@ "astro": "astro" }, "dependencies": { - "@astrojs/node": "^5.1.4", - "astro": "^2.5.6" + "@astrojs/node": "^5.3.0", + "astro": "^2.7.0" } } diff --git a/examples/hackernews/src/components/Comment.astro b/examples/hackernews/src/components/Comment.astro index 8327e666c743..6137f4e1d09e 100644 --- a/examples/hackernews/src/components/Comment.astro +++ b/examples/hackernews/src/components/Comment.astro @@ -14,7 +14,7 @@ const { comment } = Astro.props;

  • {comment.user}{' '} - {comment.time_ago} ago + {comment.time_ago}
    diff --git a/examples/hackernews/src/pages/stories/[id].astro b/examples/hackernews/src/pages/stories/[id].astro index 6cd17ea456bf..84383aa9e4ab 100644 --- a/examples/hackernews/src/pages/stories/[id].astro +++ b/examples/hackernews/src/pages/stories/[id].astro @@ -25,7 +25,7 @@ const story = (await fetchAPI(`item/${id}`)) as IStory; {story.user} - {story.time_ago} ago +  {story.time_ago}

    diff --git a/examples/integration/README.md b/examples/integration/README.md index f40c3dbd0a88..a6709d4004de 100644 --- a/examples/integration/README.md +++ b/examples/integration/README.md @@ -10,7 +10,6 @@ npm create astro@latest -- --template integration [![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/integration) [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/integration/devcontainer.json) - ## πŸš€ Project Structure Inside of your Astro project, you'll see the following folders and files: @@ -25,9 +24,10 @@ Inside of your Astro project, you'll see the following folders and files: The `index.ts` file is the "entry point" for your integration. Export your integration in `index.ts` to make them importable from your package. ## 🧞 Commands + All commands are run from the root of the project, from a terminal: -| Command | Action | -| :--------------------- | :----------------------------------------------- | -| `npm link` | Registers this package locally. Run `npm link my-integration` in an Astro project to install your integration -| `npm publish` | [Publishes](https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages#publishing-unscoped-public-packages) this package to NPM. Requires you to be [logged in](https://docs.npmjs.com/cli/v8/commands/npm-adduser) +| Command | Action | +| :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `npm link` | Registers this package locally. Run `npm link my-integration` in an Astro project to install your integration | +| `npm publish` | [Publishes](https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages#publishing-unscoped-public-packages) this package to NPM. Requires you to be [logged in](https://docs.npmjs.com/cli/v8/commands/npm-adduser) | diff --git a/examples/integration/package.json b/examples/integration/package.json index 9e38a05899d5..cd69a5f00309 100644 --- a/examples/integration/package.json +++ b/examples/integration/package.json @@ -15,7 +15,7 @@ ], "scripts": {}, "devDependencies": { - "astro": "^2.5.6" + "astro": "^2.7.0" }, "peerDependencies": { "astro": "^2.0.0-beta.0" diff --git a/examples/middleware/package.json b/examples/middleware/package.json index 9cd76a52f152..24c1ad69fe83 100644 --- a/examples/middleware/package.json +++ b/examples/middleware/package.json @@ -12,8 +12,8 @@ "server": "node dist/server/entry.mjs" }, "dependencies": { - "@astrojs/node": "^5.1.4", - "astro": "^2.5.6", + "@astrojs/node": "^5.3.0", + "astro": "^2.7.0", "html-minifier": "^4.0.0" } } diff --git a/examples/minimal/package.json b/examples/minimal/package.json index da59a3f411c4..ebb75fdc3ea5 100644 --- a/examples/minimal/package.json +++ b/examples/minimal/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^2.5.6" + "astro": "^2.7.0" } } diff --git a/examples/non-html-pages/package.json b/examples/non-html-pages/package.json index 5f161e8f5b4d..5980d6ee747c 100644 --- a/examples/non-html-pages/package.json +++ b/examples/non-html-pages/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^2.5.6" + "astro": "^2.7.0" } } diff --git a/examples/portfolio/README.md b/examples/portfolio/README.md index cc9cdd5e3871..7ca90501af54 100644 --- a/examples/portfolio/README.md +++ b/examples/portfolio/README.md @@ -12,7 +12,6 @@ npm create astro@latest -- --template portfolio ![portfolio](https://user-images.githubusercontent.com/357379/210779178-a98f0fb7-6b1a-4068-894c-8e1403e26654.jpg) - ## 🧞 Commands All commands are run from the root of the project, from a terminal: diff --git a/examples/portfolio/package.json b/examples/portfolio/package.json index 1aeb84bce35f..2294a88a47dc 100644 --- a/examples/portfolio/package.json +++ b/examples/portfolio/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^2.5.6" + "astro": "^2.7.0" } } diff --git a/examples/ssr/package.json b/examples/ssr/package.json index 039523d19df9..61406b4c9bc2 100644 --- a/examples/ssr/package.json +++ b/examples/ssr/package.json @@ -12,9 +12,9 @@ "server": "node dist/server/entry.mjs" }, "dependencies": { - "@astrojs/node": "^5.1.4", - "@astrojs/svelte": "^2.2.0", - "astro": "^2.5.6", - "svelte": "^3.58.0" + "@astrojs/node": "^5.3.0", + "@astrojs/svelte": "^3.0.0", + "astro": "^2.7.0", + "svelte": "^3.59.1" } } diff --git a/examples/with-markdoc/package.json b/examples/with-markdoc/package.json index 78464f67725b..ca45b0f247a5 100644 --- a/examples/with-markdoc/package.json +++ b/examples/with-markdoc/package.json @@ -11,7 +11,7 @@ "astro": "astro" }, "dependencies": { - "@astrojs/markdoc": "^0.3.0", - "astro": "^2.6.2" + "@astrojs/markdoc": "^0.3.3", + "astro": "^2.7.0" } } diff --git a/examples/with-markdown-plugins/package.json b/examples/with-markdown-plugins/package.json index 73074cd65b41..3fcb9e09a78c 100644 --- a/examples/with-markdown-plugins/package.json +++ b/examples/with-markdown-plugins/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@astrojs/markdown-remark": "^2.2.1", - "astro": "^2.5.6", + "astro": "^2.7.0", "hast-util-select": "^5.0.5", "rehype-autolink-headings": "^6.1.1", "rehype-slug": "^5.1.0", diff --git a/examples/with-markdown-shiki/package.json b/examples/with-markdown-shiki/package.json index 3693a32f3f9d..11adc9386ced 100644 --- a/examples/with-markdown-shiki/package.json +++ b/examples/with-markdown-shiki/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^2.5.6" + "astro": "^2.7.0" } } diff --git a/examples/with-mdx/package.json b/examples/with-mdx/package.json index 5c92ed78fdef..d3aefd99f5e1 100644 --- a/examples/with-mdx/package.json +++ b/examples/with-mdx/package.json @@ -11,9 +11,9 @@ "astro": "astro" }, "dependencies": { - "@astrojs/mdx": "^0.19.5", + "@astrojs/mdx": "^0.19.7", "@astrojs/preact": "^2.2.1", - "astro": "^2.5.6", - "preact": "^10.13.2" + "astro": "^2.7.0", + "preact": "^10.15.1" } } diff --git a/examples/with-nanostores/package.json b/examples/with-nanostores/package.json index 6aacc796638f..aa127b5e4297 100644 --- a/examples/with-nanostores/package.json +++ b/examples/with-nanostores/package.json @@ -13,8 +13,8 @@ "dependencies": { "@astrojs/preact": "^2.2.1", "@nanostores/preact": "^0.4.1", - "astro": "^2.5.6", + "astro": "^2.7.0", "nanostores": "^0.8.1", - "preact": "^10.13.2" + "preact": "^10.15.1" } } diff --git a/examples/with-tailwindcss/package.json b/examples/with-tailwindcss/package.json index e8792dc38eff..a08f28c6ee1f 100644 --- a/examples/with-tailwindcss/package.json +++ b/examples/with-tailwindcss/package.json @@ -11,13 +11,13 @@ "astro": "astro" }, "dependencies": { - "@astrojs/mdx": "^0.19.5", - "@astrojs/tailwind": "^3.1.3", + "@astrojs/mdx": "^0.19.7", + "@astrojs/tailwind": "^4.0.0", "@types/canvas-confetti": "^1.6.0", - "astro": "^2.5.6", + "astro": "^2.7.0", "autoprefixer": "^10.4.14", "canvas-confetti": "^1.6.0", - "postcss": "^8.4.23", + "postcss": "^8.4.24", "tailwindcss": "^3.3.2" } } diff --git a/examples/with-vite-plugin-pwa/package.json b/examples/with-vite-plugin-pwa/package.json index 8182f61fe9a9..d1a0b5f4db3d 100644 --- a/examples/with-vite-plugin-pwa/package.json +++ b/examples/with-vite-plugin-pwa/package.json @@ -11,8 +11,8 @@ "astro": "astro" }, "dependencies": { - "astro": "^2.5.6", + "astro": "^2.7.0", "vite-plugin-pwa": "0.14.7", - "workbox-window": "^6.5.4" + "workbox-window": "^6.6.0" } } diff --git a/examples/with-vitest/package.json b/examples/with-vitest/package.json index 307feda3ec12..7eff098f6512 100644 --- a/examples/with-vitest/package.json +++ b/examples/with-vitest/package.json @@ -12,7 +12,7 @@ "test": "vitest" }, "dependencies": { - "astro": "^2.5.6", - "vitest": "^0.31.0" + "astro": "^2.7.0", + "vitest": "^0.31.4" } } diff --git a/package.json b/package.json index 5c369d22d448..b65d19e88979 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build": "turbo run build --filter=astro --filter=create-astro --filter=\"@astrojs/*\" --filter=\"@benchmark/*\"", "build:ci": "turbo run build:ci --filter=astro --filter=create-astro --filter=\"@astrojs/*\" --filter=\"@benchmark/*\"", "build:examples": "turbo run build --filter=\"@example/*\"", - "dev": "turbo run dev --parallel --filter=astro --filter=create-astro --filter=\"@astrojs/*\" --filter=\"@benchmark/*\"", + "dev": "turbo run dev --concurrency=40 --parallel --filter=astro --filter=create-astro --filter=\"@astrojs/*\" --filter=\"@benchmark/*\"", "format": "pnpm run format:code", "format:ci": "pnpm run format:imports && pnpm run format:code", "format:code": "prettier -w . --cache --plugin-search-dir=.", @@ -29,7 +29,7 @@ "test:e2e:match": "cd packages/astro && pnpm playwright install && pnpm run test:e2e:match", "benchmark": "astro-benchmark", "lint": "eslint --cache .", - "version": "changeset version && pnpm install --no-frozen-lockfile && pnpm run format", + "version": "changeset version && node ./scripts/deps/update-example-versions.js && pnpm install --no-frozen-lockfile && pnpm run format", "preinstall": "npx only-allow pnpm" }, "workspaces": [ @@ -39,9 +39,9 @@ ], "engines": { "node": ">=16.12.0", - "pnpm": ">=8.2.0" + "pnpm": ">=8.6.2" }, - "packageManager": "pnpm@8.6.0", + "packageManager": "pnpm@8.6.2", "pnpm": { "packageExtensions": { "svelte2tsx": { @@ -68,9 +68,6 @@ "allowAny": [ "astro" ] - }, - "patchedDependencies": { - "@changesets/cli@2.23.0": "patches/@changesets__cli@2.23.0.patch" } }, "dependencies": { @@ -78,22 +75,22 @@ "astro-benchmark": "workspace:*" }, "devDependencies": { - "@changesets/changelog-github": "0.4.4", - "@changesets/cli": "2.23.0", - "@types/node": "^18.7.21", - "@typescript-eslint/eslint-plugin": "^5.58.0", - "@typescript-eslint/parser": "^5.58.0", - "esbuild": "^0.17.12", - "eslint": "^8.38.0", + "@changesets/changelog-github": "^0.4.8", + "@changesets/cli": "^2.26.1", + "@types/node": "^18.16.18", + "@typescript-eslint/eslint-plugin": "^5.60.0", + "@typescript-eslint/parser": "^5.60.0", + "esbuild": "^0.17.19", + "eslint": "^8.43.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-no-only-tests": "^2.6.0", "eslint-plugin-prettier": "^4.2.1", "only-allow": "^1.1.1", "organize-imports-cli": "^0.10.0", "prettier": "^2.8.8", - "prettier-plugin-astro": "^0.8.0", + "prettier-plugin-astro": "^0.10.0", "tiny-glob": "^0.2.9", - "turbo": "^1.9.3", + "turbo": "^1.10.3", "typescript": "~5.0.2" } } diff --git a/packages/astro-prism/README.md b/packages/astro-prism/README.md index 1e8e92fa21a4..f5627d06200c 100644 --- a/packages/astro-prism/README.md +++ b/packages/astro-prism/README.md @@ -8,7 +8,7 @@ This package exports a component to support highlighting inside an Astro file. E ```astro --- -import {Β Prism } from "@astrojs/prism" +import { Prism } from '@astrojs/prism'; --- @@ -21,11 +21,14 @@ This package exports a `runHighlighterWithAstro` function to highlight while mak ```typescript import { runHighlighterWithAstro } from '@astrojs/prism'; -runHighlighterWithAstro(` +runHighlighterWithAstro( + ` --- const helloAstro = 'Hello, Astro!'; ---
    {helloAstro}
    -`, 'astro'); +`, + 'astro' +); ``` diff --git a/packages/astro-prism/package.json b/packages/astro-prism/package.json index c658e329385f..4ad55bf7f710 100644 --- a/packages/astro-prism/package.json +++ b/packages/astro-prism/package.json @@ -32,11 +32,11 @@ "astro-component" ], "dependencies": { - "prismjs": "^1.28.0" + "prismjs": "^1.29.0" }, "devDependencies": { - "astro-scripts": "workspace:*", - "@types/prismjs": "1.26.0" + "@types/prismjs": "1.26.0", + "astro-scripts": "workspace:*" }, "engines": { "node": ">=16.12.0" diff --git a/packages/astro-rss/README.md b/packages/astro-rss/README.md index 43adaad92b6e..47dfc1747635 100644 --- a/packages/astro-rss/README.md +++ b/packages/astro-rss/README.md @@ -36,14 +36,14 @@ export async function get(context) { // Pull in your project "site" from the endpoint context // https://docs.astro.build/en/reference/api-reference/#contextsite site: context.site, - items: posts.map(post => ({ + items: posts.map((post) => ({ // Assumes all RSS feed item properties are in post frontmatter ...post.data, // Generate a `url` from each post `slug` // This assumes all blog posts are rendered as `/blog/[slug]` routes // https://docs.astro.build/en/guides/content-collections/#generating-pages-from-content-collections link: `/blog/${post.slug}/`, - })) + })), }); } ``` @@ -180,9 +180,10 @@ By default, the library will add trailing slashes to the emitted URLs. To preven ```js import rss from '@astrojs/rss'; -export const get = () => rss({ - trailingSlash: false -}); +export const get = () => + rss({ + trailingSlash: false, + }); ``` ## `RSSFeedItem` @@ -193,12 +194,13 @@ An example feed item might look like: ```js const item = { - title: "Alpha Centauri: so close you can touch it", - link: "/blog/alpha-centuari", - pubDate: new Date("2023-06-04"), - description: "Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.", - categories: ["stars", "space"] -} + title: 'Alpha Centauri: so close you can touch it', + link: '/blog/alpha-centuari', + pubDate: new Date('2023-06-04'), + description: + 'Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.', + categories: ['stars', 'space'], +}; ``` ### `title` @@ -259,15 +261,16 @@ An object that defines the `title` and `url` of the original feed for items that ```js const item = { - title: "Alpha Centauri: so close you can touch it", - link: "/blog/alpha-centuari", - pubDate: new Date("2023-06-04"), - description: "Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.", - source: { - title: "The Galactic Times", - url: "https://galactictimes.space/feed.xml" - } -} + title: 'Alpha Centauri: so close you can touch it', + link: '/blog/alpha-centuari', + pubDate: new Date('2023-06-04'), + description: + 'Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.', + source: { + title: 'The Galactic Times', + url: 'https://galactictimes.space/feed.xml', + }, +}; ``` #### `source.title` @@ -290,16 +293,17 @@ An object to specify properties for an included media source (e.g. a podcast) wi ```js const item = { - title: "Alpha Centauri: so close you can touch it", - link: "/blog/alpha-centuari", - pubDate: new Date("2023-06-04"), - description: "Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.", - enclosure: { - url: "/media/alpha-centauri.aac", + title: 'Alpha Centauri: so close you can touch it', + link: '/blog/alpha-centuari', + pubDate: new Date('2023-06-04'), + description: + 'Alpha Centauri is a triple star system, containing Proxima Centauri, the closest star to our sun at only 4.24 light-years away.', + enclosure: { + url: '/media/alpha-centauri.aac', length: 124568, - type: "audio/aac" - } -} + type: 'audio/aac', + }, +}; ``` #### `enclosure.url` @@ -361,9 +365,7 @@ export async function get(context) { title: 'Buzz’s Blog', description: 'A humble Astronaut’s guide to the stars', site: context.site, - items: await pagesGlobToRssItems( - import.meta.glob('./blog/*.{md,mdx}'), - ), + items: await pagesGlobToRssItems(import.meta.glob('./blog/*.{md,mdx}')), }); } ``` diff --git a/packages/astro-rss/package.json b/packages/astro-rss/package.json index e9a97157c316..572f9649cb64 100644 --- a/packages/astro-rss/package.json +++ b/packages/astro-rss/package.json @@ -27,18 +27,18 @@ "test": "mocha --exit --timeout 20000" }, "devDependencies": { - "@types/chai": "^4.3.1", + "@types/chai": "^4.3.5", "@types/chai-as-promised": "^7.1.5", "@types/mocha": "^9.1.1", "astro": "workspace:*", "astro-scripts": "workspace:*", - "chai": "^4.3.6", + "chai": "^4.3.7", "chai-as-promised": "^7.1.1", - "chai-xml": "^0.4.0", + "chai-xml": "^0.4.1", "mocha": "^9.2.2" }, "dependencies": { - "fast-xml-parser": "^4.0.8", + "fast-xml-parser": "^4.2.5", "kleur": "^4.1.5" } } diff --git a/packages/astro/CHANGELOG.md b/packages/astro/CHANGELOG.md index ea3dbffc23bc..917271ba12c4 100644 --- a/packages/astro/CHANGELOG.md +++ b/packages/astro/CHANGELOG.md @@ -1,5 +1,77 @@ # astro +## 2.7.0 + +### Minor Changes + +- [#7353](https://github.com/withastro/astro/pull/7353) [`76fcdb84d`](https://github.com/withastro/astro/commit/76fcdb84dd828ac373b2dc739e57fadf650820fd) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Remove legacy handling for MDX content collections. Ensure you are using `@astrojs/mdx` v0.18 or above. + +- [#7385](https://github.com/withastro/astro/pull/7385) [`8e2923cc6`](https://github.com/withastro/astro/commit/8e2923cc6219eda01ca2c749f5c7fa2fe4319455) Thanks [@ematipico](https://github.com/ematipico)! - `Astro.locals` is now exposed to the adapter API. Node Adapter can now pass in a `locals` object in the SSR handler middleware. + +- [#7220](https://github.com/withastro/astro/pull/7220) [`459b5bd05`](https://github.com/withastro/astro/commit/459b5bd05f562238f7250520efe3cf0fa156bb45) Thanks [@ematipico](https://github.com/ematipico)! - Shipped a new SSR build configuration mode: `split`. + When enabled, Astro will "split" the single `entry.mjs` file and instead emit a separate file to render each individual page during the build process. + + These files will be emitted inside `dist/pages`, mirroring the directory structure of your page files in `src/pages/`, for example: + + ``` + β”œβ”€β”€ pages + β”‚ β”œβ”€β”€ blog + β”‚ β”‚ β”œβ”€β”€ entry._slug_.astro.mjs + β”‚ β”‚ └── entry.about.astro.mjs + β”‚ └── entry.index.astro.mjs + ``` + + To enable, set `build.split: true` in your Astro config: + + ```js + // src/astro.config.mjs + export default defineConfig({ + output: 'server', + adapter: node({ + mode: 'standalone', + }), + build: { + split: true, + }, + }); + ``` + +### Patch Changes + +- [#7438](https://github.com/withastro/astro/pull/7438) [`30bb36371`](https://github.com/withastro/astro/commit/30bb363713e3d2c50d0d4816d970aa93b836a3b0) Thanks [@bluwy](https://github.com/bluwy)! - Fix `astro:build:setup` hook `updateConfig` utility, where the configuration wasn't correctly updated when the hook was fired. + +- [#7436](https://github.com/withastro/astro/pull/7436) [`3943fa390`](https://github.com/withastro/astro/commit/3943fa390a0bd41317a673d0f841e0461c7499cd) Thanks [@kossidts](https://github.com/kossidts)! - Fix an issue related to the documentation. Destructure the argument of the function to customize the Astro dev server based on the command run. + +- [#7424](https://github.com/withastro/astro/pull/7424) [`7877a06d8`](https://github.com/withastro/astro/commit/7877a06d829305eed356fbb8bfd1ef578cd5466e) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Update internal types for more stable builds for Astro maintainers. + +- [#7427](https://github.com/withastro/astro/pull/7427) [`e314a04bf`](https://github.com/withastro/astro/commit/e314a04bfbf0526838b7c9aac452251b27d69719) Thanks [@ematipico](https://github.com/ematipico)! - Correctly emit the middleware code during the build phase. The file emitted is now `dist/middleware.mjs` + +- [#7423](https://github.com/withastro/astro/pull/7423) [`33cdc8622`](https://github.com/withastro/astro/commit/33cdc8622a56c8e5465b7a50f627ecc568870c6b) Thanks [@bmenant](https://github.com/bmenant)! - Ensure injected `/_image` endpoint for image optimization is not prerendered on hybrid output. + +## 2.6.6 + +### Patch Changes + +- [#7418](https://github.com/withastro/astro/pull/7418) [`2b34fc492`](https://github.com/withastro/astro/commit/2b34fc49282cbf5bf89de46359b51a67a5c4b8bb) Thanks [@ematipico](https://github.com/ematipico)! - Correctly type the option `server.open` + +- [#7429](https://github.com/withastro/astro/pull/7429) [`89a483520`](https://github.com/withastro/astro/commit/89a4835202f05d9571aeb42740dbe907a8afc28b) Thanks [@delucis](https://github.com/delucis)! - Fix telemetry reporting for integrations that return an array + +## 2.6.5 + +### Patch Changes + +- [#7414](https://github.com/withastro/astro/pull/7414) [`bb644834e`](https://github.com/withastro/astro/commit/bb644834ef03bc00048c7381f20a1c01388438e2) Thanks [@bluwy](https://github.com/bluwy)! - Simplify telemetry Vite version detection + +- [#7399](https://github.com/withastro/astro/pull/7399) [`d2020c29c`](https://github.com/withastro/astro/commit/d2020c29cf285e699f92143a70ffa30a85122bb4) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fix edge case where injected routes would cause builds to fail in a PNPM workspace + +## 2.6.4 + +### Patch Changes + +- [#7366](https://github.com/withastro/astro/pull/7366) [`42baf62e7`](https://github.com/withastro/astro/commit/42baf62e7ca0351a2f2c7d06ec58086f90519bb7) Thanks [@aappaapp](https://github.com/aappaapp)! - Fixed `RedirectConfig` type definition + +- [#7380](https://github.com/withastro/astro/pull/7380) [`1c7b63595`](https://github.com/withastro/astro/commit/1c7b6359563f5e83325121efb2e61915d818a35a) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix missing stacktraces for Zod errors + ## 2.6.3 ### Patch Changes diff --git a/packages/astro/README.md b/packages/astro/README.md index ebd4ca3c7767..9e3ff67c3ac9 100644 --- a/packages/astro/README.md +++ b/packages/astro/README.md @@ -8,10 +8,8 @@

    - ## Install - ```bash # Recommended! npm create astro@latest @@ -20,7 +18,7 @@ npm create astro@latest npm install --save-dev astro ``` -Looking for help? Start with our [Getting Started](https://docs.astro.build/en/getting-started/) guide. +Looking for help? Start with our [Getting Started](https://docs.astro.build/en/getting-started/) guide. Looking for quick examples? [Open a starter project](https://astro.new/) right in your browser. @@ -31,9 +29,10 @@ Visit our [official documentation](https://docs.astro.build/). ## Support Having trouble? Get help in the official [Astro Discord](https://astro.build/chat). + ## Contributing -**New contributors welcome!** Check out our [Contributors Guide](/CONTRIBUTING.md) for help getting started. +**New contributors welcome!** Check out our [Contributors Guide](/CONTRIBUTING.md) for help getting started. Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll help you get your first contribution in no time! @@ -42,5 +41,3 @@ Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll Astro is generously supported by [Netlify](https://www.netlify.com/), [Vercel](https://vercel.com/), and several other amazing organizations [listed here.](https://astro.build/) [❀️ Sponsor Astro! ❀️](https://github.com/withastro/.github/blob/main/FUNDING.md) - - diff --git a/packages/astro/src/content/template/virtual-mod.mjs b/packages/astro/content-module.template.mjs similarity index 100% rename from packages/astro/src/content/template/virtual-mod.mjs rename to packages/astro/content-module.template.mjs diff --git a/packages/astro/src/content/template/types.d.ts b/packages/astro/content-types.template.d.ts similarity index 100% rename from packages/astro/src/content/template/types.d.ts rename to packages/astro/content-types.template.d.ts diff --git a/packages/astro/e2e/fixtures/astro-component/package.json b/packages/astro/e2e/fixtures/astro-component/package.json index 165b38931d70..225864913953 100644 --- a/packages/astro/e2e/fixtures/astro-component/package.json +++ b/packages/astro/e2e/fixtures/astro-component/package.json @@ -6,6 +6,6 @@ "@astrojs/preact": "workspace:*", "@e2e/astro-linked-lib": "link:../_deps/astro-linked-lib", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/e2e/fixtures/astro-envs/package.json b/packages/astro/e2e/fixtures/astro-envs/package.json index e115f9c726e1..2fa703b969de 100644 --- a/packages/astro/e2e/fixtures/astro-envs/package.json +++ b/packages/astro/e2e/fixtures/astro-envs/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/vue": "workspace:*", "astro": "workspace:*", - "vue": "^3.2.40" + "vue": "^3.3.4" } } diff --git a/packages/astro/e2e/fixtures/client-only/package.json b/packages/astro/e2e/fixtures/client-only/package.json index 2a1e89ab3630..d072e8bdd801 100644 --- a/packages/astro/e2e/fixtures/client-only/package.json +++ b/packages/astro/e2e/fixtures/client-only/package.json @@ -11,11 +11,11 @@ "astro": "workspace:*" }, "dependencies": { - "preact": "^10.7.3", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "solid-js": "^1.4.3", - "svelte": "^3.48.0", - "vue": "^3.2.37" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/e2e/fixtures/error-cyclic/package.json b/packages/astro/e2e/fixtures/error-cyclic/package.json index a1c170e71090..9a3fbde601cc 100644 --- a/packages/astro/e2e/fixtures/error-cyclic/package.json +++ b/packages/astro/e2e/fixtures/error-cyclic/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/e2e/fixtures/error-sass/package.json b/packages/astro/e2e/fixtures/error-sass/package.json index f52820ad2b35..097bad23e698 100644 --- a/packages/astro/e2e/fixtures/error-sass/package.json +++ b/packages/astro/e2e/fixtures/error-sass/package.json @@ -4,6 +4,6 @@ "private": true, "dependencies": { "astro": "workspace:*", - "sass": "^1.52.2" + "sass": "^1.63.4" } } diff --git a/packages/astro/e2e/fixtures/errors/package.json b/packages/astro/e2e/fixtures/errors/package.json index cbcab17d333a..c535e5001de4 100644 --- a/packages/astro/e2e/fixtures/errors/package.json +++ b/packages/astro/e2e/fixtures/errors/package.json @@ -9,11 +9,11 @@ "@astrojs/svelte": "workspace:*", "@astrojs/vue": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "solid-js": "^1.5.6", - "svelte": "^3.50.1", - "vue": "^3.2.39" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/e2e/fixtures/hydration-race/package.json b/packages/astro/e2e/fixtures/hydration-race/package.json index 2d2ca0673de3..f1ab746c3e95 100644 --- a/packages/astro/e2e/fixtures/hydration-race/package.json +++ b/packages/astro/e2e/fixtures/hydration-race/package.json @@ -9,6 +9,6 @@ "dependencies": { "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/e2e/fixtures/lit-component/package.json b/packages/astro/e2e/fixtures/lit-component/package.json index 06e374a42cc5..961507fe8333 100644 --- a/packages/astro/e2e/fixtures/lit-component/package.json +++ b/packages/astro/e2e/fixtures/lit-component/package.json @@ -6,6 +6,6 @@ "@astrojs/lit": "workspace:*", "@webcomponents/template-shadowroot": "^0.2.1", "astro": "workspace:*", - "lit": "^2.7.0" + "lit": "^2.7.5" } } diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/package.json b/packages/astro/e2e/fixtures/multiple-frameworks/package.json index 91f95a97a498..1037db0f7249 100644 --- a/packages/astro/e2e/fixtures/multiple-frameworks/package.json +++ b/packages/astro/e2e/fixtures/multiple-frameworks/package.json @@ -13,12 +13,12 @@ }, "dependencies": { "@webcomponents/template-shadowroot": "^0.2.1", - "lit": "^2.7.0", - "preact": "^10.7.3", + "lit": "^2.7.5", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "solid-js": "^1.4.3", - "svelte": "^3.48.0", - "vue": "^3.2.37" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/e2e/fixtures/namespaced-component/package.json b/packages/astro/e2e/fixtures/namespaced-component/package.json index 96de360e265e..5f4fd82773c1 100644 --- a/packages/astro/e2e/fixtures/namespaced-component/package.json +++ b/packages/astro/e2e/fixtures/namespaced-component/package.json @@ -8,6 +8,6 @@ "astro": "workspace:*" }, "dependencies": { - "preact": "^10.7.3" + "preact": "^10.15.1" } } diff --git a/packages/astro/e2e/fixtures/nested-in-preact/package.json b/packages/astro/e2e/fixtures/nested-in-preact/package.json index 624316f913c8..2b6db13afcfa 100644 --- a/packages/astro/e2e/fixtures/nested-in-preact/package.json +++ b/packages/astro/e2e/fixtures/nested-in-preact/package.json @@ -11,11 +11,11 @@ "astro": "workspace:*" }, "dependencies": { - "preact": "^10.7.3", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "solid-js": "^1.4.3", - "svelte": "^3.48.0", - "vue": "^3.2.37" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/e2e/fixtures/nested-in-react/package.json b/packages/astro/e2e/fixtures/nested-in-react/package.json index 29ee37d2aae5..a1708a0edae4 100644 --- a/packages/astro/e2e/fixtures/nested-in-react/package.json +++ b/packages/astro/e2e/fixtures/nested-in-react/package.json @@ -11,11 +11,11 @@ "astro": "workspace:*" }, "dependencies": { - "preact": "^10.7.3", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "solid-js": "^1.4.3", - "svelte": "^3.48.0", - "vue": "^3.2.37" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/e2e/fixtures/nested-in-solid/package.json b/packages/astro/e2e/fixtures/nested-in-solid/package.json index 9a51cb0093bb..00c6cdaf777d 100644 --- a/packages/astro/e2e/fixtures/nested-in-solid/package.json +++ b/packages/astro/e2e/fixtures/nested-in-solid/package.json @@ -11,11 +11,11 @@ "astro": "workspace:*" }, "dependencies": { - "preact": "^10.7.3", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "solid-js": "^1.4.3", - "svelte": "^3.48.0", - "vue": "^3.2.37" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/e2e/fixtures/nested-in-svelte/package.json b/packages/astro/e2e/fixtures/nested-in-svelte/package.json index ea847e24b521..03a4c3e05bc9 100644 --- a/packages/astro/e2e/fixtures/nested-in-svelte/package.json +++ b/packages/astro/e2e/fixtures/nested-in-svelte/package.json @@ -11,11 +11,11 @@ "astro": "workspace:*" }, "dependencies": { - "preact": "^10.7.3", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "solid-js": "^1.4.3", - "svelte": "^3.48.0", - "vue": "^3.2.37" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/e2e/fixtures/nested-in-vue/package.json b/packages/astro/e2e/fixtures/nested-in-vue/package.json index 30a389574779..5a0d0273bd30 100644 --- a/packages/astro/e2e/fixtures/nested-in-vue/package.json +++ b/packages/astro/e2e/fixtures/nested-in-vue/package.json @@ -11,11 +11,11 @@ "astro": "workspace:*" }, "dependencies": { - "preact": "^10.7.3", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "solid-js": "^1.4.3", - "svelte": "^3.48.0", - "vue": "^3.2.37" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/e2e/fixtures/nested-recursive/package.json b/packages/astro/e2e/fixtures/nested-recursive/package.json index 3376ef59616f..19366d54559f 100644 --- a/packages/astro/e2e/fixtures/nested-recursive/package.json +++ b/packages/astro/e2e/fixtures/nested-recursive/package.json @@ -11,12 +11,12 @@ "astro": "workspace:*" }, "dependencies": { - "preact": "^10.7.3", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "solid-js": "^1.4.3", - "svelte": "^3.48.0", - "vue": "^3.2.36" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" }, "scripts": { "dev": "astro dev" diff --git a/packages/astro/e2e/fixtures/preact-compat-component/package.json b/packages/astro/e2e/fixtures/preact-compat-component/package.json index d83ad5292a90..c8092f549651 100644 --- a/packages/astro/e2e/fixtures/preact-compat-component/package.json +++ b/packages/astro/e2e/fixtures/preact-compat-component/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.7.3" + "preact": "^10.15.1" } } diff --git a/packages/astro/e2e/fixtures/preact-component/package.json b/packages/astro/e2e/fixtures/preact-component/package.json index 0d9b8402635f..8041f36088cc 100644 --- a/packages/astro/e2e/fixtures/preact-component/package.json +++ b/packages/astro/e2e/fixtures/preact-component/package.json @@ -3,9 +3,9 @@ "version": "0.0.0", "private": true, "dependencies": { - "@astrojs/preact": "workspace:*", "@astrojs/mdx": "workspace:*", + "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.7.3" + "preact": "^10.15.1" } } diff --git a/packages/astro/e2e/fixtures/solid-circular/package.json b/packages/astro/e2e/fixtures/solid-circular/package.json index a354ec9ec165..7cca82635952 100644 --- a/packages/astro/e2e/fixtures/solid-circular/package.json +++ b/packages/astro/e2e/fixtures/solid-circular/package.json @@ -7,6 +7,6 @@ "astro": "workspace:*" }, "devDependencies": { - "solid-js": "^1.4.3" + "solid-js": "^1.7.6" } } diff --git a/packages/astro/e2e/fixtures/solid-component/package.json b/packages/astro/e2e/fixtures/solid-component/package.json index aee1bddab7e9..eaa2e84eb7e1 100644 --- a/packages/astro/e2e/fixtures/solid-component/package.json +++ b/packages/astro/e2e/fixtures/solid-component/package.json @@ -6,6 +6,6 @@ "@astrojs/mdx": "workspace:*", "@astrojs/solid-js": "workspace:*", "astro": "workspace:*", - "solid-js": "^1.5.5" + "solid-js": "^1.7.6" } } diff --git a/packages/astro/e2e/fixtures/solid-recurse/package.json b/packages/astro/e2e/fixtures/solid-recurse/package.json index 61016bf36996..c1f3f1444aad 100644 --- a/packages/astro/e2e/fixtures/solid-recurse/package.json +++ b/packages/astro/e2e/fixtures/solid-recurse/package.json @@ -7,6 +7,6 @@ "astro": "workspace:*" }, "devDependencies": { - "solid-js": "^1.4.3" + "solid-js": "^1.7.6" } } diff --git a/packages/astro/e2e/fixtures/svelte-component/package.json b/packages/astro/e2e/fixtures/svelte-component/package.json index 999a248c70f2..0756f3f1427b 100644 --- a/packages/astro/e2e/fixtures/svelte-component/package.json +++ b/packages/astro/e2e/fixtures/svelte-component/package.json @@ -3,9 +3,9 @@ "version": "0.0.0", "private": true, "dependencies": { + "@astrojs/mdx": "workspace:*", "@astrojs/svelte": "workspace:*", "astro": "workspace:*", - "@astrojs/mdx": "workspace:*", - "svelte": "^3.48.0" + "svelte": "^3.59.1" } } diff --git a/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs b/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs index 473be9666e1e..1db9d12bb664 100644 --- a/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs +++ b/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs @@ -1,9 +1,14 @@ import { defineConfig } from 'astro/config'; import tailwind from '@astrojs/tailwind'; +import { fileURLToPath } from 'url'; // https://astro.build/config export default defineConfig({ - integrations: [tailwind()], + integrations: [ + tailwind({ + configFile: fileURLToPath(new URL('./tailwind.config.js', import.meta.url)), + }), + ], vite: { build: { assetsInlineLimit: 0, diff --git a/packages/astro/e2e/fixtures/tailwindcss/package.json b/packages/astro/e2e/fixtures/tailwindcss/package.json index 908c07915c4b..7e61c0d5c3be 100644 --- a/packages/astro/e2e/fixtures/tailwindcss/package.json +++ b/packages/astro/e2e/fixtures/tailwindcss/package.json @@ -6,7 +6,7 @@ "@astrojs/tailwind": "workspace:*", "astro": "workspace:*", "autoprefixer": "^10.4.14", - "postcss": "^8.4.23", + "postcss": "^8.4.24", "tailwindcss": "^3.3.2" } } diff --git a/packages/astro/e2e/fixtures/tailwindcss/postcss.config.js b/packages/astro/e2e/fixtures/tailwindcss/postcss.config.js deleted file mode 100644 index 7df5ecb39683..000000000000 --- a/packages/astro/e2e/fixtures/tailwindcss/postcss.config.js +++ /dev/null @@ -1,9 +0,0 @@ -const path = require('path'); -module.exports = { - plugins: { - tailwindcss: { - config: path.join(__dirname, 'tailwind.config.js'), // update this if your path differs! - }, - autoprefixer: {} - }, -}; diff --git a/packages/astro/e2e/fixtures/vue-component/package.json b/packages/astro/e2e/fixtures/vue-component/package.json index 2e0c72a6b88c..81e7997830e3 100644 --- a/packages/astro/e2e/fixtures/vue-component/package.json +++ b/packages/astro/e2e/fixtures/vue-component/package.json @@ -6,6 +6,6 @@ "@astrojs/mdx": "workspace:*", "@astrojs/vue": "workspace:*", "astro": "workspace:*", - "vue": "^3.2.39" + "vue": "^3.3.4" } } diff --git a/packages/astro/package.json b/packages/astro/package.json index 91bd00560873..e530f16bc4af 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -1,6 +1,6 @@ { "name": "astro", - "version": "2.6.3", + "version": "2.7.0", "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.", "type": "module", "author": "withastro", @@ -91,12 +91,13 @@ "client.d.ts", "client-base.d.ts", "client-image.d.ts", + "content-types.template.d.ts", + "content-module.template.mjs", "import-meta.d.ts", "astro-jsx.d.ts", "types.d.ts", "README.md", - "vendor", - "src/content/template" + "vendor" ], "scripts": { "prebuild": "astro-scripts prebuild --to-string \"src/runtime/server/astro-island.ts\" \"src/runtime/client/{idle,load,media,only,visible}.ts\"", @@ -112,35 +113,35 @@ "test:e2e:match": "playwright test -g" }, "dependencies": { - "@astrojs/compiler": "^1.4.0", + "@astrojs/compiler": "^1.5.0", "@astrojs/internal-helpers": "^0.1.0", "@astrojs/language-server": "^1.0.0", "@astrojs/markdown-remark": "^2.2.1", "@astrojs/telemetry": "^2.1.1", "@astrojs/webapi": "^2.2.0", - "@babel/core": "^7.21.8", - "@babel/generator": "^7.18.2", - "@babel/parser": "^7.18.4", - "@babel/plugin-transform-react-jsx": "^7.17.12", - "@babel/traverse": "^7.18.2", - "@babel/types": "^7.21.5", - "@types/babel__core": "^7.1.19", + "@babel/core": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/plugin-transform-react-jsx": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5", + "@types/babel__core": "^7.20.1", "@types/yargs-parser": "^21.0.0", - "acorn": "^8.8.2", + "acorn": "^8.9.0", "boxen": "^6.2.1", "chokidar": "^3.5.3", - "ci-info": "^3.3.1", + "ci-info": "^3.8.0", "common-ancestor-path": "^1.0.1", "cookie": "^0.5.0", "debug": "^4.3.4", - "deepmerge-ts": "^4.2.2", + "deepmerge-ts": "^4.3.0", "devalue": "^4.3.2", "diff": "^5.1.0", - "es-module-lexer": "^1.1.0", - "esbuild": "^0.17.18", + "es-module-lexer": "^1.3.0", + "esbuild": "^0.17.19", "estree-walker": "3.0.0", "execa": "^6.1.0", - "fast-glob": "^3.2.11", + "fast-glob": "^3.2.12", "github-slugger": "^2.0.0", "gray-matter": "^4.0.3", "html-escaper": "^3.0.3", @@ -148,67 +149,65 @@ "kleur": "^4.1.4", "magic-string": "^0.27.0", "mime": "^3.0.0", - "ora": "^6.1.0", + "ora": "^6.3.1", "p-limit": "^4.0.0", "path-to-regexp": "^6.2.1", "preferred-pm": "^3.0.3", "prompts": "^2.4.2", "rehype": "^12.0.1", - "semver": "^7.3.8", + "semver": "^7.5.3", "server-destroy": "^1.0.1", "shiki": "^0.14.1", - "slash": "^4.0.0", "string-width": "^5.1.2", - "strip-ansi": "^7.0.1", - "supports-esm": "^1.0.0", + "strip-ansi": "^7.1.0", "tsconfig-resolver": "^3.0.1", "typescript": "*", - "unist-util-visit": "^4.1.0", - "vfile": "^5.3.2", - "vite": "^4.3.1", + "unist-util-visit": "^4.1.2", + "vfile": "^5.3.7", + "vite": "^4.3.9", "vitefu": "^0.2.4", - "yargs-parser": "^21.0.1", + "yargs-parser": "^21.1.1", "zod": "^3.20.6" }, "devDependencies": { "@playwright/test": "^1.29.2", "@types/babel__generator": "^7.6.4", - "@types/babel__traverse": "^7.17.1", - "@types/chai": "^4.3.1", + "@types/babel__traverse": "^7.20.1", + "@types/chai": "^4.3.5", "@types/common-ancestor-path": "^1.0.0", "@types/connect": "^3.4.35", "@types/cookie": "^0.5.1", - "@types/debug": "^4.1.7", - "@types/diff": "^5.0.2", + "@types/debug": "^4.1.8", + "@types/diff": "^5.0.3", "@types/estree": "^0.0.51", "@types/hast": "^2.3.4", "@types/html-escaper": "^3.0.0", "@types/js-yaml": "^4.0.5", "@types/mime": "^2.0.3", "@types/mocha": "^9.1.1", - "@types/prettier": "^2.6.3", - "@types/prompts": "^2.0.14", + "@types/prettier": "^2.7.3", + "@types/prompts": "^2.4.4", "@types/resolve": "^1.20.2", "@types/rimraf": "^3.0.2", "@types/send": "^0.17.1", "@types/server-destroy": "^1.0.1", "@types/unist": "^2.0.6", "astro-scripts": "workspace:*", - "chai": "^4.3.6", - "cheerio": "^1.0.0-rc.11", + "chai": "^4.3.7", + "cheerio": "1.0.0-rc.12", "eol": "^0.9.1", - "memfs": "^3.4.7", + "memfs": "^3.5.3", "mocha": "^9.2.2", - "node-mocks-http": "^1.11.0", + "node-mocks-http": "^1.12.2", "rehype-autolink-headings": "^6.1.1", "rehype-slug": "^5.0.1", "rehype-toc": "^3.0.2", "remark-code-titles": "^0.1.2", - "rollup": "^3.9.0", - "sass": "^1.52.2", + "rollup": "^3.25.1", + "sass": "^1.63.4", "sharp": "^0.32.1", "srcset-parse": "^1.1.0", - "undici": "^5.22.0", + "undici": "^5.22.1", "unified": "^10.1.2" }, "peerDependencies": { diff --git a/packages/astro/performance/fixtures/md/package.json b/packages/astro/performance/fixtures/md/package.json index ffc37be1e7ec..a5efef0ef295 100644 --- a/packages/astro/performance/fixtures/md/package.json +++ b/packages/astro/performance/fixtures/md/package.json @@ -16,8 +16,8 @@ "dependencies": { "@astrojs/react": "workspace:*", "@performance/utils": "workspace:*", - "@types/react": "^18.0.21", - "@types/react-dom": "^18.0.6", + "@types/react": "^18.2.13", + "@types/react-dom": "^18.2.6", "astro": "workspace:*", "react": "^18.0.0", "react-dom": "^18.0.0" diff --git a/packages/astro/performance/fixtures/mdoc/package.json b/packages/astro/performance/fixtures/mdoc/package.json index 032396900752..612bd78c2074 100644 --- a/packages/astro/performance/fixtures/mdoc/package.json +++ b/packages/astro/performance/fixtures/mdoc/package.json @@ -17,8 +17,8 @@ "@astrojs/markdoc": "workspace:*", "@astrojs/react": "workspace:*", "@performance/utils": "workspace:*", - "@types/react": "^18.0.21", - "@types/react-dom": "^18.0.6", + "@types/react": "^18.2.13", + "@types/react-dom": "^18.2.6", "astro": "workspace:*", "react": "^18.0.0", "react-dom": "^18.0.0" diff --git a/packages/astro/performance/fixtures/mdx/package.json b/packages/astro/performance/fixtures/mdx/package.json index da2045b9f27d..59d98b27f788 100644 --- a/packages/astro/performance/fixtures/mdx/package.json +++ b/packages/astro/performance/fixtures/mdx/package.json @@ -17,8 +17,8 @@ "@astrojs/mdx": "workspace:*", "@astrojs/react": "workspace:*", "@performance/utils": "workspace:*", - "@types/react": "^18.0.21", - "@types/react-dom": "^18.0.6", + "@types/react": "^18.2.13", + "@types/react-dom": "^18.2.6", "astro": "workspace:*", "react": "^18.0.0", "react-dom": "^18.0.0" diff --git a/packages/astro/performance/package.json b/packages/astro/performance/package.json index 66193df49b4e..e09f291736c2 100644 --- a/packages/astro/performance/package.json +++ b/packages/astro/performance/package.json @@ -15,6 +15,6 @@ "cross-env": "^7.0.3", "kleur": "^4.1.5", "npm-run-all": "^4.1.5", - "yargs-parser": "^21.0.1" + "yargs-parser": "^21.1.1" } } diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 59594446c110..43069aa1795d 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -335,6 +335,22 @@ type ServerConfig = { * Set custom HTTP response headers to be sent in `astro dev` and `astro preview`. */ headers?: OutgoingHttpHeaders; + + /** + * @name server.open + * @type {boolean} + * @default `false` + * @version 2.1.8 + * @description + * Control whether the dev server should open in your browser window on startup. + * + * ```js + * { + * server: { open: true } + * } + * ``` + */ + open?: boolean; }; export interface ViteUserConfig extends vite.UserConfig { @@ -822,6 +838,30 @@ export interface AstroUserConfig { * ``` */ inlineStylesheets?: 'always' | 'auto' | 'never'; + + /** + * @docs + * @name build.split + * @type {boolean} + * @default {false} + * @version 2.7.0 + * @description + * Defines how the SSR code should be bundled when built. + * + * When `split` is `true`, Astro will emit a file for each page. + * Each file emitted will render only one page. The pages will be emitted + * inside a `dist/pages/` directory, and the emitted files will keep the same file paths + * of the `src/pages` directory. + * + * ```js + * { + * build: { + * split: true + * } + * } + * ``` + */ + split?: boolean; }; /** @@ -843,7 +883,7 @@ export interface AstroUserConfig { * ```js * { * // Example: Use the function syntax to customize based on command - * server: (command) => ({ port: command === 'dev' ? 3000 : 4000 }) + * server: ({ command }) => ({ port: command === 'dev' ? 3000 : 4000 }) * } * ``` */ @@ -878,6 +918,21 @@ export interface AstroUserConfig { * ``` */ + /** + * @name server.open + * @type {boolean} + * @default `false` + * @version 2.1.8 + * @description + * Control whether the dev server should open in your browser window on startup. + * + * ```js + * { + * server: { open: true } + * } + * ``` + */ + /** * @docs * @name server.headers @@ -1238,6 +1293,7 @@ export type InjectedScriptStage = 'before-hydration' | 'head-inline' | 'page' | export interface InjectedRoute { pattern: string; entryPoint: string; + prerender?: boolean; } export interface AstroConfig extends z.output { // Public: @@ -1793,7 +1849,14 @@ export interface AstroIntegration { 'astro:server:setup'?: (options: { server: vite.ViteDevServer }) => void | Promise; 'astro:server:start'?: (options: { address: AddressInfo }) => void | Promise; 'astro:server:done'?: () => void | Promise; - 'astro:build:ssr'?: (options: { manifest: SerializedSSRManifest }) => void | Promise; + 'astro:build:ssr'?: (options: { + manifest: SerializedSSRManifest; + /** + * This maps a {@link RouteData} to an {@link URL}, this URL represents + * the physical file you should import. + */ + entryPoints: Map; + }) => void | Promise; 'astro:build:start'?: () => void | Promise; 'astro:build:setup'?: (options: { vite: vite.InlineConfig; diff --git a/packages/astro/src/assets/utils/emitAsset.ts b/packages/astro/src/assets/utils/emitAsset.ts index 9b8d6fc08b3c..b1e01b3e4e22 100644 --- a/packages/astro/src/assets/utils/emitAsset.ts +++ b/packages/astro/src/assets/utils/emitAsset.ts @@ -1,8 +1,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; -import slash from 'slash'; -import { prependForwardSlash } from '../../core/path.js'; +import { prependForwardSlash, slash } from '../../core/path.js'; import { imageMetadata, type Metadata } from './metadata.js'; export async function emitESMImage( @@ -46,7 +45,6 @@ export async function emitESMImage( } function fileURLToNormalizedPath(filePath: URL): string { - // Uses `slash` package instead of Vite's `normalizePath` - // to avoid CJS bundling issues. + // Uses `slash` instead of Vite's `normalizePath` to avoid CJS bundling issues. return slash(fileURLToPath(filePath) + filePath.search).replace(/\\/g, '/'); } diff --git a/packages/astro/src/content/utils.ts b/packages/astro/src/content/utils.ts index 3cee0765c293..631f30e1f19f 100644 --- a/packages/astro/src/content/utils.ts +++ b/packages/astro/src/content/utils.ts @@ -24,7 +24,7 @@ import { createImage } from './runtime-assets.js'; /** * Amap from a collection + slug to the local file path. * This is used internally to resolve entry imports when using `getEntry()`. - * @see `src/content/virtual-mod.mjs` + * @see `content-module.template.mjs` */ export type ContentLookupMap = { [collectionName: string]: { type: 'content' | 'data'; entries: { [lookupId: string]: string } }; @@ -432,7 +432,6 @@ export type ContentPaths = { cacheDir: URL; typesTemplate: URL; virtualModTemplate: URL; - virtualAssetsModTemplate: URL; config: { exists: boolean; url: URL; @@ -444,14 +443,13 @@ export function getContentPaths( fs: typeof fsMod = fsMod ): ContentPaths { const configStats = search(fs, srcDir); - const templateDir = new URL('../../src/content/template/', import.meta.url); + const pkgBase = new URL('../../', import.meta.url); return { cacheDir: new URL('.astro/', root), contentDir: new URL('./content/', srcDir), assetsDir: new URL('./assets/', srcDir), - typesTemplate: new URL('types.d.ts', templateDir), - virtualModTemplate: new URL('virtual-mod.mjs', templateDir), - virtualAssetsModTemplate: new URL('virtual-mod-assets.mjs', templateDir), + typesTemplate: new URL('content-types.template.d.ts', pkgBase), + virtualModTemplate: new URL('content-module.template.mjs', pkgBase), config: configStats, }; } diff --git a/packages/astro/src/content/vite-plugin-content-imports.ts b/packages/astro/src/content/vite-plugin-content-imports.ts index aa2fec1797a5..98ad1ea76479 100644 --- a/packages/astro/src/content/vite-plugin-content-imports.ts +++ b/packages/astro/src/content/vite-plugin-content-imports.ts @@ -371,7 +371,6 @@ function stringifyEntryData(data: Record): string { }); } else { throw new AstroError({ - code: 99999, message: 'Unexpected error processing content collection data.', }); } diff --git a/packages/astro/src/content/vite-plugin-content-virtual-mod.ts b/packages/astro/src/content/vite-plugin-content-virtual-mod.ts index 33aae964d890..62ba612e962e 100644 --- a/packages/astro/src/content/vite-plugin-content-virtual-mod.ts +++ b/packages/astro/src/content/vite-plugin-content-virtual-mod.ts @@ -6,6 +6,7 @@ import pLimit from 'p-limit'; import type { Plugin } from 'vite'; import type { AstroSettings, ContentEntryType } from '../@types/astro.js'; import { AstroError, AstroErrorData } from '../core/errors/index.js'; +import { appendForwardSlash } from '../core/path.js'; import { rootRelativePath } from '../core/util.js'; import { VIRTUAL_MODULE_ID } from './consts.js'; import { @@ -94,7 +95,7 @@ export function astroContentVirtualModPlugin({ /** * Generate a map from a collection + slug to the local file path. * This is used internally to resolve entry imports when using `getEntry()`. - * @see `src/content/virtual-mod.mjs` + * @see `content-module.template.mjs` */ export async function getStringifiedLookupMap({ contentPaths, @@ -209,5 +210,10 @@ const UnexpectedLookupMapError = new AstroError({ function globWithUnderscoresIgnored(relContentDir: string, exts: string[]): string[] { const extGlob = getExtGlob(exts); - return [`${relContentDir}/**/*${extGlob}`, `!**/_*/**${extGlob}`, `!**/_*${extGlob}`]; + const contentDir = appendForwardSlash(relContentDir); + return [ + `${contentDir}**/*${extGlob}`, + `!${contentDir}_*/**${extGlob}`, + `!${contentDir}_*${extGlob}`, + ]; } diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts index 56d22eafcdf2..ae0c3fb00e78 100644 --- a/packages/astro/src/core/app/index.ts +++ b/packages/astro/src/core/app/index.ts @@ -1,13 +1,12 @@ +import mime from 'mime'; import type { EndpointHandler, ManifestData, MiddlewareResponseHandler, RouteData, SSRElement, + SSRManifest, } from '../../@types/astro'; -import type { RouteInfo, SSRManifest as Manifest } from './types'; - -import mime from 'mime'; import type { SinglePageBuiltModule } from '../build/types'; import { attachToResponse, getSetCookiesFromResponse } from '../cookies/index.js'; import { callEndpoint, createAPIContext } from '../endpoint/index.js'; @@ -29,6 +28,7 @@ import { createStylesheetElementSet, } from '../render/ssr-element.js'; import { matchRoute } from '../routing/match.js'; +import type { RouteInfo } from './types'; export { deserializeManifest } from './common.js'; const clientLocalsSymbol = Symbol.for('astro.locals'); @@ -41,7 +41,7 @@ export interface MatchOptions { export class App { #env: Environment; - #manifest: Manifest; + #manifest: SSRManifest; #manifestData: ManifestData; #routeDataToRouteInfo: Map; #encoder = new TextEncoder(); @@ -52,7 +52,7 @@ export class App { #base: string; #baseWithoutTrailingSlash: string; - constructor(manifest: Manifest, streaming = true) { + constructor(manifest: SSRManifest, streaming = true) { this.#manifest = manifest; this.#manifestData = { routes: manifest.routes.map((route) => route.routeData), @@ -115,7 +115,7 @@ export class App { return undefined; } } - async render(request: Request, routeData?: RouteData): Promise { + async render(request: Request, routeData?: RouteData, locals?: object): Promise { let defaultStatus = 200; if (!routeData) { routeData = this.match(request); @@ -131,7 +131,7 @@ export class App { } } - Reflect.set(request, clientLocalsSymbol, {}); + Reflect.set(request, clientLocalsSymbol, locals ?? {}); // Use the 404 status code for 404.astro components if (routeData.route === '/404') { @@ -175,14 +175,23 @@ export class App { if (route.type === 'redirect') { return RedirectSinglePageBuiltModule; } else { - const importComponentInstance = this.#manifest.pageMap.get(route.component); - if (!importComponentInstance) { + if (this.#manifest.pageMap) { + const importComponentInstance = this.#manifest.pageMap.get(route.component); + if (!importComponentInstance) { + throw new Error( + `Unexpectedly unable to find a component instance for route ${route.route}` + ); + } + const pageModule = await importComponentInstance(); + return pageModule; + } else if (this.#manifest.pageModule) { + const importComponentInstance = this.#manifest.pageModule; + return importComponentInstance; + } else { throw new Error( - `Unexpectedly unable to find a component instance for route ${route.route}` + "Astro couldn't find the correct page to render, probably because it wasn't correctly mapped for SSR usage. This is an internal error, please file an issue." ); } - const built = await importComponentInstance(); - return built; } } @@ -236,15 +245,14 @@ export class App { site: this.#env.site, adapterName: this.#env.adapterName, }); - const onRequest = page.middleware?.onRequest; let response; - if (onRequest) { + if (page.onRequest) { response = await callMiddleware( this.#env.logging, - onRequest as MiddlewareResponseHandler, + page.onRequest as MiddlewareResponseHandler, apiContext, () => { - return renderPage({ mod, renderContext, env: this.#env, apiContext }); + return renderPage({ mod, renderContext, env: this.#env, cookies: apiContext.cookies }); } ); } else { @@ -252,7 +260,7 @@ export class App { mod, renderContext, env: this.#env, - apiContext, + cookies: apiContext.cookies, }); } Reflect.set(request, responseSentSymbol, true); @@ -287,7 +295,7 @@ export class App { mod: handler as any, }); - const result = await callEndpoint(handler, this.#env, ctx, this.#logging, page.middleware); + const result = await callEndpoint(handler, this.#env, ctx, this.#logging, page.onRequest); if (result.type === 'response') { if (result.response.headers.get('X-Astro-Response') === 'Not-Found') { diff --git a/packages/astro/src/core/app/node.ts b/packages/astro/src/core/app/node.ts index 6bd2677a79e0..40b7b4e7ce6e 100644 --- a/packages/astro/src/core/app/node.ts +++ b/packages/astro/src/core/app/node.ts @@ -41,11 +41,12 @@ export class NodeApp extends App { match(req: NodeIncomingMessage | Request, opts: MatchOptions = {}) { return super.match(req instanceof Request ? req : createRequestFromNodeRequest(req), opts); } - render(req: NodeIncomingMessage | Request, routeData?: RouteData) { + render(req: NodeIncomingMessage | Request, routeData?: RouteData, locals?: object) { if (typeof req.body === 'string' && req.body.length > 0) { return super.render( req instanceof Request ? req : createRequestFromNodeRequest(req, Buffer.from(req.body)), - routeData + routeData, + locals ); } @@ -54,7 +55,8 @@ export class NodeApp extends App { req instanceof Request ? req : createRequestFromNodeRequest(req, Buffer.from(JSON.stringify(req.body))), - routeData + routeData, + locals ); } @@ -75,13 +77,15 @@ export class NodeApp extends App { return reqBodyComplete.then(() => { return super.render( req instanceof Request ? req : createRequestFromNodeRequest(req, body), - routeData + routeData, + locals ); }); } return super.render( req instanceof Request ? req : createRequestFromNodeRequest(req), - routeData + routeData, + locals ); } } diff --git a/packages/astro/src/core/app/types.ts b/packages/astro/src/core/app/types.ts index 1283f1a10f26..9af15bf50252 100644 --- a/packages/astro/src/core/app/types.ts +++ b/packages/astro/src/core/app/types.ts @@ -30,16 +30,16 @@ export interface RouteInfo { export type SerializedRouteInfo = Omit & { routeData: SerializedRouteData; }; -type ImportComponentInstance = () => Promise; -export interface SSRManifest { +export type ImportComponentInstance = () => Promise; + +export type SSRManifest = { adapterName: string; routes: RouteInfo[]; site?: string; base?: string; assetsPrefix?: string; markdown: MarkdownRenderingOptions; - pageMap: Map; renderers: SSRLoadedRenderer[]; /** * Map of directive name (e.g. `load`) to the directive script code @@ -48,7 +48,9 @@ export interface SSRManifest { entryModules: Record; assets: Set; componentMetadata: SSRResult['componentMetadata']; -} + pageModule?: SinglePageBuiltModule; + pageMap?: Map; +}; export type SerializedSSRManifest = Omit< SSRManifest, diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index c1fd34654a10..551f7afa8395 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -5,13 +5,13 @@ import type { OutputAsset, OutputChunk } from 'rollup'; import { fileURLToPath } from 'url'; import type { AstroConfig, - AstroMiddlewareInstance, AstroSettings, ComponentInstance, EndpointHandler, EndpointOutput, GetStaticPathsItem, ImageTransform, + MiddlewareHandler, MiddlewareResponseHandler, RouteData, RouteType, @@ -29,6 +29,7 @@ import { type BuildInternals, } from '../../core/build/internal.js'; import { + isRelativePath, prependForwardSlash, removeLeadingForwardSlash, removeTrailingForwardSlash, @@ -228,7 +229,7 @@ async function generatePage( .reduce(mergeInlineCss, []); const pageModulePromise = ssrEntry.page; - const middleware = ssrEntry.middleware; + const onRequest = ssrEntry.onRequest; if (!pageModulePromise) { throw new Error( @@ -252,14 +253,18 @@ async function generatePage( }; const icon = pageData.route.type === 'page' ? green('β–Ά') : magenta('Ξ»'); - info(opts.logging, null, `${icon} ${pageData.route.component}`); + if (isRelativePath(pageData.route.component)) { + info(opts.logging, null, `${icon} ${pageData.route.route}`); + } else { + info(opts.logging, null, `${icon} ${pageData.route.component}`); + } // Get paths for the route, calling getStaticPaths if needed. const paths = await getPathsForRoute(pageData, pageModule, opts, builtPaths); for (let i = 0; i < paths.length; i++) { const path = paths[i]; - await generatePath(path, opts, generationOptions, middleware); + await generatePath(path, opts, generationOptions, onRequest); const timeEnd = performance.now(); const timeChange = getTimeStat(timeStart, timeEnd); const timeIncrease = `(+${timeChange})`; @@ -443,7 +448,7 @@ async function generatePath( pathname: string, opts: StaticBuildOptions, gopts: GeneratePathOptions, - middleware?: AstroMiddlewareInstance + onRequest?: MiddlewareHandler ) { const { settings, logging, origin, routeCache } = opts; const { @@ -564,7 +569,7 @@ async function generatePath( env, renderContext, logging, - middleware as AstroMiddlewareInstance + onRequest as MiddlewareHandler ); if (result.type === 'response') { @@ -588,7 +593,6 @@ async function generatePath( adapterName: env.adapterName, }); - const onRequest = middleware?.onRequest; if (onRequest) { response = await callMiddleware( env.logging, @@ -599,8 +603,8 @@ async function generatePath( mod, renderContext, env, - apiContext, isCompressHTML: settings.config.compressHTML, + cookies: apiContext.cookies, }); } ); @@ -609,8 +613,8 @@ async function generatePath( mod, renderContext, env, - apiContext, isCompressHTML: settings.config.compressHTML, + cookies: apiContext.cookies, }); } } catch (err) { diff --git a/packages/astro/src/core/build/internal.ts b/packages/astro/src/core/build/internal.ts index 4cf40cb9ad83..8c7da07d4319 100644 --- a/packages/astro/src/core/build/internal.ts +++ b/packages/astro/src/core/build/internal.ts @@ -1,13 +1,10 @@ import type { Rollup } from 'vite'; -import type { SSRResult } from '../../@types/astro'; +import type { RouteData, SSRResult } from '../../@types/astro'; import type { PageOptions } from '../../vite-plugin-astro/types'; import { prependForwardSlash, removeFileExtension } from '../path.js'; import { viteID } from '../util.js'; -import { - ASTRO_PAGE_EXTENSION_POST_PATTERN, - ASTRO_PAGE_MODULE_ID, - getVirtualModulePageIdFromPath, -} from './plugins/plugin-pages.js'; +import { ASTRO_PAGE_MODULE_ID, getVirtualModulePageIdFromPath } from './plugins/plugin-pages.js'; +import { ASTRO_PAGE_EXTENSION_POST_PATTERN } from './plugins/util.js'; import type { PageBuildData, StylesheetAsset, ViteID } from './types'; export interface BuildInternals { @@ -84,6 +81,8 @@ export interface BuildInternals { staticFiles: Set; // The SSR entry chunk. Kept in internals to share between ssr/client build steps ssrEntryChunk?: Rollup.OutputChunk; + entryPoints: Map; + ssrSplitEntryChunks: Map; componentMetadata: SSRResult['componentMetadata']; } @@ -114,6 +113,8 @@ export function createBuildInternals(): BuildInternals { discoveredScripts: new Set(), staticFiles: new Set(), componentMetadata: new Map(), + ssrSplitEntryChunks: new Map(), + entryPoints: new Map(), }; } diff --git a/packages/astro/src/core/build/plugins/README.md b/packages/astro/src/core/build/plugins/README.md index 32ac8c448f6f..1451581631f1 100644 --- a/packages/astro/src/core/build/plugins/README.md +++ b/packages/astro/src/core/build/plugins/README.md @@ -2,12 +2,11 @@ This file serves as developer documentation to explain how the internal plugins work - ## `plugin-middleware` This plugin is responsible to retrieve the `src/middleware.{ts.js}` file and emit an entry point during the SSR build. -The final file is emitted only if the user has the middleware file. The final name of the file is `middleware.mjs`. +The final file is emitted only if the user has the middleware file. The final name of the file is `middleware.mjs`. This is **not** a virtual module. The plugin will try to resolve the physical file. @@ -20,7 +19,12 @@ The emitted file is called `renderers.mjs`. The emitted file has content similar to: ```js -const renderers = [Object.assign({"name":"astro:jsx","serverEntrypoint":"astro/jsx/server.js","jsxImportSource":"astro"}, { ssr: server_default }),]; +const renderers = [ + Object.assign( + { name: 'astro:jsx', serverEntrypoint: 'astro/jsx/server.js', jsxImportSource: 'astro' }, + { ssr: server_default } + ), +]; export { renderers }; ``` @@ -32,19 +36,20 @@ This plugin is responsible to collect all pages inside an Astro application, and This plugin **will emit code** only when building a static site. In order to achieve that, the plugin emits these pages as **virtual modules**. Doing so allows us to bypass: + - rollup resolution of the files - possible plugins that get triggered when the name of the module has an extension e.g. `.astro` The plugin does the following operations: + - loop through all the pages and collects their paths; - with each path, we create a new [string](#plugin-pages-mapping-resolution) that will serve and virtual module for that particular page - when resolving the page, we check if the `id` of the module starts with `@astro-page` - once the module is resolved, we emit [the code of the module](#plugin-pages-code-generation) - ### `plugin pages` mapping resolution -The mapping is as follows: +The mapping is as follows: ``` src/pages/index.astro => @astro-page:src/pages/index@_@astro @@ -53,14 +58,13 @@ src/pages/index.astro => @astro-page:src/pages/index@_@astro 1. We add a fixed prefix, which is used as virtual module naming convention; 2. We replace the dot that belongs extension with an arbitrary string. -This kind of patterns will then allow us to retrieve the path physical path of the +This kind of patterns will then allow us to retrieve the path physical path of the file back from that string. This is important for the [code generation](#plugin-pages-code-generation) - - ### `plugin pages` code generation When generating the code of the page, we will import and export the following modules: + - the `renderers.mjs` - the `middleware.mjs` - the page, via dynamic import @@ -79,6 +83,7 @@ export { middleware, page }; ``` If we have a `pages/` folder that looks like this: + ``` β”œβ”€β”€ blog β”‚ β”œβ”€β”€ first.astro @@ -89,8 +94,9 @@ If we have a `pages/` folder that looks like this: └── second.astro ``` -The emitted entry points will be stored inside a `pages/` folder, and they +The emitted entry points will be stored inside a `pages/` folder, and they will look like this: + ``` β”œβ”€β”€ _astro β”‚ β”œβ”€β”€ first.132e69e0.css @@ -117,7 +123,7 @@ will look like this: └── renderers.mjs ``` -Of course, all these files will be deleted by Astro at the end build. +Of course, all these files will be deleted by Astro at the end build. ## `plugin-ssr` (WIP) @@ -130,15 +136,14 @@ The plugin will collect all the [virtual pages](#plugin-pages) and create a JavaScript `Map`. These map will look like this: ```js -const _page$0 = () => import("../chunks/.mjs") -const _page$1 = () => import("../chunks/.mjs") +const _page$0 = () => import('../chunks/.mjs'); +const _page$1 = () => import('../chunks/.mjs'); const pageMap = new Map([ - ["src/pages/index.astro", _page$0], - ["src/pages/about.astro", _page$1], -]) + ['src/pages/index.astro', _page$0], + ['src/pages/about.astro', _page$1], +]); ``` It will also import the [`renderers`](#plugin-renderers) virtual module and the [`middleware`](#plugin-middleware) virtual module. - diff --git a/packages/astro/src/core/build/plugins/index.ts b/packages/astro/src/core/build/plugins/index.ts index f6fcacfb1b7d..4563bb6964d7 100644 --- a/packages/astro/src/core/build/plugins/index.ts +++ b/packages/astro/src/core/build/plugins/index.ts @@ -11,7 +11,7 @@ import { pluginMiddleware } from './plugin-middleware.js'; import { pluginPages } from './plugin-pages.js'; import { pluginPrerender } from './plugin-prerender.js'; import { pluginRenderers } from './plugin-renderers.js'; -import { pluginSSR } from './plugin-ssr.js'; +import { pluginSSR, pluginSSRSplit } from './plugin-ssr.js'; export function registerAllPlugins({ internals, options, register }: AstroBuildPluginContainer) { register(pluginComponentEntry(internals)); @@ -27,4 +27,5 @@ export function registerAllPlugins({ internals, options, register }: AstroBuildP register(astroConfigBuildPlugin(options, internals)); register(pluginHoistedScripts(options, internals)); register(pluginSSR(options, internals)); + register(pluginSSRSplit(options, internals)); } diff --git a/packages/astro/src/core/build/plugins/plugin-middleware.ts b/packages/astro/src/core/build/plugins/plugin-middleware.ts index 6bd63b44f3a0..7e3ea8cb9d9a 100644 --- a/packages/astro/src/core/build/plugins/plugin-middleware.ts +++ b/packages/astro/src/core/build/plugins/plugin-middleware.ts @@ -1,11 +1,14 @@ import type { Plugin as VitePlugin } from 'vite'; import { MIDDLEWARE_PATH_SEGMENT_NAME } from '../../constants.js'; +import { addRollupInput } from '../add-rollup-input.js'; import type { BuildInternals } from '../internal.js'; import type { AstroBuildPlugin } from '../plugin'; import type { StaticBuildOptions } from '../types'; export const MIDDLEWARE_MODULE_ID = '@astro-middleware'; +const EMPTY_MIDDLEWARE = '\0empty-middleware'; + export function vitePluginMiddleware( opts: StaticBuildOptions, _internals: BuildInternals @@ -13,6 +16,10 @@ export function vitePluginMiddleware( return { name: '@astro/plugin-middleware', + options(options) { + return addRollupInput(options, [MIDDLEWARE_MODULE_ID]); + }, + async resolveId(id) { if (id === MIDDLEWARE_MODULE_ID) { const middlewareId = await this.resolve( @@ -20,8 +27,19 @@ export function vitePluginMiddleware( ); if (middlewareId) { return middlewareId.id; + } else { + return EMPTY_MIDDLEWARE; } } + if (id === EMPTY_MIDDLEWARE) { + return EMPTY_MIDDLEWARE; + } + }, + + load(id) { + if (id === EMPTY_MIDDLEWARE) { + return 'export const onRequest = undefined'; + } }, }; } diff --git a/packages/astro/src/core/build/plugins/plugin-pages.ts b/packages/astro/src/core/build/plugins/plugin-pages.ts index f767a9c5bd79..c40449a39e2e 100644 --- a/packages/astro/src/core/build/plugins/plugin-pages.ts +++ b/packages/astro/src/core/build/plugins/plugin-pages.ts @@ -7,12 +7,10 @@ import type { AstroBuildPlugin } from '../plugin'; import type { StaticBuildOptions } from '../types'; import { MIDDLEWARE_MODULE_ID } from './plugin-middleware.js'; import { RENDERERS_MODULE_ID } from './plugin-renderers.js'; +import { ASTRO_PAGE_EXTENSION_POST_PATTERN, getPathFromVirtualModulePageName } from './util.js'; export const ASTRO_PAGE_MODULE_ID = '@astro-page:'; -export const ASTRO_PAGE_RESOLVED_MODULE_ID = '\0@astro-page:'; - -// This is an arbitrary string that we are going to replace the dot of the extension -export const ASTRO_PAGE_EXTENSION_POST_PATTERN = '@_@'; +export const ASTRO_PAGE_RESOLVED_MODULE_ID = '\0' + ASTRO_PAGE_MODULE_ID; /** * 1. We add a fixed prefix, which is used as virtual module naming convention; @@ -64,13 +62,8 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V if (id.startsWith(ASTRO_PAGE_RESOLVED_MODULE_ID)) { const imports: string[] = []; const exports: string[] = []; - - // we remove the module name prefix from id, this will result into a string that will start with "src/..." - const pageName = id.slice(ASTRO_PAGE_RESOLVED_MODULE_ID.length); - // We replaced the `.` of the extension with ASTRO_PAGE_EXTENSION_POST_PATTERN, let's replace it back - const pageData = internals.pagesByComponent.get( - `${pageName.replace(ASTRO_PAGE_EXTENSION_POST_PATTERN, '.')}` - ); + const pageName = getPathFromVirtualModulePageName(ASTRO_PAGE_RESOLVED_MODULE_ID, id); + const pageData = internals.pagesByComponent.get(pageName); if (pageData) { const resolvedPage = await this.resolve(pageData.moduleSpecifier); if (resolvedPage) { @@ -82,8 +75,8 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V const middlewareModule = await this.resolve(MIDDLEWARE_MODULE_ID); if (middlewareModule) { - imports.push(`import * as middleware from "${middlewareModule.id}";`); - exports.push(`export { middleware };`); + imports.push(`import { onRequest } from "${middlewareModule.id}";`); + exports.push(`export { onRequest };`); } return `${imports.join('\n')}${exports.join('\n')}`; diff --git a/packages/astro/src/core/build/plugins/plugin-ssr.ts b/packages/astro/src/core/build/plugins/plugin-ssr.ts index 3c2825e4c63c..486c314340b7 100644 --- a/packages/astro/src/core/build/plugins/plugin-ssr.ts +++ b/packages/astro/src/core/build/plugins/plugin-ssr.ts @@ -1,7 +1,8 @@ import glob from 'fast-glob'; -import { fileURLToPath } from 'url'; +import { join } from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; import type { Plugin as VitePlugin } from 'vite'; -import type { AstroAdapter } from '../../../@types/astro'; +import type { AstroAdapter, AstroConfig } from '../../../@types/astro'; import { runHookBuildSsr } from '../../../integrations/index.js'; import { isServerLikeOutput } from '../../../prerender/utils.js'; import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../../vite-plugin-scripts/index.js'; @@ -13,9 +14,10 @@ import { addRollupInput } from '../add-rollup-input.js'; import { getOutFile, getOutFolder } from '../common.js'; import { cssOrder, mergeInlineCss, type BuildInternals } from '../internal.js'; import type { AstroBuildPlugin } from '../plugin'; -import type { StaticBuildOptions } from '../types'; -import { getVirtualModulePageNameFromPath } from './plugin-pages.js'; +import type { OutputChunk, StaticBuildOptions } from '../types'; +import { ASTRO_PAGE_MODULE_ID } from './plugin-pages.js'; import { RENDERERS_MODULE_ID } from './plugin-renderers.js'; +import { getPathFromVirtualModulePageName, getVirtualModulePageNameFromPath } from './util.js'; export const SSR_VIRTUAL_MODULE_ID = '@astrojs-ssr-virtual-entry'; const RESOLVED_SSR_VIRTUAL_MODULE_ID = '\0' + SSR_VIRTUAL_MODULE_ID; @@ -28,7 +30,7 @@ function vitePluginSSR( options: StaticBuildOptions ): VitePlugin { return { - name: '@astrojs/vite-plugin-astro-ssr', + name: '@astrojs/vite-plugin-astro-ssr-server', enforce: 'post', options(opts) { return addRollupInput(opts, [SSR_VIRTUAL_MODULE_ID]); @@ -54,7 +56,7 @@ function vitePluginSSR( if (routeIsRedirect(pageData.route)) { continue; } - const virtualModuleName = getVirtualModulePageNameFromPath(path); + const virtualModuleName = getVirtualModulePageNameFromPath(ASTRO_PAGE_MODULE_ID, path); let module = await this.resolve(virtualModuleName); if (module) { const variable = `_page${i}`; @@ -71,12 +73,226 @@ function vitePluginSSR( contents.push(`const pageMap = new Map([${pageMap.join(',')}]);`); exports.push(`export { pageMap }`); - const content = `import * as adapter from '${adapter.serverEntrypoint}'; + const ssrCode = generateSSRCode(options.settings.config, adapter); + imports.push(...ssrCode.imports); + contents.push(...ssrCode.contents); + return `${imports.join('\n')}${contents.join('\n')}${exports.join('\n')}`; + } + return void 0; + }, + async generateBundle(_opts, bundle) { + // Add assets from this SSR chunk as well. + for (const [_chunkName, chunk] of Object.entries(bundle)) { + if (chunk.type === 'asset') { + internals.staticFiles.add(chunk.fileName); + } + } + + for (const [chunkName, chunk] of Object.entries(bundle)) { + if (chunk.type === 'asset') { + continue; + } + if (chunk.modules[RESOLVED_SSR_VIRTUAL_MODULE_ID]) { + internals.ssrEntryChunk = chunk; + delete bundle[chunkName]; + } + } + }, + }; +} + +export function pluginSSR( + options: StaticBuildOptions, + internals: BuildInternals +): AstroBuildPlugin { + const ssr = isServerLikeOutput(options.settings.config); + return { + build: 'ssr', + hooks: { + 'build:before': () => { + let vitePlugin = + ssr && !options.settings.config.build.split + ? vitePluginSSR(internals, options.settings.adapter!, options) + : undefined; + + return { + enforce: 'after-user-plugins', + vitePlugin, + }; + }, + 'build:post': async ({ mutate }) => { + if (!ssr) { + return; + } + + if (options.settings.config.build.split) { + return; + } + + if (!internals.ssrEntryChunk) { + throw new Error(`Did not generate an entry chunk for SSR`); + } + // Mutate the filename + internals.ssrEntryChunk.fileName = options.settings.config.build.serverEntry; + + const manifest = await createManifest(options, internals); + await runHookBuildSsr({ + config: options.settings.config, + manifest, + logging: options.logging, + entryPoints: internals.entryPoints, + }); + const code = injectManifest(manifest, internals.ssrEntryChunk); + mutate(internals.ssrEntryChunk, 'server', code); + }, + }, + }; +} + +export const SPLIT_MODULE_ID = '@astro-page-split:'; +export const RESOLVED_SPLIT_MODULE_ID = '\0@astro-page-split:'; + +function vitePluginSSRSplit( + internals: BuildInternals, + adapter: AstroAdapter, + options: StaticBuildOptions +): VitePlugin { + return { + name: '@astrojs/vite-plugin-astro-ssr-split', + enforce: 'post', + options(opts) { + if (options.settings.config.build.split) { + const inputs: Set = new Set(); + + for (const path of Object.keys(options.allPages)) { + inputs.add(getVirtualModulePageNameFromPath(SPLIT_MODULE_ID, path)); + } + + return addRollupInput(opts, Array.from(inputs)); + } + }, + resolveId(id) { + if (id.startsWith(SPLIT_MODULE_ID)) { + return '\0' + id; + } + }, + async load(id) { + if (id.startsWith(RESOLVED_SPLIT_MODULE_ID)) { + const { + settings: { config }, + allPages, + } = options; + const imports: string[] = []; + const contents: string[] = []; + const exports: string[] = []; + + const path = getPathFromVirtualModulePageName(RESOLVED_SPLIT_MODULE_ID, id); + const virtualModuleName = getVirtualModulePageNameFromPath(ASTRO_PAGE_MODULE_ID, path); + let module = await this.resolve(virtualModuleName); + if (module) { + // we need to use the non-resolved ID in order to resolve correctly the virtual module + imports.push(`import * as pageModule from "${virtualModuleName}";`); + } + + const ssrCode = generateSSRCode(options.settings.config, adapter); + imports.push(...ssrCode.imports); + contents.push(...ssrCode.contents); + + return `${imports.join('\n')}${contents.join('\n')}${exports.join('\n')}`; + } + return void 0; + }, + async generateBundle(_opts, bundle) { + // Add assets from this SSR chunk as well. + for (const [_chunkName, chunk] of Object.entries(bundle)) { + if (chunk.type === 'asset') { + internals.staticFiles.add(chunk.fileName); + } + } + + for (const [chunkName, chunk] of Object.entries(bundle)) { + if (chunk.type === 'asset') { + continue; + } + let shouldDeleteBundle = false; + for (const moduleKey of Object.keys(chunk.modules)) { + if (moduleKey.startsWith(RESOLVED_SPLIT_MODULE_ID)) { + internals.ssrSplitEntryChunks.set(moduleKey, chunk); + storeEntryPoint(moduleKey, options, internals, chunk.fileName); + shouldDeleteBundle = true; + } + } + if (shouldDeleteBundle) { + delete bundle[chunkName]; + } + } + }, + }; +} + +export function pluginSSRSplit( + options: StaticBuildOptions, + internals: BuildInternals +): AstroBuildPlugin { + const ssr = isServerLikeOutput(options.settings.config); + return { + build: 'ssr', + hooks: { + 'build:before': () => { + let vitePlugin = + ssr && options.settings.config.build.split + ? vitePluginSSRSplit(internals, options.settings.adapter!, options) + : undefined; + + return { + enforce: 'after-user-plugins', + vitePlugin, + }; + }, + 'build:post': async ({ mutate }) => { + if (!ssr) { + return; + } + if (!options.settings.config.build.split) { + return; + } + + if (internals.ssrSplitEntryChunks.size === 0) { + throw new Error(`Did not generate an entry chunk for SSR serverless`); + } + + const manifest = await createManifest(options, internals); + await runHookBuildSsr({ + config: options.settings.config, + manifest, + logging: options.logging, + entryPoints: internals.entryPoints, + }); + for (const [moduleName, chunk] of internals.ssrSplitEntryChunks) { + const code = injectManifest(manifest, chunk); + mutate(chunk, 'server', code); + } + }, + }, + }; +} + +function generateSSRCode(config: AstroConfig, adapter: AstroAdapter) { + const imports: string[] = []; + const contents: string[] = []; + let pageMap; + if (config.build.split) { + pageMap = 'pageModule'; + } else { + pageMap = 'pageMap'; + } + + contents.push(`import * as adapter from '${adapter.serverEntrypoint}'; import { renderers } from '${RENDERERS_MODULE_ID}'; import { deserializeManifest as _deserializeManifest } from 'astro/app'; import { _privateSetManifestDontUseThis } from 'astro:ssr-manifest'; const _manifest = Object.assign(_deserializeManifest('${manifestReplace}'), { - pageMap, + ${pageMap}, renderers, }); _privateSetManifestDontUseThis(_manifest); @@ -101,41 +317,45 @@ export { _default as default };`; const _start = 'start'; if(_start in adapter) { adapter[_start](_manifest, _args); -}`; - return `${imports.join('\n')}${contents.join('\n')}${content}${exports.join('\n')}`; - } - return void 0; - }, - async generateBundle(_opts, bundle) { - // Add assets from this SSR chunk as well. - for (const [_chunkName, chunk] of Object.entries(bundle)) { - if (chunk.type === 'asset') { - internals.staticFiles.add(chunk.fileName); - } - } - - for (const [chunkName, chunk] of Object.entries(bundle)) { - if (chunk.type === 'asset') { - continue; - } - if (chunk.modules[RESOLVED_SSR_VIRTUAL_MODULE_ID]) { - internals.ssrEntryChunk = chunk; - delete bundle[chunkName]; - } - } - }, +}`); + return { + imports, + contents, }; } -export async function injectManifest(buildOpts: StaticBuildOptions, internals: BuildInternals) { - if (!internals.ssrEntryChunk) { - throw new Error(`Did not generate an entry chunk for SSR`); +/** + * It injects the manifest in the given output rollup chunk. It returns the new emitted code + * @param buildOpts + * @param internals + * @param chunk + */ +export function injectManifest(manifest: SerializedSSRManifest, chunk: Readonly) { + const code = chunk.code; + + return code.replace(replaceExp, () => { + return JSON.stringify(manifest); + }); +} + +export async function createManifest( + buildOpts: StaticBuildOptions, + internals: BuildInternals +): Promise { + if (buildOpts.settings.config.build.split) { + if (internals.ssrSplitEntryChunks.size === 0) { + throw new Error(`Did not generate an entry chunk for SSR in serverless mode`); + } + } else { + if (!internals.ssrEntryChunk) { + throw new Error(`Did not generate an entry chunk for SSR`); + } } // Add assets from the client build. const clientStatics = new Set( await glob('**/*', { - cwd: fileURLToPath(buildOpts.buildConfig.client), + cwd: fileURLToPath(buildOpts.settings.config.build.client), }) ); for (const file of clientStatics) { @@ -143,19 +363,29 @@ export async function injectManifest(buildOpts: StaticBuildOptions, internals: B } const staticFiles = internals.staticFiles; - const manifest = buildManifest(buildOpts, internals, Array.from(staticFiles)); - await runHookBuildSsr({ - config: buildOpts.settings.config, - manifest, - logging: buildOpts.logging, - }); - - const chunk = internals.ssrEntryChunk; - const code = chunk.code; + return buildManifest(buildOpts, internals, Array.from(staticFiles)); +} - return code.replace(replaceExp, () => { - return JSON.stringify(manifest); - }); +/** + * Because we delete the bundle from rollup at the end of this function, + * we can't use `writeBundle` hook to get the final file name of the entry point written on disk. + * We use this hook instead. + * + * We retrieve the {@link RouteData} that belongs the current moduleKey + */ +function storeEntryPoint( + moduleKey: string, + options: StaticBuildOptions, + internals: BuildInternals, + fileName: string +) { + const componentPath = getPathFromVirtualModulePageName(RESOLVED_SPLIT_MODULE_ID, moduleKey); + for (const [page, pageData] of Object.entries(options.allPages)) { + if (componentPath == page) { + const publicPath = fileURLToPath(options.settings.config.outDir); + internals.entryPoints.set(pageData.route, pathToFileURL(join(publicPath, fileName))); + } + } } function buildManifest( @@ -254,7 +484,6 @@ function buildManifest( base: settings.config.base, assetsPrefix: settings.config.build.assetsPrefix, markdown: settings.config.markdown, - pageMap: null as any, componentMetadata: Array.from(internals.componentMetadata), renderers: [], clientDirectives: Array.from(settings.clientDirectives), @@ -264,39 +493,3 @@ function buildManifest( return ssrManifest; } - -export function pluginSSR( - options: StaticBuildOptions, - internals: BuildInternals -): AstroBuildPlugin { - const ssr = isServerLikeOutput(options.settings.config); - return { - build: 'ssr', - hooks: { - 'build:before': () => { - let vitePlugin = ssr - ? vitePluginSSR(internals, options.settings.adapter!, options) - : undefined; - - return { - enforce: 'after-user-plugins', - vitePlugin, - }; - }, - 'build:post': async ({ mutate }) => { - if (!ssr) { - return; - } - - if (!internals.ssrEntryChunk) { - throw new Error(`Did not generate an entry chunk for SSR`); - } - // Mutate the filename - internals.ssrEntryChunk.fileName = options.settings.config.build.serverEntry; - - const code = await injectManifest(options, internals); - mutate(internals.ssrEntryChunk, 'server', code); - }, - }, - }; -} diff --git a/packages/astro/src/core/build/plugins/util.ts b/packages/astro/src/core/build/plugins/util.ts index 50f5e07059b8..fa79d72bdf3d 100644 --- a/packages/astro/src/core/build/plugins/util.ts +++ b/packages/astro/src/core/build/plugins/util.ts @@ -1,3 +1,4 @@ +import { extname } from 'node:path'; import type { Plugin as VitePlugin } from 'vite'; // eslint-disable-next-line @typescript-eslint/ban-types @@ -38,3 +39,33 @@ export function extendManualChunks(outputOptions: OutputOptions, hooks: ExtendMa return null; }; } + +// This is an arbitrary string that we are going to replace the dot of the extension +export const ASTRO_PAGE_EXTENSION_POST_PATTERN = '@_@'; + +/** + * 1. We add a fixed prefix, which is used as virtual module naming convention; + * 2. We replace the dot that belongs extension with an arbitrary string. + * + * @param virtualModulePrefix + * @param path + */ +export function getVirtualModulePageNameFromPath(virtualModulePrefix: string, path: string) { + // we mask the extension, so this virtual file + // so rollup won't trigger other plugins in the process + const extension = extname(path); + return `${virtualModulePrefix}${path.replace( + extension, + extension.replace('.', ASTRO_PAGE_EXTENSION_POST_PATTERN) + )}`; +} + +/** + * + * @param virtualModulePrefix + * @param id + */ +export function getPathFromVirtualModulePageName(virtualModulePrefix: string, id: string) { + const pageName = id.slice(virtualModulePrefix.length); + return pageName.replace(ASTRO_PAGE_EXTENSION_POST_PATTERN, '.'); +} diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index 72bfd698836f..7d6004c0dd89 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -3,9 +3,11 @@ import * as eslexer from 'es-module-lexer'; import glob from 'fast-glob'; import fs from 'fs'; import { bgGreen, bgMagenta, black, dim } from 'kleur/colors'; +import { extname } from 'node:path'; import path from 'path'; import { fileURLToPath } from 'url'; import * as vite from 'vite'; +import type { RouteData } from '../../@types/astro'; import { createBuildInternals, eachPageData, @@ -24,12 +26,11 @@ import { generatePages } from './generate.js'; import { trackPageData } from './internal.js'; import { createPluginContainer, type AstroBuildPluginContainer } from './plugin.js'; import { registerAllPlugins } from './plugins/index.js'; -import { - ASTRO_PAGE_EXTENSION_POST_PATTERN, - ASTRO_PAGE_RESOLVED_MODULE_ID, -} from './plugins/plugin-pages.js'; +import { MIDDLEWARE_MODULE_ID } from './plugins/plugin-middleware.js'; +import { ASTRO_PAGE_RESOLVED_MODULE_ID } from './plugins/plugin-pages.js'; import { RESOLVED_RENDERERS_MODULE_ID } from './plugins/plugin-renderers.js'; -import { SSR_VIRTUAL_MODULE_ID } from './plugins/plugin-ssr.js'; +import { RESOLVED_SPLIT_MODULE_ID, SSR_VIRTUAL_MODULE_ID } from './plugins/plugin-ssr.js'; +import { ASTRO_PAGE_EXTENSION_POST_PATTERN } from './plugins/util.js'; import type { PageBuildData, StaticBuildOptions } from './types'; import { getTimeStat } from './util.js'; @@ -143,10 +144,10 @@ async function ssrBuild( input: Set, container: AstroBuildPluginContainer ) { - const { settings, viteConfig } = opts; + const { allPages, settings, viteConfig } = opts; const ssr = isServerLikeOutput(settings.config); const out = ssr ? opts.buildConfig.server : getOutDirWithinCwd(settings.config.outDir); - + const routes = Object.values(allPages).map((pd) => pd.route); const { lastVitePlugins, vitePlugins } = container.runBeforeHook('ssr', input); const viteBuildConfig: vite.InlineConfig = { @@ -175,13 +176,14 @@ async function ssrBuild( ...viteConfig.build?.rollupOptions?.output, entryFileNames(chunkInfo) { if (chunkInfo.facadeModuleId?.startsWith(ASTRO_PAGE_RESOLVED_MODULE_ID)) { - return makeAstroPageEntryPointFileName(chunkInfo.facadeModuleId); - } else if ( - // checks if the path of the module we have middleware, e.g. middleware.js / middleware/index.js - chunkInfo.moduleIds.find((m) => m.includes('middleware')) !== undefined && - // checks if the file actually export the `onRequest` function - chunkInfo.exports.includes('_middleware') - ) { + return makeAstroPageEntryPointFileName( + ASTRO_PAGE_RESOLVED_MODULE_ID, + chunkInfo.facadeModuleId, + routes + ); + } else if (chunkInfo.facadeModuleId?.startsWith(RESOLVED_SPLIT_MODULE_ID)) { + return makeSplitEntryPointFileName(chunkInfo.facadeModuleId, routes); + } else if (chunkInfo.facadeModuleId === MIDDLEWARE_MODULE_ID) { return 'middleware.mjs'; } else if (chunkInfo.facadeModuleId === SSR_VIRTUAL_MODULE_ID) { return opts.settings.config.build.serverEntry; @@ -205,7 +207,7 @@ async function ssrBuild( base: settings.config.base, }; - await runHookBuildSetup({ + const updatedViteBuildConfig = await runHookBuildSetup({ config: settings.config, pages: internals.pagesByComponent, vite: viteBuildConfig, @@ -213,7 +215,7 @@ async function ssrBuild( logging: opts.logging, }); - return await vite.build(viteBuildConfig); + return await vite.build(updatedViteBuildConfig); } async function clientBuild( @@ -418,27 +420,73 @@ async function ssrMoveAssets(opts: StaticBuildOptions) { } /** - * This function takes as input the virtual module name of an astro page and transform - * to generate an `.mjs` file: + * This function takes the virtual module name of any page entrypoint and + * transforms it to generate a final `.mjs` output file. * * Input: `@astro-page:src/pages/index@_@astro` - * * Output: `pages/index.astro.mjs` + * Input: `@astro-page:../node_modules/my-dep/injected@_@astro` + * Output: `pages/injected.mjs` * - * 1. We remove the module id prefix, `@astro-page:` - * 2. We remove `src/` - * 3. We replace square brackets with underscore, for example `[slug]` - * 4. At last, we replace the extension pattern with a simple dot - * 5. We append the `.mjs` string, so the file will always be a JS file + * 1. We clean the `facadeModuleId` by removing the `ASTRO_PAGE_MODULE_ID` prefix and `ASTRO_PAGE_EXTENSION_POST_PATTERN`. + * 2. We find the matching route pattern in the manifest (or fallback to the cleaned module id) + * 3. We replace square brackets with underscore (`[slug]` => `_slug_`) and `...` with `` (`[...slug]` => `_---slug_`). + * 4. We append the `.mjs` extension, so the file will always be an ESM module + * + * @param prefix string + * @param facadeModuleId string + * @param pages AllPagesData + */ +export function makeAstroPageEntryPointFileName( + prefix: string, + facadeModuleId: string, + routes: RouteData[] +) { + const pageModuleId = facadeModuleId + .replace(prefix, '') + .replace(ASTRO_PAGE_EXTENSION_POST_PATTERN, '.'); + let route = routes.find((routeData) => { + return routeData.route === pageModuleId; + }); + let name = pageModuleId; + if (route) { + name = route.route; + } + if (name.endsWith('/')) name += 'index'; + const fileName = `${name.replaceAll('[', '_').replaceAll(']', '_').replaceAll('...', '---')}.mjs`; + if (name.startsWith('..')) { + return `pages${fileName}`; + } + return fileName; +} + +/** + * The `facadeModuleId` has a shape like: \0@astro-serverless-page:src/pages/index@_@astro. + * + * 1. We call `makeAstroPageEntryPointFileName` which normalise its name, making it like a file path + * 2. We split the file path using the file system separator and attempt to retrieve the last entry + * 3. The last entry should be the file + * 4. We prepend the file name with `entry.` + * 5. We built the file path again, using the new entry built in the previous step * * @param facadeModuleId + * @param opts */ -function makeAstroPageEntryPointFileName(facadeModuleId: string) { - return `${facadeModuleId - .replace(ASTRO_PAGE_RESOLVED_MODULE_ID, '') - .replace('src/', '') - .replaceAll('[', '_') - .replaceAll(']', '_') - // this must be last - .replace(ASTRO_PAGE_EXTENSION_POST_PATTERN, '.')}.mjs`; +export function makeSplitEntryPointFileName(facadeModuleId: string, routes: RouteData[]) { + const filePath = `${makeAstroPageEntryPointFileName( + RESOLVED_SPLIT_MODULE_ID, + facadeModuleId, + routes + )}`; + + const pathComponents = filePath.split(path.sep); + const lastPathComponent = pathComponents.pop(); + if (lastPathComponent) { + const extension = extname(lastPathComponent); + if (extension.length > 0) { + const newFileName = `entry.${lastPathComponent}`; + return [...pathComponents, newFileName].join(path.sep); + } + } + return filePath; } diff --git a/packages/astro/src/core/build/types.ts b/packages/astro/src/core/build/types.ts index 772235697751..5b6db5d49d9a 100644 --- a/packages/astro/src/core/build/types.ts +++ b/packages/astro/src/core/build/types.ts @@ -1,11 +1,11 @@ import type { default as vite, InlineConfig } from 'vite'; import type { AstroConfig, - AstroMiddlewareInstance, AstroSettings, BuildConfig, ComponentInstance, ManifestData, + MiddlewareHandler, RouteData, RuntimeMode, SSRLoadedRenderer, @@ -51,7 +51,10 @@ type ImportComponentInstance = () => Promise; export interface SinglePageBuiltModule { page: ImportComponentInstance; - middleware: AstroMiddlewareInstance; + /** + * The `onRequest` hook exported by the middleware + */ + onRequest?: MiddlewareHandler; renderers: SSRLoadedRenderer[]; } diff --git a/packages/astro/src/core/compile/compile.ts b/packages/astro/src/core/compile/compile.ts index 4c76c4c65694..e78a761a4932 100644 --- a/packages/astro/src/core/compile/compile.ts +++ b/packages/astro/src/core/compile/compile.ts @@ -82,7 +82,6 @@ function handleCompileResultErrors(result: TransformResult, cssTransformErrors: if (compilerError) { throw new CompilerError({ - code: compilerError.code, message: compilerError.text, location: { line: compilerError.location.line, @@ -98,15 +97,11 @@ function handleCompileResultErrors(result: TransformResult, cssTransformErrors: break; case 1: { const error = cssTransformErrors[0]; - if (!error.errorCode) { - error.errorCode = AstroErrorData.UnknownCSSError.code; - } throw cssTransformErrors[0]; } default: { throw new AggregateError({ ...cssTransformErrors[0], - code: cssTransformErrors[0].errorCode, errors: cssTransformErrors, }); } diff --git a/packages/astro/src/core/compile/style.ts b/packages/astro/src/core/compile/style.ts index 951babd434de..4ac1cdc70652 100644 --- a/packages/astro/src/core/compile/style.ts +++ b/packages/astro/src/core/compile/style.ts @@ -88,7 +88,6 @@ function enhanceCSSError(err: any, filename: string) { errorPosition.line += 1; return new CSSError({ - code: AstroErrorData.UnknownCSSError.code, message: err.message, location: { file: filename, diff --git a/packages/astro/src/core/config/schema.ts b/packages/astro/src/core/config/schema.ts index 3edabc5d54e3..99ef653d0788 100644 --- a/packages/astro/src/core/config/schema.ts +++ b/packages/astro/src/core/config/schema.ts @@ -24,6 +24,7 @@ const ASTRO_CONFIG_DEFAULTS: AstroUserConfig & any = { serverEntry: 'entry.mjs', redirects: true, inlineStylesheets: 'never', + split: false, }, compressHTML: false, server: { @@ -120,6 +121,8 @@ export const AstroConfigSchema = z.object({ .enum(['always', 'auto', 'never']) .optional() .default(ASTRO_CONFIG_DEFAULTS.build.inlineStylesheets), + + split: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.build.split), }) .optional() .default({}), @@ -279,6 +282,8 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: URL) { .enum(['always', 'auto', 'never']) .optional() .default(ASTRO_CONFIG_DEFAULTS.build.inlineStylesheets), + + split: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.build.split), }) .optional() .default({}), diff --git a/packages/astro/src/core/config/settings.ts b/packages/astro/src/core/config/settings.ts index 1494a5eddeb2..c5e9def8ce43 100644 --- a/packages/astro/src/core/config/settings.ts +++ b/packages/astro/src/core/config/settings.ts @@ -24,7 +24,7 @@ export function createBaseSettings(config: AstroConfig): AstroSettings { adapter: undefined, injectedRoutes: config.experimental.assets && isServerLikeOutput(config) - ? [{ pattern: '/_image', entryPoint: 'astro/assets/image-endpoint' }] + ? [{ pattern: '/_image', entryPoint: 'astro/assets/image-endpoint', prerender: false }] : [], pageExtensions: ['.astro', '.html', ...SUPPORTED_MARKDOWN_FILE_EXTENSIONS], contentEntryTypes: [markdownContentEntryType], diff --git a/packages/astro/src/core/endpoint/dev/index.ts b/packages/astro/src/core/endpoint/dev/index.ts index b829754765ec..04e11b578007 100644 --- a/packages/astro/src/core/endpoint/dev/index.ts +++ b/packages/astro/src/core/endpoint/dev/index.ts @@ -21,5 +21,5 @@ export async function call(options: SSROptions, logging: LogOptions) { mod: endpointHandler as any, }); - return await callEndpoint(endpointHandler, env, ctx, logging, middleware); + return await callEndpoint(endpointHandler, env, ctx, logging, middleware?.onRequest); } diff --git a/packages/astro/src/core/endpoint/index.ts b/packages/astro/src/core/endpoint/index.ts index 5822685cf987..dde07cd9c625 100644 --- a/packages/astro/src/core/endpoint/index.ts +++ b/packages/astro/src/core/endpoint/index.ts @@ -1,10 +1,10 @@ import type { APIContext, AstroConfig, - AstroMiddlewareInstance, EndpointHandler, EndpointOutput, MiddlewareEndpointHandler, + MiddlewareHandler, Params, } from '../../@types/astro'; import type { Environment, RenderContext } from '../render/index'; @@ -78,6 +78,7 @@ export function createAPIContext({ // We define a custom property, so we can check the value passed to locals Object.defineProperty(context, 'locals', { + enumerable: true, get() { return Reflect.get(request, clientLocalsSymbol); }, @@ -97,7 +98,7 @@ export async function callEndpoint env: Environment, ctx: RenderContext, logging: LogOptions, - middleware?: AstroMiddlewareInstance | undefined + onRequest?: MiddlewareHandler | undefined ): Promise { const context = createAPIContext({ request: ctx.request, @@ -108,11 +109,10 @@ export async function callEndpoint }); let response; - if (middleware && middleware.onRequest) { - const onRequest = middleware.onRequest as MiddlewareEndpointHandler; + if (onRequest) { response = await callMiddleware( env.logging, - onRequest, + onRequest as MiddlewareEndpointHandler, context, async () => { return await renderEndpoint(mod, context, env.ssr); diff --git a/packages/astro/src/core/errors/README.md b/packages/astro/src/core/errors/README.md index 2e6ffb3ae826..fd040d8162c1 100644 --- a/packages/astro/src/core/errors/README.md +++ b/packages/astro/src/core/errors/README.md @@ -9,57 +9,48 @@ **Error Format** Name (key of the object definition): -- As with the error code, this property is a static reference to the error. The shape should be similar to JavaScript's native errors (TypeError, ReferenceError): pascal-cased, no spaces, no special characters etc. (ex: `ClientAddressNotAvailable`) + +- This property is a static reference to the error. The shape should be similar to JavaScript's native errors (TypeError, ReferenceError): pascal-cased, no spaces, no special characters etc. (ex: `ClientAddressNotAvailable`) - This is the only part of the error message that should not be written as a full, proper sentence complete with Capitalization and end punctuation. Title: + - Use this property to briefly describe the error in a few words. This is the user's way to see at a glance what has happened and will be prominently displayed in the UI (ex: `{feature} is not available in static mode.`) Do not include further details such as why this error occurred or possible solutions. Message: + - Begin with **what happened** and **why**. (ex: `Could not use {feature} because Server⁠-⁠side Rendering is not enabled.`) - Then, **describe the action the user should take**. (ex: `Update your Astro config with `output: 'server'` to enable Server⁠-⁠side Rendering.`) - Although this does not need to be as brief as the `title`, try to keep sentences short, clear and direct to give the reader all the necessary information quickly as possible. - Instead of writing a longer message, consider using a `hint`. Hint: + - A `hint` can be used for any additional info that might help the user. (ex: a link to the documentation, or a common cause) **Writing Style** + - Write in proper sentences. Include periods at the end of sentences. Avoid using exclamation marks! (Leave them to Houston!) - Technical jargon is mostly okay! But, most abbreviations should be avoided. If a developer is unfamiliar with a technical term, spelling it out in full allows them to look it up on the web more easily. -- Describe the _what_, _why_ and _action to take_ from the user's perspective. Assume they don't know Astro internals, and care only about how Astro is _used_. (ex: `You are missing...` vs `Astro/file cannot find...`) +- Describe the _what_, _why_ and _action to take_ from the user's perspective. Assume they don't know Astro internals, and care only about how Astro is _used_. (ex: `You are missing...` vs `Astro/file cannot find...`) - Avoid using cutesy language. (ex: Oops!) This tone minimizes the significance of the error, which _is_ important to the developer. The developer may be frustrated and your error message shouldn't be making jokes about their struggles. Only include words and phrases that help the developer **interpret the error** and **fix the problem**. -**Choosing an Error Code** - -Choose any available error code in the appropriate range: -- 01xxx and 02xxx are reserved for compiler errors and warnings respectively -- 03xxx: Astro errors (your error most likely goes here!) -- 04xxx: Vite errors -- 05xxx: CSS errors -- 06xxx: Markdown errors -- 07xxx: Configuration errors -- 07xxx-98xxx <- Need to add a category? Add it here! -- 99xxx: Catch-alls for unknown errors - -As long as it is unique, the exact error code used is unimportant. For example, error 5005 and error 5006 don't necessarily have to be related, or follow any logical pattern. - -Users are not reading codes sequentially. They're much more likely to directly land on the error or search for a specific code. - -If you are unsure about which error code to choose, ask [Erika](https://github.com/Princesseuh)! +If you are unsure about anything, ask [Erika](https://github.com/Princesseuh)! ### CLI specifics tips: + - If the error happened **during an action that changes the state of the project** (ex: editing configuration, creating files), the error should **reassure the user** about the state of their project (ex: "Failed to update configuration. Your project has been restored to its previous state.") - If an "error" happened because of a conscious user action (ex: pressing CTRL+C during a choice), it is okay to add more personality (ex: "Operation cancelled. See you later, astronaut!"). Do keep in mind the previous point however (ex: "Operation cancelled. No worries, your project folder has already been created") ### Shape -- **Error codes and names are permanent**, and should never be changed, nor deleted. Users should always be able to find an error by searching, and this ensures a matching result. When an error is no longer relevant, it should be deprecated, not removed. + +- **Names are permanent**, and should never be changed, nor deleted. Users should always be able to find an error by searching, and this ensures a matching result. When an error is no longer relevant, it should be deprecated, not removed. - Contextual information may be used to enhance the message or the hint. However, the code that caused the error or the position of the error should not be included in the message as they will already be shown as part of the error. - Do not prefix `title`, `message` and `hint` with descriptive words such as "Error:" or "Hint:" as it may lead to duplicated labels in the UI / CLI. - Dynamic error messages must use the following shape: ```js -message: (arguments) => `text ${substitute}` +message: (arguments) => `text ${substitute}`; ``` Please avoid including too much logic inside the errors if you can. The last thing you want is for a bug to happen inside what's already an error! @@ -70,28 +61,30 @@ Using light logic to add / remove different parts of the message is okay, howeve ### Documentation support through JSDoc -Using JSDoc comments, [a reference for every error message](https://docs.astro.build/en/reference/error-reference/) is built automatically on our docs. Users can then search for a error code to find more information on how to fix the error they encountered. +Using JSDoc comments, [a reference for every error message](https://docs.astro.build/en/reference/error-reference/) is built automatically on our docs. Here's how to create and format the comments: ```js /** - * @docs <- Needed for the comment to be used for docs - * @message <- (Optional) Clearer error message to show in cases where the original one is too complex (ex: because of conditional messages) - * @see <- List of additional references users can look at - * @description <- Description of the error - */ + * @docs <- Needed for the comment to be used for docs + * @message <- (Optional) Clearer error message to show in cases where the original one is too complex (ex: because of conditional messages) + * @see <- List of additional references users can look at + * @description <- Description of the error + */ ``` + Example: + ```js /** - * @docs - * @message Route returned a `returnedValue`. Only a Response can be returned from Astro files. - * @see - * - [Response](https://docs.astro.build/en/guides/server-side-rendering/#response) - * @description - * Only instances of [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) can be returned inside Astro files. - */ + * @docs + * @message Route returned a `returnedValue`. Only a Response can be returned from Astro files. + * @see + * - [Response](https://docs.astro.build/en/guides/server-side-rendering/#response) + * @description + * Only instances of [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) can be returned inside Astro files. + */ ``` The `@message` property is intended to provide slightly more context when it is helpful: a more descriptive error message or a collection of common messages if there are multiple possible error messages. Try to avoid making substantial changes to existing messages so that they are easy to find for users who copy and search the exact content of an error message. diff --git a/packages/astro/src/core/errors/dev/utils.ts b/packages/astro/src/core/errors/dev/utils.ts index 28445ba32385..29468c7fd8d2 100644 --- a/packages/astro/src/core/errors/dev/utils.ts +++ b/packages/astro/src/core/errors/dev/utils.ts @@ -24,9 +24,13 @@ export function collectErrorMetadata(e: any, rootFolder?: URL | undefined): Erro ? (e.errors as SSRError[]) : [e as SSRError]; - err.forEach((error) => { - if (error.stack) { - error = collectInfoFromStacktrace(e); + err.forEach((error, idx) => { + if (e.stack) { + const stackInfo = collectInfoFromStacktrace(e); + error.stack = stackInfo.stack; + error.loc = stackInfo.loc; + error.plugin = stackInfo.plugin; + error.pluginCode = stackInfo.pluginCode; } // Make sure the file location is absolute, otherwise: @@ -141,15 +145,22 @@ See https://docs.astro.build/en/guides/troubleshooting/#document-or-window-is-no return err.hint; } -function collectInfoFromStacktrace(error: SSRError): SSRError { - if (!error.stack) return error; +type StackInfo = Pick; + +function collectInfoFromStacktrace(error: SSRError & { stack: string }): StackInfo { + let stackInfo: StackInfo = { + stack: error.stack, + plugin: error.plugin, + pluginCode: error.pluginCode, + loc: error.loc, + }; // normalize error stack line-endings to \n - error.stack = normalizeLF(error.stack); + stackInfo.stack = normalizeLF(error.stack); const stackText = stripAnsi(error.stack); // Try to find possible location from stack if we don't have one - if (!error.loc || (!error.loc.column && !error.loc.line)) { + if (!stackInfo.loc || (!stackInfo.loc.column && !stackInfo.loc.line)) { const possibleFilePath = error.loc?.file || error.pluginCode || @@ -168,7 +179,7 @@ function collectInfoFromStacktrace(error: SSRError): SSRError { file = fileURLToPath(file); } catch {} - error.loc = { + stackInfo.loc = { file, line: Number.parseInt(line), column: Number.parseInt(column), @@ -177,17 +188,17 @@ function collectInfoFromStacktrace(error: SSRError): SSRError { } // Derive plugin from stack (if possible) - if (!error.plugin) { - error.plugin = + if (!stackInfo.plugin) { + stackInfo.plugin = /withastro\/astro\/packages\/integrations\/([\w-]+)/gim.exec(stackText)?.at(1) || /(@astrojs\/[\w-]+)\/(server|client|index)/gim.exec(stackText)?.at(1) || undefined; } // Normalize stack (remove `/@fs/` urls, etc) - error.stack = cleanErrorStack(error.stack); + stackInfo.stack = cleanErrorStack(error.stack); - return error; + return stackInfo; } function cleanErrorStack(stack: string) { diff --git a/packages/astro/src/core/errors/dev/vite.ts b/packages/astro/src/core/errors/dev/vite.ts index 9bc2e8c25f26..cb19ca8f6bff 100644 --- a/packages/astro/src/core/errors/dev/vite.ts +++ b/packages/astro/src/core/errors/dev/vite.ts @@ -45,7 +45,6 @@ export function enhanceViteSSRError({ safeError.name = 'FailedToLoadModuleSSR'; safeError.message = AstroErrorData.FailedToLoadModuleSSR.message(importName); safeError.hint = AstroErrorData.FailedToLoadModuleSSR.hint; - safeError.code = AstroErrorData.FailedToLoadModuleSSR.code; const line = lns.findIndex((ln) => ln.includes(importName!)); if (line !== -1) { @@ -84,7 +83,6 @@ export function enhanceViteSSRError({ safeError.message = AstroErrorData.InvalidGlob.message(globPattern); safeError.name = 'InvalidGlob'; safeError.hint = AstroErrorData.InvalidGlob.hint; - safeError.code = AstroErrorData.InvalidGlob.code; safeError.title = AstroErrorData.InvalidGlob.title; const line = lns.findIndex((ln) => ln.includes(globPattern)); @@ -139,17 +137,7 @@ export async function getViteErrorPayload(err: ErrorWithMetadata): Promise string); hint?: string | ((...params: any) => string); @@ -30,7 +29,6 @@ export const AstroErrorData = { */ UnknownCompilerError: { title: 'Unknown compiler error.', - code: 1000, hint: 'This is almost always a problem with the Astro compiler, not your code. Please open an issue at https://astro.build/issues/compiler.', }, // 1xxx and 2xxx codes are reserved for compiler errors and warnings respectively @@ -47,7 +45,6 @@ export const AstroErrorData = { */ StaticRedirectNotAvailable: { title: '`Astro.redirect` is not available in static mode.', - code: 3001, message: "Redirects are only available when using `output: 'server'` or `output: 'hybrid'`. Update your Astro config if you need SSR features.", hint: 'See https://docs.astro.build/en/guides/server-side-rendering/#enabling-ssr-in-your-project for more information on how to enable SSR.', @@ -62,7 +59,6 @@ export const AstroErrorData = { */ ClientAddressNotAvailable: { title: '`Astro.clientAddress` is not available in current adapter.', - code: 3002, message: (adapterName: string) => `\`Astro.clientAddress\` is not available in the \`${adapterName}\` adapter. File an issue with the adapter to add support.`, }, @@ -78,7 +74,6 @@ export const AstroErrorData = { */ StaticClientAddressNotAvailable: { title: '`Astro.clientAddress` is not available in static mode.', - code: 3003, message: "`Astro.clientAddress` is only available when using `output: 'server'` or `output: 'hybrid'`. Update your Astro config if you need SSR features.", hint: 'See https://docs.astro.build/en/guides/server-side-rendering/#enabling-ssr-in-your-project for more information on how to enable SSR.', @@ -92,7 +87,6 @@ export const AstroErrorData = { */ NoMatchingStaticPathFound: { title: 'No static path found for requested path.', - code: 3004, message: (pathName: string) => `A \`getStaticPaths()\` route pattern was matched, but no matching static path was found for requested path \`${pathName}\`.`, hint: (possibleRoutes: string[]) => @@ -120,7 +114,6 @@ export const AstroErrorData = { */ OnlyResponseCanBeReturned: { title: 'Invalid type returned by Astro page.', - code: 3005, message: (route: string | undefined, returnedValue: string) => `Route \`${ route ? route : '' @@ -140,7 +133,6 @@ export const AstroErrorData = { */ MissingMediaQueryDirective: { title: 'Missing value for `client:media` directive.', - code: 3006, message: 'Media query not provided for `client:media` directive. A media query similar to `client:media="(max-width: 600px)"` must be provided', }, @@ -157,7 +149,6 @@ export const AstroErrorData = { */ NoMatchingRenderer: { title: 'No matching renderer found.', - code: 3007, message: ( componentName: string, componentExtension: string | undefined, @@ -192,7 +183,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon */ NoClientEntrypoint: { title: 'No client entrypoint specified in renderer.', - code: 3008, message: (componentName: string, clientDirective: string, rendererName: string) => `\`${componentName}\` component has a \`client:${clientDirective}\` directive, but no client entrypoint was provided by \`${rendererName}\`.`, hint: 'See https://docs.astro.build/en/reference/integrations-reference/#addrenderer-option for more information on how to configure your renderer.', @@ -211,7 +201,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon */ NoClientOnlyHint: { title: 'Missing hint on client:only directive.', - code: 3009, message: (componentName: string) => `Unable to render \`${componentName}\`. When using the \`client:only\` hydration strategy, Astro needs a hint to use the correct renderer.`, hint: (probableRenderers: string) => @@ -238,7 +227,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon */ InvalidGetStaticPathParam: { title: 'Invalid value returned by a `getStaticPaths` path.', - code: 3010, message: (paramType) => `Invalid params given to \`getStaticPaths\` path. Expected an \`object\`, got \`${paramType}\``, hint: 'See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths.', @@ -262,7 +250,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon */ InvalidGetStaticPathsReturn: { title: 'Invalid value returned by getStaticPaths.', - code: 3011, message: (returnType) => `Invalid type returned by \`getStaticPaths\`. Expected an \`array\`, got \`${returnType}\``, hint: 'See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths.', @@ -276,7 +263,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon */ GetStaticPathsRemovedRSSHelper: { title: 'getStaticPaths RSS helper is not available anymore.', - code: 3012, message: 'The RSS helper has been removed from `getStaticPaths`. Try the new @astrojs/rss package instead.', hint: 'See https://docs.astro.build/en/guides/rss/ for more information.', @@ -303,7 +289,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon */ GetStaticPathsExpectedParams: { title: 'Missing params property on `getStaticPaths` route.', - code: 3013, message: 'Missing or empty required `params` property on `getStaticPaths` route.', hint: 'See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths.', }, @@ -343,7 +328,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon */ GetStaticPathsInvalidRouteParam: { title: 'Invalid value for `getStaticPaths` route parameter.', - code: 3014, message: (key: string, value: any, valueType: any) => `Invalid getStaticPaths route parameter for \`${key}\`. Expected undefined, a string or a number, received \`${valueType}\` (\`${value}\`)`, hint: 'See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths.', @@ -359,7 +343,6 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon */ GetStaticPathsRequired: { title: '`getStaticPaths()` function required for dynamic routes.', - code: 3015, message: '`getStaticPaths()` function is required for dynamic routes. Make sure that you `export` a `getStaticPaths` function from your dynamic route.', hint: `See https://docs.astro.build/en/core-concepts/routing/#dynamic-routes for more information on dynamic routes. @@ -376,7 +359,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ ReservedSlotName: { title: 'Invalid slot name.', - code: 3016, message: (slotName: string) => `Unable to create a slot named \`${slotName}\`. \`${slotName}\` is a reserved slot name. Please update the name of this slot.`, }, @@ -390,7 +372,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ NoAdapterInstalled: { title: 'Cannot use Server-side Rendering without an adapter.', - code: 3017, message: `Cannot use \`output: 'server'\` or \`output: 'hybrid'\` without an adapter. Please install and configure the appropriate server adapter for your final deployment.`, hint: 'See https://docs.astro.build/en/guides/server-side-rendering/ for more information.', }, @@ -401,7 +382,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ NoMatchingImport: { title: 'No import found for component.', - code: 3018, message: (componentName: string) => `Could not render \`${componentName}\`. No matching import has been found for \`${componentName}\`.`, hint: 'Please make sure the component is properly imported.', @@ -416,7 +396,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ InvalidPrerenderExport: { title: 'Invalid prerender export.', - code: 3019, message: (prefix: string, suffix: string, isHydridOuput: boolean) => { const defaultExpectedValue = isHydridOuput ? 'false' : 'true'; let msg = `A \`prerender\` export has been detected, but its value cannot be statically analyzed.`; @@ -437,7 +416,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ InvalidComponentArgs: { title: 'Invalid component arguments.', - code: 3020, message: (name: string) => `Invalid arguments passed to${name ? ` <${name}>` : ''} component.`, hint: 'Astro components cannot be rendered directly via function call, such as `Component()` or `{items.map(Component)}`.', }, @@ -450,7 +428,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ PageNumberParamNotFound: { title: 'Page number param not found.', - code: 3021, message: (paramName: string) => `[paginate()] page number param \`${paramName}\` not found in your filepath.`, hint: 'Rename your file to `[page].astro` or `[...page].astro`.', @@ -468,7 +445,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ ImageMissingAlt: { title: 'Missing alt property.', - code: 3022, message: 'The alt property is required.', hint: "The `alt` property is important for the purpose of accessibility, without it users using screen readers or other assistive technologies won't be able to understand what your image is supposed to represent. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-alt for more information.", }, @@ -483,7 +459,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ InvalidImageService: { title: 'Error while loading image service.', - code: 3023, message: 'There was an error loading the configured image service. Please see the stack trace for more information.', }, @@ -501,7 +476,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ MissingImageDimension: { title: 'Missing image dimensions', - code: 3024, message: (missingDimension: 'width' | 'height' | 'both', imageURL: string) => `Missing ${ missingDimension === 'both' @@ -526,7 +500,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ UnsupportedImageFormat: { title: 'Unsupported image format', - code: 3025, message: (format: string, imagePath: string, supportedFormats: readonly string[]) => `Received unsupported format \`${format}\` from \`${imagePath}\`. Currently only ${supportedFormats.join( ', ' @@ -545,11 +518,8 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ PrerenderDynamicEndpointPathCollide: { title: 'Prerendered dynamic endpoint has path collision.', - code: 3026, message: (pathname: string) => - `Could not render \`${pathname}\` with an \`undefined\` param as the generated path will collide during prerendering. ` + - `Prevent passing \`undefined\` as \`params\` for the endpoint's \`getStaticPaths()\` function, ` + - `or add an additional extension to the endpoint's filename.`, + `Could not render \`${pathname}\` with an \`undefined\` param as the generated path will collide during prerendering. Prevent passing \`undefined\` as \`params\` for the endpoint's \`getStaticPaths()\` function, or add an additional extension to the endpoint's filename.`, hint: (filename: string) => `Rename \`${filename}\` to \`${filename.replace(/\.(js|ts)/, (m) => `.json` + m)}\``, }, @@ -574,7 +544,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ ExpectedImage: { title: 'Expected src to be an image.', - code: 3027, message: (options: string) => `Expected \`src\` property to be either an ESM imported image or a string with the path of a remote image. Received \`${options}\`.`, hint: 'This error can often happen because of a wrong path. Make sure the path to your image is correct.', @@ -597,7 +566,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ ExpectedImageOptions: { title: 'Expected image options.', - code: 3028, message: (options: string) => `Expected getImage() parameter to be an object. Received \`${options}\`.`, }, @@ -614,7 +582,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ MarkdownImageNotFound: { title: 'Image not found.', - code: 3029, message: (imagePath: string, fullImagePath: string | undefined) => `Could not find requested image \`${imagePath}\`${ fullImagePath ? ` at \`${fullImagePath}\`.` : '.' @@ -628,7 +595,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ ResponseSentError: { title: 'Unable to set response.', - code: 3030, message: 'The response has already been sent to the browser and cannot be altered.', }, @@ -648,7 +614,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ MiddlewareNoDataOrNextCalled: { title: "The middleware didn't return a response or call `next`.", - code: 3031, message: 'The middleware needs to either return a `Response` object or call the `next` function.', }, @@ -668,7 +633,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ MiddlewareNotAResponse: { title: 'The middleware returned something that is not a `Response` object.', - code: 3032, message: 'Any data returned from middleware must be a valid `Response` object.', }, @@ -689,12 +653,11 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ LocalsNotAnObject: { title: 'Value assigned to `locals` is not accepted.', - code: 3033, message: '`locals` can only be assigned to an object. Other values like numbers, strings, etc. are not accepted.', hint: 'If you tried to remove some information from the `locals` object, try to use `delete` or set the property to `undefined`.', }, - /* + /** * @docs * @see * - [Assets (Experimental)](https://docs.astro.build/en/guides/assets/) @@ -716,7 +679,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ LocalImageUsedWrongly: { title: 'ESM imported images must be passed as-is.', - code: 3034, message: (imageFilePath: string) => `\`Image\`'s and \`getImage\`'s \`src\` parameter must be an imported image or an URL, it cannot be a filepath. Received \`${imageFilePath}\`.`, }, @@ -730,7 +692,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ AstroGlobUsedOutside: { title: 'Astro.glob() used outside of an Astro file.', - code: 3035, message: (globStr: string) => `\`Astro.glob(${globStr})\` can only be used in \`.astro\` files. \`import.meta.glob(${globStr})\` can be used instead to achieve a similar result.`, hint: "See Vite's documentation on `import.meta.glob` for more information: https://vitejs.dev/guide/features.html#glob-import", @@ -745,7 +706,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ AstroGlobNoMatch: { title: 'Astro.glob() did not match any files.', - code: 3036, message: (globStr: string) => `\`Astro.glob(${globStr})\` did not return any matching files. Check the pattern for typos.`, }, @@ -758,7 +718,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ RedirectWithNoLocation: { title: 'A redirect must be given a location with the `Location` header.', - code: 3037, }, /** * @docs @@ -769,7 +728,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ InvalidDynamicRoute: { title: 'Invalid dynamic route.', - code: 3038, message: (route: string, invalidParam: string, received: string) => `The ${invalidParam} param for route ${route} is invalid. Received **${received}**.`, }, @@ -786,7 +744,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ UnknownViteError: { title: 'Unknown Vite Error.', - code: 4000, }, /** * @docs @@ -799,7 +756,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ FailedToLoadModuleSSR: { title: 'Could not import file.', - code: 4001, message: (importName: string) => `Could not import \`${importName}\`.`, hint: 'This is often caused by a typo in the import path. Please make sure the file exists.', }, @@ -812,11 +768,20 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ InvalidGlob: { title: 'Invalid glob pattern.', - code: 4002, message: (globPattern: string) => `Invalid glob pattern: \`${globPattern}\`. Glob patterns must start with './', '../' or '/'.`, hint: 'See https://docs.astro.build/en/guides/imports/#glob-patterns for more information on supported glob patterns.', }, + /** + * @docs + * @description + * Astro couldn't find the correct page to render, probably because it wasn't correctly mapped for SSR usage. This is an internal error. + */ + FailedToFindPageMapSSR: { + title: "Astro couldn't find the correct page to render", + message: + "Astro couldn't find the correct page to render, probably because it wasn't correctly mapped for SSR usage. This is an internal error. Please file an issue.", + }, /** * @docs * @kind heading @@ -832,7 +797,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ UnknownCSSError: { title: 'Unknown CSS Error.', - code: 5000, }, /** * @docs @@ -845,7 +809,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ CSSSyntaxError: { title: 'CSS Syntax Error.', - code: 5001, }, /** * @docs @@ -860,7 +823,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ UnknownMarkdownError: { title: 'Unknown Markdown Error.', - code: 6000, }, /** * @docs @@ -875,7 +837,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ MarkdownFrontmatterParseError: { title: 'Failed to parse Markdown frontmatter.', - code: 6001, }, /** * @docs @@ -886,7 +847,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ InvalidFrontmatterInjectionError: { title: 'Invalid frontmatter injection.', - code: 6003, message: 'A remark or rehype plugin attempted to inject invalid frontmatter. Ensure "astro.frontmatter" is set to a valid JSON object that is not `null` or `undefined`.', hint: 'See the frontmatter injection docs https://docs.astro.build/en/guides/markdown-content/#modifying-frontmatter-programmatically for more information.', @@ -900,7 +860,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ MdxIntegrationMissingError: { title: 'MDX integration missing.', - code: 6004, message: (file: string) => `Unable to render ${file}. Ensure that the \`@astrojs/mdx\` integration is installed.`, hint: 'See the MDX integration docs for installation and usage instructions: https://docs.astro.build/en/guides/integrations-guide/mdx/', @@ -918,7 +877,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ UnknownConfigError: { title: 'Unknown configuration error.', - code: 7000, }, /** * @docs @@ -929,7 +887,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ ConfigNotFound: { title: 'Specified configuration file not found.', - code: 7001, message: (configFile: string) => `Unable to resolve \`--config "${configFile}"\`. Does the file exist?`, }, @@ -942,7 +899,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ ConfigLegacyKey: { title: 'Legacy configuration detected.', - code: 7002, message: (legacyConfigKey: string) => `Legacy configuration detected: \`${legacyConfigKey}\`.`, hint: 'Please update your configuration to the new format.\nSee https://astro.build/config for more information.', }, @@ -961,7 +917,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ UnknownCLIError: { title: 'Unknown CLI Error.', - code: 8000, }, /** * @docs @@ -972,7 +927,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ GenerateContentTypesError: { title: 'Failed to generate content types.', - code: 8001, message: (errorMessage: string) => `\`astro sync\` command failed to generate content collection types: ${errorMessage}`, hint: 'Check your `src/content/config.*` file for typos.', @@ -993,7 +947,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ UnknownContentCollectionError: { title: 'Unknown Content Collection Error.', - code: 9000, }, /** * @docs @@ -1010,7 +963,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ InvalidContentEntryFrontmatterError: { title: 'Content entry frontmatter does not match schema.', - code: 9001, message: (collection: string, entryId: string, error: ZodError) => { return [ `**${String(collection)} β†’ ${String( @@ -1031,7 +983,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ InvalidContentEntrySlugError: { title: 'Invalid content entry slug.', - code: 9002, message: (collection: string, entryId: string) => { return `${String(collection)} β†’ ${String( entryId @@ -1042,13 +993,12 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati /** * @docs * @see - * - [The reserved entry `slug` field](https://docs.astro.build/en/guides/content-collections/) + * - [The reserved entry `slug` field](https://docs.astro.build/en/guides/content-collections/#defining-custom-slugs) * @description - * A content collection schema should not contain the `slug` field. This is reserved by Astro for generating entry slugs. Remove the `slug` field from your schema, or choose a different name. + * A content collection schema should not contain the `slug` field. This is reserved by Astro for generating entry slugs. Remove `slug` from your schema. You can still use custom slugs in your frontmatter. */ ContentSchemaContainsSlugError: { title: 'Content Schema should not contain `slug`.', - code: 9003, message: (collectionName: string) => `A content collection schema should not contain \`slug\` since it is reserved for slug generation. Remove this from your ${collectionName} collection schema.`, hint: 'See https://docs.astro.build/en/guides/content-collections/ for more on the `slug` field.', @@ -1062,7 +1012,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ CollectionDoesNotExistError: { title: 'Collection does not exist', - code: 9004, message: (collectionName: string) => `The collection **${collectionName}** does not exist. Ensure a collection directory with this name exists.`, hint: 'See https://docs.astro.build/en/guides/content-collections/ for more on creating collections.', @@ -1077,7 +1026,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ MixedContentDataCollectionError: { title: 'Content and data cannot be in same collection.', - code: 9005, message: (collection: string) => { return `**${collection}** contains a mix of content and data entries. All entries must be of the same type.`; }, @@ -1093,7 +1041,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ ContentCollectionTypeMismatchError: { title: 'Collection contains entries of a different type.', - code: 9006, message: (collection: string, expectedType: string, actualType: string) => { return `${collection} contains ${expectedType} entries, but is configured as a ${actualType} collection.`; }, @@ -1106,7 +1053,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ DataCollectionEntryParseError: { title: 'Data collection entry failed to parse.', - code: 9007, message: (entryId: string, errorMessage: string) => { return `**${entryId}** failed to parse: ${errorMessage}`; }, @@ -1114,12 +1060,12 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati }, /** * @docs + * @message `COLLECTION_NAME` contains multiple entries with the same slug: `SLUG`. Slugs must be unique. * @description * Content collection entries must have unique slugs. Duplicates are often caused by the `slug` frontmatter property. */ DuplicateContentEntrySlugError: { title: 'Duplicate content entry slug.', - code: 9008, message: (collection: string, slug: string) => { return `**${collection}** contains multiple entries with the same slug: \`${slug}\`. Slugs must be unique.`; }, @@ -1134,7 +1080,6 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati */ UnsupportedConfigTransformError: { title: 'Unsupported transform in content config.', - code: 9008, message: (parseError: string) => `\`transform()\` functions in your content config must return valid JSON, or data types compatible with the devalue library (including Dates, Maps, and Sets).\nFull error: ${parseError}`, hint: 'See the devalue library for all supported types: https://github.com/rich-harris/devalue', @@ -1143,11 +1088,5 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati // Generic catch-all - Only use this in extreme cases, like if there was a cosmic ray bit flip UnknownError: { title: 'Unknown Error.', - code: 99999, }, } as const satisfies Record; - -type ValueOf = T[keyof T]; -export type AstroErrorCodes = ValueOf<{ - [T in keyof typeof AstroErrorData]: (typeof AstroErrorData)[T]['code']; -}>; diff --git a/packages/astro/src/core/errors/errors.ts b/packages/astro/src/core/errors/errors.ts index 995f401ef27d..cda4f328af5a 100644 --- a/packages/astro/src/core/errors/errors.ts +++ b/packages/astro/src/core/errors/errors.ts @@ -1,10 +1,7 @@ -import type { DiagnosticCode } from '@astrojs/compiler/shared/diagnostics.js'; -import type { AstroErrorCodes } from './errors-data.js'; import { codeFrame } from './printer.js'; -import { getErrorDataByCode } from './utils.js'; +import { getErrorDataByTitle } from './utils.js'; interface ErrorProperties { - code: AstroErrorCodes | DiagnosticCode; title?: string; name?: string; message?: string; @@ -33,10 +30,6 @@ export function isAstroError(e: unknown): e is AstroError { } export class AstroError extends Error { - // NOTE: If this property is named `code`, Rollup will use it to fill the `pluginCode` property downstream - // This cause issues since we expect `pluginCode` to be a string containing code - // @see https://github.com/rollup/rollup/blob/9a741639f69f204ded8ea404675f725b8d56adca/src/utils/error.ts#L725 - public errorCode: AstroErrorCodes | DiagnosticCode; public loc: ErrorLocation | undefined; public title: string | undefined; public hint: string | undefined; @@ -47,16 +40,19 @@ export class AstroError extends Error { constructor(props: ErrorProperties, ...params: any) { super(...params); - const { code, name, title, message, stack, location, hint, frame } = props; + const { name, title, message, stack, location, hint, frame } = props; + this.title = title; - this.errorCode = code; if (name && name !== 'Error') { this.name = name; - } else { - // If we don't have a name, let's generate one from the code - this.name = getErrorDataByCode(this.errorCode)?.name ?? 'UnknownError'; + } else if (this.title) { + const errorData = getErrorDataByTitle(this.title)?.name; + + if (errorData) { + this.name = errorData; + } } - this.title = title; + if (message) this.message = message; // Only set this if we actually have a stack passed, otherwise uses Error's this.stack = stack ? stack : this.stack; @@ -65,10 +61,6 @@ export class AstroError extends Error { this.frame = frame; } - public setErrorCode(errorCode: AstroErrorCodes) { - this.errorCode = errorCode; - } - public setLocation(location: ErrorLocation): void { this.loc = location; } @@ -97,7 +89,7 @@ export class AstroError extends Error { export class CompilerError extends AstroError { type: ErrorTypes = 'CompilerError'; - constructor(props: Omit & { code: DiagnosticCode }, ...params: any) { + constructor(props: ErrorProperties, ...params: any) { super(props, ...params); this.name = 'CompilerError'; @@ -160,7 +152,6 @@ export interface ErrorWithMetadata { type?: ErrorTypes; message: string; stack: string; - errorCode?: number; hint?: string; id?: string; frame?: string; diff --git a/packages/astro/src/core/errors/index.ts b/packages/astro/src/core/errors/index.ts index 56a6af8c2cf5..b3ef91e28b5e 100644 --- a/packages/astro/src/core/errors/index.ts +++ b/packages/astro/src/core/errors/index.ts @@ -1,5 +1,5 @@ export type { ErrorLocation, ErrorWithMetadata } from './errors'; -export { AstroErrorData, type AstroErrorCodes } from './errors-data.js'; +export { AstroErrorData } from './errors-data.js'; export { AggregateError, AstroError, diff --git a/packages/astro/src/core/errors/utils.ts b/packages/astro/src/core/errors/utils.ts index f4408c305947..99cdde028e52 100644 --- a/packages/astro/src/core/errors/utils.ts +++ b/packages/astro/src/core/errors/utils.ts @@ -1,8 +1,7 @@ -import type { DiagnosticCode } from '@astrojs/compiler/shared/diagnostics.js'; import type { YAMLException } from 'js-yaml'; import type { ErrorPayload as ViteErrorPayload } from 'vite'; import type { SSRError } from '../../@types/astro.js'; -import { AstroErrorData, type AstroErrorCodes, type ErrorData } from './errors-data.js'; +import { AstroErrorData, type ErrorData } from './errors-data.js'; /** * Get the line and character based on the offset @@ -107,8 +106,8 @@ export function normalizeLF(code: string) { return code.replace(/\r\n|\r(?!\n)|\n/g, '\n'); } -export function getErrorDataByCode(code: AstroErrorCodes | DiagnosticCode) { - const entry = Object.entries(AstroErrorData).find((data) => data[1].code === code); +export function getErrorDataByTitle(title: string) { + const entry = Object.entries(AstroErrorData).find((data) => data[1].title === title); if (entry) { return { diff --git a/packages/astro/src/core/module-loader/loader.ts b/packages/astro/src/core/module-loader/loader.ts index 84bb862d0fa4..39c24253ed26 100644 --- a/packages/astro/src/core/module-loader/loader.ts +++ b/packages/astro/src/core/module-loader/loader.ts @@ -42,6 +42,10 @@ export interface ModuleNode { id: string | null; url: string; ssrModule: Record | null; + ssrTransformResult: { + deps?: string[]; + dynamicDeps?: string[]; + } | null; ssrError: Error | null; importedModules: Set; } diff --git a/packages/astro/src/core/redirects/component.ts b/packages/astro/src/core/redirects/component.ts index f76b82517887..d10cae4feed5 100644 --- a/packages/astro/src/core/redirects/component.ts +++ b/packages/astro/src/core/redirects/component.ts @@ -1,4 +1,4 @@ -import type { AstroMiddlewareInstance, ComponentInstance } from '../../@types/astro'; +import type { ComponentInstance } from '../../@types/astro'; import type { SinglePageBuiltModule } from '../build/types'; // A stub of a component instance for a given route @@ -10,12 +10,8 @@ export const RedirectComponentInstance: ComponentInstance = { }, }; -const StaticMiddlewareInstance: AstroMiddlewareInstance = { - onRequest: (ctx, next) => next(), -}; - export const RedirectSinglePageBuiltModule: SinglePageBuiltModule = { page: () => Promise.resolve(RedirectComponentInstance), - middleware: StaticMiddlewareInstance, + onRequest: (ctx, next) => next(), renderers: [], }; diff --git a/packages/astro/src/core/render/context.ts b/packages/astro/src/core/render/context.ts index 90aaae0d2029..a43650a556cb 100644 --- a/packages/astro/src/core/render/context.ts +++ b/packages/astro/src/core/render/context.ts @@ -7,9 +7,12 @@ import type { SSRElement, SSRResult, } from '../../@types/astro'; +import { AstroError, AstroErrorData } from '../errors/index.js'; import { getParamsAndPropsOrThrow } from './core.js'; import type { Environment } from './environment'; +const clientLocalsSymbol = Symbol.for('astro.locals'); + /** * The RenderContext represents the parts of rendering that are specific to one request. */ @@ -27,6 +30,7 @@ export interface RenderContext { cookies?: AstroCookies; params: Params; props: Props; + locals?: object; } export type CreateRenderContextArgs = Partial & { @@ -51,7 +55,8 @@ export async function createRenderContext( logging: options.env.logging, ssr: options.env.ssr, }); - return { + + let context = { ...options, origin, pathname, @@ -59,4 +64,21 @@ export async function createRenderContext( params, props, }; + + // We define a custom property, so we can check the value passed to locals + Object.defineProperty(context, 'locals', { + enumerable: true, + get() { + return Reflect.get(request, clientLocalsSymbol); + }, + set(val) { + if (typeof val !== 'object') { + throw new AstroError(AstroErrorData.LocalsNotAnObject); + } else { + Reflect.set(request, clientLocalsSymbol, val); + } + }, + }); + + return context; } diff --git a/packages/astro/src/core/render/core.ts b/packages/astro/src/core/render/core.ts index 282c78f2b903..91b668479b0a 100644 --- a/packages/astro/src/core/render/core.ts +++ b/packages/astro/src/core/render/core.ts @@ -1,4 +1,4 @@ -import type { APIContext, ComponentInstance, Params, Props, RouteData } from '../../@types/astro'; +import type { AstroCookies, ComponentInstance, Params, Props, RouteData } from '../../@types/astro'; import { renderPage as runtimeRenderPage } from '../../runtime/server/index.js'; import { attachToResponse } from '../cookies/index.js'; import { AstroError, AstroErrorData } from '../errors/index.js'; @@ -108,15 +108,15 @@ export type RenderPage = { mod: ComponentInstance; renderContext: RenderContext; env: Environment; - apiContext?: APIContext; isCompressHTML?: boolean; + cookies: AstroCookies; }; export async function renderPage({ mod, renderContext, env, - apiContext, + cookies, isCompressHTML = false, }: RenderPage) { if (routeIsRedirect(renderContext.route)) { @@ -133,8 +133,6 @@ export async function renderPage({ if (!Component) throw new Error(`Expected an exported Astro component but received typeof ${typeof Component}`); - let locals = apiContext?.locals ?? {}; - const result = createResult({ adapterName: env.adapterName, links: renderContext.links, @@ -155,8 +153,8 @@ export async function renderPage({ scripts: renderContext.scripts, ssr: env.ssr, status: renderContext.status ?? 200, - cookies: apiContext?.cookies, - locals, + cookies, + locals: renderContext.locals ?? {}, }); // Support `export const components` for `MDX` pages diff --git a/packages/astro/src/core/render/dev/index.ts b/packages/astro/src/core/render/dev/index.ts index c0113739285a..67d0b0581266 100644 --- a/packages/astro/src/core/render/dev/index.ts +++ b/packages/astro/src/core/render/dev/index.ts @@ -180,22 +180,31 @@ export async function renderPage(options: SSROptions): Promise { mod, env, }); + const apiContext = createAPIContext({ + request: options.request, + params: renderContext.params, + props: renderContext.props, + adapterName: options.env.adapterName, + }); if (options.middleware) { if (options.middleware && options.middleware.onRequest) { - const apiContext = createAPIContext({ - request: options.request, - params: renderContext.params, - props: renderContext.props, - adapterName: options.env.adapterName, - }); - const onRequest = options.middleware.onRequest as MiddlewareResponseHandler; const response = await callMiddleware(env.logging, onRequest, apiContext, () => { - return coreRenderPage({ mod, renderContext, env: options.env, apiContext }); + return coreRenderPage({ + mod, + renderContext, + env: options.env, + cookies: apiContext.cookies, + }); }); return response; } } - return await coreRenderPage({ mod, renderContext, env: options.env }); // NOTE: without "await", errors won’t get caught below + return await coreRenderPage({ + mod, + renderContext, + env: options.env, + cookies: apiContext.cookies, + }); // NOTE: without "await", errors won’t get caught below } diff --git a/packages/astro/src/core/render/dev/vite.ts b/packages/astro/src/core/render/dev/vite.ts index fe4d3f7916b2..39df7d269c93 100644 --- a/packages/astro/src/core/render/dev/vite.ts +++ b/packages/astro/src/core/render/dev/vite.ts @@ -41,48 +41,50 @@ export async function* crawlGraph( continue; } if (id === entry.id) { + const urlDeps = getDepsFromEntry(entry); scanned.add(id); const entryIsStyle = isCSSRequest(id); for (const importedModule of entry.importedModules) { - // A propagation stopping point is a module with the ?astroPropagatedAssets flag. - // When we encounter one of these modules we don't want to continue traversing. - let isPropagationStoppingPoint = false; + if (!importedModule.id) continue; + // some dynamically imported modules are *not* server rendered in time // to only SSR modules that we can safely transform, we check against // a list of file extensions based on our built-in vite plugins - if (importedModule.id) { - // Strip special query params like "?content". - // NOTE: Cannot use `new URL()` here because not all IDs will be valid paths. - // For example, `virtual:image-loader` if you don't have the plugin installed. - const importedModulePathname = importedModule.id.replace(STRIP_QUERY_PARAMS_REGEX, ''); - // If the entry is a style, skip any modules that are not also styles. - // Tools like Tailwind might add HMR dependencies as `importedModules` - // but we should skip them--they aren't really imported. Without this, - // every hoisted script in the project is added to every page! - if (entryIsStyle && !isCSSRequest(importedModulePathname)) { - continue; - } - const isFileTypeNeedingSSR = fileExtensionsToSSR.has( - npath.extname(importedModulePathname) - ); - isPropagationStoppingPoint = ASTRO_PROPAGATED_ASSET_REGEX.test(importedModule.id); - if ( - isFileTypeNeedingSSR && - // Should not SSR a module with ?astroPropagatedAssets - !isPropagationStoppingPoint - ) { - const mod = loader.getModuleById(importedModule.id); - if (!mod?.ssrModule) { - try { - await loader.import(importedModule.id); - } catch { - /** Likely an out-of-date module entry! Silently continue. */ - } + + // Strip special query params like "?content". + // NOTE: Cannot use `new URL()` here because not all IDs will be valid paths. + // For example, `virtual:image-loader` if you don't have the plugin installed. + const importedModulePathname = importedModule.id.replace(STRIP_QUERY_PARAMS_REGEX, ''); + // If the entry is a style, skip any modules that are not also styles. + // Tools like Tailwind might add HMR dependencies as `importedModules` + // but we should skip them--they aren't really imported. Without this, + // every hoisted script in the project is added to every page! + if (entryIsStyle && !isCSSRequest(importedModulePathname)) { + continue; + } + + const isFileTypeNeedingSSR = fileExtensionsToSSR.has(npath.extname(importedModulePathname)); + // A propagation stopping point is a module with the ?astroPropagatedAssets flag. + // When we encounter one of these modules we don't want to continue traversing. + const isPropagationStoppingPoint = ASTRO_PROPAGATED_ASSET_REGEX.test(importedModule.id); + if ( + isFileTypeNeedingSSR && + // Should not SSR a module with ?astroPropagatedAssets + !isPropagationStoppingPoint + ) { + const mod = loader.getModuleById(importedModule.id); + if (!mod?.ssrModule) { + try { + await loader.import(importedModule.id); + } catch { + /** Likely an out-of-date module entry! Silently continue. */ } } } - if (!isPropagationStoppingPoint) { + + // Make sure the `importedModule` traversed is explicitly imported by the user, and not by HMR + if (urlDeps.includes(importedModule.url) && !isPropagationStoppingPoint) { importedModules.add(importedModule); } } @@ -100,3 +102,11 @@ export async function* crawlGraph( yield* crawlGraph(loader, importedModule.id, false, scanned); } } + +function getDepsFromEntry(entry: ModuleNode) { + let deps = entry.ssrTransformResult?.deps ?? []; + if (entry.ssrTransformResult?.dynamicDeps) { + deps = deps.concat(entry.ssrTransformResult.dynamicDeps); + } + return deps.map((dep) => unwrapId(dep)); +} diff --git a/packages/astro/src/core/render/ssr-element.ts b/packages/astro/src/core/render/ssr-element.ts index 84b0ab531293..2d9bf9ae8d59 100644 --- a/packages/astro/src/core/render/ssr-element.ts +++ b/packages/astro/src/core/render/ssr-element.ts @@ -1,13 +1,12 @@ -import slashify from 'slash'; import type { SSRElement } from '../../@types/astro'; -import { joinPaths, prependForwardSlash } from '../../core/path.js'; +import { joinPaths, prependForwardSlash, slash } from '../../core/path.js'; import type { StylesheetAsset } from '../app/types'; export function createAssetLink(href: string, base?: string, assetsPrefix?: string): string { if (assetsPrefix) { - return joinPaths(assetsPrefix, slashify(href)); + return joinPaths(assetsPrefix, slash(href)); } else if (base) { - return prependForwardSlash(joinPaths(base, slashify(href))); + return prependForwardSlash(joinPaths(base, slash(href))); } else { return href; } diff --git a/packages/astro/src/core/request.ts b/packages/astro/src/core/request.ts index d8ac9033db1a..d229ceaa4c84 100644 --- a/packages/astro/src/core/request.ts +++ b/packages/astro/src/core/request.ts @@ -13,6 +13,7 @@ export interface CreateRequestOptions { body?: RequestBody | undefined; logging: LogOptions; ssr: boolean; + locals?: object | undefined; } const clientAddressSymbol = Symbol.for('astro.clientAddress'); @@ -26,6 +27,7 @@ export function createRequest({ body = undefined, logging, ssr, + locals, }: CreateRequestOptions): Request { let headersObj = headers instanceof Headers @@ -66,7 +68,7 @@ export function createRequest({ Reflect.set(request, clientAddressSymbol, clientAddress); } - Reflect.set(request, clientLocalsSymbol, {}); + Reflect.set(request, clientLocalsSymbol, locals ?? {}); return request; } diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts index 4a998fee930c..b5a6831643a5 100644 --- a/packages/astro/src/core/routing/manifest/create.ts +++ b/packages/astro/src/core/routing/manifest/create.ts @@ -11,12 +11,11 @@ import type { LogOptions } from '../../logger/core'; import nodeFs from 'fs'; import { createRequire } from 'module'; import path from 'path'; -import slash from 'slash'; import { fileURLToPath } from 'url'; import { getPrerenderDefault } from '../../../prerender/utils.js'; import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from '../../constants.js'; import { warn } from '../../logger/core.js'; -import { removeLeadingForwardSlash } from '../../path.js'; +import { removeLeadingForwardSlash, slash } from '../../path.js'; import { resolvePages } from '../../util.js'; import { getRouteGenerator } from './generator.js'; const require = createRequire(import.meta.url); @@ -387,7 +386,7 @@ export function createRouteManifest( comparator(injectedRouteToItem({ config, cwd }, a), injectedRouteToItem({ config, cwd }, b)) ) .reverse() // prepend to the routes array from lowest to highest priority - .forEach(({ pattern: name, entryPoint }) => { + .forEach(({ pattern: name, entryPoint, prerender: prerenderInjected }) => { let resolved: string; try { resolved = require.resolve(entryPoint, { paths: [cwd || fileURLToPath(config.root)] }); @@ -440,7 +439,7 @@ export function createRouteManifest( component, generate, pathname: pathname || void 0, - prerender, + prerender: prerenderInjected ?? prerender, }); }); diff --git a/packages/astro/src/core/util.ts b/packages/astro/src/core/util.ts index 403d41527626..2529e89c2439 100644 --- a/packages/astro/src/core/util.ts +++ b/packages/astro/src/core/util.ts @@ -1,13 +1,12 @@ import fs from 'fs'; import path from 'path'; -import slash from 'slash'; import { fileURLToPath } from 'url'; import { normalizePath } from 'vite'; import type { AstroConfig, AstroSettings, RouteType } from '../@types/astro'; import { isServerLikeOutput } from '../prerender/utils.js'; import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './constants.js'; import type { ModuleLoader } from './module-loader'; -import { prependForwardSlash, removeTrailingForwardSlash } from './path.js'; +import { prependForwardSlash, removeTrailingForwardSlash, slash } from './path.js'; /** Returns true if argument is an object of any prototype/class (but not null). */ export function isObject(value: unknown): value is Record { @@ -90,15 +89,18 @@ export function parseNpmName( * Windows: C:/Users/astro/code/my-project/src/pages/index.astro */ export function viteID(filePath: URL): string { - return slash(fileURLToPath(filePath) + filePath.search).replace(/\\/g, '/'); + return slash(fileURLToPath(filePath) + filePath.search); } export const VALID_ID_PREFIX = `/@id/`; +export const NULL_BYTE_PLACEHOLDER = `__x00__`; -// Strip valid id prefix. This is prepended to resolved Ids that are -// not valid browser import specifiers by the importAnalysis plugin. +// Strip valid id prefix and replace null byte placeholder. Both are prepended to resolved ids +// as they are not valid browser import specifiers (by the Vite's importAnalysis plugin) export function unwrapId(id: string): string { - return id.startsWith(VALID_ID_PREFIX) ? id.slice(VALID_ID_PREFIX.length) : id; + return id.startsWith(VALID_ID_PREFIX) + ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, '\0') + : id; } export function resolvePages(config: AstroConfig) { diff --git a/packages/astro/src/events/error.ts b/packages/astro/src/events/error.ts index 2c2c857b37f6..73ac2b5e410e 100644 --- a/packages/astro/src/events/error.ts +++ b/packages/astro/src/events/error.ts @@ -1,11 +1,10 @@ import type { ZodError } from 'zod'; +import type { ErrorData } from '../core/errors/errors-data.js'; import { AstroError, AstroErrorData, type ErrorWithMetadata } from '../core/errors/index.js'; -import { getErrorDataByCode } from '../core/errors/utils.js'; const EVENT_ERROR = 'ASTRO_CLI_ERROR'; interface ErrorEventPayload { - code: number | undefined; name: string; isFatal: boolean; plugin?: string | undefined; @@ -46,7 +45,6 @@ export function eventConfigError({ isFatal: boolean; }): { eventName: string; payload: ConfigErrorEventPayload }[] { const payload: ConfigErrorEventPayload = { - code: AstroErrorData.UnknownConfigError.code, name: 'ZodError', isFatal, isConfig: true, @@ -66,10 +64,9 @@ export function eventError({ isFatal: boolean; }): { eventName: string; payload: ErrorEventPayload }[] { const errorData = - AstroError.is(err) && err.errorCode ? getErrorDataByCode(err.errorCode)?.data : undefined; + AstroError.is(err) && (AstroErrorData[err.name as keyof typeof AstroErrorData] as ErrorData); const payload: ErrorEventPayload = { - code: err.code || err.errorCode || AstroErrorData.UnknownError.code, name: err.name, plugin: err.plugin, cliCommand: cmd, diff --git a/packages/astro/src/events/index.ts b/packages/astro/src/events/index.ts index 31e549ad7bdd..7af647d449e5 100644 --- a/packages/astro/src/events/index.ts +++ b/packages/astro/src/events/index.ts @@ -1,19 +1,10 @@ import { AstroTelemetry } from '@astrojs/telemetry'; -import { createRequire } from 'module'; +import { version as viteVersion } from 'vite'; import { ASTRO_VERSION } from '../core/constants.js'; -const require = createRequire(import.meta.url); - -function getViteVersion() { - try { - const { version } = require('vite/package.json'); - return version; - } catch (e) {} - return undefined; -} export const telemetry = new AstroTelemetry({ astroVersion: ASTRO_VERSION, - viteVersion: getViteVersion(), + viteVersion, }); export * from './error.js'; diff --git a/packages/astro/src/events/session.ts b/packages/astro/src/events/session.ts index f2c26d980750..706779d4b8c2 100644 --- a/packages/astro/src/events/session.ts +++ b/packages/astro/src/events/session.ts @@ -83,7 +83,10 @@ export function eventCliSession( ) ?? []), ] as string[], adapter: userConfig?.adapter?.name ?? null, - integrations: (userConfig?.integrations ?? []).filter(Boolean).map((i: any) => i?.name), + integrations: (userConfig?.integrations ?? []) + .filter(Boolean) + .flat() + .map((i: any) => i?.name), trailingSlash: userConfig?.trailingSlash, build: userConfig?.build ? { diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts index 53a75fbea1ad..f0abd1576263 100644 --- a/packages/astro/src/integrations/index.ts +++ b/packages/astro/src/integrations/index.ts @@ -19,7 +19,6 @@ import { buildClientDirectiveEntrypoint } from '../core/client-directive/index.j import { mergeConfig } from '../core/config/config.js'; import { info, type LogOptions } from '../core/logger/core.js'; import { isServerLikeOutput } from '../prerender/utils.js'; -import { mdxContentEntryType } from '../vite-plugin-markdown/content-entry-type.js'; async function withTakingALongTimeMsg({ name, @@ -150,15 +149,6 @@ export async function runHookConfigSetup({ logging, }); - // Add MDX content entry type to support older `@astrojs/mdx` versions - // TODO: remove in next Astro minor release - if ( - integration.name === '@astrojs/mdx' && - !updatedSettings.contentEntryTypes.find((c) => c.extensions.includes('.mdx')) - ) { - addContentEntryType(mdxContentEntryType); - } - // Add custom client directives to settings, waiting for compiled code by esbuild for (const [name, compiled] of addedClientDirectives) { updatedSettings.clientDirectives.set(name, await compiled); @@ -286,7 +276,9 @@ export async function runHookBuildSetup({ pages: Map; target: 'server' | 'client'; logging: LogOptions; -}) { +}): Promise { + let updatedConfig = vite; + for (const integration of config.integrations) { if (integration?.hooks?.['astro:build:setup']) { await withTakingALongTimeMsg({ @@ -296,29 +288,33 @@ export async function runHookBuildSetup({ pages, target, updateConfig: (newConfig) => { - mergeConfig(vite, newConfig); + updatedConfig = mergeConfig(updatedConfig, newConfig); }, }), logging, }); } } + + return updatedConfig; } export async function runHookBuildSsr({ config, manifest, logging, + entryPoints, }: { config: AstroConfig; manifest: SerializedSSRManifest; logging: LogOptions; + entryPoints: Map; }) { for (const integration of config.integrations) { if (integration?.hooks?.['astro:build:ssr']) { await withTakingALongTimeMsg({ name: integration.name, - hookResult: integration.hooks['astro:build:ssr']({ manifest }), + hookResult: integration.hooks['astro:build:ssr']({ manifest, entryPoints }), logging, }); } diff --git a/packages/astro/src/jsx/babel.ts b/packages/astro/src/jsx/babel.ts index 9caf42aaf33a..1ccd05fbc4ca 100644 --- a/packages/astro/src/jsx/babel.ts +++ b/packages/astro/src/jsx/babel.ts @@ -192,7 +192,7 @@ export default function astroJSX(): PluginObj { ) { return; } - const parent = path.findParent((n) => t.isJSXElement(n))!; + const parent = path.findParent((n) => t.isJSXElement(n.node))!; const parentNode = parent.node as t.JSXElement; const tagName = getTagName(parentNode); if (!isComponent(tagName)) return; @@ -249,9 +249,9 @@ export default function astroJSX(): PluginObj { } }, JSXIdentifier(path, state) { - const isAttr = path.findParent((n) => t.isJSXAttribute(n)); + const isAttr = path.findParent((n) => t.isJSXAttribute(n.node)); if (isAttr) return; - const parent = path.findParent((n) => t.isJSXElement(n))!; + const parent = path.findParent((n) => t.isJSXElement(n.node))!; const parentNode = parent.node as t.JSXElement; const tagName = getTagName(parentNode); if (!isComponent(tagName)) return; diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts index 9be1c81afc05..a610b4b743da 100644 --- a/packages/astro/src/vite-plugin-astro-server/route.ts +++ b/packages/astro/src/vite-plugin-astro-server/route.ts @@ -21,6 +21,8 @@ import { isServerLikeOutput } from '../prerender/utils.js'; import { log404 } from './common.js'; import { handle404Response, writeSSRResult, writeWebResponse } from './response.js'; +const clientLocalsSymbol = Symbol.for('astro.locals'); + type AsyncReturnType Promise> = T extends ( ...args: any ) => Promise @@ -153,6 +155,7 @@ export async function handleRoute( logging, ssr: buildingToSSR, clientAddress: buildingToSSR ? req.socket.remoteAddress : undefined, + locals: Reflect.get(req, clientLocalsSymbol), // Allows adapters to pass in locals in dev mode. }); // Set user specified headers to response object. diff --git a/packages/astro/src/vite-plugin-astro/compile.ts b/packages/astro/src/vite-plugin-astro/compile.ts index 799e09e8e565..6bee4f672ae0 100644 --- a/packages/astro/src/vite-plugin-astro/compile.ts +++ b/packages/astro/src/vite-plugin-astro/compile.ts @@ -41,6 +41,8 @@ export async function cachedFullCompilation({ tsconfigRaw: { compilerOptions: { // Ensure client:only imports are treeshaken + // @ts-expect-error anticipate esbuild 0.18 feature + verbatimModuleSyntax: false, importsNotUsedAsValues: 'remove', }, }, diff --git a/packages/astro/src/vite-plugin-config-alias/README.md b/packages/astro/src/vite-plugin-config-alias/README.md index 85971c90aa0a..3b470adeda33 100644 --- a/packages/astro/src/vite-plugin-config-alias/README.md +++ b/packages/astro/src/vite-plugin-config-alias/README.md @@ -18,9 +18,9 @@ Consider the following example configuration: With this configuration, the following imports would map to the same location. ```js -import Test from '../components/Test.astro' +import Test from '../components/Test.astro'; -import Test from 'components/Test.astro' +import Test from 'components/Test.astro'; -import Test from 'components:Test' +import Test from 'components:Test'; ``` diff --git a/packages/astro/src/vite-plugin-jsx/index.ts b/packages/astro/src/vite-plugin-jsx/index.ts index 91aa63909d2d..9364a4e0b77a 100644 --- a/packages/astro/src/vite-plugin-jsx/index.ts +++ b/packages/astro/src/vite-plugin-jsx/index.ts @@ -160,6 +160,8 @@ export default function jsx({ settings, logging }: AstroPluginJSXOptions): Plugi tsconfigRaw: { compilerOptions: { // Ensure client:only imports are treeshaken + // @ts-expect-error anticipate esbuild 0.18 feature + verbatimModuleSyntax: false, importsNotUsedAsValues: 'remove', }, }, diff --git a/packages/astro/src/vite-plugin-load-fallback/index.ts b/packages/astro/src/vite-plugin-load-fallback/index.ts index 7c853245be34..084cb885f7ef 100644 --- a/packages/astro/src/vite-plugin-load-fallback/index.ts +++ b/packages/astro/src/vite-plugin-load-fallback/index.ts @@ -1,7 +1,7 @@ import nodeFs from 'fs'; import npath from 'path'; -import slashify from 'slash'; import type * as vite from 'vite'; +import { slash } from '../core/path.js'; type NodeFileSystemModule = typeof nodeFs; @@ -47,7 +47,7 @@ export default function loadFallbackPlugin({ async resolveId(id, parent) { // See if this can be loaded from our fs if (parent) { - const candidateId = npath.posix.join(npath.posix.dirname(slashify(parent)), id); + const candidateId = npath.posix.join(npath.posix.dirname(slash(parent)), id); try { // Check to see if this file exists and is not a directory. const stats = await fs.promises.stat(candidateId); diff --git a/packages/astro/src/vite-plugin-markdown/content-entry-type.ts b/packages/astro/src/vite-plugin-markdown/content-entry-type.ts index a3489c940132..92bb118d43a7 100644 --- a/packages/astro/src/vite-plugin-markdown/content-entry-type.ts +++ b/packages/astro/src/vite-plugin-markdown/content-entry-type.ts @@ -16,32 +16,3 @@ export const markdownContentEntryType: ContentEntryType = { // We need to handle propagation for Markdown because they support layouts which will bring in styles. handlePropagation: true, }; - -/** - * MDX content type for compatibility with older `@astrojs/mdx` versions - * TODO: remove in next Astro minor release - */ -export const mdxContentEntryType: ContentEntryType = { - extensions: ['.mdx'], - async getEntryInfo({ fileUrl, contents }: { fileUrl: URL; contents: string }) { - const parsed = parseFrontmatter(contents, fileURLToPath(fileUrl)); - return { - data: parsed.data, - body: parsed.content, - slug: parsed.data.slug, - rawData: parsed.matter, - }; - }, - // MDX can import scripts and styles, - // so wrap all MDX files with script / style propagation checks - handlePropagation: true, - contentModuleTypes: `declare module 'astro:content' { - interface Render { - '.mdx': Promise<{ - Content: import('astro').MarkdownInstance<{}>['Content']; - headings: import('astro').MarkdownHeading[]; - remarkPluginFrontmatter: Record; - }>; - } -}`, -}; diff --git a/packages/astro/src/vite-plugin-markdown/index.ts b/packages/astro/src/vite-plugin-markdown/index.ts index c3f08f2c4e15..fcdaf04ea147 100644 --- a/packages/astro/src/vite-plugin-markdown/index.ts +++ b/packages/astro/src/vite-plugin-markdown/index.ts @@ -27,7 +27,6 @@ function safeMatter(source: string, id: string) { return matter(source); } catch (err: any) { const markdownError = new MarkdownError({ - code: AstroErrorData.UnknownMarkdownError.code, message: err.message, stack: err.stack, location: { @@ -36,7 +35,6 @@ function safeMatter(source: string, id: string) { }); if (err.name === 'YAMLException') { - markdownError.setErrorCode(AstroErrorData.MarkdownFrontmatterParseError.code); markdownError.setLocation({ file: id, line: err.mark.line, diff --git a/packages/astro/test/astro-scripts.test.js b/packages/astro/test/astro-scripts.test.js index da3fc7c6660d..ae2268d8097f 100644 --- a/packages/astro/test/astro-scripts.test.js +++ b/packages/astro/test/astro-scripts.test.js @@ -1,7 +1,6 @@ import { expect } from 'chai'; import * as cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -import { tailwind } from './fixtures/astro-scripts/deps.mjs'; describe('Scripts (hoisted and not)', () => { describe('Build', () => { @@ -141,7 +140,6 @@ describe('Scripts (hoisted and not)', () => { fixture = await loadFixture({ root: './fixtures/astro-scripts/', integrations: [ - tailwind(), { name: 'test-script-injection-with-injected-route', hooks: { diff --git a/packages/astro/test/core-image.test.js b/packages/astro/test/core-image.test.js index f7a537e9809a..0edc26426343 100644 --- a/packages/astro/test/core-image.test.js +++ b/packages/astro/test/core-image.test.js @@ -4,8 +4,8 @@ import { basename } from 'node:path'; import { Writable } from 'node:stream'; import { removeDir } from '../dist/core/fs/index.js'; import testAdapter from './test-adapter.js'; -import { loadFixture } from './test-utils.js'; import { testImageService } from './test-image-service.js'; +import { loadFixture } from './test-utils.js'; describe('astro:image', () => { /** @type {import('./test-utils').Fixture} */ @@ -118,7 +118,7 @@ describe('astro:image', () => { expect(logs[0].message).to.contain('Received unsupported format'); }); - it("errors when an ESM imported image's src is passed to Image/getImage instead of the full import ssss", async () => { + it("errors when an ESM imported image's src is passed to Image/getImage instead of the full import", async () => { logs.length = 0; let res = await fixture.fetch('/error-image-src-passed'); await res.text(); diff --git a/packages/astro/test/custom-404-injected-from-dep.test.js b/packages/astro/test/custom-404-injected-from-dep.test.js new file mode 100644 index 000000000000..d9a822f4ed61 --- /dev/null +++ b/packages/astro/test/custom-404-injected-from-dep.test.js @@ -0,0 +1,22 @@ +import { expect } from 'chai'; +import { loadFixture } from './test-utils.js'; + +describe('Custom 404 with injectRoute from dependency', () => { + describe('build', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/custom-404-injected-from-dep/', + site: 'http://example.com', + }); + await fixture.build(); + }); + + it('Build succeeds', async () => { + const html = await fixture.readFile('/404.html'); + expect(html).to.contain(''); + }); + }); +}); diff --git a/packages/astro/test/dynamic-endpoint-collision.test.js b/packages/astro/test/dynamic-endpoint-collision.test.js index e1f4b2f03ea7..c0a11b5f8372 100644 --- a/packages/astro/test/dynamic-endpoint-collision.test.js +++ b/packages/astro/test/dynamic-endpoint-collision.test.js @@ -18,7 +18,7 @@ describe('Dynamic endpoint collision', () => { }); it('throw error when dynamic endpoint has path collision', async () => { - expect(errorMsg.errorCode).to.eq(3026); + expect(errorMsg.name).to.eq('PrerenderDynamicEndpointPathCollide'); }); }); diff --git a/packages/astro/test/events.test.js b/packages/astro/test/events.test.js index 98eaa2d54097..47f37b645e9a 100644 --- a/packages/astro/test/events.test.js +++ b/packages/astro/test/events.test.js @@ -385,6 +385,14 @@ describe('Events', () => { expect(payload.config.integrations.length).to.equal(0); }); + it('finds names for integration arrays', () => { + const config = { + integrations: [{ name: 'foo' }, [{ name: 'bar' }, { name: 'baz' }]], + }; + const [{ payload }] = events.eventCliSession({ cliCommand: 'dev' }, config); + expect(payload.config.integrations).to.deep.equal(['foo', 'bar', 'baz']); + }); + it('includes cli flags in payload', () => { const config = {}; const flags = { @@ -427,7 +435,6 @@ describe('Events', () => { expect(event).to.deep.equal({ eventName: 'ASTRO_CLI_ERROR', payload: { - code: AstroErrorData.UnknownConfigError.code, name: 'ZodError', isFatal: true, isConfig: true, @@ -451,7 +458,6 @@ describe('Events', () => { expect(event).to.deep.equal({ eventName: 'ASTRO_CLI_ERROR', payload: { - code: 1234, plugin: 'TEST PLUGIN', name: 'Error', isFatal: true, @@ -477,7 +483,6 @@ describe('Events', () => { anonymousMessageHint: '`Astro.clientAddress` is not available in the `ADAPTER_NAME` adapter. File an issue with the adapter to add support.', cliCommand: 'COMMAND_NAME', - code: 3002, isFatal: false, name: 'ClientAddressNotAvailable', plugin: undefined, @@ -494,7 +499,6 @@ describe('Events', () => { expect(event).to.deep.equal({ eventName: 'ASTRO_CLI_ERROR', payload: { - code: AstroErrorData.UnknownError.code, name: 'Error', plugin: undefined, isFatal: false, diff --git a/packages/astro/test/fixtures/0-css/package.json b/packages/astro/test/fixtures/0-css/package.json index bec81c0fb616..4a5d7734367c 100644 --- a/packages/astro/test/fixtures/0-css/package.json +++ b/packages/astro/test/fixtures/0-css/package.json @@ -9,7 +9,7 @@ "astro": "workspace:*", "react": "^18.1.0", "react-dom": "^18.1.0", - "svelte": "^3.48.0", - "vue": "^3.2.39" + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json index 6fcb9106ce3a..d4113b4fc8ff 100644 --- a/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json +++ b/packages/astro/test/fixtures/alias-tsconfig-baseurl-only/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/svelte": "workspace:*", "astro": "workspace:*", - "svelte": "^3.48.0" + "svelte": "^3.59.1" } } diff --git a/packages/astro/test/fixtures/alias-tsconfig/package.json b/packages/astro/test/fixtures/alias-tsconfig/package.json index dc4b7e7b9ea2..4abb4367fe02 100644 --- a/packages/astro/test/fixtures/alias-tsconfig/package.json +++ b/packages/astro/test/fixtures/alias-tsconfig/package.json @@ -6,6 +6,6 @@ "@astrojs/svelte": "workspace:*", "@test/namespace-package": "workspace:*", "astro": "workspace:*", - "svelte": "^3.48.0" + "svelte": "^3.59.1" } } diff --git a/packages/astro/test/fixtures/alias/package.json b/packages/astro/test/fixtures/alias/package.json index c3f6f56d83a3..e543a6967bc9 100644 --- a/packages/astro/test/fixtures/alias/package.json +++ b/packages/astro/test/fixtures/alias/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/svelte": "workspace:*", "astro": "workspace:*", - "svelte": "^3.48.0" + "svelte": "^3.59.1" } } diff --git a/packages/astro/test/fixtures/astro-assets-prefix/astro.config.mjs b/packages/astro/test/fixtures/astro-assets-prefix/astro.config.mjs index 869cf811b06d..7393b72b8aff 100644 --- a/packages/astro/test/fixtures/astro-assets-prefix/astro.config.mjs +++ b/packages/astro/test/fixtures/astro-assets-prefix/astro.config.mjs @@ -1,15 +1,19 @@ import { defineConfig } from 'astro/config'; -import react from '@astrojs/react' +import react from '@astrojs/react'; +import { testImageService } from '../../test-image-service.js'; // https://astro.build/config export default defineConfig({ - // test custom base to make sure things work - base: '/custom-base', - integrations: [react()], - build: { - assetsPrefix: 'http://localhost:4321' - }, - experimental: { - assets: true - } + // test custom base to make sure things work + base: '/custom-base', + integrations: [react()], + build: { + assetsPrefix: 'http://localhost:4321', + }, + experimental: { + assets: true, + }, + image: { + service: testImageService(), + }, }); diff --git a/packages/astro/test/fixtures/astro-basic/package.json b/packages/astro/test/fixtures/astro-basic/package.json index a6312565805d..c30c850dc7f0 100644 --- a/packages/astro/test/fixtures/astro-basic/package.json +++ b/packages/astro/test/fixtures/astro-basic/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/astro-children/package.json b/packages/astro/test/fixtures/astro-children/package.json index 0ba89d0a9782..1f40029857dd 100644 --- a/packages/astro/test/fixtures/astro-children/package.json +++ b/packages/astro/test/fixtures/astro-children/package.json @@ -7,8 +7,8 @@ "@astrojs/svelte": "workspace:*", "@astrojs/vue": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0", - "svelte": "^3.48.0", - "vue": "^3.2.39" + "preact": "^10.15.1", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/test/fixtures/astro-client-only/package.json b/packages/astro/test/fixtures/astro-client-only/package.json index 219a1a6a7380..4ac537e042a8 100644 --- a/packages/astro/test/fixtures/astro-client-only/package.json +++ b/packages/astro/test/fixtures/astro-client-only/package.json @@ -9,6 +9,6 @@ "astro": "workspace:*", "react": "^18.1.0", "react-dom": "^18.1.0", - "svelte": "^3.48.0" + "svelte": "^3.59.1" } } diff --git a/packages/astro/test/fixtures/astro-dynamic/package.json b/packages/astro/test/fixtures/astro-dynamic/package.json index 844513ebfc42..1499fa7f35fe 100644 --- a/packages/astro/test/fixtures/astro-dynamic/package.json +++ b/packages/astro/test/fixtures/astro-dynamic/package.json @@ -8,6 +8,6 @@ "astro": "workspace:*", "react": "^18.1.0", "react-dom": "^18.1.0", - "svelte": "^3.48.0" + "svelte": "^3.59.1" } } diff --git a/packages/astro/test/fixtures/astro-envs/package.json b/packages/astro/test/fixtures/astro-envs/package.json index a90a9c01c0a2..c46f4d6814ac 100644 --- a/packages/astro/test/fixtures/astro-envs/package.json +++ b/packages/astro/test/fixtures/astro-envs/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/vue": "workspace:*", "astro": "workspace:*", - "vue": "^3.2.39" + "vue": "^3.3.4" } } diff --git a/packages/astro/test/fixtures/astro-expr/package.json b/packages/astro/test/fixtures/astro-expr/package.json index 31ecdeb13360..b9fc5565ec35 100644 --- a/packages/astro/test/fixtures/astro-expr/package.json +++ b/packages/astro/test/fixtures/astro-expr/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/astro-fallback/package.json b/packages/astro/test/fixtures/astro-fallback/package.json index 31e7941edc4f..52d3f6731576 100644 --- a/packages/astro/test/fixtures/astro-fallback/package.json +++ b/packages/astro/test/fixtures/astro-fallback/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/astro-markdown-frontmatter-injection/package.json b/packages/astro/test/fixtures/astro-markdown-frontmatter-injection/package.json index 1b7fcc25b7a3..fd7f414c2f68 100644 --- a/packages/astro/test/fixtures/astro-markdown-frontmatter-injection/package.json +++ b/packages/astro/test/fixtures/astro-markdown-frontmatter-injection/package.json @@ -4,8 +4,8 @@ "private": true, "dependencies": { "astro": "workspace:*", - "mdast-util-to-string": "^3.1.0", + "mdast-util-to-string": "^3.2.0", "reading-time": "^1.5.0", - "unist-util-visit": "^4.1.0" + "unist-util-visit": "^4.1.2" } } diff --git a/packages/astro/test/fixtures/astro-scripts/astro.config.mjs b/packages/astro/test/fixtures/astro-scripts/astro.config.mjs index e841c915cfed..f34407295d8a 100644 --- a/packages/astro/test/fixtures/astro-scripts/astro.config.mjs +++ b/packages/astro/test/fixtures/astro-scripts/astro.config.mjs @@ -1,8 +1,11 @@ import { defineConfig } from 'astro/config'; import tailwind from '@astrojs/tailwind'; +import { fileURLToPath } from 'url'; export default defineConfig({ integrations: [ - tailwind() - ] -}) + tailwind({ + configFile: fileURLToPath(new URL('./tailwind.config.cjs', import.meta.url)), + }), + ], +}); diff --git a/packages/astro/test/fixtures/astro-scripts/deps.mjs b/packages/astro/test/fixtures/astro-scripts/deps.mjs deleted file mode 100644 index e6a090e7ba97..000000000000 --- a/packages/astro/test/fixtures/astro-scripts/deps.mjs +++ /dev/null @@ -1,2 +0,0 @@ -export { default as tailwind } from '@astrojs/tailwind'; - diff --git a/packages/astro/test/fixtures/astro-scripts/tailwind.config.cjs b/packages/astro/test/fixtures/astro-scripts/tailwind.config.cjs new file mode 100644 index 000000000000..f5368a76ab04 --- /dev/null +++ b/packages/astro/test/fixtures/astro-scripts/tailwind.config.cjs @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], + theme: { + extend: {}, + }, + plugins: [], +} diff --git a/packages/astro/test/fixtures/astro-slot-with-client/package.json b/packages/astro/test/fixtures/astro-slot-with-client/package.json index 141bf165d008..9427f65ab3d4 100644 --- a/packages/astro/test/fixtures/astro-slot-with-client/package.json +++ b/packages/astro/test/fixtures/astro-slot-with-client/package.json @@ -2,8 +2,8 @@ "name": "@test/astro-slot-with-client", "private": true, "dependencies": { - "astro": "workspace:*", "@astrojs/preact": "workspace:*", - "preact": "^10.11.0" + "astro": "workspace:*", + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/astro-slots-nested/package.json b/packages/astro/test/fixtures/astro-slots-nested/package.json index 7e57372ec3bb..e0d74ee802ef 100644 --- a/packages/astro/test/fixtures/astro-slots-nested/package.json +++ b/packages/astro/test/fixtures/astro-slots-nested/package.json @@ -5,15 +5,15 @@ "dependencies": { "@astrojs/preact": "workspace:*", "@astrojs/react": "workspace:*", - "@astrojs/vue": "workspace:*", "@astrojs/solid-js": "workspace:*", "@astrojs/svelte": "workspace:*", + "@astrojs/vue": "workspace:*", "astro": "workspace:*", + "preact": "^10.15.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "solid-js": "^1.7.4", - "svelte": "^3.58.0", - "vue": "^3.2.47", - "preact": "^10.13.2" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/test/fixtures/before-hydration/package.json b/packages/astro/test/fixtures/before-hydration/package.json index f04a39ae0944..0eaf3d77ae8f 100644 --- a/packages/astro/test/fixtures/before-hydration/package.json +++ b/packages/astro/test/fixtures/before-hydration/package.json @@ -4,6 +4,6 @@ "dependencies": { "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/build-assets/package.json b/packages/astro/test/fixtures/build-assets/package.json index 6dd278c2bcea..feb883935782 100644 --- a/packages/astro/test/fixtures/build-assets/package.json +++ b/packages/astro/test/fixtures/build-assets/package.json @@ -4,6 +4,6 @@ "dependencies": { "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/component-library-shared/package.json b/packages/astro/test/fixtures/component-library-shared/package.json index f5c344316685..5d87d1941de6 100644 --- a/packages/astro/test/fixtures/component-library-shared/package.json +++ b/packages/astro/test/fixtures/component-library-shared/package.json @@ -18,7 +18,7 @@ "astro": "workspace:*" }, "dependencies": { - "preact": "^10.11.0", + "preact": "^10.15.1", "react": "^18.2.0" } } diff --git a/packages/astro/test/fixtures/component-library/package.json b/packages/astro/test/fixtures/component-library/package.json index 0a677ced2c1d..90b3cdf47554 100644 --- a/packages/astro/test/fixtures/component-library/package.json +++ b/packages/astro/test/fixtures/component-library/package.json @@ -8,9 +8,9 @@ "@astrojs/svelte": "workspace:*", "@test/component-library-shared": "workspace:*", "astro": "workspace:*", - "preact": "^10.13.2", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "svelte": "^3.58.0" + "svelte": "^3.59.1" } } diff --git a/packages/astro/test/fixtures/content-collection-references/astro.config.mjs b/packages/astro/test/fixtures/content-collection-references/astro.config.mjs index 913ddc87651f..7287a125921a 100644 --- a/packages/astro/test/fixtures/content-collection-references/astro.config.mjs +++ b/packages/astro/test/fixtures/content-collection-references/astro.config.mjs @@ -1,8 +1,12 @@ import { defineConfig } from 'astro/config'; +import { testImageService } from '../../test-image-service.js'; // https://astro.build/config export default defineConfig({ - experimental: { - assets: true - }, + experimental: { + assets: true, + }, + image: { + service: testImageService(), + }, }); diff --git a/packages/astro/test/fixtures/custom-404-injected-from-dep/astro.config.mjs b/packages/astro/test/fixtures/custom-404-injected-from-dep/astro.config.mjs new file mode 100644 index 000000000000..840a9524cbdb --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-injected-from-dep/astro.config.mjs @@ -0,0 +1,18 @@ +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig({ + integrations: [ + { + name: '404-integration', + hooks: { + 'astro:config:setup': ({ injectRoute }) => { + injectRoute({ + pattern: '404', + entryPoint: '@test/custom-404-pkg/404.astro', + }); + }, + }, + }, + ], +}); diff --git a/packages/astro/test/fixtures/custom-404-injected-from-dep/package.json b/packages/astro/test/fixtures/custom-404-injected-from-dep/package.json new file mode 100644 index 000000000000..6af83260253a --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-injected-from-dep/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/custom-404-injected-from-dep", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*", + "@test/custom-404-pkg": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/custom-404-injected-from-dep/src/pages/index.astro b/packages/astro/test/fixtures/custom-404-injected-from-dep/src/pages/index.astro new file mode 100644 index 000000000000..cf5ef9b586c6 --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-injected-from-dep/src/pages/index.astro @@ -0,0 +1,11 @@ +--- +--- + + + + Custom 404 + + +

    Home

    + + diff --git a/packages/astro/test/fixtures/custom-404-pkg/404.astro b/packages/astro/test/fixtures/custom-404-pkg/404.astro new file mode 100644 index 000000000000..63d560b0fb91 --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-pkg/404.astro @@ -0,0 +1,13 @@ +--- +const canonicalURL = new URL(Astro.url.pathname, Astro.site); +--- + + + + Not Found - Custom 404 + + +

    Page not found

    +

    {canonicalURL.pathname}

    + + diff --git a/packages/astro/test/fixtures/custom-404-pkg/package.json b/packages/astro/test/fixtures/custom-404-pkg/package.json new file mode 100644 index 000000000000..f3207353448b --- /dev/null +++ b/packages/astro/test/fixtures/custom-404-pkg/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/custom-404-pkg", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/entry-file-names/package.json b/packages/astro/test/fixtures/entry-file-names/package.json index 392886491d4c..3ba4d666af07 100644 --- a/packages/astro/test/fixtures/entry-file-names/package.json +++ b/packages/astro/test/fixtures/entry-file-names/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/preact": "workspace:", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/fetch/package.json b/packages/astro/test/fixtures/fetch/package.json index 39d0a4e867c4..43f4ff24c036 100644 --- a/packages/astro/test/fixtures/fetch/package.json +++ b/packages/astro/test/fixtures/fetch/package.json @@ -7,8 +7,8 @@ "@astrojs/svelte": "workspace:*", "@astrojs/vue": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0", - "svelte": "^3.48.0", - "vue": "^3.2.39" + "preact": "^10.15.1", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/test/fixtures/hydration-race/package.json b/packages/astro/test/fixtures/hydration-race/package.json index 4b97e86f6f1a..2f415a655e08 100644 --- a/packages/astro/test/fixtures/hydration-race/package.json +++ b/packages/astro/test/fixtures/hydration-race/package.json @@ -9,6 +9,6 @@ "dependencies": { "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/jsx/package.json b/packages/astro/test/fixtures/jsx/package.json index eb2c75d6931a..1e7001b47ea3 100644 --- a/packages/astro/test/fixtures/jsx/package.json +++ b/packages/astro/test/fixtures/jsx/package.json @@ -11,11 +11,11 @@ "astro": "workspace:*" }, "dependencies": { - "preact": "^10.7.3", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "solid-js": "^1.4.3", - "svelte": "^3.48.0", - "vue": "^3.2.36" + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/test/fixtures/large-array/package.json b/packages/astro/test/fixtures/large-array/package.json index b5061ebf558b..f2d7f854c1c6 100644 --- a/packages/astro/test/fixtures/large-array/package.json +++ b/packages/astro/test/fixtures/large-array/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/solid-js": "workspace:*", "astro": "workspace:*", - "solid-js": "^1.5.6" + "solid-js": "^1.7.6" } } diff --git a/packages/astro/test/fixtures/lit-element/package.json b/packages/astro/test/fixtures/lit-element/package.json index 2b3b252ac795..487feb01880d 100644 --- a/packages/astro/test/fixtures/lit-element/package.json +++ b/packages/astro/test/fixtures/lit-element/package.json @@ -6,6 +6,6 @@ "@astrojs/lit": "workspace:*", "@webcomponents/template-shadowroot": "^0.2.1", "astro": "workspace:*", - "lit": "^2.7.0" + "lit": "^2.7.5" } } diff --git a/packages/astro/test/fixtures/middleware-tailwind/astro.config.mjs b/packages/astro/test/fixtures/middleware-tailwind/astro.config.mjs index db58bbf858ea..ebb824269aa5 100644 --- a/packages/astro/test/fixtures/middleware-tailwind/astro.config.mjs +++ b/packages/astro/test/fixtures/middleware-tailwind/astro.config.mjs @@ -1,8 +1,12 @@ import { defineConfig } from 'astro/config'; import tailwind from '@astrojs/tailwind'; - +import { fileURLToPath } from 'url'; // https://astro.build/config export default defineConfig({ - integrations: [tailwind()], + integrations: [ + tailwind({ + configFile: fileURLToPath(new URL('./tailwind.config.cjs', import.meta.url)), + }), + ], }); diff --git a/packages/astro/test/fixtures/middleware-tailwind/tailwind.config.cjs b/packages/astro/test/fixtures/middleware-tailwind/tailwind.config.cjs new file mode 100644 index 000000000000..f5368a76ab04 --- /dev/null +++ b/packages/astro/test/fixtures/middleware-tailwind/tailwind.config.cjs @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], + theme: { + extend: {}, + }, + plugins: [], +} diff --git a/packages/astro/test/fixtures/postcss/package.json b/packages/astro/test/fixtures/postcss/package.json index 7d240362b919..e41429b48e95 100644 --- a/packages/astro/test/fixtures/postcss/package.json +++ b/packages/astro/test/fixtures/postcss/package.json @@ -8,12 +8,12 @@ "@astrojs/vue": "workspace:*", "astro": "workspace:*", "autoprefixer": "^10.4.14", - "postcss": "^8.4.23", - "solid-js": "^1.5.6", - "svelte": "^3.48.0", - "vue": "^3.2.39" + "postcss": "^8.4.24", + "solid-js": "^1.7.6", + "svelte": "^3.59.1", + "vue": "^3.3.4" }, "devDependencies": { - "postcss-preset-env": "^7.7.1" + "postcss-preset-env": "^7.8.3" } } diff --git a/packages/astro/test/fixtures/preact-compat-component/package.json b/packages/astro/test/fixtures/preact-compat-component/package.json index 9cef449cc829..84e29114565a 100644 --- a/packages/astro/test/fixtures/preact-compat-component/package.json +++ b/packages/astro/test/fixtures/preact-compat-component/package.json @@ -6,6 +6,6 @@ "@astrojs/preact": "workspace:*", "@test/react-lib": "workspace:*", "astro": "workspace:*", - "preact": "^10.10.1" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/preact-component/package.json b/packages/astro/test/fixtures/preact-component/package.json index 96bd63693d9c..4898cdd2fdae 100644 --- a/packages/astro/test/fixtures/preact-component/package.json +++ b/packages/astro/test/fixtures/preact-component/package.json @@ -4,8 +4,8 @@ "private": true, "dependencies": { "@astrojs/preact": "workspace:*", + "@preact/signals": "1.1.1", "astro": "workspace:*", - "preact": "^10.11.0", - "@preact/signals": "1.1.1" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/react-and-solid/package.json b/packages/astro/test/fixtures/react-and-solid/package.json index 644e1911c254..fb0f67710365 100644 --- a/packages/astro/test/fixtures/react-and-solid/package.json +++ b/packages/astro/test/fixtures/react-and-solid/package.json @@ -7,6 +7,6 @@ "astro": "workspace:*", "react": "^18.2.0", "react-dom": "^18.1.0", - "solid-js": "^1.5.6" + "solid-js": "^1.7.6" } } diff --git a/packages/astro/test/fixtures/react-component/package.json b/packages/astro/test/fixtures/react-component/package.json index dc9b2fd6f01d..cf7b2b057fce 100644 --- a/packages/astro/test/fixtures/react-component/package.json +++ b/packages/astro/test/fixtures/react-component/package.json @@ -8,6 +8,6 @@ "astro": "workspace:*", "react": "^18.1.0", "react-dom": "^18.1.0", - "vue": "^3.2.37" + "vue": "^3.3.4" } } diff --git a/packages/astro/test/fixtures/reexport-astro-containing-client-component/package.json b/packages/astro/test/fixtures/reexport-astro-containing-client-component/package.json index f5b58cbcb8f5..fe687c1021fb 100644 --- a/packages/astro/test/fixtures/reexport-astro-containing-client-component/package.json +++ b/packages/astro/test/fixtures/reexport-astro-containing-client-component/package.json @@ -4,6 +4,6 @@ "dependencies": { "@astrojs/preact": "workspace:", "astro": "workspace:", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/slots-preact/package.json b/packages/astro/test/fixtures/slots-preact/package.json index d06192b83ae1..b234a5fa4631 100644 --- a/packages/astro/test/fixtures/slots-preact/package.json +++ b/packages/astro/test/fixtures/slots-preact/package.json @@ -6,6 +6,6 @@ "@astrojs/mdx": "workspace:*", "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/slots-solid/package.json b/packages/astro/test/fixtures/slots-solid/package.json index 82bd822cc0e6..0d8f1e80465f 100644 --- a/packages/astro/test/fixtures/slots-solid/package.json +++ b/packages/astro/test/fixtures/slots-solid/package.json @@ -6,6 +6,6 @@ "@astrojs/mdx": "workspace:*", "@astrojs/solid-js": "workspace:*", "astro": "workspace:*", - "solid-js": "^1.5.6" + "solid-js": "^1.7.6" } } diff --git a/packages/astro/test/fixtures/slots-svelte/package.json b/packages/astro/test/fixtures/slots-svelte/package.json index 28d7022c6c7b..c30158d9c2cc 100644 --- a/packages/astro/test/fixtures/slots-svelte/package.json +++ b/packages/astro/test/fixtures/slots-svelte/package.json @@ -6,6 +6,6 @@ "@astrojs/mdx": "workspace:*", "@astrojs/svelte": "workspace:*", "astro": "workspace:*", - "svelte": "^3.48.0" + "svelte": "^3.59.1" } } diff --git a/packages/astro/test/fixtures/slots-vue/package.json b/packages/astro/test/fixtures/slots-vue/package.json index 7992ea47628c..e61cf2bbec64 100644 --- a/packages/astro/test/fixtures/slots-vue/package.json +++ b/packages/astro/test/fixtures/slots-vue/package.json @@ -6,6 +6,6 @@ "@astrojs/mdx": "workspace:*", "@astrojs/vue": "workspace:*", "astro": "workspace:*", - "vue": "^3.2.39" + "vue": "^3.3.4" } } diff --git a/packages/astro/test/fixtures/solid-component/deps/solid-jsx-component/package.json b/packages/astro/test/fixtures/solid-component/deps/solid-jsx-component/package.json index 09971c1899f5..3dea01dde783 100644 --- a/packages/astro/test/fixtures/solid-component/deps/solid-jsx-component/package.json +++ b/packages/astro/test/fixtures/solid-component/deps/solid-jsx-component/package.json @@ -10,6 +10,6 @@ } }, "dependencies": { - "solid-js": "^1.5.6" + "solid-js": "^1.7.6" } } diff --git a/packages/astro/test/fixtures/solid-component/package.json b/packages/astro/test/fixtures/solid-component/package.json index abf476952c12..121dc69563e3 100644 --- a/packages/astro/test/fixtures/solid-component/package.json +++ b/packages/astro/test/fixtures/solid-component/package.json @@ -4,9 +4,9 @@ "private": true, "dependencies": { "@astrojs/solid-js": "workspace:*", - "@solidjs/router": "^0.5.0", + "@solidjs/router": "^0.5.1", "@test/solid-jsx-component": "file:./deps/solid-jsx-component", "astro": "workspace:*", - "solid-js": "^1.5.6" + "solid-js": "^1.7.6" } } diff --git a/packages/astro/test/fixtures/ssr-env/package.json b/packages/astro/test/fixtures/ssr-env/package.json index 7bb284752b28..d1ffd55adbed 100644 --- a/packages/astro/test/fixtures/ssr-env/package.json +++ b/packages/astro/test/fixtures/ssr-env/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/preact": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/ssr-locals/package.json b/packages/astro/test/fixtures/ssr-locals/package.json new file mode 100644 index 000000000000..ae9ee4649690 --- /dev/null +++ b/packages/astro/test/fixtures/ssr-locals/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/ssr-locals", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/ssr-locals/src/pages/api.js b/packages/astro/test/fixtures/ssr-locals/src/pages/api.js new file mode 100644 index 000000000000..d4f7386fb85c --- /dev/null +++ b/packages/astro/test/fixtures/ssr-locals/src/pages/api.js @@ -0,0 +1,10 @@ + +export async function get({ locals }) { + let out = { ...locals }; + + return new Response(JSON.stringify(out), { + headers: { + 'Content-Type': 'application/json' + } + }); +} diff --git a/packages/astro/test/fixtures/ssr-locals/src/pages/foo.astro b/packages/astro/test/fixtures/ssr-locals/src/pages/foo.astro new file mode 100644 index 000000000000..66b1f7a045b1 --- /dev/null +++ b/packages/astro/test/fixtures/ssr-locals/src/pages/foo.astro @@ -0,0 +1,4 @@ +--- +const { foo } = Astro.locals; +--- +

    { foo }

    diff --git a/packages/astro/test/fixtures/ssr-request/astro.config.mjs b/packages/astro/test/fixtures/ssr-request/astro.config.mjs new file mode 100644 index 000000000000..3bd2a19a386e --- /dev/null +++ b/packages/astro/test/fixtures/ssr-request/astro.config.mjs @@ -0,0 +1,8 @@ +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig({ + build: { + split: false + } +}); diff --git a/packages/astro/test/fixtures/ssr-scripts/package.json b/packages/astro/test/fixtures/ssr-scripts/package.json index ac49fda2e510..f5c996ebc077 100644 --- a/packages/astro/test/fixtures/ssr-scripts/package.json +++ b/packages/astro/test/fixtures/ssr-scripts/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/preact": "workspace:", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/ssr-split-manifest/astro.config.mjs b/packages/astro/test/fixtures/ssr-split-manifest/astro.config.mjs new file mode 100644 index 000000000000..171de39d9e24 --- /dev/null +++ b/packages/astro/test/fixtures/ssr-split-manifest/astro.config.mjs @@ -0,0 +1,7 @@ +import { defineConfig } from 'astro/config'; +export default defineConfig({ + build: { + split: true + }, + output: "server" +}) \ No newline at end of file diff --git a/packages/astro/test/fixtures/ssr-split-manifest/package.json b/packages/astro/test/fixtures/ssr-split-manifest/package.json new file mode 100644 index 000000000000..b980cc8a7b2e --- /dev/null +++ b/packages/astro/test/fixtures/ssr-split-manifest/package.json @@ -0,0 +1,8 @@ +{ + "name": "@test/ssr-split-manifest", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/ssr-split-manifest/src/pages/[...post].astro b/packages/astro/test/fixtures/ssr-split-manifest/src/pages/[...post].astro new file mode 100644 index 000000000000..8bac75eb9404 --- /dev/null +++ b/packages/astro/test/fixtures/ssr-split-manifest/src/pages/[...post].astro @@ -0,0 +1,18 @@ +--- +export async function getStaticPaths() { + return [ + { + params: { page: 1 }, + }, + { + params: { page: 2 }, + }, + { + params: { page: 3 } + } + ] +}; +--- + + + \ No newline at end of file diff --git a/packages/astro/test/fixtures/ssr-split-manifest/src/pages/index.astro b/packages/astro/test/fixtures/ssr-split-manifest/src/pages/index.astro new file mode 100644 index 000000000000..f189e711c19a --- /dev/null +++ b/packages/astro/test/fixtures/ssr-split-manifest/src/pages/index.astro @@ -0,0 +1,17 @@ +--- +import { manifest } from 'astro:ssr-manifest'; +--- + + + Testing + + + +

    Testing

    +
    + + diff --git a/packages/astro/test/fixtures/ssr-split-manifest/src/pages/lorem.md b/packages/astro/test/fixtures/ssr-split-manifest/src/pages/lorem.md new file mode 100644 index 000000000000..8a38d58c1963 --- /dev/null +++ b/packages/astro/test/fixtures/ssr-split-manifest/src/pages/lorem.md @@ -0,0 +1 @@ +# Title \ No newline at end of file diff --git a/packages/astro/test/fixtures/ssr-split-manifest/src/pages/zod.astro b/packages/astro/test/fixtures/ssr-split-manifest/src/pages/zod.astro new file mode 100644 index 000000000000..06d949d47f6c --- /dev/null +++ b/packages/astro/test/fixtures/ssr-split-manifest/src/pages/zod.astro @@ -0,0 +1,17 @@ +--- +import { manifest } from 'astro:ssr-manifest'; +--- + + + Testing + + + +

    Testing

    +
    + + \ No newline at end of file diff --git a/packages/astro/test/fixtures/static-build-frameworks/package.json b/packages/astro/test/fixtures/static-build-frameworks/package.json index 89fd24ee454e..17895a034e0a 100644 --- a/packages/astro/test/fixtures/static-build-frameworks/package.json +++ b/packages/astro/test/fixtures/static-build-frameworks/package.json @@ -6,7 +6,7 @@ "@astrojs/preact": "workspace:*", "@astrojs/react": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0", + "preact": "^10.15.1", "react": "^18.1.0", "react-dom": "^18.1.0" } diff --git a/packages/astro/test/fixtures/static-build/package.json b/packages/astro/test/fixtures/static-build/package.json index f4d9ae9a24ce..720e718f4553 100644 --- a/packages/astro/test/fixtures/static-build/package.json +++ b/packages/astro/test/fixtures/static-build/package.json @@ -6,6 +6,6 @@ "@astrojs/preact": "workspace:*", "@test/static-build-pkg": "workspace:*", "astro": "workspace:*", - "preact": "^10.11.0" + "preact": "^10.15.1" } } diff --git a/packages/astro/test/fixtures/svelte-component/package.json b/packages/astro/test/fixtures/svelte-component/package.json index 21d01c911ab1..c0de64d05b70 100644 --- a/packages/astro/test/fixtures/svelte-component/package.json +++ b/packages/astro/test/fixtures/svelte-component/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/svelte": "workspace:*", "astro": "workspace:*", - "svelte": "^3.48.0" + "svelte": "^3.59.1" } } diff --git a/packages/astro/test/fixtures/tailwindcss-ts/astro.config.ts b/packages/astro/test/fixtures/tailwindcss-ts/astro.config.ts index 0a5f36a87f53..5b16f3f9b341 100644 --- a/packages/astro/test/fixtures/tailwindcss-ts/astro.config.ts +++ b/packages/astro/test/fixtures/tailwindcss-ts/astro.config.ts @@ -1,7 +1,12 @@ import { defineConfig } from 'astro/config'; -import tailwind from "@astrojs/tailwind"; +import tailwind from '@astrojs/tailwind'; +import { fileURLToPath } from 'url'; // https://astro.build/config export default defineConfig({ - integrations: [tailwind()] -}); \ No newline at end of file + integrations: [ + tailwind({ + configFile: fileURLToPath(new URL('./tailwind.config.js', import.meta.url)), + }), + ], +}); diff --git a/packages/astro/test/fixtures/tailwindcss-ts/package.json b/packages/astro/test/fixtures/tailwindcss-ts/package.json index 3ab11a25def1..175841649908 100644 --- a/packages/astro/test/fixtures/tailwindcss-ts/package.json +++ b/packages/astro/test/fixtures/tailwindcss-ts/package.json @@ -5,7 +5,7 @@ "dependencies": { "@astrojs/tailwind": "workspace:*", "astro": "workspace:*", - "tailwindcss": "^3.3.2", - "postcss": "^8.4.23" + "postcss": "^8.4.24", + "tailwindcss": "^3.3.2" } } diff --git a/packages/astro/test/fixtures/tailwindcss/astro.config.mjs b/packages/astro/test/fixtures/tailwindcss/astro.config.mjs index 8274fd3b9e58..6b584904c19c 100644 --- a/packages/astro/test/fixtures/tailwindcss/astro.config.mjs +++ b/packages/astro/test/fixtures/tailwindcss/astro.config.mjs @@ -1,10 +1,16 @@ import { defineConfig } from 'astro/config'; import tailwind from '@astrojs/tailwind'; import mdx from '@astrojs/mdx'; +import { fileURLToPath } from 'url'; // https://astro.build/config export default defineConfig({ - integrations: [tailwind(), mdx()], + integrations: [ + tailwind({ + configFile: fileURLToPath(new URL('./tailwind.config.js', import.meta.url)), + }), + mdx(), + ], vite: { build: { assetsInlineLimit: 0, diff --git a/packages/astro/test/fixtures/tailwindcss/package.json b/packages/astro/test/fixtures/tailwindcss/package.json index 78cfb17cb41f..fae589b2964a 100644 --- a/packages/astro/test/fixtures/tailwindcss/package.json +++ b/packages/astro/test/fixtures/tailwindcss/package.json @@ -3,11 +3,11 @@ "version": "0.0.0", "private": true, "dependencies": { - "@astrojs/tailwind": "workspace:*", "@astrojs/mdx": "workspace:*", + "@astrojs/tailwind": "workspace:*", "astro": "workspace:*", "autoprefixer": "^10.4.14", - "postcss": "^8.4.23", + "postcss": "^8.4.24", "tailwindcss": "^3.3.2" } } diff --git a/packages/astro/test/fixtures/tailwindcss/postcss.config.js b/packages/astro/test/fixtures/tailwindcss/postcss.config.js deleted file mode 100644 index 779a7e47fb53..000000000000 --- a/packages/astro/test/fixtures/tailwindcss/postcss.config.js +++ /dev/null @@ -1,10 +0,0 @@ -const path = require('path'); - -module.exports = { - plugins: { - tailwindcss: { - config: path.join(__dirname, 'tailwind.config.js'), // update this if your path differs! - }, - autoprefixer: {} - }, -}; diff --git a/packages/astro/test/fixtures/third-party-astro/package.json b/packages/astro/test/fixtures/third-party-astro/package.json index 26e11aefdd6f..c705eac920f0 100644 --- a/packages/astro/test/fixtures/third-party-astro/package.json +++ b/packages/astro/test/fixtures/third-party-astro/package.json @@ -4,6 +4,6 @@ "private": true, "dependencies": { "astro": "workspace:*", - "astro-embed": "^0.1.1" + "astro-embed": "^0.1.3" } } diff --git a/packages/astro/test/fixtures/vue-component/package.json b/packages/astro/test/fixtures/vue-component/package.json index 1096ac057d65..b1f716dd65fc 100644 --- a/packages/astro/test/fixtures/vue-component/package.json +++ b/packages/astro/test/fixtures/vue-component/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/vue": "workspace:*", "astro": "workspace:*", - "vue": "^3.2.39" + "vue": "^3.3.4" } } diff --git a/packages/astro/test/fixtures/vue-jsx/package.json b/packages/astro/test/fixtures/vue-jsx/package.json index 8aaa1991b590..e04e8077d66c 100644 --- a/packages/astro/test/fixtures/vue-jsx/package.json +++ b/packages/astro/test/fixtures/vue-jsx/package.json @@ -5,6 +5,6 @@ "dependencies": { "@astrojs/vue": "workspace:*", "astro": "workspace:*", - "vue": "^3.2.39" + "vue": "^3.3.4" } } diff --git a/packages/astro/test/fixtures/vue-with-multi-renderer/package.json b/packages/astro/test/fixtures/vue-with-multi-renderer/package.json index 9680471749fc..36f4e9b81acd 100644 --- a/packages/astro/test/fixtures/vue-with-multi-renderer/package.json +++ b/packages/astro/test/fixtures/vue-with-multi-renderer/package.json @@ -6,7 +6,7 @@ "@astrojs/svelte": "workspace:*", "@astrojs/vue": "workspace:*", "astro": "workspace:*", - "svelte": "^3.48.0", - "vue": "^3.2.39" + "svelte": "^3.59.1", + "vue": "^3.3.4" } } diff --git a/packages/astro/test/parallel.js b/packages/astro/test/parallel.js index 2ad50f2d6ca2..22b76eda01c2 100644 --- a/packages/astro/test/parallel.js +++ b/packages/astro/test/parallel.js @@ -21,15 +21,15 @@ describe('Component parallelization', () => { Number(element.children[0].data) ); - let renderStartWithin = Math.max(...startTimes) - Math.min(...startTimes); + const renderStartWithin = Math.max(...startTimes) - Math.min(...startTimes); expect(renderStartWithin).to.be.lessThan( - 10, // in theory, this should be 0, so 10ms tolerance + 40, // in theory, this should be 0, but add 40ms tolerance for CI "The components didn't start rendering in parallel" ); const totalRenderTime = Math.max(...finishTimes) - Math.min(...startTimes); expect(totalRenderTime).to.be.lessThan( - 60, // max component delay is 40ms + 80, // max component delay is 40ms, add 40ms tolerance for CI 'The total render time was significantly longer than the max component delay' ); }); diff --git a/packages/astro/test/ssr-locals.test.js b/packages/astro/test/ssr-locals.test.js new file mode 100644 index 000000000000..41e5710fbbb8 --- /dev/null +++ b/packages/astro/test/ssr-locals.test.js @@ -0,0 +1,40 @@ +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; +import testAdapter from './test-adapter.js'; + +describe('SSR Astro.locals from server', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/ssr-locals/', + output: 'server', + adapter: testAdapter(), + }); + await fixture.build(); + }); + + it('Can access Astro.locals in page', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/foo'); + const locals = { foo: 'bar' }; + const response = await app.render(request, undefined, locals); + const html = await response.text(); + + const $ = cheerio.load(html); + expect($('#foo').text()).to.equal('bar'); + }); + + it('Can access Astro.locals in api context', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/api'); + const locals = { foo: 'bar' }; + const response = await app.render(request, undefined, locals); + expect(response.status).to.equal(200); + const body = await response.json(); + + expect(body.foo).to.equal('bar'); + }); +}); diff --git a/packages/astro/test/ssr-split-manifest.test.js b/packages/astro/test/ssr-split-manifest.test.js new file mode 100644 index 000000000000..5005f6279953 --- /dev/null +++ b/packages/astro/test/ssr-split-manifest.test.js @@ -0,0 +1,49 @@ +import { expect } from 'chai'; +import { loadFixture } from './test-utils.js'; +import testAdapter from './test-adapter.js'; +import * as cheerio from 'cheerio'; +import { fileURLToPath } from 'node:url'; +import { existsSync } from 'node:fs'; + +describe('astro:ssr-manifest, split', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + let entryPoints; + let currentRoutes; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/ssr-split-manifest/', + output: 'server', + adapter: testAdapter({ + setEntryPoints(entries) { + entryPoints = entries; + }, + setRoutes(routes) { + currentRoutes = routes; + }, + }), + }); + await fixture.build(); + }); + + it('should be able to render a specific entry point', async () => { + const pagePath = 'src/pages/index.astro'; + const app = await fixture.loadEntryPoint(pagePath, currentRoutes); + const request = new Request('http://example.com/'); + const response = await app.render(request); + const html = await response.text(); + + const $ = cheerio.load(html); + expect($('#assets').text()).to.equal('["/_astro/index.a8a337e4.css"]'); + }); + + it('should give access to entry points that exists on file system', async () => { + // number of the pages inside src/ + expect(entryPoints.size).to.equal(4); + for (const fileUrl in entryPoints.values()) { + let filePath = fileURLToPath(fileUrl); + expect(existsSync(filePath)).to.be.true; + } + }); +}); diff --git a/packages/astro/test/test-adapter.js b/packages/astro/test/test-adapter.js index cc34e3c3373c..af5a7777b8c1 100644 --- a/packages/astro/test/test-adapter.js +++ b/packages/astro/test/test-adapter.js @@ -4,7 +4,11 @@ import { viteID } from '../dist/core/util.js'; * * @returns {import('../src/@types/astro').AstroIntegration} */ -export default function ({ provideAddress = true, extendAdapter } = { provideAddress: true }) { +export default function ( + { provideAddress = true, extendAdapter, setEntryPoints = undefined, setRoutes = undefined } = { + provideAddress: true, + } +) { return { name: 'my-ssr-adapter', hooks: { @@ -34,7 +38,7 @@ export default function ({ provideAddress = true, extendAdapter } = { provideAdd this.#manifest = manifest; } - async render(request, routeData) { + async render(request, routeData, locals) { const url = new URL(request.url); if(this.#manifest.assets.has(url.pathname)) { const filePath = new URL('../client/' + this.removeBase(url.pathname), import.meta.url); @@ -42,9 +46,8 @@ export default function ({ provideAddress = true, extendAdapter } = { provideAdd return new Response(data); } - Reflect.set(request, Symbol.for('astro.locals'), {}); ${provideAddress ? `request[Symbol.for('astro.clientAddress')] = '0.0.0.0';` : ''} - return super.render(request, routeData); + return super.render(request, routeData, locals); } } @@ -71,6 +74,16 @@ export default function ({ provideAddress = true, extendAdapter } = { provideAdd ...extendAdapter, }); }, + 'astro:build:ssr': ({ entryPoints }) => { + if (setEntryPoints) { + setEntryPoints(entryPoints); + } + }, + 'astro:build:done': ({ routes }) => { + if (setRoutes) { + setRoutes(routes); + } + }, }, }; } diff --git a/packages/astro/test/test-utils.js b/packages/astro/test/test-utils.js index b618f8593a42..11b181779bbc 100644 --- a/packages/astro/test/test-utils.js +++ b/packages/astro/test/test-utils.js @@ -13,6 +13,9 @@ import dev from '../dist/core/dev/index.js'; import { nodeLogDestination } from '../dist/core/logger/node.js'; import preview from '../dist/core/preview/index.js'; import { check } from '../dist/cli/check/index.js'; +import { getVirtualModulePageNameFromPath } from '../dist/core/build/plugins/util.js'; +import { RESOLVED_SPLIT_MODULE_ID } from '../dist/core/build/plugins/plugin-ssr.js'; +import { makeSplitEntryPointFileName } from '../dist/core/build/static-build.js'; // polyfill WebAPIs to globalThis for Node v12, Node v14, and Node v16 polyfill(globalThis, { @@ -245,6 +248,15 @@ export async function loadFixture(inlineConfig) { app.manifest = manifest; return app; }, + loadEntryPoint: async (pagePath, routes, streaming) => { + const virtualModule = getVirtualModulePageNameFromPath(RESOLVED_SPLIT_MODULE_ID, pagePath); + const filePath = makeSplitEntryPointFileName(virtualModule, routes); + const url = new URL(`./server/${filePath}?id=${fixtureId}`, config.outDir); + const { createApp, manifest, middleware } = await import(url); + const app = createApp(streaming); + app.manifest = manifest; + return app; + }, editFile: async (filePath, newContentsOrCallback) => { const fileUrl = new URL(filePath.replace(/^\//, ''), config.root); const contents = await fs.promises.readFile(fileUrl, 'utf-8'); diff --git a/packages/astro/test/units/content-collections/frontmatter.test.js b/packages/astro/test/units/content-collections/frontmatter.test.js index c4c9826fddb5..d35a6df33668 100644 --- a/packages/astro/test/units/content-collections/frontmatter.test.js +++ b/packages/astro/test/units/content-collections/frontmatter.test.js @@ -1,7 +1,6 @@ import { fileURLToPath } from 'node:url'; import nodeFS from 'node:fs'; import path from 'node:path'; -import slash from 'slash'; import { runInContainer } from '../../../dist/core/dev/index.js'; import { attachContentServerListeners } from '../../../dist/content/index.js'; @@ -10,8 +9,10 @@ import { createFs, triggerFSEvent } from '../test-utils.js'; const root = new URL('../../fixtures/alias/', import.meta.url); function getTypesDts() { - const typesdtsURL = new URL('../../../src/content/template/types.d.ts', import.meta.url); - const relpath = slash(path.relative(fileURLToPath(root), fileURLToPath(typesdtsURL))); + const typesdtsURL = new URL('../../../content-types.template.d.ts', import.meta.url); + const relpath = path + .relative(fileURLToPath(root), fileURLToPath(typesdtsURL)) + .replace(/\\/g, '/'); return { [relpath]: nodeFS.readFileSync(typesdtsURL, 'utf-8'), }; diff --git a/packages/astro/test/units/cookies/error.test.js b/packages/astro/test/units/cookies/error.test.js index 3052042d40f4..9cfe1ec0f0ac 100644 --- a/packages/astro/test/units/cookies/error.test.js +++ b/packages/astro/test/units/cookies/error.test.js @@ -14,7 +14,7 @@ describe('astro/src/core/cookies', () => { cookies.set('foo', 'bar'); expect(false).to.equal(true); } catch (err) { - expect(err.errorCode).to.equal(3030); + expect(err.name).to.equal('ResponseSentError'); } }); }); diff --git a/packages/astro/test/units/dev/collections-mixed-content-errors.test.js b/packages/astro/test/units/dev/collections-mixed-content-errors.test.js index d323946f8d5b..64fb1c296f41 100644 --- a/packages/astro/test/units/dev/collections-mixed-content-errors.test.js +++ b/packages/astro/test/units/dev/collections-mixed-content-errors.test.js @@ -1,10 +1,10 @@ import { expect } from 'chai'; -import { createFsWithFallback } from '../test-utils.js'; -import { defaultLogging } from '../../test-utils.js'; +import { fileURLToPath } from 'url'; import { validateConfig } from '../../../dist/core/config/config.js'; import { createSettings } from '../../../dist/core/config/index.js'; -import { fileURLToPath } from 'url'; import { sync as _sync } from '../../../dist/core/sync/index.js'; +import { defaultLogging } from '../../test-utils.js'; +import { createFsWithFallback } from '../test-utils.js'; const root = new URL('../../fixtures/content-mixed-errors/', import.meta.url); const logging = defaultLogging; @@ -27,16 +27,16 @@ name: Ben # Ben`, '/src/content/authors/tony.json': `{ "name": "Tony" }`, '/src/content/config.ts': ` - + import { z, defineCollection } from 'astro:content'; - + const authors = defineCollection({ type: 'data', schema: z.object({ name: z.string(), }), }); - + export const collections = { authors };`, }, root @@ -48,7 +48,6 @@ name: Ben } catch (e) { expect(e).to.be.instanceOf(Error); expect(e.type).to.equal('AstroError'); - expect(e.errorCode).to.equal(9005); expect(e.message).to.include('authors'); } }); @@ -63,16 +62,16 @@ title: Post # Post`, '/src/content/blog/post.yaml': `title: YAML Post`, '/src/content/config.ts': ` - + import { z, defineCollection } from 'astro:content'; - + const blog = defineCollection({ type: 'content', schema: z.object({ title: z.string(), }), }); - + export const collections = { blog };`, }, root @@ -84,7 +83,7 @@ title: Post } catch (e) { expect(e).to.be.instanceOf(Error); expect(e.type).to.equal('AstroError'); - expect(e.errorCode).to.equal(9005); + expect(e.message).to.include('blog'); } }); @@ -94,16 +93,16 @@ title: Post { '/src/content/banners/welcome.json': `{ "src": "/example", "alt": "Welcome" }`, '/src/content/config.ts': ` - + import { z, defineCollection } from 'astro:content'; - + const banners = defineCollection({ schema: z.object({ src: z.string(), alt: z.string(), }), }); - + export const collections = { banners };`, }, root @@ -115,7 +114,6 @@ title: Post } catch (e) { expect(e).to.be.instanceOf(Error); expect(e.type).to.equal('AstroError'); - expect(e.errorCode).to.equal(9006); expect(e.hint).to.include("Try adding `type: 'data'`"); } }); @@ -127,14 +125,14 @@ title: Post '/src/content/i18n/_placeholder.txt': 'Need content here', '/src/content/config.ts': ` import { z, defineCollection } from 'astro:content'; - + const i18n = defineCollection({ type: 'data', schema: z.object({ greeting: z.string(), }), }); - + export const collections = { i18n };`, }, root diff --git a/packages/astro/test/units/dev/styles.test.js b/packages/astro/test/units/dev/styles.test.js new file mode 100644 index 000000000000..76af929beb08 --- /dev/null +++ b/packages/astro/test/units/dev/styles.test.js @@ -0,0 +1,70 @@ +import { expect } from 'chai'; +import { fileURLToPath } from 'url'; + +import { getStylesForURL } from '../../../dist/core/render/dev/css.js'; +import { viteID } from '../../../dist/core/util.js'; + +const root = new URL('../../fixtures/alias/', import.meta.url); + +class TestLoader { + constructor(modules) { + this.modules = new Map(modules.map((m) => [m.id, m])); + } + getModuleById(id) { + return this.modules.get(id); + } + getModulesByFile(id) { + return this.modules.has(id) ? [this.modules.get(id)] : []; + } +} + +describe('Crawling graph for CSS', () => { + let loader; + before(() => { + const indexId = viteID(new URL('./src/pages/index.astro', root)); + const aboutId = viteID(new URL('./src/pages/about.astro', root)); + loader = new TestLoader([ + { + id: indexId, + importedModules: [ + { + id: aboutId, + url: aboutId, + }, + { + id: indexId + '?astro&style.css', + url: indexId + '?astro&style.css', + ssrModule: {}, + }, + ], + ssrTransformResult: { + deps: [indexId + '?astro&style.css'], + }, + }, + { + id: aboutId, + importedModules: [ + { + id: aboutId + '?astro&style.css', + url: aboutId + '?astro&style.css', + ssrModule: {}, + }, + ], + ssrTransformResult: { + deps: [aboutId + '?astro&style.css'], + }, + }, + ]); + }); + + it("importedModules is checked against the child's importers", async () => { + // In dev mode, HMR modules tracked are added to importedModules. We use `importers` + // to verify that they are true importers. + const res = await getStylesForURL( + new URL('./src/pages/index.astro', root), + loader, + 'development' + ); + expect(res.urls.size).to.equal(1); + }); +}); diff --git a/packages/astro/test/units/integrations/api.test.js b/packages/astro/test/units/integrations/api.test.js new file mode 100644 index 000000000000..919628da2901 --- /dev/null +++ b/packages/astro/test/units/integrations/api.test.js @@ -0,0 +1,30 @@ +import { expect } from 'chai'; +import { runHookBuildSetup } from '../../../dist/integrations/index.js'; + +describe('Integration API', () => { + it('runHookBuildSetup should work', async () => { + const updatedViteConfig = await runHookBuildSetup({ + config: { + integrations: [ + { + name: 'test', + hooks: { + 'astro:build:setup'({ updateConfig }) { + updateConfig({ + define: { + foo: 'bar', + }, + }); + }, + }, + }, + ], + }, + vite: {}, + logging: {}, + pages: new Map(), + target: 'server', + }); + expect(updatedViteConfig).to.haveOwnProperty('define'); + }); +}); diff --git a/packages/astro/test/units/vite-plugin-scanner/scan.test.js b/packages/astro/test/units/vite-plugin-scanner/scan.test.js index 3bfc15960b25..7b9c598bef6a 100644 --- a/packages/astro/test/units/vite-plugin-scanner/scan.test.js +++ b/packages/astro/test/units/vite-plugin-scanner/scan.test.js @@ -52,7 +52,6 @@ describe('astro scan', () => { const result = await scan(`export let prerender = true;`, '/src/components/index.astro'); expect(false).to.be.true; } catch (e) { - expect(e.errorCode).to.equal(3019); expect(e.message).to.contain( `A \`prerender\` export has been detected, but its value cannot be statically analyzed.` ); @@ -64,7 +63,6 @@ describe('astro scan', () => { const result = await scan(`export var prerender = true;`, '/src/components/index.astro'); expect(false).to.be.true; } catch (e) { - expect(e.errorCode).to.equal(3019); expect(e.message).to.contain( `A \`prerender\` export has been detected, but its value cannot be statically analyzed.` ); @@ -76,7 +74,6 @@ describe('astro scan', () => { const result = await scan(`export const prerender = !!value;`, '/src/components/index.astro'); expect(false).to.be.true; } catch (e) { - expect(e.errorCode).to.equal(3019); expect(e.message).to.contain( `A \`prerender\` export has been detected, but its value cannot be statically analyzed.` ); @@ -88,7 +85,6 @@ describe('astro scan', () => { const result = await scan(`export const prerender = value;`, '/src/components/index.astro'); expect(false).to.be.true; } catch (e) { - expect(e.errorCode).to.equal(3019); expect(e.message).to.contain( `A \`prerender\` export has been detected, but its value cannot be statically analyzed.` ); @@ -103,7 +99,6 @@ describe('astro scan', () => { ); expect(false).to.be.true; } catch (e) { - expect(e.errorCode).to.equal(3019); expect(e.message).to.contain( `A \`prerender\` export has been detected, but its value cannot be statically analyzed.` ); @@ -118,7 +113,6 @@ describe('astro scan', () => { ); expect(false).to.be.true; } catch (e) { - expect(e.errorCode).to.equal(3019); expect(e.message).to.contain( `A \`prerender\` export has been detected, but its value cannot be statically analyzed.` ); diff --git a/packages/create-astro/CHANGELOG.md b/packages/create-astro/CHANGELOG.md index d1e06d4cb55d..471f90329e5c 100644 --- a/packages/create-astro/CHANGELOG.md +++ b/packages/create-astro/CHANGELOG.md @@ -1,5 +1,11 @@ # create-astro +## 3.1.8 + +### Patch Changes + +- [#7435](https://github.com/withastro/astro/pull/7435) [`3f9f5c117`](https://github.com/withastro/astro/commit/3f9f5c117e4e9e4a0c0a648cb6db9a3073cd5727) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix registry failures using unexpected package managers when running create-astro + ## 3.1.7 ### Patch Changes diff --git a/packages/create-astro/README.md b/packages/create-astro/README.md index 0b0c9813c309..5341d60f02e5 100644 --- a/packages/create-astro/README.md +++ b/packages/create-astro/README.md @@ -26,6 +26,7 @@ npm create astro@latest my-astro-project -- --template minimal # yarn yarn create astro my-astro-project --template minimal ``` + [Check out the full list][examples] of example templates, available on GitHub. You can also use any GitHub repo as a template: @@ -38,16 +39,16 @@ npm create astro@latest my-astro-project -- --template cassidoo/shopify-react-as May be provided in place of prompts -| Name | Description | -|:-------------|:----------------------------------------------------| -| `--template ` | Specify your template. | -| `--install` / `--no-install` | Install dependencies (or not). | -| `--git` / `--no-git` | Initialize git repo (or not). | -| `--yes` (`-y`) | Skip all prompt by accepting defaults. | -| `--no` (`-n`) | Skip all prompt by declining defaults. | -| `--dry-run` | Walk through steps without executing. | -| `--skip-houston` | Skip Houston animation. | -| `--typescript