Merge branch 'main' into bare-standalone-paths

This commit is contained in:
Rishi Raj Jain 2023-09-20 23:06:28 +05:30 committed by GitHub
commit a122c2a228
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
73 changed files with 510 additions and 556 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/node': patch
---
The node adapter now logs uncaught errors encountered during rendering a page.

View file

@ -1,5 +0,0 @@
---
'astro': patch
---
add hide to style & script generated for island

View file

@ -1,5 +0,0 @@
---
'astro': patch
---
Fix small types issues related to `astro:assets`'s AVIF support and `getImage`

View file

@ -0,0 +1,20 @@
---
'@astrojs/cloudflare': minor
---
Add support for the following Node.js Runtime APIs, which are availabe in [Cloudflare](https://developers.cloudflare.com/workers/runtime-apis/nodejs) using the `node:` syntax.
- assert
- AsyncLocalStorage
- Buffer
- Diagnostics Channel
- EventEmitter
- path
- process
- Streams
- StringDecoder
- util
```js
import { Buffer } from 'node:buffer';
```

View file

@ -1,5 +0,0 @@
---
'@astrojs/vercel': patch
---
log only once in serverless adapter

View file

@ -0,0 +1,6 @@
---
'@astrojs/telemetry': patch
'astro': patch
---
Improve config info telemetry

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fix alias plugin causing CSS ordering issue

View file

@ -1,5 +0,0 @@
---
'@astrojs/cloudflare': patch
---
add the option to type environment variables using a generic

View file

@ -1,5 +0,0 @@
---
'astro': patch
---
show redirect symbol as of the page

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Prevent body scripts from re-executing on navigation

View file

@ -11,6 +11,6 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.1.0" "astro": "^3.1.1"
} }
} }

View file

@ -14,6 +14,6 @@
"@astrojs/mdx": "^1.1.0", "@astrojs/mdx": "^1.1.0",
"@astrojs/rss": "^3.0.0", "@astrojs/rss": "^3.0.0",
"@astrojs/sitemap": "^3.0.0", "@astrojs/sitemap": "^3.0.0",
"astro": "^3.1.0" "astro": "^3.1.1"
} }
} }

View file

@ -15,7 +15,7 @@
], ],
"scripts": {}, "scripts": {},
"devDependencies": { "devDependencies": {
"astro": "^3.1.0" "astro": "^3.1.1"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "^2.0.0-beta.0" "astro": "^2.0.0-beta.0"

View file

@ -10,7 +10,7 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.1.0" "astro": "^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"@astrojs/deno": "^5.0.0" "@astrojs/deno": "^5.0.0"

View file

@ -14,6 +14,6 @@
"@astrojs/alpinejs": "^0.3.0", "@astrojs/alpinejs": "^0.3.0",
"@types/alpinejs": "^3.7.2", "@types/alpinejs": "^3.7.2",
"alpinejs": "^3.12.3", "alpinejs": "^3.12.3",
"astro": "^3.1.0" "astro": "^3.1.1"
} }
} }

View file

@ -13,7 +13,7 @@
"dependencies": { "dependencies": {
"@astrojs/lit": "^3.0.0", "@astrojs/lit": "^3.0.0",
"@webcomponents/template-shadowroot": "^0.2.1", "@webcomponents/template-shadowroot": "^0.2.1",
"astro": "^3.1.0", "astro": "^3.1.1",
"lit": "^2.8.0" "lit": "^2.8.0"
} }
} }

View file

@ -16,7 +16,7 @@
"@astrojs/solid-js": "^3.0.1", "@astrojs/solid-js": "^3.0.1",
"@astrojs/svelte": "^4.0.2", "@astrojs/svelte": "^4.0.2",
"@astrojs/vue": "^3.0.0", "@astrojs/vue": "^3.0.0",
"astro": "^3.1.0", "astro": "^3.1.1",
"preact": "^10.17.1", "preact": "^10.17.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",

View file

@ -13,7 +13,7 @@
"dependencies": { "dependencies": {
"@astrojs/preact": "^3.0.0", "@astrojs/preact": "^3.0.0",
"@preact/signals": "^1.2.1", "@preact/signals": "^1.2.1",
"astro": "^3.1.0", "astro": "^3.1.1",
"preact": "^10.17.1" "preact": "^10.17.1"
} }
} }

View file

@ -14,7 +14,7 @@
"@astrojs/react": "^3.0.2", "@astrojs/react": "^3.0.2",
"@types/react": "^18.2.21", "@types/react": "^18.2.21",
"@types/react-dom": "^18.2.7", "@types/react-dom": "^18.2.7",
"astro": "^3.1.0", "astro": "^3.1.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0"
} }

View file

@ -12,7 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/solid-js": "^3.0.1", "@astrojs/solid-js": "^3.0.1",
"astro": "^3.1.0", "astro": "^3.1.1",
"solid-js": "^1.7.11" "solid-js": "^1.7.11"
} }
} }

View file

@ -12,7 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/svelte": "^4.0.2", "@astrojs/svelte": "^4.0.2",
"astro": "^3.1.0", "astro": "^3.1.1",
"svelte": "^4.2.0" "svelte": "^4.2.0"
} }
} }

View file

@ -12,7 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/vue": "^3.0.0", "@astrojs/vue": "^3.0.0",
"astro": "^3.1.0", "astro": "^3.1.1",
"vue": "^3.3.4" "vue": "^3.3.4"
} }
} }

View file

@ -12,6 +12,6 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/node": "^6.0.0", "@astrojs/node": "^6.0.0",
"astro": "^3.1.0" "astro": "^3.1.1"
} }
} }

View file

@ -15,7 +15,7 @@
], ],
"scripts": {}, "scripts": {},
"devDependencies": { "devDependencies": {
"astro": "^3.1.0" "astro": "^3.1.1"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "^2.0.0-beta.0" "astro": "^2.0.0-beta.0"

View file

@ -13,7 +13,7 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/node": "^6.0.0", "@astrojs/node": "^6.0.0",
"astro": "^3.1.0", "astro": "^3.1.1",
"html-minifier": "^4.0.0" "html-minifier": "^4.0.0"
} }
} }

View file

@ -11,6 +11,6 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.1.0" "astro": "^3.1.1"
} }
} }

View file

@ -11,6 +11,6 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.1.0" "astro": "^3.1.1"
} }
} }

View file

@ -11,6 +11,6 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.1.0" "astro": "^3.1.1"
} }
} }

View file

@ -83,7 +83,7 @@ const projects = (await getCollection('work'))
<header class="section-header stack gap-2 lg:gap-4"> <header class="section-header stack gap-2 lg:gap-4">
<h3>Mentions</h3> <h3>Mentions</h3>
<p> <p>
I have been fortunate enough to recieve praise for my work in several publications. Take I have been fortunate enough to receive praise for my work in several publications. Take
a look below to learn more. a look below to learn more.
</p> </p>
</header> </header>

View file

@ -14,7 +14,7 @@
"dependencies": { "dependencies": {
"@astrojs/node": "^6.0.0", "@astrojs/node": "^6.0.0",
"@astrojs/svelte": "^4.0.2", "@astrojs/svelte": "^4.0.2",
"astro": "^3.1.0", "astro": "^3.1.1",
"svelte": "^4.2.0" "svelte": "^4.2.0"
} }
} }

View file

@ -12,6 +12,6 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/markdoc": "^0.5.0", "@astrojs/markdoc": "^0.5.0",
"astro": "^3.1.0" "astro": "^3.1.1"
} }
} }

View file

@ -12,7 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@astrojs/markdown-remark": "^3.2.0", "@astrojs/markdown-remark": "^3.2.0",
"astro": "^3.1.0", "astro": "^3.1.1",
"hast-util-select": "^5.0.5", "hast-util-select": "^5.0.5",
"rehype-autolink-headings": "^6.1.1", "rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.1.0", "rehype-slug": "^5.1.0",

View file

@ -11,6 +11,6 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.1.0" "astro": "^3.1.1"
} }
} }

View file

@ -13,7 +13,7 @@
"dependencies": { "dependencies": {
"@astrojs/mdx": "^1.1.0", "@astrojs/mdx": "^1.1.0",
"@astrojs/preact": "^3.0.0", "@astrojs/preact": "^3.0.0",
"astro": "^3.1.0", "astro": "^3.1.1",
"preact": "^10.17.1" "preact": "^10.17.1"
} }
} }

View file

@ -13,7 +13,7 @@
"dependencies": { "dependencies": {
"@astrojs/preact": "^3.0.0", "@astrojs/preact": "^3.0.0",
"@nanostores/preact": "^0.5.0", "@nanostores/preact": "^0.5.0",
"astro": "^3.1.0", "astro": "^3.1.1",
"nanostores": "^0.9.3", "nanostores": "^0.9.3",
"preact": "^10.17.1" "preact": "^10.17.1"
} }

View file

@ -14,7 +14,7 @@
"@astrojs/mdx": "^1.1.0", "@astrojs/mdx": "^1.1.0",
"@astrojs/tailwind": "^5.0.0", "@astrojs/tailwind": "^5.0.0",
"@types/canvas-confetti": "^1.6.0", "@types/canvas-confetti": "^1.6.0",
"astro": "^3.1.0", "astro": "^3.1.1",
"autoprefixer": "^10.4.15", "autoprefixer": "^10.4.15",
"canvas-confetti": "^1.6.0", "canvas-confetti": "^1.6.0",
"postcss": "^8.4.28", "postcss": "^8.4.28",

View file

@ -11,7 +11,7 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^3.1.0", "astro": "^3.1.1",
"vite-plugin-pwa": "0.16.4", "vite-plugin-pwa": "0.16.4",
"workbox-window": "^7.0.0" "workbox-window": "^7.0.0"
} }

View file

@ -12,7 +12,7 @@
"test": "vitest" "test": "vitest"
}, },
"dependencies": { "dependencies": {
"astro": "^3.1.0", "astro": "^3.1.1",
"vitest": "^0.34.2" "vitest": "^0.34.2"
} }
} }

View file

@ -1,5 +1,15 @@
# astro # astro
## 3.1.1
### Patch Changes
- [#8580](https://github.com/withastro/astro/pull/8580) [`8d361169b`](https://github.com/withastro/astro/commit/8d361169b8e487933d671ce347f0ce74922c80cc) Thanks [@rishi-raj-jain](https://github.com/rishi-raj-jain)! - add hide to style & script generated for island
- [#8568](https://github.com/withastro/astro/pull/8568) [`95b5f6280`](https://github.com/withastro/astro/commit/95b5f6280d124f8d6f866dc3286406c272ee91bf) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Fix small types issues related to `astro:assets`'s AVIF support and `getImage`
- [#8579](https://github.com/withastro/astro/pull/8579) [`0586e20e8`](https://github.com/withastro/astro/commit/0586e20e8338e077b8eb1a3a96bdd19f5950c22f) Thanks [@rishi-raj-jain](https://github.com/rishi-raj-jain)! - show redirect symbol as of the page
## 3.1.0 ## 3.1.0
### Minor Changes ### Minor Changes

View file

@ -129,31 +129,18 @@ const { fallback = 'animate' } = Astro.props as Props;
var noopEl = document.createElement('div'); var noopEl = document.createElement('div');
} }
async function updateDOM(doc: Document, loc: URL, state?: State, fallback?: Fallback) { async function updateDOM(newDocument: Document, loc: URL, state?: State, fallback?: Fallback) {
// Check for a head element that should persist, either because it has the data // Check for a head element that should persist, either because it has the data
// attribute or is a link el. // attribute or is a link el.
const persistedHeadElement = (el: HTMLElement): Element | null => { const persistedHeadElement = (el: HTMLElement): Element | null => {
const id = el.getAttribute(PERSIST_ATTR); const id = el.getAttribute(PERSIST_ATTR);
const newEl = id && doc.head.querySelector(`[${PERSIST_ATTR}="${id}"]`); const newEl = id && newDocument.head.querySelector(`[${PERSIST_ATTR}="${id}"]`);
if (newEl) { if (newEl) {
return newEl; return newEl;
} }
if (el.matches('link[rel=stylesheet]')) { if (el.matches('link[rel=stylesheet]')) {
const href = el.getAttribute('href'); const href = el.getAttribute('href');
return doc.head.querySelector(`link[rel=stylesheet][href="${href}"]`); return newDocument.head.querySelector(`link[rel=stylesheet][href="${href}"]`);
}
if (el.tagName === 'SCRIPT') {
let s1 = el as HTMLScriptElement;
for (const s2 of doc.scripts) {
if (
// Inline
(s1.textContent && s1.textContent === s2.textContent) ||
// External
(s1.type === s2.type && s1.src === s2.src)
) {
return s2;
}
}
} }
// Only run this in dev. This will get stripped from production builds and is not needed. // Only run this in dev. This will get stripped from production builds and is not needed.
if (import.meta.env.DEV) { if (import.meta.env.DEV) {
@ -161,7 +148,7 @@ const { fallback = 'animate' } = Astro.props as Props;
const devId = el.dataset.viteDevId; const devId = el.dataset.viteDevId;
// If this same style tag exists, remove it from the new page // If this same style tag exists, remove it from the new page
return ( return (
doc.querySelector(`style[data-astro-dev-id="${devId}"]`) || newDocument.querySelector(`style[data-astro-dev-id="${devId}"]`) ||
// Otherwise, keep it anyways. This is client:only styles. // Otherwise, keep it anyways. This is client:only styles.
noopEl noopEl
); );
@ -173,7 +160,7 @@ const { fallback = 'animate' } = Astro.props as Props;
const swap = () => { const swap = () => {
// noscript tags inside head element are not honored on swap (#7969). // noscript tags inside head element are not honored on swap (#7969).
// Remove them before swapping. // Remove them before swapping.
doc.querySelectorAll('head noscript').forEach((el) => el.remove()); newDocument.querySelectorAll('head noscript').forEach((el) => el.remove());
// swap attributes of the html element // swap attributes of the html element
// - delete all attributes from the current document // - delete all attributes from the current document
@ -183,10 +170,26 @@ const { fallback = 'animate' } = Astro.props as Props;
const astro = [...html.attributes].filter( const astro = [...html.attributes].filter(
({ name }) => (html.removeAttribute(name), name.startsWith('data-astro-')) ({ name }) => (html.removeAttribute(name), name.startsWith('data-astro-'))
); );
[...doc.documentElement.attributes, ...astro].forEach(({ name, value }) => [...newDocument.documentElement.attributes, ...astro].forEach(({ name, value }) =>
html.setAttribute(name, value) html.setAttribute(name, value)
); );
// Replace scripts in both the head and body.
for (const s1 of document.scripts) {
for (const s2 of newDocument.scripts) {
if (
// Inline
(s1.textContent && s1.textContent === s2.textContent) ||
// External
(s1.type === s2.type && s1.src === s2.src)
) {
s2.remove();
} else {
s1.remove();
}
}
}
// Swap head // Swap head
for (const el of Array.from(document.head.children)) { for (const el of Array.from(document.head.children)) {
const newEl = persistedHeadElement(el as HTMLElement); const newEl = persistedHeadElement(el as HTMLElement);
@ -199,12 +202,13 @@ const { fallback = 'animate' } = Astro.props as Props;
el.remove(); el.remove();
} }
} }
// Everything left in the new head is new, append it all. // Everything left in the new head is new, append it all.
document.head.append(...doc.head.children); document.head.append(...newDocument.head.children);
// Persist elements in the existing body // Persist elements in the existing body
const oldBody = document.body; const oldBody = document.body;
document.body.replaceWith(doc.body); document.body.replaceWith(newDocument.body);
for (const el of oldBody.querySelectorAll(`[${PERSIST_ATTR}]`)) { for (const el of oldBody.querySelectorAll(`[${PERSIST_ATTR}]`)) {
const id = el.getAttribute(PERSIST_ATTR); const id = el.getAttribute(PERSIST_ATTR);
const newEl = document.querySelector(`[${PERSIST_ATTR}="${id}"]`); const newEl = document.querySelector(`[${PERSIST_ATTR}="${id}"]`);
@ -247,7 +251,7 @@ const { fallback = 'animate' } = Astro.props as Props;
// Wait on links to finish, to prevent FOUC // Wait on links to finish, to prevent FOUC
const links: Promise<any>[] = []; const links: Promise<any>[] = [];
for (const el of doc.querySelectorAll('head link[rel=stylesheet]')) { for (const el of newDocument.querySelectorAll('head link[rel=stylesheet]')) {
// Do not preload links that are already on the page. // Do not preload links that are already on the page.
if ( if (
!document.querySelector( !document.querySelector(
@ -299,8 +303,8 @@ const { fallback = 'animate' } = Astro.props as Props;
return; return;
} }
const doc = parser.parseFromString(html, mediaType); const newDocument = parser.parseFromString(html, mediaType);
if (!doc.querySelector('[name="astro-view-transitions-enabled"]')) { if (!newDocument.querySelector('[name="astro-view-transitions-enabled"]')) {
location.href = href; location.href = href;
return; return;
} }
@ -310,9 +314,9 @@ const { fallback = 'animate' } = Astro.props as Props;
document.documentElement.dataset.astroTransition = dir; document.documentElement.dataset.astroTransition = dir;
if (supportsViewTransitions) { if (supportsViewTransitions) {
finished = document.startViewTransition(() => updateDOM(doc, loc, state)).finished; finished = document.startViewTransition(() => updateDOM(newDocument, loc, state)).finished;
} else { } else {
finished = updateDOM(doc, loc, state, getFallback()); finished = updateDOM(newDocument, loc, state, getFallback());
} }
try { try {
await finished; await finished;

View file

@ -0,0 +1,9 @@
<div id="counter">Count</div>
<script is:inline>
let count = 1;
const onAfterSwap = () => {
count++;
document.querySelector('#counter').textContent = `Count: ${count}`;
}
document.addEventListener('astro:page-load', onAfterSwap);
</script>

View file

@ -11,4 +11,5 @@ import Layout from '../components/Layout.astro';
</a> </a>
<a id="click-two" href="/two" data-astro-reload>load page / no navigation</a> <a id="click-two" href="/two" data-astro-reload>load page / no navigation</a>
<a id="click-logo" href="/logo.svg" download>load page / no navigation</a> <a id="click-logo" href="/logo.svg" download>load page / no navigation</a>
<a id="click-svg" href="/logo.svg">load page / no navigation</a>
</Layout> </Layout>

View file

@ -0,0 +1,8 @@
---
import Layout from '../components/Layout.astro';
import InlineScript from '../components/InlineScript.astro';
---
<Layout>
<InlineScript />
<a id="click-one" href="/inline-script-two">Go to 2</a>
</Layout>

View file

@ -0,0 +1,8 @@
---
import Layout from '../components/Layout.astro';
import InlineScript from '../components/InlineScript.astro';
---
<Layout>
<InlineScript />
<a id="click-two" href="/inline-script-one">Go to 1</a>
</Layout>

View file

@ -520,6 +520,22 @@ test.describe('View Transitions', () => {
await downloadPromise; await downloadPromise;
}); });
test('data-astro-reload not required for non-html content', async ({ page, astro }) => {
const loads = [];
page.addListener('load', (p) => {
loads.push(p.title());
});
// Go to page 4
await page.goto(astro.resolveUrl('/four'));
let p = page.locator('#four');
await expect(p, 'should have content').toHaveText('Page 4');
await page.click('#click-svg');
p = page.locator('svg');
await expect(p).toBeVisible();
expect(loads.length, 'There should be 2 page load').toEqual(2);
});
test('Scroll position is restored on back navigation from page w/o ViewTransitions', async ({ test('Scroll position is restored on back navigation from page w/o ViewTransitions', async ({
page, page,
astro, astro,
@ -663,4 +679,22 @@ test.describe('View Transitions', () => {
locator = page.locator('#click-one'); locator = page.locator('#click-one');
await expect(locator).not.toBeInViewport(); await expect(locator).not.toBeInViewport();
}); });
test('body inline scripts do not re-execute on navigation', async ({ page, astro }) => {
const errors = [];
page.addListener('pageerror', (err) => {
errors.push(err);
});
await page.goto(astro.resolveUrl('/inline-script-one'));
let article = page.locator('#counter');
await expect(article, 'should have script content').toBeVisible('exists');
await page.click('#click-one');
article = page.locator('#counter');
await expect(article, 'should have script content').toHaveText('Count: 3');
expect(errors).toHaveLength(0);
});
}); });

View file

@ -1,6 +1,6 @@
{ {
"name": "astro", "name": "astro",
"version": "3.1.0", "version": "3.1.1",
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.", "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
"type": "module", "type": "module",
"author": "withastro", "author": "withastro",

View file

@ -9,7 +9,12 @@ import ora from 'ora';
import preferredPM from 'preferred-pm'; import preferredPM from 'preferred-pm';
import prompts from 'prompts'; import prompts from 'prompts';
import type yargs from 'yargs-parser'; import type yargs from 'yargs-parser';
import { loadTSConfig, resolveConfigPath, resolveRoot } from '../../core/config/index.js'; import {
loadTSConfig,
resolveConfig,
resolveConfigPath,
resolveRoot,
} from '../../core/config/index.js';
import { import {
defaultTSConfig, defaultTSConfig,
presets, presets,
@ -23,7 +28,7 @@ import { appendForwardSlash } from '../../core/path.js';
import { apply as applyPolyfill } from '../../core/polyfill.js'; import { apply as applyPolyfill } from '../../core/polyfill.js';
import { parseNpmName } from '../../core/util.js'; import { parseNpmName } from '../../core/util.js';
import { eventCliSession, telemetry } from '../../events/index.js'; import { eventCliSession, telemetry } from '../../events/index.js';
import { createLoggerFromFlags } from '../flags.js'; import { createLoggerFromFlags, flagsToAstroInlineConfig } from '../flags.js';
import { generate, parse, t, visit } from './babel.js'; import { generate, parse, t, visit } from './babel.js';
import { ensureImport } from './imports.js'; import { ensureImport } from './imports.js';
import { wrapDefaultExport } from './wrapper.js'; import { wrapDefaultExport } from './wrapper.js';
@ -87,7 +92,9 @@ async function getRegistry(): Promise<string> {
} }
export async function add(names: string[], { flags }: AddOptions) { export async function add(names: string[], { flags }: AddOptions) {
telemetry.record(eventCliSession('add')); const inlineConfig = flagsToAstroInlineConfig(flags);
const { userConfig } = await resolveConfig(inlineConfig, 'add');
telemetry.record(eventCliSession('add', userConfig));
applyPolyfill(); applyPolyfill();
if (flags.help || names.length === 0) { if (flags.help || names.length === 0) {
printHelp({ printHelp({

View file

@ -140,7 +140,6 @@ export const AstroConfigSchema = z.object({
.optional() .optional()
.default(ASTRO_CONFIG_DEFAULTS.build.excludeMiddleware), .default(ASTRO_CONFIG_DEFAULTS.build.excludeMiddleware),
}) })
.optional()
.default({}), .default({}),
server: z.preprocess( server: z.preprocess(
// preprocess // preprocess
@ -158,7 +157,6 @@ export const AstroConfigSchema = z.object({
port: z.number().optional().default(ASTRO_CONFIG_DEFAULTS.server.port), port: z.number().optional().default(ASTRO_CONFIG_DEFAULTS.server.port),
headers: z.custom<OutgoingHttpHeaders>().optional(), headers: z.custom<OutgoingHttpHeaders>().optional(),
}) })
.optional()
.default({}) .default({})
), ),
redirects: z redirects: z
@ -274,27 +272,11 @@ export const AstroConfigSchema = z.object({
.optional() .optional()
.default(ASTRO_CONFIG_DEFAULTS.experimental.optimizeHoistedScript), .default(ASTRO_CONFIG_DEFAULTS.experimental.optimizeHoistedScript),
}) })
.passthrough() .strict(
.refine( `Invalid or outdated experimental feature.\nCheck for incorrect spelling or outdated Astro version.\nSee https://docs.astro.build/en/reference/configuration-reference/#experimental-flags for a list of all current experiments.`
(d) => {
const validKeys = Object.keys(ASTRO_CONFIG_DEFAULTS.experimental);
const invalidKeys = Object.keys(d).filter((key) => !validKeys.includes(key));
if (invalidKeys.length > 0) return false;
return true;
},
(d) => {
const validKeys = Object.keys(ASTRO_CONFIG_DEFAULTS.experimental);
const invalidKeys = Object.keys(d).filter((key) => !validKeys.includes(key));
return {
message: `Invalid experimental key: \`${invalidKeys.join(
', '
)}\`. \nMake sure the spelling is correct, and that your Astro version supports this experiment.\nSee https://docs.astro.build/en/reference/configuration-reference/#experimental-flags for more information.`,
};
}
) )
.optional()
.default({}), .default({}),
legacy: z.object({}).optional().default({}), legacy: z.object({}).default({}),
}); });
export type AstroConfigType = z.infer<typeof AstroConfigSchema>; export type AstroConfigType = z.infer<typeof AstroConfigSchema>;

View file

@ -1,25 +1,8 @@
import type { AstroUserConfig } from '../@types/astro.js'; import type { AstroIntegration, AstroUserConfig } from '../@types/astro.js';
import { AstroConfigSchema } from '../core/config/schema.js';
const EVENT_SESSION = 'ASTRO_CLI_SESSION_STARTED'; const EVENT_SESSION = 'ASTRO_CLI_SESSION_STARTED';
interface ConfigInfo {
markdownPlugins: string[];
adapter: string | null;
integrations: string[];
trailingSlash: undefined | 'always' | 'never' | 'ignore';
build:
| undefined
| {
format: undefined | 'file' | 'directory';
};
markdown:
| undefined
| {
drafts: undefined | boolean;
syntaxHighlight: undefined | 'shiki' | 'prism' | false;
};
}
interface EventPayload { interface EventPayload {
cliCommand: string; cliCommand: string;
config?: ConfigInfo; config?: ConfigInfo;
@ -28,87 +11,126 @@ interface EventPayload {
optionalIntegrations?: number; optionalIntegrations?: number;
} }
const multiLevelKeys = new Set([ type ConfigInfoValue = string | boolean | string[] | undefined;
'build', type ConfigInfoRecord = Record<string, ConfigInfoValue>;
'markdown', type ConfigInfoBase = {
'markdown.shikiConfig', [alias in keyof AstroUserConfig]: ConfigInfoValue | ConfigInfoRecord;
'server', };
'vite', export interface ConfigInfo extends ConfigInfoBase {
'vite.resolve', build: ConfigInfoRecord;
'vite.css', image: ConfigInfoRecord;
'vite.json', markdown: ConfigInfoRecord;
'vite.server', experimental: ConfigInfoRecord;
'vite.server.fs', legacy: ConfigInfoRecord;
'vite.build', vite: ConfigInfoRecord | undefined;
'vite.preview', }
'vite.optimizeDeps',
'vite.ssr', function measureIsDefined(val: unknown) {
'vite.worker', // if val is undefined, measure undefined as a value
]); if (val === undefined) {
function configKeys(obj: Record<string, any> | undefined, parentKey: string): string[] { return undefined;
if (!obj) {
return [];
} }
// otherwise, convert the value to a boolean
return Boolean(val);
}
return Object.entries(obj) type StringLiteral<T> = T extends string ? (string extends T ? never : T) : never;
.map(([key, value]) => {
if (typeof value === 'object' && !Array.isArray(value)) {
const localKey = parentKey ? parentKey + '.' + key : key;
if (multiLevelKeys.has(localKey)) {
let keys = configKeys(value, localKey).map((subkey) => key + '.' + subkey);
keys.unshift(key);
return keys;
}
}
return key; /**
}) * Measure supports string literal values. Passing a generic `string` type
.flat(1); * results in an error, to make sure generic user input is never measured directly.
*/
function measureStringLiteral<T extends string>(
val: StringLiteral<T> | boolean | undefined
): string | boolean | undefined {
return val;
}
function measureIntegration(val: AstroIntegration | false | null | undefined): string | undefined {
if (!val || !val.name) {
return undefined;
}
return val.name;
}
function sanitizeConfigInfo(obj: object | undefined, validKeys: string[]): ConfigInfoRecord {
if (!obj || validKeys.length === 0) {
return {};
}
return validKeys.reduce(
(result, key) => {
result[key] = measureIsDefined((obj as Record<string, unknown>)[key]);
return result;
},
{} as Record<string, boolean | undefined>
);
}
/**
* This function creates an anonymous ConfigInfo object from the user's config.
* All values are sanitized to preserve anonymity. Simple "exist" boolean checks
* are used by default, with a few additional sanitized values added manually.
* Helper functions should always be used to ensure correct sanitization.
*/
function createAnonymousConfigInfo(userConfig: AstroUserConfig) {
// Sanitize and measure the generic config object
// NOTE(fks): Using _def is the correct, documented way to get the `shape`
// from a Zod object that includes a wrapping default(), optional(), etc.
// Even though `_def` appears private, it is type-checked for us so that
// any changes between versions will be detected.
const configInfo: ConfigInfo = {
...sanitizeConfigInfo(userConfig, Object.keys(AstroConfigSchema.shape)),
build: sanitizeConfigInfo(
userConfig.build,
Object.keys(AstroConfigSchema.shape.build._def.innerType.shape)
),
image: sanitizeConfigInfo(
userConfig.image,
Object.keys(AstroConfigSchema.shape.image._def.innerType.shape)
),
markdown: sanitizeConfigInfo(
userConfig.markdown,
Object.keys(AstroConfigSchema.shape.markdown._def.innerType.shape)
),
experimental: sanitizeConfigInfo(
userConfig.experimental,
Object.keys(AstroConfigSchema.shape.experimental._def.innerType.shape)
),
legacy: sanitizeConfigInfo(
userConfig.legacy,
Object.keys(AstroConfigSchema.shape.legacy._def.innerType.shape)
),
vite: userConfig.vite
? sanitizeConfigInfo(userConfig.vite, Object.keys(userConfig.vite))
: undefined,
};
// Measure string literal/enum configuration values
configInfo.build.format = measureStringLiteral(userConfig.build?.format);
configInfo.markdown.syntaxHighlight = measureStringLiteral(userConfig.markdown?.syntaxHighlight);
configInfo.output = measureStringLiteral(userConfig.output);
configInfo.scopedStyleStrategy = measureStringLiteral(userConfig.scopedStyleStrategy);
configInfo.trailingSlash = measureStringLiteral(userConfig.trailingSlash);
// Measure integration & adapter usage
configInfo.adapter = measureIntegration(userConfig.adapter);
configInfo.integrations = userConfig.integrations
?.flat(100)
.map(measureIntegration)
.filter(Boolean) as string[];
// Return the sanitized ConfigInfo object
return configInfo;
} }
export function eventCliSession( export function eventCliSession(
cliCommand: string, cliCommand: string,
userConfig?: AstroUserConfig, userConfig: AstroUserConfig,
flags?: Record<string, any> flags?: Record<string, any>
): { eventName: string; payload: EventPayload }[] { ): { eventName: string; payload: EventPayload }[] {
// Filter out falsy integrations
const configValues = userConfig
? {
markdownPlugins: [
...(userConfig?.markdown?.remarkPlugins?.map((p) =>
typeof p === 'string' ? p : typeof p
) ?? []),
...(userConfig?.markdown?.rehypePlugins?.map((p) =>
typeof p === 'string' ? p : typeof p
) ?? []),
] as string[],
adapter: userConfig?.adapter?.name ?? null,
integrations: (userConfig?.integrations ?? [])
.filter(Boolean)
.flat()
.map((i: any) => i?.name),
trailingSlash: userConfig?.trailingSlash,
build: userConfig?.build
? {
format: userConfig?.build?.format,
}
: undefined,
markdown: userConfig?.markdown
? {
drafts: userConfig.markdown?.drafts,
syntaxHighlight: userConfig.markdown?.syntaxHighlight,
}
: undefined,
}
: undefined;
// Filter out yargs default `_` flag which is the cli command // Filter out yargs default `_` flag which is the cli command
const cliFlags = flags ? Object.keys(flags).filter((name) => name != '_') : undefined; const cliFlags = flags ? Object.keys(flags).filter((name) => name != '_') : undefined;
const payload: EventPayload = { const payload: EventPayload = {
cliCommand, cliCommand,
configKeys: userConfig ? configKeys(userConfig, '') : undefined, config: createAnonymousConfigInfo(userConfig),
config: configValues,
flags: cliFlags, flags: cliFlags,
}; };
return [{ eventName: EVENT_SESSION, payload }]; return [{ eventName: EVENT_SESSION, payload }];

View file

@ -70,7 +70,8 @@ export default function configAliasVitePlugin({
const plugin: VitePlugin = { const plugin: VitePlugin = {
name: 'astro:tsconfig-alias', name: 'astro:tsconfig-alias',
enforce: 'pre', // use post to only resolve ids that all other plugins before it can't
enforce: 'post',
configResolved(config) { configResolved(config) {
patchCreateResolver(config, plugin); patchCreateResolver(config, plugin);
}, },
@ -100,7 +101,7 @@ export default function configAliasVitePlugin({
* *
* Vite may simplify this soon: https://github.com/vitejs/vite/pull/10555 * Vite may simplify this soon: https://github.com/vitejs/vite/pull/10555
*/ */
function patchCreateResolver(config: ResolvedConfig, prePlugin: VitePlugin) { function patchCreateResolver(config: ResolvedConfig, postPlugin: VitePlugin) {
const _createResolver = config.createResolver; const _createResolver = config.createResolver;
// @ts-expect-error override readonly property intentionally // @ts-expect-error override readonly property intentionally
config.createResolver = function (...args1: any) { config.createResolver = function (...args1: any) {
@ -124,15 +125,16 @@ function patchCreateResolver(config: ResolvedConfig, prePlugin: VitePlugin) {
ssr, ssr,
}; };
const result = await resolver.apply(_createResolver, args2);
if (result) return result;
// @ts-expect-error resolveId exists // @ts-expect-error resolveId exists
const resolved = await prePlugin.resolveId.apply(fakePluginContext, [ const resolved = await postPlugin.resolveId.apply(fakePluginContext, [
id, id,
importer, importer,
fakeResolveIdOpts, fakeResolveIdOpts,
]); ]);
if (resolved) return resolved; if (resolved) return resolved;
return resolver.apply(_createResolver, args2);
}; };
}; };
} }

View file

@ -5,44 +5,7 @@ import * as events from '../dist/events/index.js';
describe('Events', () => { describe('Events', () => {
describe('eventCliSession()', () => { describe('eventCliSession()', () => {
it('All top-level keys added', () => { it('string literal "build.format" is included', () => {
const config = {
root: 1,
srcDir: 2,
publicDir: 3,
outDir: 4,
site: 5,
base: 6,
trailingSlash: 7,
experimental: 8,
};
const expected = Object.keys(config);
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).to.deep.equal(expected);
});
it('configKeys includes format', () => {
const config = {
srcDir: 1,
build: {
format: 'file',
},
};
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).to.deep.equal(['srcDir', 'build', 'build.format']);
});
it('config.build.format', () => {
const config = { const config = {
srcDir: 1, srcDir: 1,
build: { build: {
@ -58,59 +21,7 @@ describe('Events', () => {
expect(payload.config.build.format).to.equal('file'); expect(payload.config.build.format).to.equal('file');
}); });
it('configKeys includes server props', () => { it('string literal "markdown.syntaxHighlight" is included', () => {
const config = {
srcDir: 1,
server: {
host: 'example.com',
port: 8033,
},
};
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).to.deep.equal(['srcDir', 'server', 'server.host', 'server.port']);
});
it('configKeys is deep', () => {
const config = {
publicDir: 1,
markdown: {
drafts: true,
shikiConfig: {
lang: 1,
theme: 2,
wrap: 3,
},
syntaxHighlight: 'shiki',
remarkPlugins: [],
rehypePlugins: [],
},
};
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).to.deep.equal([
'publicDir',
'markdown',
'markdown.drafts',
'markdown.shikiConfig',
'markdown.shikiConfig.lang',
'markdown.shikiConfig.theme',
'markdown.shikiConfig.wrap',
'markdown.syntaxHighlight',
'markdown.remarkPlugins',
'markdown.rehypePlugins',
]);
});
it('syntaxHighlight', () => {
const config = { const config = {
markdown: { markdown: {
syntaxHighlight: 'shiki', syntaxHighlight: 'shiki',
@ -145,233 +56,16 @@ describe('Events', () => {
}, },
config config
); );
expect(payload.configKeys).is.deep.equal([ expect(Object.keys(payload.config.vite)).is.deep.equal([
'root', 'css',
'vite', 'base',
'vite.css', 'mode',
'vite.css.modules', 'define',
'vite.base', 'publicDir',
'vite.mode',
'vite.define',
'vite.publicDir',
]); ]);
}); });
it('vite.resolve keys are captured', async () => { it('falsy integrations are handled', () => {
const config = {
vite: {
resolve: {
alias: {
a: 'b',
},
dedupe: ['one', 'two'],
},
},
};
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).is.deep.equal([
'vite',
'vite.resolve',
'vite.resolve.alias',
'vite.resolve.dedupe',
]);
});
it('vite.css keys are captured', async () => {
const config = {
vite: {
resolve: {
dedupe: ['one', 'two'],
},
css: {
modules: [],
postcss: {},
},
},
};
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).is.deep.equal([
'vite',
'vite.resolve',
'vite.resolve.dedupe',
'vite.css',
'vite.css.modules',
'vite.css.postcss',
]);
});
it('vite.server keys are captured', async () => {
const config = {
vite: {
server: {
host: 'example.com',
open: true,
fs: {
strict: true,
allow: ['a', 'b'],
},
},
},
};
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).is.deep.equal([
'vite',
'vite.server',
'vite.server.host',
'vite.server.open',
'vite.server.fs',
'vite.server.fs.strict',
'vite.server.fs.allow',
]);
});
it('vite.build keys are captured', async () => {
const config = {
vite: {
build: {
target: 'one',
outDir: 'some/dir',
cssTarget: {
one: 'two',
},
},
},
};
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).is.deep.equal([
'vite',
'vite.build',
'vite.build.target',
'vite.build.outDir',
'vite.build.cssTarget',
]);
});
it('vite.preview keys are captured', async () => {
const config = {
vite: {
preview: {
host: 'example.com',
port: 8080,
another: {
a: 'b',
},
},
},
};
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).is.deep.equal([
'vite',
'vite.preview',
'vite.preview.host',
'vite.preview.port',
'vite.preview.another',
]);
});
it('vite.optimizeDeps keys are captured', async () => {
const config = {
vite: {
optimizeDeps: {
entries: ['one', 'two'],
exclude: ['secret', 'name'],
},
},
};
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).is.deep.equal([
'vite',
'vite.optimizeDeps',
'vite.optimizeDeps.entries',
'vite.optimizeDeps.exclude',
]);
});
it('vite.ssr keys are captured', async () => {
const config = {
vite: {
ssr: {
external: ['a'],
target: { one: 'two' },
},
},
};
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).is.deep.equal([
'vite',
'vite.ssr',
'vite.ssr.external',
'vite.ssr.target',
]);
});
it('vite.worker keys are captured', async () => {
const config = {
vite: {
worker: {
format: { a: 'b' },
plugins: ['a', 'b'],
},
},
};
const [{ payload }] = events.eventCliSession(
{
cliCommand: 'dev',
},
config
);
expect(payload.configKeys).is.deep.equal([
'vite',
'vite.worker',
'vite.worker.format',
'vite.worker.plugins',
]);
});
it('falsy integrations', () => {
const config = { const config = {
srcDir: 1, srcDir: 1,
integrations: [null, undefined, false], integrations: [null, undefined, false],
@ -385,7 +79,7 @@ describe('Events', () => {
expect(payload.config.integrations.length).to.equal(0); expect(payload.config.integrations.length).to.equal(0);
}); });
it('finds names for integration arrays', () => { it('only integration names are included', () => {
const config = { const config = {
integrations: [{ name: 'foo' }, [{ name: 'bar' }, { name: 'baz' }]], integrations: [{ name: 'foo' }, [{ name: 'bar' }, { name: 'baz' }]],
}; };
@ -393,6 +87,14 @@ describe('Events', () => {
expect(payload.config.integrations).to.deep.equal(['foo', 'bar', 'baz']); expect(payload.config.integrations).to.deep.equal(['foo', 'bar', 'baz']);
}); });
it('only adapter name is included', () => {
const config = {
adapter: { name: 'ADAPTER_NAME' },
};
const [{ payload }] = events.eventCliSession({ cliCommand: 'dev' }, config);
expect(payload.config.adapter).to.equal('ADAPTER_NAME');
});
it('includes cli flags in payload', () => { it('includes cli flags in payload', () => {
const config = {}; const config = {};
const flags = { const flags = {

View file

@ -1,5 +1,11 @@
# create-astro # create-astro
## 4.2.0
### Minor Changes
- [#8551](https://github.com/withastro/astro/pull/8551) [`1d5b3f079`](https://github.com/withastro/astro/commit/1d5b3f079d0b4aa5a5c46f97b8b724ab88497fbe) Thanks [@jacobthesheep](https://github.com/jacobthesheep)! - Adds `--yes` and `dry-run` flags to project-name and the `yes` flag to template.
## 4.1.0 ## 4.1.0
### Minor Changes ### Minor Changes

View file

@ -1,6 +1,6 @@
{ {
"name": "create-astro", "name": "create-astro",
"version": "4.1.0", "version": "4.2.0",
"type": "module", "type": "module",
"author": "withastro", "author": "withastro",
"license": "MIT", "license": "MIT",

View file

@ -6,7 +6,9 @@ import { info, log, title } from '../messages.js';
import { isEmpty, toValidName } from './shared.js'; import { isEmpty, toValidName } from './shared.js';
export async function projectName(ctx: Pick<Context, 'cwd' | 'prompt' | 'projectName' | 'exit'>) { export async function projectName(
ctx: Pick<Context, 'cwd' | 'yes' | 'dryRun' | 'prompt' | 'projectName' | 'exit'>
) {
await checkCwd(ctx.cwd); await checkCwd(ctx.cwd);
if (!ctx.cwd || !isEmpty(ctx.cwd)) { if (!ctx.cwd || !isEmpty(ctx.cwd)) {
@ -14,6 +16,13 @@ export async function projectName(ctx: Pick<Context, 'cwd' | 'prompt' | 'project
await info('Hmm...', `${color.reset(`"${ctx.cwd}"`)}${color.dim(` is not empty!`)}`); await info('Hmm...', `${color.reset(`"${ctx.cwd}"`)}${color.dim(` is not empty!`)}`);
} }
if (ctx.yes) {
ctx.projectName = generateProjectName();
ctx.cwd = `./${ctx.projectName}`;
await info('dir', `Project created at ./${ctx.projectName}`);
return;
}
const { name } = await ctx.prompt({ const { name } = await ctx.prompt({
name: 'name', name: 'name',
type: 'text', type: 'text',
@ -33,6 +42,10 @@ export async function projectName(ctx: Pick<Context, 'cwd' | 'prompt' | 'project
ctx.cwd = name!.trim(); ctx.cwd = name!.trim();
ctx.projectName = toValidName(name!); ctx.projectName = toValidName(name!);
if (ctx.dryRun) {
await info('--dry-run', 'Skipping project naming');
return;
}
} else { } else {
let name = ctx.cwd; let name = ctx.cwd;
if (name === '.' || name === './') { if (name === '.' || name === './') {

View file

@ -6,8 +6,13 @@ import fs from 'node:fs';
import path from 'node:path'; import path from 'node:path';
import { error, info, spinner, title } from '../messages.js'; import { error, info, spinner, title } from '../messages.js';
export async function template(ctx: Pick<Context, 'template' | 'prompt' | 'dryRun' | 'exit'>) { export async function template(
if (!ctx.template) { ctx: Pick<Context, 'template' | 'prompt' | 'yes' | 'dryRun' | 'exit'>
) {
if (ctx.yes) {
ctx.template = 'basics';
await info('tmpl', `Using ${color.reset(ctx.template)}${color.dim(' as project template')}`);
} else if (!ctx.template) {
const { template: tmpl } = await ctx.prompt({ const { template: tmpl } = await ctx.prompt({
name: 'template', name: 'template',
type: 'select', type: 'select',

View file

@ -92,4 +92,48 @@ describe('project name', () => {
expect(context.cwd).to.eq('@astro/site'); expect(context.cwd).to.eq('@astro/site');
expect(context.projectName).to.eq('@astro/site'); expect(context.projectName).to.eq('@astro/site');
}); });
it('--yes', async () => {
const context = {
projectName: '',
cwd: './foo/bar/baz',
yes: true,
prompt: () => {},
};
await projectName(context);
expect(context.projectName).to.eq('baz');
});
it('dry run with name', async () => {
const context = {
projectName: '',
cwd: './foo/bar/baz',
dryRun: true,
prompt: () => {},
};
await projectName(context);
expect(context.projectName).to.eq('baz');
});
it('dry run with dot', async () => {
const context = {
projectName: '',
cwd: '.',
dryRun: true,
prompt: () => ({ name: 'foobar' }),
};
await projectName(context);
expect(context.projectName).to.eq('foobar');
});
it('dry run with empty', async () => {
const context = {
projectName: '',
cwd: './test/fixtures/empty',
dryRun: true,
prompt: () => ({ name: 'foobar' }),
};
await projectName(context);
expect(context.projectName).to.eq('empty');
});
}); });

View file

@ -1,5 +1,15 @@
# @astrojs/cloudflare # @astrojs/cloudflare
## 7.1.1
### Patch Changes
- [#8560](https://github.com/withastro/astro/pull/8560) [`3da5d8404`](https://github.com/withastro/astro/commit/3da5d8404e56a05da93f6b0a70841acda5ca1a8f) Thanks [@alexanderniebuhr](https://github.com/alexanderniebuhr)! - add the option to type environment variables using a generic
- Updated dependencies [[`8d361169b`](https://github.com/withastro/astro/commit/8d361169b8e487933d671ce347f0ce74922c80cc), [`95b5f6280`](https://github.com/withastro/astro/commit/95b5f6280d124f8d6f866dc3286406c272ee91bf), [`0586e20e8`](https://github.com/withastro/astro/commit/0586e20e8338e077b8eb1a3a96bdd19f5950c22f)]:
- astro@3.1.1
- @astrojs/underscore-redirects@0.3.0
## 7.1.0 ## 7.1.0
### Minor Changes ### Minor Changes

View file

@ -202,6 +202,33 @@ This will enable Cloudflare to serve files and process static redirects without
See [Cloudflare's documentation](https://developers.cloudflare.com/pages/platform/functions/routing/#create-a-_routesjson-file) for more details. See [Cloudflare's documentation](https://developers.cloudflare.com/pages/platform/functions/routing/#create-a-_routesjson-file) for more details.
## Node.js compatibility
Astro's Cloudflare adapter allows you to use any Node.js runtime API supported by Cloudflare:
- assert
- AsyncLocalStorage
- Buffer
- Diagnostics Channel
- EventEmitter
- path
- process
- Streams
- StringDecoder
- util
To use these APIs, your page or endpoint must be server-side rendered (not pre-rendered) and must use the the `import {} from 'node:*'` import syntax.
```js
// pages/api/endpoint.js
export const prerender = false;
import { Buffer } from 'node:buffer';
```
Additionally, you'll need to enable the Compatibility Flag in Cloudflare. The configuration for this flag may vary based on where you deploy your Astro site.
For detailed guidance, please refer to the [Cloudflare documentation](https://developers.cloudflare.com/workers/runtime-apis/nodejs).
## Troubleshooting ## Troubleshooting
For help, check out the `#support` channel on [Discord](https://astro.build/chat). Our friendly Support Squad members are here to help! For help, check out the `#support` channel on [Discord](https://astro.build/chat). Our friendly Support Squad members are here to help!

View file

@ -1,7 +1,7 @@
{ {
"name": "@astrojs/cloudflare", "name": "@astrojs/cloudflare",
"description": "Deploy your site to Cloudflare Workers/Pages", "description": "Deploy your site to Cloudflare Workers/Pages",
"version": "7.1.0", "version": "7.1.1",
"type": "module", "type": "module",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"author": "withastro", "author": "withastro",
@ -51,7 +51,7 @@
"tiny-glob": "^0.2.9" "tiny-glob": "^0.2.9"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.1.0" "astro": "workspace:^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"@types/iarna__toml": "^2.0.2", "@types/iarna__toml": "^2.0.2",

View file

@ -296,6 +296,18 @@ export default function createIntegration(args?: Options): AstroIntegration {
target: 'es2020', target: 'es2020',
platform: 'browser', platform: 'browser',
conditions: ['workerd', 'worker', 'browser'], conditions: ['workerd', 'worker', 'browser'],
external: [
'node:assert',
'node:async_hooks',
'node:buffer',
'node:diagnostics_channel',
'node:events',
'node:path',
'node:process',
'node:stream',
'node:string_decoder',
'node:util',
],
entryPoints: entryPaths, entryPoints: entryPaths,
outdir: outputDir, outdir: outputDir,
allowOverwrite: true, allowOverwrite: true,
@ -357,6 +369,18 @@ export default function createIntegration(args?: Options): AstroIntegration {
target: 'es2020', target: 'es2020',
platform: 'browser', platform: 'browser',
conditions: ['workerd', 'worker', 'browser'], conditions: ['workerd', 'worker', 'browser'],
external: [
'node:assert',
'node:async_hooks',
'node:buffer',
'node:diagnostics_channel',
'node:events',
'node:path',
'node:process',
'node:stream',
'node:string_decoder',
'node:util',
],
entryPoints: [entryPath], entryPoints: [entryPath],
outfile: buildPath, outfile: buildPath,
allowOverwrite: true, allowOverwrite: true,

View file

@ -36,7 +36,7 @@
"esbuild": "^0.19.2" "esbuild": "^0.19.2"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.1.0" "astro": "workspace:^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"astro": "workspace:*", "astro": "workspace:*",

View file

@ -75,7 +75,7 @@
"zod": "3.21.1" "zod": "3.21.1"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.1.0" "astro": "workspace:^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"@astrojs/markdown-remark": "workspace:*", "@astrojs/markdown-remark": "workspace:*",

View file

@ -51,7 +51,7 @@
"vfile": "^5.3.7" "vfile": "^5.3.7"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.1.0" "astro": "workspace:^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"@types/chai": "^4.3.5", "@types/chai": "^4.3.5",

View file

@ -43,7 +43,7 @@
"esbuild": "^0.19.2" "esbuild": "^0.19.2"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.1.0" "astro": "workspace:^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"@netlify/edge-functions": "^2.0.0", "@netlify/edge-functions": "^2.0.0",

View file

@ -37,7 +37,7 @@
"server-destroy": "^1.0.1" "server-destroy": "^1.0.1"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.1.0" "astro": "workspace:^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^18.17.8", "@types/node": "^18.17.8",

View file

@ -51,6 +51,9 @@ export default function (app: NodeApp, mode: Options['mode']) {
await writeWebResponse(app, res, response); await writeWebResponse(app, res, response);
} }
} catch (err: unknown) { } catch (err: unknown) {
const logger = app.getAdapterLogger();
logger.error(`Could not render ${req.url}`);
console.error(err);
if (!res.headersSent) { if (!res.headersSent) {
res.writeHead(500, `Server error`); res.writeHead(500, `Server error`);
res.end(); res.end();

View file

@ -48,7 +48,7 @@
"vite": "^4.4.9" "vite": "^4.4.9"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.1.0", "astro": "workspace:^3.1.1",
"svelte": "^3.55.0 || ^4.0.0" "svelte": "^3.55.0 || ^4.0.0"
}, },
"engines": { "engines": {

View file

@ -43,7 +43,7 @@
"vite": "^4.4.9" "vite": "^4.4.9"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.1.0", "astro": "workspace:^3.1.1",
"tailwindcss": "^3.0.24" "tailwindcss": "^3.0.24"
} }
} }

View file

@ -1,5 +1,14 @@
# @astrojs/vercel # @astrojs/vercel
## 5.0.1
### Patch Changes
- [#8581](https://github.com/withastro/astro/pull/8581) [`d0e513f21`](https://github.com/withastro/astro/commit/d0e513f214fe3cb30bab6d98936cda796477f2f8) Thanks [@rishi-raj-jain](https://github.com/rishi-raj-jain)! - log only once in serverless adapter
- Updated dependencies [[`8d361169b`](https://github.com/withastro/astro/commit/8d361169b8e487933d671ce347f0ce74922c80cc), [`95b5f6280`](https://github.com/withastro/astro/commit/95b5f6280d124f8d6f866dc3286406c272ee91bf), [`0586e20e8`](https://github.com/withastro/astro/commit/0586e20e8338e077b8eb1a3a96bdd19f5950c22f)]:
- astro@3.1.1
## 5.0.0 ## 5.0.0
### Major Changes ### Major Changes

View file

@ -1,7 +1,7 @@
{ {
"name": "@astrojs/vercel", "name": "@astrojs/vercel",
"description": "Deploy your site to Vercel", "description": "Deploy your site to Vercel",
"version": "5.0.0", "version": "5.0.1",
"type": "module", "type": "module",
"author": "withastro", "author": "withastro",
"license": "MIT", "license": "MIT",
@ -61,7 +61,7 @@
"web-vitals": "^3.4.0" "web-vitals": "^3.4.0"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.1.0" "astro": "workspace:^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"@types/set-cookie-parser": "^2.4.3", "@types/set-cookie-parser": "^2.4.3",

View file

@ -56,7 +56,7 @@
"vue": "^3.3.4" "vue": "^3.3.4"
}, },
"peerDependencies": { "peerDependencies": {
"astro": "workspace:^3.1.0", "astro": "workspace:^3.1.1",
"vue": "^3.2.30" "vue": "^3.2.30"
}, },
"engines": { "engines": {

View file

@ -1,9 +1,17 @@
# Astro Telemetry # Astro Telemetry
This package is used to collect anonymous telemetry data within the Astro CLI. It is enabled by default. Telemetry data does not contain any personal identifying information and can be disabled via: This package is used to collect anonymous telemetry data within the Astro CLI.
It can be disabled in Astro using either method documented below:
```shell ```shell
# Option 1: Run this to disable telemetry globally across your entire machine.
astro telemetry disable astro telemetry disable
``` ```
See the [CLI documentation](https://docs.astro.build/en/reference/cli-reference/#astro-telemetry) for more options on configuration telemetry. ```shell
# Option 2: The ASTRO_TELEMETRY_DISABLED environment variable disables telemetry when set.
ASTRO_TELEMETRY_DISABLED=1 astro dev
```
Visit https://astro.build/telemetry/ for more information about our approach to anonymous telemetry in Astro.

View file

@ -125,7 +125,7 @@ importers:
examples/basics: examples/basics:
dependencies: dependencies:
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
examples/blog: examples/blog:
@ -140,19 +140,19 @@ importers:
specifier: ^3.0.0 specifier: ^3.0.0
version: link:../../packages/integrations/sitemap version: link:../../packages/integrations/sitemap
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
examples/component: examples/component:
devDependencies: devDependencies:
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
examples/deno: examples/deno:
dependencies: dependencies:
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
devDependencies: devDependencies:
'@astrojs/deno': '@astrojs/deno':
@ -171,7 +171,7 @@ importers:
specifier: ^3.12.3 specifier: ^3.12.3
version: 3.12.3 version: 3.12.3
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
examples/framework-lit: examples/framework-lit:
@ -183,7 +183,7 @@ importers:
specifier: ^0.2.1 specifier: ^0.2.1
version: 0.2.1 version: 0.2.1
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
lit: lit:
specifier: ^2.8.0 specifier: ^2.8.0
@ -207,7 +207,7 @@ importers:
specifier: ^3.0.0 specifier: ^3.0.0
version: link:../../packages/integrations/vue version: link:../../packages/integrations/vue
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
preact: preact:
specifier: ^10.17.1 specifier: ^10.17.1
@ -237,7 +237,7 @@ importers:
specifier: ^1.2.1 specifier: ^1.2.1
version: 1.2.1(preact@10.17.1) version: 1.2.1(preact@10.17.1)
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
preact: preact:
specifier: ^10.17.1 specifier: ^10.17.1
@ -255,7 +255,7 @@ importers:
specifier: ^18.2.7 specifier: ^18.2.7
version: 18.2.7 version: 18.2.7
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
react: react:
specifier: ^18.2.0 specifier: ^18.2.0
@ -270,7 +270,7 @@ importers:
specifier: ^3.0.1 specifier: ^3.0.1
version: link:../../packages/integrations/solid version: link:../../packages/integrations/solid
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
solid-js: solid-js:
specifier: ^1.7.11 specifier: ^1.7.11
@ -282,7 +282,7 @@ importers:
specifier: ^4.0.2 specifier: ^4.0.2
version: link:../../packages/integrations/svelte version: link:../../packages/integrations/svelte
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
svelte: svelte:
specifier: ^4.2.0 specifier: ^4.2.0
@ -294,7 +294,7 @@ importers:
specifier: ^3.0.0 specifier: ^3.0.0
version: link:../../packages/integrations/vue version: link:../../packages/integrations/vue
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
vue: vue:
specifier: ^3.3.4 specifier: ^3.3.4
@ -306,13 +306,13 @@ importers:
specifier: ^6.0.0 specifier: ^6.0.0
version: link:../../packages/integrations/node version: link:../../packages/integrations/node
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
examples/integration: examples/integration:
devDependencies: devDependencies:
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
examples/middleware: examples/middleware:
@ -321,7 +321,7 @@ importers:
specifier: ^6.0.0 specifier: ^6.0.0
version: link:../../packages/integrations/node version: link:../../packages/integrations/node
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
html-minifier: html-minifier:
specifier: ^4.0.0 specifier: ^4.0.0
@ -330,19 +330,19 @@ importers:
examples/minimal: examples/minimal:
dependencies: dependencies:
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
examples/non-html-pages: examples/non-html-pages:
dependencies: dependencies:
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
examples/portfolio: examples/portfolio:
dependencies: dependencies:
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
examples/ssr: examples/ssr:
@ -354,7 +354,7 @@ importers:
specifier: ^4.0.2 specifier: ^4.0.2
version: link:../../packages/integrations/svelte version: link:../../packages/integrations/svelte
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
svelte: svelte:
specifier: ^4.2.0 specifier: ^4.2.0
@ -366,7 +366,7 @@ importers:
specifier: ^0.5.0 specifier: ^0.5.0
version: link:../../packages/integrations/markdoc version: link:../../packages/integrations/markdoc
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
examples/with-markdown-plugins: examples/with-markdown-plugins:
@ -375,7 +375,7 @@ importers:
specifier: ^3.2.0 specifier: ^3.2.0
version: link:../../packages/markdown/remark version: link:../../packages/markdown/remark
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
hast-util-select: hast-util-select:
specifier: ^5.0.5 specifier: ^5.0.5
@ -396,7 +396,7 @@ importers:
examples/with-markdown-shiki: examples/with-markdown-shiki:
dependencies: dependencies:
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
examples/with-mdx: examples/with-mdx:
@ -408,7 +408,7 @@ importers:
specifier: ^3.0.0 specifier: ^3.0.0
version: link:../../packages/integrations/preact version: link:../../packages/integrations/preact
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
preact: preact:
specifier: ^10.17.1 specifier: ^10.17.1
@ -423,7 +423,7 @@ importers:
specifier: ^0.5.0 specifier: ^0.5.0
version: 0.5.0(nanostores@0.9.3)(preact@10.17.1) version: 0.5.0(nanostores@0.9.3)(preact@10.17.1)
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
nanostores: nanostores:
specifier: ^0.9.3 specifier: ^0.9.3
@ -444,7 +444,7 @@ importers:
specifier: ^1.6.0 specifier: ^1.6.0
version: 1.6.0 version: 1.6.0
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
autoprefixer: autoprefixer:
specifier: ^10.4.15 specifier: ^10.4.15
@ -462,7 +462,7 @@ importers:
examples/with-vite-plugin-pwa: examples/with-vite-plugin-pwa:
dependencies: dependencies:
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
vite-plugin-pwa: vite-plugin-pwa:
specifier: 0.16.4 specifier: 0.16.4
@ -474,7 +474,7 @@ importers:
examples/with-vitest: examples/with-vitest:
dependencies: dependencies:
astro: astro:
specifier: ^3.1.0 specifier: ^3.1.1
version: link:../../packages/astro version: link:../../packages/astro
vitest: vitest:
specifier: ^0.34.2 specifier: ^0.34.2