diff --git a/.changeset/all-loops-deny.md b/.changeset/all-loops-deny.md
new file mode 100644
index 000000000000..96d0db76dbac
--- /dev/null
+++ b/.changeset/all-loops-deny.md
@@ -0,0 +1,9 @@
+---
+'astro': minor
+---
+
+Updates the `NodeApp.match()` function in the Adapter API to accept a second, optional parameter to allow adapter authors to add headers to static, prerendered pages.
+
+`NodeApp.match(request)` currently checks whether there is a route that matches the given `Request`. If there is a prerendered route, the function returns `undefined`, because static routes are already rendered and their headers cannot be updated.
+
+When the new, optional boolean parameter is passed (e.g. `NodeApp.match(request, true)`), Astro will return the first matched route, even when it's a prerendered route. This allows your adapter to now access static routes and provides the opportunity to set headers for these pages, for example, to implement a Content Security Policy (CSP).
diff --git a/.changeset/full-hoops-hear.md b/.changeset/full-hoops-hear.md
new file mode 100644
index 000000000000..7535c5e1ab39
--- /dev/null
+++ b/.changeset/full-hoops-hear.md
@@ -0,0 +1,7 @@
+---
+'@astrojs/netlify': patch
+'@astrojs/vercel': patch
+---
+
+Fixes the internal implementation of the new feature `experimentalStaticHeaders`, where dynamic routes
+were mapped to use always the same header.
diff --git a/.changeset/purple-spoons-jog.md b/.changeset/purple-spoons-jog.md
new file mode 100644
index 000000000000..0e69da0ed12c
--- /dev/null
+++ b/.changeset/purple-spoons-jog.md
@@ -0,0 +1,22 @@
+---
+'@astrojs/node': minor
+---
+
+Adds support for the [experimental static headers Astro feature](https://docs.astro.build/en/reference/adapter-reference/#experimentalstaticheaders).
+
+When the feature is enabled via the option `experimentalStaticHeaders`, and [experimental Content Security Policy](https://docs.astro.build/en/reference/experimental-flags/csp/) is enabled, the adapter will generate `Response` headers for static pages, which allows support for CSP directives that are not supported inside a `` tag (e.g. `frame-ancestors`).
+
+```js
+import { defineConfig } from "astro/config";
+import node from "@astrojs/node";
+
+export default defineConfig({
+ adapter: node({
+ mode: "standalone",
+ experimentalStaticHeaders: true
+ }),
+ experimental: {
+ cps: true
+ }
+})
+```
diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts
index 188d0390edde..2075c2c1c2af 100644
--- a/packages/astro/src/core/app/index.ts
+++ b/packages/astro/src/core/app/index.ts
@@ -191,7 +191,15 @@ export class App {
}
}
- match(request: Request): RouteData | undefined {
+ /**
+ * Given a `Request`, it returns the `RouteData` that matches its `pathname`. By default, prerendered
+ * routes aren't returned, even if they are matched.
+ *
+ * When `allowPrerenderedRoutes` is `true`, the function returns matched prerendered routes too.
+ * @param request
+ * @param allowPrerenderedRoutes
+ */
+ match(request: Request, allowPrerenderedRoutes = false): RouteData | undefined {
const url = new URL(request.url);
// ignore requests matching public assets
if (this.#manifest.assets.has(url.pathname)) return undefined;
@@ -201,8 +209,14 @@ export class App {
}
let routeData = matchRoute(decodeURI(pathname), this.#manifestData);
+ if (!routeData) return undefined;
+ if (allowPrerenderedRoutes) {
+ return routeData;
+ }
// missing routes fall-through, pre rendered are handled by static layer
- if (!routeData || routeData.prerender) return undefined;
+ else if (routeData.prerender) {
+ return undefined;
+ }
return routeData;
}
diff --git a/packages/astro/src/core/app/node.ts b/packages/astro/src/core/app/node.ts
index dc0a1de21343..71fcd0b6eb14 100644
--- a/packages/astro/src/core/app/node.ts
+++ b/packages/astro/src/core/app/node.ts
@@ -7,7 +7,7 @@ import { deserializeManifest } from './common.js';
import { createOutgoingHttpHeaders } from './createOutgoingHttpHeaders.js';
import type { RenderOptions } from './index.js';
import { App } from './index.js';
-import type { SerializedSSRManifest, SSRManifest } from './types.js';
+import type { NodeAppHeadersJson, SerializedSSRManifest, SSRManifest } from './types.js';
export { apply as applyPolyfills } from '../polyfill.js';
@@ -20,13 +20,19 @@ interface NodeRequest extends IncomingMessage {
}
export class NodeApp extends App {
- match(req: NodeRequest | Request) {
+ headersMap: NodeAppHeadersJson | undefined = undefined;
+
+ public setHeadersMap(headers: NodeAppHeadersJson) {
+ this.headersMap = headers;
+ }
+
+ match(req: NodeRequest | Request, allowPrerenderedRoutes = false) {
if (!(req instanceof Request)) {
req = NodeApp.createRequest(req, {
skipBody: true,
});
}
- return super.match(req);
+ return super.match(req, allowPrerenderedRoutes);
}
render(request: NodeRequest | Request, options?: RenderOptions): Promise;
/**
diff --git a/packages/astro/src/core/app/types.ts b/packages/astro/src/core/app/types.ts
index 2a761045ef13..c736eda5eb4b 100644
--- a/packages/astro/src/core/app/types.ts
+++ b/packages/astro/src/core/app/types.ts
@@ -139,3 +139,11 @@ export type SerializedSSRManifest = Omit<
serverIslandNameMap: [string, string][];
key: string;
};
+
+export type NodeAppHeadersJson = {
+ pathname: string;
+ headers: {
+ key: string;
+ value: string;
+ }[];
+}[];
diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts
index 05798adae4f9..806eb5033954 100644
--- a/packages/astro/src/core/build/generate.ts
+++ b/packages/astro/src/core/build/generate.ts
@@ -21,7 +21,7 @@ import { getServerOutputDirectory } from '../../prerender/utils.js';
import type { AstroSettings, ComponentInstance } from '../../types/astro.js';
import type { GetStaticPathsItem, MiddlewareHandler } from '../../types/public/common.js';
import type { AstroConfig } from '../../types/public/config.js';
-import type { IntegrationResolvedRoute } from '../../types/public/index.js';
+import type { IntegrationResolvedRoute, RouteToHeaders } from '../../types/public/index.js';
import type {
RouteData,
RouteType,
@@ -102,7 +102,7 @@ export async function generatePages(options: StaticBuildOptions, internals: Buil
logger.info('SKIP_FORMAT', `\n${bgGreen(black(` ${verb} static routes `))}`);
const builtPaths = new Set();
const pagesToGenerate = pipeline.retrieveRoutesToGenerate();
- const routeToHeaders = new Map();
+ const routeToHeaders: RouteToHeaders = new Map();
if (ssr) {
for (const [pageData, filePath] of pagesToGenerate) {
if (pageData.route.prerender) {
@@ -234,7 +234,7 @@ async function generatePage(
ssrEntry: SinglePageBuiltModule,
builtPaths: Set,
pipeline: BuildPipeline,
- routeToHeaders: Map,
+ routeToHeaders: RouteToHeaders,
) {
// prepare information we need
const { config, logger } = pipeline;
@@ -264,6 +264,7 @@ async function generatePage(
async function generatePathWithLogs(
path: string,
route: RouteData,
+ integrationRoute: IntegrationResolvedRoute,
index: number,
paths: string[],
isConcurrent: boolean,
@@ -281,7 +282,14 @@ async function generatePage(
logger.info(null, ` ${blue(lineIcon)} ${dim(filePath)}`, false);
}
- const created = await generatePath(path, pipeline, generationOptions, route, routeToHeaders);
+ const created = await generatePath(
+ path,
+ pipeline,
+ generationOptions,
+ route,
+ integrationRoute,
+ routeToHeaders,
+ );
const timeEnd = performance.now();
const isSlow = timeEnd - timeStart > THRESHOLD_SLOW_RENDER_TIME_MS;
@@ -298,6 +306,7 @@ async function generatePage(
// Now we explode the routes. A route render itself, and it can render its fallbacks (i18n routing)
for (const route of eachRouteInRouteData(pageData)) {
+ const integrationRoute = toIntegrationResolvedRoute(route);
const icon =
route.type === 'page' || route.type === 'redirect' || route.type === 'fallback'
? green('▶')
@@ -313,13 +322,15 @@ async function generatePage(
const promises: Promise[] = [];
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
- promises.push(limit(() => generatePathWithLogs(path, route, i, paths, true)));
+ promises.push(
+ limit(() => generatePathWithLogs(path, route, integrationRoute, i, paths, true)),
+ );
}
await Promise.all(promises);
} else {
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
- await generatePathWithLogs(path, route, i, paths, false);
+ await generatePathWithLogs(path, route, integrationRoute, i, paths, false);
}
}
}
@@ -499,7 +510,8 @@ async function generatePath(
pipeline: BuildPipeline,
gopts: GeneratePathOptions,
route: RouteData,
- routeToHeaders: Map,
+ integrationRoute: IntegrationResolvedRoute,
+ routeToHeaders: RouteToHeaders,
): Promise {
const { mod } = gopts;
const { config, logger, options } = pipeline;
@@ -569,20 +581,14 @@ async function generatePath(
throw err;
}
- if (
- pipeline.settings.adapter?.adapterFeatures?.experimentalStaticHeaders &&
- pipeline.settings.config.experimental?.csp
- ) {
- routeToHeaders.set(toIntegrationResolvedRoute(route), response.headers);
- }
-
+ const responseHeaders = response.headers;
if (response.status >= 300 && response.status < 400) {
// Adapters may handle redirects themselves, turning off Astro's redirect handling using `config.build.redirects` in the process.
// In that case, we skip rendering static files for the redirect routes.
if (routeIsRedirect(route) && !config.build.redirects) {
return undefined;
}
- const locationSite = getRedirectLocationOrThrow(response.headers);
+ const locationSite = getRedirectLocationOrThrow(responseHeaders);
const siteURL = config.site;
const location = siteURL ? new URL(locationSite, siteURL) : locationSite;
const fromPath = new URL(request.url).pathname;
@@ -616,6 +622,13 @@ async function generatePath(
route.distURL = [outFile];
}
+ if (
+ pipeline.settings.adapter?.adapterFeatures?.experimentalStaticHeaders &&
+ pipeline.settings.config.experimental?.csp
+ ) {
+ routeToHeaders.set(pathname, { headers: responseHeaders, route: integrationRoute });
+ }
+
await fs.promises.mkdir(outFolder, { recursive: true });
await fs.promises.writeFile(outFile, body);
diff --git a/packages/astro/src/core/build/plugins/plugin-manifest.ts b/packages/astro/src/core/build/plugins/plugin-manifest.ts
index fdd1ea2c4b7a..4cd4c2f3c62e 100644
--- a/packages/astro/src/core/build/plugins/plugin-manifest.ts
+++ b/packages/astro/src/core/build/plugins/plugin-manifest.ts
@@ -244,9 +244,15 @@ async function buildManifest(
staticFiles.push(file);
}
+ const needsStaticHeaders = settings.adapter?.adapterFeatures?.experimentalStaticHeaders ?? false;
+
for (const route of opts.routesList.routes) {
const pageData = internals.pagesByKeys.get(makePageDataKey(route.route, route.component));
- if (route.prerender || !pageData) continue;
+ if (!pageData) continue;
+
+ if (route.prerender && !needsStaticHeaders) {
+ continue;
+ }
const scripts: SerializedRouteInfo['scripts'] = [];
if (settings.scripts.some((script) => script.stage === 'page')) {
const src = entryModules[PAGE_SCRIPT_ID];
diff --git a/packages/astro/src/integrations/hooks.ts b/packages/astro/src/integrations/hooks.ts
index 0ff4225ee33a..7e28a782d7d6 100644
--- a/packages/astro/src/integrations/hooks.ts
+++ b/packages/astro/src/integrations/hooks.ts
@@ -32,6 +32,7 @@ import type {
IntegrationResolvedRoute,
IntegrationRouteData,
RouteOptions,
+ RouteToHeaders,
} from '../types/public/integrations.js';
import type { RouteData } from '../types/public/internal.js';
import { validateSupportedFeatures } from './features-validation.js';
@@ -590,7 +591,7 @@ export async function runHookBuildGenerated({
}: {
settings: AstroSettings;
logger: Logger;
- experimentalRouteToHeaders: Map;
+ experimentalRouteToHeaders: RouteToHeaders;
}) {
const dir =
settings.buildOutput === 'server' ? settings.config.build.client : settings.config.outDir;
diff --git a/packages/astro/src/types/public/index.ts b/packages/astro/src/types/public/index.ts
index e473ab0f96fe..42c131fc2b68 100644
--- a/packages/astro/src/types/public/index.ts
+++ b/packages/astro/src/types/public/index.ts
@@ -21,7 +21,7 @@ export type {
UnresolvedImageTransform,
} from '../../assets/types.js';
export type { ContainerRenderer } from '../../container/index.js';
-export type { AssetsPrefix, SSRManifest } from '../../core/app/types.js';
+export type { AssetsPrefix, NodeAppHeadersJson, SSRManifest } from '../../core/app/types.js';
export type {
AstroCookieGetOptions,
AstroCookieSetOptions,
diff --git a/packages/astro/src/types/public/integrations.ts b/packages/astro/src/types/public/integrations.ts
index 1ef37af44a5d..da08c0bd913f 100644
--- a/packages/astro/src/types/public/integrations.ts
+++ b/packages/astro/src/types/public/integrations.ts
@@ -234,7 +234,7 @@ export interface BaseIntegrationHooks {
'astro:build:generated': (options: {
dir: URL;
logger: AstroIntegrationLogger;
- experimentalRouteToHeaders: Map;
+ experimentalRouteToHeaders: RouteToHeaders;
}) => void | Promise;
'astro:build:done': (options: {
pages: { pathname: string }[];
@@ -277,6 +277,13 @@ export type IntegrationRouteData = Omit<
redirectRoute?: IntegrationRouteData;
};
+export type RouteToHeaders = Map;
+
+export type HeaderPayload = {
+ headers: Headers;
+ route: IntegrationResolvedRoute;
+};
+
export interface IntegrationResolvedRoute
extends Pick<
RouteData,
diff --git a/packages/astro/test/csp.test.js b/packages/astro/test/csp.test.js
index 13e0810ed88c..7efe59102bbf 100644
--- a/packages/astro/test/csp.test.js
+++ b/packages/astro/test/csp.test.js
@@ -321,13 +321,14 @@ describe('CSP', () => {
await fixture.build();
app = await fixture.loadTestAdapterApp();
- assert.equal(
- routeToHeaders.size,
- 4,
- 'expected four routes: /, /scripts, /title/foo, /title/bar',
- );
+ assert.equal(routeToHeaders.size, 4, 'expected four routes: /, /scripts, /foo, /bar');
+
+ assert.ok(routeToHeaders.has('/'), 'should have a CSP header for /');
+ assert.ok(routeToHeaders.has('/scripts'), 'should have a CSP header for /scripts');
+ assert.ok(routeToHeaders.has('/foo'), 'should have a CSP header for /foo');
+ assert.ok(routeToHeaders.has('/bar'), 'should have a CSP header for /bar');
- for (const headers of routeToHeaders.values()) {
+ for (const { headers } of routeToHeaders.values()) {
assert.ok(headers.has('content-security-policy'), 'should have a CSP header');
}
});
diff --git a/packages/astro/test/fixtures/csp-adapter/src/pages/[title].astro b/packages/astro/test/fixtures/csp-adapter/src/pages/[title].astro
index fe289397a4fe..07ce2ece662d 100644
--- a/packages/astro/test/fixtures/csp-adapter/src/pages/[title].astro
+++ b/packages/astro/test/fixtures/csp-adapter/src/pages/[title].astro
@@ -5,8 +5,8 @@ export const prerender = true
export const getStaticPaths = (() => {
return [
- { params: { title: 'Foo' } },
- { params: { title: 'Bar' } },
+ { params: { title: 'foo' } },
+ { params: { title: 'bar' } },
];
});
diff --git a/packages/integrations/netlify/src/index.ts b/packages/integrations/netlify/src/index.ts
index 0ed91a8ddbb3..67b47aba1d9d 100644
--- a/packages/integrations/netlify/src/index.ts
+++ b/packages/integrations/netlify/src/index.ts
@@ -3,11 +3,7 @@ import { appendFile, mkdir, readFile, writeFile } from 'node:fs/promises';
import type { IncomingMessage } from 'node:http';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { emptyDir } from '@astrojs/internal-helpers/fs';
-import {
- createHostedRouteDefinition,
- createRedirectsFromAstroRoutes,
- printAsRedirects,
-} from '@astrojs/underscore-redirects';
+import { createRedirectsFromAstroRoutes, printAsRedirects } from '@astrojs/underscore-redirects';
import type { Context } from '@netlify/functions';
import type {
AstroConfig,
@@ -15,6 +11,7 @@ import type {
AstroIntegrationLogger,
HookParameters,
IntegrationResolvedRoute,
+ RouteToHeaders,
} from 'astro';
import { build } from 'esbuild';
import { glob, globSync } from 'tinyglobby';
@@ -109,7 +106,7 @@ export function remotePatternToRegex(
async function writeNetlifyFrameworkConfig(
config: AstroConfig,
- staticHeaders: Map | undefined,
+ staticHeaders: RouteToHeaders | undefined,
logger: AstroIntegrationLogger,
) {
const remoteImages: Array = [];
@@ -135,22 +132,13 @@ async function writeNetlifyFrameworkConfig(
}
if (staticHeaders && staticHeaders.size > 0) {
- for (const [route, routeHeaders] of staticHeaders.entries()) {
- if (!route.isPrerendered) {
- continue;
- }
- if (route.redirect) {
- continue;
- }
-
- const definition = createHostedRouteDefinition(route, config);
-
+ for (const [pathname, { headers: routeHeaders }] of staticHeaders.entries()) {
if (config.experimental.csp) {
const csp = routeHeaders.get('Content-Security-Policy');
if (csp) {
headers.push({
- for: definition.input,
+ for: pathname,
values: {
'Content-Security-Policy': csp,
},
@@ -259,7 +247,7 @@ export default function netlifyIntegration(
let outDir: URL;
let rootDir: URL;
let astroMiddlewareEntryPoint: URL | undefined = undefined;
- let staticHeadersMap: Map | undefined = undefined;
+ let staticHeadersMap: RouteToHeaders | undefined = undefined;
// Extra files to be merged with `includeFiles` during build
const extraFilesToInclude: URL[] = [];
// Secret used to verify that the caller is the astro-generated edge middleware and not a third-party
diff --git a/packages/integrations/node/package.json b/packages/integrations/node/package.json
index 37583ac453ab..2020307fd983 100644
--- a/packages/integrations/node/package.json
+++ b/packages/integrations/node/package.json
@@ -27,6 +27,7 @@
"dist"
],
"scripts": {
+ "dev": "astro-scripts dev \"src/**/*.ts\"",
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
"build:ci": "astro-scripts build \"src/**/*.ts\"",
"test": "astro-scripts test \"test/**/*.test.js\""
diff --git a/packages/integrations/node/src/index.ts b/packages/integrations/node/src/index.ts
index 26ffd2ad05c5..68ea4b08d06e 100644
--- a/packages/integrations/node/src/index.ts
+++ b/packages/integrations/node/src/index.ts
@@ -1,6 +1,8 @@
import { fileURLToPath } from 'node:url';
-import type { AstroAdapter, AstroIntegration } from 'astro';
+import { writeJson } from '@astrojs/internal-helpers/fs';
+import type { AstroAdapter, AstroConfig, AstroIntegration, NodeAppHeadersJson, RouteToHeaders } from 'astro';
import { AstroError } from 'astro/errors';
+import { STATIC_HEADERS_FILE } from './shared.js';
import type { Options, UserOptions } from './types.js';
export function getAdapter(options: Options): AstroAdapter {
@@ -13,6 +15,7 @@ export function getAdapter(options: Options): AstroAdapter {
adapterFeatures: {
buildOutput: 'server',
edgeMiddleware: false,
+ experimentalStaticHeaders: options.experimentalStaticHeaders,
},
supportedAstroFeatures: {
hybridOutput: 'stable',
@@ -31,12 +34,14 @@ export default function createIntegration(userOptions: UserOptions): AstroIntegr
}
let _options: Options;
+ let _config: AstroConfig | undefined = undefined;
+ let _routeToHeaders: RouteToHeaders | undefined = undefined;
return {
name: '@astrojs/node',
hooks: {
'astro:config:setup': async ({ updateConfig, config, logger }) => {
let session = config.session;
-
+ _config = config;
if (!session?.driver) {
logger.info('Enabling sessions with filesystem storage');
session = {
@@ -63,6 +68,9 @@ export default function createIntegration(userOptions: UserOptions): AstroIntegr
},
});
},
+ 'astro:build:generated': ({ experimentalRouteToHeaders }) => {
+ _routeToHeaders = experimentalRouteToHeaders;
+ },
'astro:config:done': ({ setAdapter, config }) => {
_options = {
...userOptions,
@@ -71,9 +79,39 @@ export default function createIntegration(userOptions: UserOptions): AstroIntegr
host: config.server.host,
port: config.server.port,
assets: config.build.assets,
+ experimentalStaticHeaders: userOptions.experimentalStaticHeaders ?? false,
};
setAdapter(getAdapter(_options));
},
+ 'astro:build:done': async () => {
+ if (!_config) {
+ return;
+ }
+
+ if (_routeToHeaders && _routeToHeaders.size > 0) {
+ const headersFileUrl = new URL(STATIC_HEADERS_FILE, _config.outDir);
+ const headersValue: NodeAppHeadersJson = [];
+
+ for (const [pathname, { headers }] of _routeToHeaders.entries()) {
+ if (_config.experimental.csp) {
+ const csp = headers.get('Content-Security-Policy');
+ if (csp) {
+ headersValue.push({
+ pathname,
+ headers: [
+ {
+ key: 'Content-Security-Policy',
+ value: csp,
+ },
+ ],
+ });
+ }
+ }
+ }
+
+ await writeJson(headersFileUrl, headersValue);
+ }
+ },
},
};
}
diff --git a/packages/integrations/node/src/serve-static.ts b/packages/integrations/node/src/serve-static.ts
index f26a2ff1f8f3..8114552bb024 100644
--- a/packages/integrations/node/src/serve-static.ts
+++ b/packages/integrations/node/src/serve-static.ts
@@ -33,6 +33,18 @@ export function createStaticHandler(app: NodeApp, options: Options) {
const hasSlash = urlPath.endsWith('/');
let pathname = urlPath;
+ if (app.headersMap && app.headersMap.length > 0) {
+ const routeData = app.match(req, true);
+ if (routeData && routeData.prerender) {
+ const matchedRoute = app.headersMap.find((header) => header.pathname.includes(pathname));
+ if (matchedRoute) {
+ for (const header of matchedRoute.headers) {
+ res.setHeader(header.key, header.value);
+ }
+ }
+ }
+ }
+
switch (trailingSlash) {
case 'never': {
if (isDirectory && urlPath !== '/' && hasSlash) {
diff --git a/packages/integrations/node/src/server.ts b/packages/integrations/node/src/server.ts
index af27ec36dde9..0ed42cb3bb01 100644
--- a/packages/integrations/node/src/server.ts
+++ b/packages/integrations/node/src/server.ts
@@ -1,10 +1,12 @@
// Keep at the top
import './polyfill.js';
-import type { SSRManifest } from 'astro';
+import { existsSync, readFileSync } from 'node:fs';
+import type { NodeAppHeadersJson, SSRManifest } from 'astro';
import { NodeApp } from 'astro/app/node';
import { setGetEnv } from 'astro/env/setup';
import createMiddleware from './middleware.js';
+import { STATIC_HEADERS_FILE } from './shared.js';
import startServer, { createStandaloneHandler } from './standalone.js';
import type { Options } from './types.js';
@@ -12,6 +14,14 @@ setGetEnv((key) => process.env[key]);
export function createExports(manifest: SSRManifest, options: Options) {
const app = new NodeApp(manifest);
+ let headersMap: NodeAppHeadersJson | undefined = undefined;
+ if (options.experimentalStaticHeaders) {
+ headersMap = readHeadersJson(manifest.outDir);
+ }
+
+ if (headersMap) {
+ app.setHeadersMap(headersMap);
+ }
options.trailingSlash = manifest.trailingSlash;
return {
options: options,
@@ -26,6 +36,30 @@ export function start(manifest: SSRManifest, options: Options) {
return;
}
+ let headersMap: NodeAppHeadersJson | undefined = undefined;
+ if (options.experimentalStaticHeaders) {
+ headersMap = readHeadersJson(manifest.outDir);
+ }
+
const app = new NodeApp(manifest);
+ if (headersMap) {
+ app.setHeadersMap(headersMap);
+ }
startServer(app, options);
}
+
+function readHeadersJson(outDir: string | URL): NodeAppHeadersJson | undefined {
+ let headersMap: NodeAppHeadersJson | undefined = undefined;
+
+ const headersUrl = new URL(STATIC_HEADERS_FILE, outDir);
+ if (existsSync(headersUrl)) {
+ const content = readFileSync(headersUrl, 'utf-8');
+ try {
+ headersMap = JSON.parse(content) as NodeAppHeadersJson;
+ } catch (e: any) {
+ console.error('[@astrojs/node] Error parsing _headers.json: ' + e.message);
+ console.error('[@astrojs/node] Please make sure your _headers.json is valid JSON.');
+ }
+ }
+ return headersMap;
+}
diff --git a/packages/integrations/node/src/shared.ts b/packages/integrations/node/src/shared.ts
new file mode 100644
index 000000000000..499fa92b9ef6
--- /dev/null
+++ b/packages/integrations/node/src/shared.ts
@@ -0,0 +1 @@
+export const STATIC_HEADERS_FILE = "_experimentalHeaders.json"
diff --git a/packages/integrations/node/src/types.ts b/packages/integrations/node/src/types.ts
index 37773e24cad8..5cf225270347 100644
--- a/packages/integrations/node/src/types.ts
+++ b/packages/integrations/node/src/types.ts
@@ -9,6 +9,14 @@ export interface UserOptions {
* - 'standalone' - Build to a standalone server. The server starts up just by running the built script.
*/
mode: 'middleware' | 'standalone';
+
+ /**
+ * If enabled, the adapter will save [static headers in the framework API file](https://docs.netlify.com/frameworks-api/#headers).
+ *
+ * Here the list of the headers that are added:
+ * - The CSP header of the static pages is added when CSP support is enabled.
+ */
+ experimentalStaticHeaders?: boolean;
}
export interface Options extends UserOptions {
@@ -18,6 +26,7 @@ export interface Options extends UserOptions {
client: string;
assets: string;
trailingSlash?: SSRManifest['trailingSlash'];
+ experimentalStaticHeaders: boolean;
}
export type RequestHandler = (...args: RequestHandlerParams) => void | Promise;
diff --git a/packages/integrations/node/test/fixtures/sessions/src/middleware.ts b/packages/integrations/node/test/fixtures/sessions/src/middleware.ts
index 7f56f11f364f..8b4458961e4a 100644
--- a/packages/integrations/node/test/fixtures/sessions/src/middleware.ts
+++ b/packages/integrations/node/test/fixtures/sessions/src/middleware.ts
@@ -10,8 +10,6 @@ export const onRequest = defineMiddleware(async (context, next) => {
const { action, setActionResult, serializeActionResult } =
getActionContext(context);
- console.log(action?.name)
-
const actionPayload = await context.session.get(ACTION_SESSION_KEY);
if (actionPayload) {
diff --git a/packages/integrations/node/test/fixtures/static-headers/astro.config.mjs b/packages/integrations/node/test/fixtures/static-headers/astro.config.mjs
new file mode 100644
index 000000000000..552699376862
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/static-headers/astro.config.mjs
@@ -0,0 +1,12 @@
+import node from '@astrojs/node'
+
+export default {
+ output: 'server',
+ adapter: node({
+ mode: 'standalone',
+ experimentalStaticHeaders: true
+ }),
+ experimental: {
+ csp: true
+ }
+};
diff --git a/packages/integrations/node/test/fixtures/static-headers/package.json b/packages/integrations/node/test/fixtures/static-headers/package.json
new file mode 100644
index 000000000000..aa36f5296fd1
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/static-headers/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@test/node-static-headers",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "@astrojs/node": "workspace:*",
+ "astro": "workspace:*"
+ }
+}
diff --git a/packages/integrations/node/test/fixtures/static-headers/src/components/Island.astro b/packages/integrations/node/test/fixtures/static-headers/src/components/Island.astro
new file mode 100644
index 000000000000..305caf85a9e1
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/static-headers/src/components/Island.astro
@@ -0,0 +1 @@
+I am a server island
diff --git a/packages/integrations/node/test/fixtures/static-headers/src/pages/[slug].astro b/packages/integrations/node/test/fixtures/static-headers/src/pages/[slug].astro
new file mode 100644
index 000000000000..c2f3faae327a
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/static-headers/src/pages/[slug].astro
@@ -0,0 +1,18 @@
+---
+import type { GetStaticPaths } from "astro";
+export const getStaticPaths = (() => {
+ return [
+ { params: { slug: "one" } },
+ { params: { slug: "two" } },
+ { params: { slug: "three" }},
+ ];
+}) satisfies GetStaticPaths;
+
+export const prerender = true;
+---
+
+{Astro.params.slug}
+
+Index
+
+
diff --git a/packages/integrations/node/test/fixtures/static-headers/src/pages/index.astro b/packages/integrations/node/test/fixtures/static-headers/src/pages/index.astro
new file mode 100644
index 000000000000..7937887b0396
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/static-headers/src/pages/index.astro
@@ -0,0 +1,11 @@
+---
+import Island from "../components/Island.astro"
+export const prerender = true;
+---
+
+Index
+
+Index
+
+
+
diff --git a/packages/integrations/node/test/static-headers.test.js b/packages/integrations/node/test/static-headers.test.js
new file mode 100644
index 000000000000..626064c2abee
--- /dev/null
+++ b/packages/integrations/node/test/static-headers.test.js
@@ -0,0 +1,71 @@
+import * as assert from 'node:assert/strict';
+import { after, before, describe, it } from 'node:test';
+import nodejs from '../dist/index.js';
+import { loadFixture, waitServerListen } from './test-utils.js';
+
+describe('Static headers', () => {
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({ root: './fixtures/static-headers' });
+ await fixture.build();
+ });
+
+ it('CSP headers are added when CSP is enabled', async () => {
+ const headers = JSON.parse(await fixture.readFile('../dist/_experimentalHeaders.json'));
+
+ const csp = headers
+ .find((x) => x.pathname === '/')
+ .headers.find((x) => x.key === 'Content-Security-Policy');
+
+ assert.notEqual(csp, undefined, 'the index must have CSP headers');
+ assert.ok(
+ csp.value.includes('script-src'),
+ 'must contain the script-src directive because of the server island',
+ );
+ });
+
+ it('CSP headers are added to the request', async () => {});
+});
+
+describe('Static headers', () => {
+ /** @type {import('./test-utils').Fixture} */
+ let fixture;
+ let server;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/static-headers/',
+ output: 'server',
+ adapter: nodejs({ mode: 'standalone', experimentalStaticHeaders: true }),
+ });
+ await fixture.build();
+ const { startServer } = await fixture.loadAdapterEntryModule();
+ const res = startServer();
+ server = res.server;
+ await waitServerListen(server.server);
+ });
+
+ after(async () => {
+ await server.stop();
+ // await fixture.clean();
+ });
+
+ it('CSP headers are added to the request', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/`);
+ const cps = res.headers.get('Content-Security-Policy');
+ assert.ok(
+ cps.includes('script-src'),
+ 'should contain script-src directive due to server island',
+ );
+ });
+
+ it('CSP headers are added to dynamic orute', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/one`);
+ const cps = res.headers.get('Content-Security-Policy');
+ assert.ok(
+ cps.includes('script-src'),
+ 'should contain script-src directive due to server island',
+ );
+ });
+});
diff --git a/packages/integrations/vercel/package.json b/packages/integrations/vercel/package.json
index 59dd196a6f12..d7e8d22abf0d 100644
--- a/packages/integrations/vercel/package.json
+++ b/packages/integrations/vercel/package.json
@@ -54,8 +54,7 @@
"@vercel/nft": "^0.29.2",
"@vercel/routing-utils": "^5.0.4",
"esbuild": "^0.25.0",
- "tinyglobby": "^0.2.13",
- "@astrojs/underscore-redirects": "workspace:*"
+ "tinyglobby": "^0.2.13"
},
"peerDependencies": {
"astro": "^5.0.0"
diff --git a/packages/integrations/vercel/src/index.ts b/packages/integrations/vercel/src/index.ts
index 237c56221a7f..a1e889589f72 100644
--- a/packages/integrations/vercel/src/index.ts
+++ b/packages/integrations/vercel/src/index.ts
@@ -2,7 +2,6 @@ import { cpSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
import { basename } from 'node:path';
import { pathToFileURL } from 'node:url';
import { emptyDir, removeDir, writeJson } from '@astrojs/internal-helpers/fs';
-import { createHostedRouteDefinition } from '@astrojs/underscore-redirects';
import {
getTransformedRoutes,
type Header,
@@ -16,6 +15,7 @@ import type {
AstroIntegrationLogger,
HookParameters,
IntegrationResolvedRoute,
+ RouteToHeaders,
} from 'astro';
import { AstroError } from 'astro/errors';
import { globSync } from 'tinyglobby';
@@ -204,7 +204,7 @@ export default function vercelAdapter({
let _serverEntry: string;
let _entryPoints: Map, URL>;
let _middlewareEntryPoint: URL | undefined;
- let _routeToHeaders: Map | undefined = undefined;
+ let _routeToHeaders: RouteToHeaders | undefined = undefined;
// Extra files to be merged with `includeFiles` during build
const extraFilesToInclude: URL[] = [];
// Secret used to verify that the caller is the astro-generated edge middleware and not a third-party
@@ -739,27 +739,15 @@ function getRuntime(process: NodeJS.Process, logger: AstroIntegrationLogger): Ru
return 'nodejs18.x';
}
-function createConfigHeaders(
- staticHeaders: Map,
- config: AstroConfig,
-): Header[] {
+function createConfigHeaders(staticHeaders: RouteToHeaders, config: AstroConfig): Header[] {
const vercelHeaders: Header[] = [];
- for (const [route, routeHeaders] of staticHeaders.entries()) {
- if (!route.isPrerendered) {
- continue;
- }
- if (route.redirect) {
- continue;
- }
-
- const definition = createHostedRouteDefinition(route, config);
-
+ for (const [pathname, { headers }] of staticHeaders.entries()) {
if (config.experimental.csp) {
- const csp = routeHeaders.get('Content-Security-Policy');
+ const csp = headers.get('Content-Security-Policy');
if (csp) {
vercelHeaders.push({
- source: definition.input,
+ source: pathname,
headers: [
{
key: 'Content-Security-Policy',
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f27fbcafad3d..b722e7dbcea5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -252,7 +252,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.7
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -315,7 +315,7 @@ importers:
version: link:../../packages/astro
svelte:
specifier: ^5.25.7
- version: 5.34.7
+ version: 5.34.9
examples/framework-vue:
dependencies:
@@ -369,7 +369,7 @@ importers:
version: link:../../packages/astro
svelte:
specifier: ^5.25.7
- version: 5.34.7
+ version: 5.34.9
examples/starlog:
dependencies:
@@ -751,7 +751,7 @@ importers:
version: 5.8.3
undici:
specifier: ^7.5.0
- version: 7.10.0
+ version: 7.11.0
unified:
specifier: ^11.0.5
version: 11.0.5
@@ -929,7 +929,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1074,7 +1074,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1131,7 +1131,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1187,7 +1187,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1227,7 +1227,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1267,7 +1267,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1307,7 +1307,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1347,7 +1347,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1387,7 +1387,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1583,7 +1583,7 @@ importers:
version: link:../../..
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/e2e/fixtures/tailwindcss:
dependencies:
@@ -1643,7 +1643,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1787,7 +1787,7 @@ importers:
version: 18.3.1(react@18.3.1)
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1808,7 +1808,7 @@ importers:
version: link:../../..
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/test/fixtures/alias-tsconfig:
dependencies:
@@ -1823,7 +1823,7 @@ importers:
version: link:../../..
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/test/fixtures/alias-tsconfig-baseurl-only:
dependencies:
@@ -1835,7 +1835,7 @@ importers:
version: link:../../..
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/test/fixtures/alias-tsconfig/deps/namespace-package: {}
@@ -1960,7 +1960,7 @@ importers:
version: 10.26.9
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -1993,7 +1993,7 @@ importers:
version: 18.3.1(react@18.3.1)
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/test/fixtures/astro-client-only/pkg: {}
@@ -2085,7 +2085,7 @@ importers:
version: 18.3.1(react@18.3.1)
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/test/fixtures/astro-env:
dependencies:
@@ -2433,7 +2433,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -2523,7 +2523,7 @@ importers:
version: 18.3.1(react@18.3.1)
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/test/fixtures/component-library-shared:
dependencies:
@@ -2880,7 +2880,7 @@ importers:
version: link:../../..
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/test/fixtures/css-import-as-inline:
dependencies:
@@ -3162,7 +3162,7 @@ importers:
version: 10.26.9
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -3384,7 +3384,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -3596,7 +3596,7 @@ importers:
version: 1.9.7
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -3814,7 +3814,7 @@ importers:
version: link:../../../..
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/test/fixtures/server-islands/ssr:
dependencies:
@@ -3829,7 +3829,7 @@ importers:
version: link:../../../..
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/test/fixtures/sessions:
dependencies:
@@ -3904,7 +3904,7 @@ importers:
version: link:../../..
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/test/fixtures/slots-vue:
dependencies:
@@ -4241,7 +4241,7 @@ importers:
version: link:../../..
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
packages/astro/test/fixtures/tailwindcss:
dependencies:
@@ -4352,7 +4352,7 @@ importers:
version: link:../../..
svelte:
specifier: ^5.25.3
- version: 5.34.7
+ version: 5.34.9
vue:
specifier: ^3.5.13
version: 3.5.17(typescript@5.8.3)
@@ -4418,7 +4418,7 @@ importers:
version: 1.0.2
drizzle-orm:
specifier: ^0.42.0
- version: 0.42.0(@cloudflare/workers-types@4.20250607.0)(@libsql/client@0.15.2)
+ version: 0.42.0(@cloudflare/workers-types@4.20250507.0)(@libsql/client@0.15.2)
github-slugger:
specifier: ^2.0.0
version: 2.0.0
@@ -4680,7 +4680,7 @@ importers:
version: link:../../underscore-redirects
'@cloudflare/workers-types':
specifier: ^4.20250507.0
- version: 4.20250607.0
+ version: 4.20250507.0
tinyglobby:
specifier: ^0.2.13
version: 0.2.13
@@ -4689,7 +4689,7 @@ importers:
version: 6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)
wrangler:
specifier: ^4.14.1
- version: 4.14.1(@cloudflare/workers-types@4.20250607.0)
+ version: 4.14.1(@cloudflare/workers-types@4.20250507.0)
devDependencies:
astro:
specifier: workspace:*
@@ -4721,7 +4721,7 @@ importers:
devDependencies:
wrangler:
specifier: ^4.14.1
- version: 4.14.1(@cloudflare/workers-types@4.20250607.0)
+ version: 4.14.1(@cloudflare/workers-types@4.20250507.0)
packages/integrations/cloudflare/test/fixtures/astro-env:
dependencies:
@@ -4734,7 +4734,7 @@ importers:
devDependencies:
wrangler:
specifier: ^4.14.1
- version: 4.14.1(@cloudflare/workers-types@4.20250607.0)
+ version: 4.14.1(@cloudflare/workers-types@4.20250507.0)
packages/integrations/cloudflare/test/fixtures/compile-image-service:
dependencies:
@@ -4801,7 +4801,7 @@ importers:
version: link:../../../../../astro
wrangler:
specifier: ^4.14.1
- version: 4.14.1(@cloudflare/workers-types@4.20250607.0)
+ version: 4.14.1(@cloudflare/workers-types@4.20250507.0)
packages/integrations/cloudflare/test/fixtures/with-base:
dependencies:
@@ -4840,7 +4840,7 @@ importers:
version: link:../../../../../astro
svelte:
specifier: ^5.28.2
- version: 5.34.7
+ version: 5.34.9
packages/integrations/cloudflare/test/fixtures/with-vue:
dependencies:
@@ -5567,6 +5567,15 @@ importers:
specifier: workspace:*
version: link:../../../../../astro
+ packages/integrations/node/test/fixtures/static-headers:
+ dependencies:
+ '@astrojs/node':
+ specifier: workspace:*
+ version: link:../../..
+ astro:
+ specifier: workspace:*
+ version: link:../../../../../astro
+
packages/integrations/node/test/fixtures/trailing-slash:
dependencies:
'@astrojs/node':
@@ -5614,7 +5623,7 @@ importers:
dependencies:
'@preact/preset-vite':
specifier: ^2.10.1
- version: 2.10.1(@babel/core@7.27.4)(preact@10.26.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))
+ version: 2.10.1(@babel/core@7.27.7)(preact@10.26.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))
'@preact/signals':
specifier: ^2.2.0
version: 2.2.0(preact@10.26.9)
@@ -5774,10 +5783,10 @@ importers:
dependencies:
'@sveltejs/vite-plugin-svelte':
specifier: ^5.1.0
- version: 5.1.0(svelte@5.34.7)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))
+ version: 5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))
svelte2tsx:
specifier: ^0.7.40
- version: 0.7.40(svelte@5.34.7)(typescript@5.8.3)
+ version: 0.7.40(svelte@5.34.9)(typescript@5.8.3)
vite:
specifier: ^6.3.5
version: 6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)
@@ -5790,19 +5799,16 @@ importers:
version: link:../../../scripts
svelte:
specifier: ^5.34.7
- version: 5.34.7
+ version: 5.34.9
packages/integrations/vercel:
dependencies:
'@astrojs/internal-helpers':
specifier: workspace:*
version: link:../../internal-helpers
- '@astrojs/underscore-redirects':
- specifier: workspace:*
- version: link:../../underscore-redirects
'@vercel/analytics':
specifier: ^1.5.0
- version: 1.5.0(react@19.1.0)(svelte@5.34.7)(vue@3.5.17(typescript@5.8.3))
+ version: 1.5.0(react@19.1.0)(svelte@5.34.9)(vue@3.5.17(typescript@5.8.3))
'@vercel/edge':
specifier: ^1.2.1
version: 1.2.1
@@ -6451,8 +6457,8 @@ packages:
resolution: {integrity: sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==}
engines: {node: '>=6.9.0'}
- '@babel/core@7.27.4':
- resolution: {integrity: sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==}
+ '@babel/core@7.27.7':
+ resolution: {integrity: sha512-BU2f9tlKQ5CAthiMIgpzAh4eDTLWo1mqi9jqE2OxMG0E/OM199VJt2q8BztTxpnSW0i1ymdwLXRJnYzvDM5r2w==}
engines: {node: '>=6.9.0'}
'@babel/generator@7.27.5':
@@ -6525,8 +6531,8 @@ packages:
resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==}
engines: {node: '>=6.9.0'}
- '@babel/parser@7.27.5':
- resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==}
+ '@babel/parser@7.27.7':
+ resolution: {integrity: sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -6603,16 +6609,16 @@ packages:
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
engines: {node: '>=6.9.0'}
- '@babel/traverse@7.27.4':
- resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==}
+ '@babel/traverse@7.27.7':
+ resolution: {integrity: sha512-X6ZlfR/O/s5EQ/SnUSLzr+6kGnkg8HXGMzpgsMsrJVcfDtH1vIp6ctCN4eZ1LS5c0+te5Cb6Y514fASjMRJ1nw==}
engines: {node: '>=6.9.0'}
'@babel/types@7.26.10':
resolution: {integrity: sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==}
engines: {node: '>=6.9.0'}
- '@babel/types@7.27.6':
- resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==}
+ '@babel/types@7.27.7':
+ resolution: {integrity: sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==}
engines: {node: '>=6.9.0'}
'@biomejs/biome@2.0.0':
@@ -6787,8 +6793,8 @@ packages:
cpu: [x64]
os: [win32]
- '@cloudflare/workers-types@4.20250607.0':
- resolution: {integrity: sha512-OYmKNzC2eQy6CNj+j0go8Ut3SezjsprCgJyEaBzJql+473WAN9ndVnNZy9lj/tTyLV6wzpQkZWmRAKGDmacvkg==}
+ '@cloudflare/workers-types@4.20250507.0':
+ resolution: {integrity: sha512-fkrq7A6XWgPEmXJDwu9TS/Zw7qho3eGlrOlicKue32Bdul0Ma4Mym4sh7ZeGbayBXxkOx/fHpm5GfhVEtngRWQ==}
'@codspeed/core@4.0.1':
resolution: {integrity: sha512-fJ53arfgtzCDZa8DuGJhpTZ3Ll9A1uW5nQ2jSJnfO4Hl5MRD2cP8P4vPvIUAGbdbjwCxR1jat6cW8OloMJkJXw==}
@@ -12592,8 +12598,8 @@ packages:
svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0
typescript: ^4.9.4 || ^5.0.0
- svelte@5.34.7:
- resolution: {integrity: sha512-5PEg+QQKce4t1qiOtVUhUS3AQRTtxJyGBTpxLcNWnr0Ve8q4r06bMo0Gv8uhtCPWlztZHoi3Ye7elLhu+PCTMg==}
+ svelte@5.34.9:
+ resolution: {integrity: sha512-sld35zFpooaSRSj4qw8Vl/cyyK0/sLQq9qhJ7BGZo/Kd0ggYtEnvNYLlzhhoqYsYQzA0hJqkzt3RBO/8KoTZOg==}
engines: {node: '>=18'}
svgo@3.3.2:
@@ -12830,8 +12836,8 @@ packages:
resolution: {integrity: sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==}
engines: {node: '>=18.17'}
- undici@7.10.0:
- resolution: {integrity: sha512-u5otvFBOBZvmdjWLVW+5DAc9Nkq8f24g0O9oY7qw2JVIF1VocIFoyz9JFkuVOS2j41AufeO0xnlweJ2RLT8nGw==}
+ undici@7.11.0:
+ resolution: {integrity: sha512-heTSIac3iLhsmZhUCjyS3JQEkZELateufzZuBaVM5RHXdSBMb1LPMQf5x+FH7qjsZYDP0ttAc3nnVpUB+wYbOg==}
engines: {node: '>=20.18.1'}
unenv@2.0.0-rc.15:
@@ -13622,18 +13628,18 @@ snapshots:
'@babel/compat-data@7.27.2': {}
- '@babel/core@7.27.4':
+ '@babel/core@7.27.7':
dependencies:
'@ampproject/remapping': 2.3.0
'@babel/code-frame': 7.27.1
'@babel/generator': 7.27.5
'@babel/helper-compilation-targets': 7.27.2
- '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4)
+ '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.7)
'@babel/helpers': 7.27.6
- '@babel/parser': 7.27.5
+ '@babel/parser': 7.27.7
'@babel/template': 7.27.2
- '@babel/traverse': 7.27.4
- '@babel/types': 7.27.6
+ '@babel/traverse': 7.27.7
+ '@babel/types': 7.27.7
convert-source-map: 2.0.0
debug: 4.4.1
gensync: 1.0.0-beta.2
@@ -13644,15 +13650,15 @@ snapshots:
'@babel/generator@7.27.5':
dependencies:
- '@babel/parser': 7.27.5
- '@babel/types': 7.27.6
+ '@babel/parser': 7.27.7
+ '@babel/types': 7.27.7
'@jridgewell/gen-mapping': 0.3.5
'@jridgewell/trace-mapping': 0.3.25
jsesc: 3.0.2
'@babel/helper-annotate-as-pure@7.27.1':
dependencies:
- '@babel/types': 7.27.6
+ '@babel/types': 7.27.7
'@babel/helper-compilation-targets@7.27.2':
dependencies:
@@ -13662,65 +13668,65 @@ snapshots:
lru-cache: 5.1.1
semver: 6.3.1
- '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.27.4)':
+ '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-annotate-as-pure': 7.27.1
'@babel/helper-member-expression-to-functions': 7.27.1
'@babel/helper-optimise-call-expression': 7.27.1
- '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.4)
+ '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.7)
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/traverse': 7.27.7
semver: 6.3.1
transitivePeerDependencies:
- supports-color
'@babel/helper-member-expression-to-functions@7.27.1':
dependencies:
- '@babel/traverse': 7.27.4
- '@babel/types': 7.27.6
+ '@babel/traverse': 7.27.7
+ '@babel/types': 7.27.7
transitivePeerDependencies:
- supports-color
'@babel/helper-module-imports@7.18.6':
dependencies:
- '@babel/types': 7.27.6
+ '@babel/types': 7.27.7
'@babel/helper-module-imports@7.27.1':
dependencies:
- '@babel/traverse': 7.27.4
- '@babel/types': 7.27.6
+ '@babel/traverse': 7.27.7
+ '@babel/types': 7.27.7
transitivePeerDependencies:
- supports-color
- '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.4)':
+ '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-module-imports': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/traverse': 7.27.7
transitivePeerDependencies:
- supports-color
'@babel/helper-optimise-call-expression@7.27.1':
dependencies:
- '@babel/types': 7.27.6
+ '@babel/types': 7.27.7
'@babel/helper-plugin-utils@7.27.1': {}
- '@babel/helper-replace-supers@7.27.1(@babel/core@7.27.4)':
+ '@babel/helper-replace-supers@7.27.1(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-member-expression-to-functions': 7.27.1
'@babel/helper-optimise-call-expression': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/traverse': 7.27.7
transitivePeerDependencies:
- supports-color
'@babel/helper-skip-transparent-expression-wrappers@7.27.1':
dependencies:
- '@babel/traverse': 7.27.4
- '@babel/types': 7.27.6
+ '@babel/traverse': 7.27.7
+ '@babel/types': 7.27.7
transitivePeerDependencies:
- supports-color
@@ -13733,82 +13739,82 @@ snapshots:
'@babel/helpers@7.27.6':
dependencies:
'@babel/template': 7.27.2
- '@babel/types': 7.27.6
+ '@babel/types': 7.27.7
- '@babel/parser@7.27.5':
+ '@babel/parser@7.27.7':
dependencies:
- '@babel/types': 7.27.6
+ '@babel/types': 7.27.7
- '@babel/plugin-proposal-decorators@7.24.7(@babel/core@7.27.4)':
+ '@babel/plugin-proposal-decorators@7.24.7(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.27.7
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.7)
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-decorators': 7.24.7(@babel/core@7.27.4)
+ '@babel/plugin-syntax-decorators': 7.24.7(@babel/core@7.27.7)
transitivePeerDependencies:
- supports-color
- '@babel/plugin-syntax-decorators@7.24.7(@babel/core@7.27.4)':
+ '@babel/plugin-syntax-decorators@7.24.7(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-import-attributes@7.25.6(@babel/core@7.27.4)':
+ '@babel/plugin-syntax-import-attributes@7.25.6(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.27.4)':
+ '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.27.4)':
+ '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-react-jsx-development@7.25.9(@babel/core@7.27.4)':
+ '@babel/plugin-transform-react-jsx-development@7.25.9(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
- '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.27.4)
+ '@babel/core': 7.27.7
+ '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.27.7)
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.27.4)':
+ '@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-annotate-as-pure': 7.27.1
'@babel/helper-module-imports': 7.27.1
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.27.4)
- '@babel/types': 7.27.6
+ '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.27.7)
+ '@babel/types': 7.27.7
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-typescript@7.27.1(@babel/core@7.27.4)':
+ '@babel/plugin-transform-typescript@7.27.1(@babel/core@7.27.7)':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-annotate-as-pure': 7.27.1
- '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.4)
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.7)
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-skip-transparent-expression-wrappers': 7.27.1
- '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.4)
+ '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.7)
transitivePeerDependencies:
- supports-color
@@ -13819,16 +13825,16 @@ snapshots:
'@babel/template@7.27.2':
dependencies:
'@babel/code-frame': 7.27.1
- '@babel/parser': 7.27.5
- '@babel/types': 7.27.6
+ '@babel/parser': 7.27.7
+ '@babel/types': 7.27.7
- '@babel/traverse@7.27.4':
+ '@babel/traverse@7.27.7':
dependencies:
'@babel/code-frame': 7.27.1
'@babel/generator': 7.27.5
- '@babel/parser': 7.27.5
+ '@babel/parser': 7.27.7
'@babel/template': 7.27.2
- '@babel/types': 7.27.6
+ '@babel/types': 7.27.7
debug: 4.4.1
globals: 11.12.0
transitivePeerDependencies:
@@ -13839,7 +13845,7 @@ snapshots:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
- '@babel/types@7.27.6':
+ '@babel/types@7.27.7':
dependencies:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
@@ -14084,7 +14090,7 @@ snapshots:
'@cloudflare/workerd-windows-64@1.20250428.0':
optional: true
- '@cloudflare/workers-types@4.20250607.0': {}
+ '@cloudflare/workers-types@4.20250507.0': {}
'@codspeed/core@4.0.1':
dependencies:
@@ -15080,7 +15086,7 @@ snapshots:
'@netlify/zip-it-and-ship-it@10.0.7(rollup@4.40.2)':
dependencies:
- '@babel/parser': 7.27.5
+ '@babel/parser': 7.27.7
'@babel/types': 7.26.10
'@netlify/binary-info': 1.0.0
'@netlify/serverless-functions-api': 1.38.0
@@ -15199,14 +15205,14 @@ snapshots:
'@polka/url@1.0.0-next.25': {}
- '@preact/preset-vite@2.10.1(@babel/core@7.27.4)(preact@10.26.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))':
+ '@preact/preset-vite@2.10.1(@babel/core@7.27.7)(preact@10.26.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))':
dependencies:
- '@babel/core': 7.27.4
- '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.27.4)
- '@babel/plugin-transform-react-jsx-development': 7.25.9(@babel/core@7.27.4)
+ '@babel/core': 7.27.7
+ '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.27.7)
+ '@babel/plugin-transform-react-jsx-development': 7.25.9(@babel/core@7.27.7)
'@prefresh/vite': 2.4.5(preact@10.26.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))
'@rollup/pluginutils': 4.2.1
- babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.27.4)
+ babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.27.7)
debug: 4.4.1
kolorist: 1.8.0
vite: 6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)
@@ -15237,7 +15243,7 @@ snapshots:
'@prefresh/vite@2.4.5(preact@10.26.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))':
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@prefresh/babel-plugin': 0.5.1
'@prefresh/core': 1.5.2(preact@10.26.9)
'@prefresh/utils': 1.2.0
@@ -15373,23 +15379,23 @@ snapshots:
dependencies:
acorn: 8.14.1
- '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.7)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)))(svelte@5.34.7)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))':
+ '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))':
dependencies:
- '@sveltejs/vite-plugin-svelte': 5.1.0(svelte@5.34.7)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))
+ '@sveltejs/vite-plugin-svelte': 5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))
debug: 4.4.1
- svelte: 5.34.7
+ svelte: 5.34.9
vite: 6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)
transitivePeerDependencies:
- supports-color
- '@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.7)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))':
+ '@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))':
dependencies:
- '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.7)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)))(svelte@5.34.7)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))
+ '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))
debug: 4.4.1
deepmerge: 4.3.1
kleur: 4.1.5
magic-string: 0.30.17
- svelte: 5.34.7
+ svelte: 5.34.9
vite: 6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)
vitefu: 1.0.6(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))
transitivePeerDependencies:
@@ -15472,24 +15478,24 @@ snapshots:
'@types/babel__core@7.20.5':
dependencies:
- '@babel/parser': 7.27.5
- '@babel/types': 7.27.6
+ '@babel/parser': 7.27.7
+ '@babel/types': 7.27.7
'@types/babel__generator': 7.6.8
'@types/babel__template': 7.4.4
'@types/babel__traverse': 7.20.6
'@types/babel__generator@7.6.8':
dependencies:
- '@babel/types': 7.27.6
+ '@babel/types': 7.27.7
'@types/babel__template@7.4.4':
dependencies:
- '@babel/parser': 7.27.5
- '@babel/types': 7.27.6
+ '@babel/parser': 7.27.7
+ '@babel/types': 7.27.7
'@types/babel__traverse@7.20.6':
dependencies:
- '@babel/types': 7.27.6
+ '@babel/types': 7.27.7
'@types/canvas-confetti@1.9.0': {}
@@ -15761,10 +15767,10 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
- '@vercel/analytics@1.5.0(react@19.1.0)(svelte@5.34.7)(vue@3.5.17(typescript@5.8.3))':
+ '@vercel/analytics@1.5.0(react@19.1.0)(svelte@5.34.9)(vue@3.5.17(typescript@5.8.3))':
optionalDependencies:
react: 19.1.0
- svelte: 5.34.7
+ svelte: 5.34.9
vue: 3.5.17(typescript@5.8.3)
'@vercel/edge@1.2.1': {}
@@ -15816,9 +15822,9 @@ snapshots:
'@vitejs/plugin-react@4.6.0(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))':
dependencies:
- '@babel/core': 7.27.4
- '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.4)
- '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.27.7
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.7)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.27.7)
'@rolldown/pluginutils': 1.0.0-beta.19
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
@@ -15828,10 +15834,10 @@ snapshots:
'@vitejs/plugin-vue-jsx@4.2.0(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1))(vue@3.5.17(typescript@5.8.3))':
dependencies:
- '@babel/core': 7.27.4
- '@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.4)
+ '@babel/core': 7.27.7
+ '@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.7)
'@rolldown/pluginutils': 1.0.0-beta.19
- '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.27.4)
+ '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.27.7)
vite: 6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)
vue: 3.5.17(typescript@5.8.3)
transitivePeerDependencies:
@@ -15934,36 +15940,36 @@ snapshots:
'@vue/babel-helper-vue-transform-on@1.4.0': {}
- '@vue/babel-plugin-jsx@1.4.0(@babel/core@7.27.4)':
+ '@vue/babel-plugin-jsx@1.4.0(@babel/core@7.27.7)':
dependencies:
'@babel/helper-module-imports': 7.27.1
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.27.4)
+ '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.27.7)
'@babel/template': 7.27.2
- '@babel/traverse': 7.27.4
- '@babel/types': 7.27.6
+ '@babel/traverse': 7.27.7
+ '@babel/types': 7.27.7
'@vue/babel-helper-vue-transform-on': 1.4.0
- '@vue/babel-plugin-resolve-type': 1.4.0(@babel/core@7.27.4)
+ '@vue/babel-plugin-resolve-type': 1.4.0(@babel/core@7.27.7)
'@vue/shared': 3.5.17
optionalDependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
transitivePeerDependencies:
- supports-color
- '@vue/babel-plugin-resolve-type@1.4.0(@babel/core@7.27.4)':
+ '@vue/babel-plugin-resolve-type@1.4.0(@babel/core@7.27.7)':
dependencies:
'@babel/code-frame': 7.27.1
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-module-imports': 7.27.1
'@babel/helper-plugin-utils': 7.27.1
- '@babel/parser': 7.27.5
+ '@babel/parser': 7.27.7
'@vue/compiler-sfc': 3.5.17
transitivePeerDependencies:
- supports-color
'@vue/compiler-core@3.5.17':
dependencies:
- '@babel/parser': 7.27.5
+ '@babel/parser': 7.27.7
'@vue/shared': 3.5.17
entities: 4.5.0
estree-walker: 2.0.2
@@ -15976,7 +15982,7 @@ snapshots:
'@vue/compiler-sfc@3.5.17':
dependencies:
- '@babel/parser': 7.27.5
+ '@babel/parser': 7.27.7
'@vue/compiler-core': 3.5.17
'@vue/compiler-dom': 3.5.17
'@vue/compiler-ssr': 3.5.17
@@ -16300,23 +16306,23 @@ snapshots:
axobject-query@4.1.0: {}
- babel-plugin-jsx-dom-expressions@0.38.5(@babel/core@7.27.4):
+ babel-plugin-jsx-dom-expressions@0.38.5(@babel/core@7.27.7):
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@babel/helper-module-imports': 7.18.6
- '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.27.4)
- '@babel/types': 7.27.6
+ '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.27.7)
+ '@babel/types': 7.27.7
html-entities: 2.3.3
validate-html-nesting: 1.2.2
- babel-plugin-transform-hook-names@1.0.2(@babel/core@7.27.4):
+ babel-plugin-transform-hook-names@1.0.2(@babel/core@7.27.7):
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
- babel-preset-solid@1.8.22(@babel/core@7.27.4):
+ babel-preset-solid@1.8.22(@babel/core@7.27.7):
dependencies:
- '@babel/core': 7.27.4
- babel-plugin-jsx-dom-expressions: 0.38.5(@babel/core@7.27.4)
+ '@babel/core': 7.27.7
+ babel-plugin-jsx-dom-expressions: 0.38.5(@babel/core@7.27.7)
bail@2.0.2: {}
@@ -16508,7 +16514,7 @@ snapshots:
parse5: 7.3.0
parse5-htmlparser2-tree-adapter: 7.1.0
parse5-parser-stream: 7.1.2
- undici: 7.10.0
+ undici: 7.11.0
whatwg-mimetype: 4.0.0
chokidar@4.0.3:
@@ -16908,9 +16914,9 @@ snapshots:
dotenv@8.6.0: {}
- drizzle-orm@0.42.0(@cloudflare/workers-types@4.20250607.0)(@libsql/client@0.15.2):
+ drizzle-orm@0.42.0(@cloudflare/workers-types@4.20250507.0)(@libsql/client@0.15.2):
optionalDependencies:
- '@cloudflare/workers-types': 4.20250607.0
+ '@cloudflare/workers-types': 4.20250507.0
'@libsql/client': 0.15.2
dset@3.1.4: {}
@@ -18308,8 +18314,8 @@ snapshots:
magicast@0.3.5:
dependencies:
- '@babel/parser': 7.27.5
- '@babel/types': 7.27.6
+ '@babel/parser': 7.27.7
+ '@babel/types': 7.27.7
source-map-js: 1.2.1
make-dir@3.1.0:
@@ -19012,7 +19018,7 @@ snapshots:
node-source-walk@6.0.2:
dependencies:
- '@babel/parser': 7.27.5
+ '@babel/parser': 7.27.7
nopt@5.0.0:
dependencies:
@@ -20301,7 +20307,7 @@ snapshots:
dependencies:
'@babel/generator': 7.27.5
'@babel/helper-module-imports': 7.27.1
- '@babel/types': 7.27.6
+ '@babel/types': 7.27.7
solid-js: 1.9.7
transitivePeerDependencies:
- supports-color
@@ -20460,14 +20466,14 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
- svelte2tsx@0.7.40(svelte@5.34.7)(typescript@5.8.3):
+ svelte2tsx@0.7.40(svelte@5.34.9)(typescript@5.8.3):
dependencies:
dedent-js: 1.0.1
pascal-case: 3.1.2
- svelte: 5.34.7
+ svelte: 5.34.9
typescript: 5.8.3
- svelte@5.34.7:
+ svelte@5.34.9:
dependencies:
'@ampproject/remapping': 2.3.0
'@jridgewell/sourcemap-codec': 1.5.0
@@ -20683,7 +20689,7 @@ snapshots:
undici@6.21.0: {}
- undici@7.10.0: {}
+ undici@7.11.0: {}
unenv@2.0.0-rc.15:
dependencies:
@@ -20912,9 +20918,9 @@ snapshots:
vite-plugin-solid@2.11.7(solid-js@1.9.7)(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)):
dependencies:
- '@babel/core': 7.27.4
+ '@babel/core': 7.27.7
'@types/babel__core': 7.20.5
- babel-preset-solid: 1.8.22(@babel/core@7.27.4)
+ babel-preset-solid: 1.8.22(@babel/core@7.27.7)
merge-anything: 5.1.7
solid-js: 1.9.7
solid-refresh: 0.6.3(solid-js@1.9.7)
@@ -20941,12 +20947,12 @@ snapshots:
vite-plugin-vue-inspector@5.3.1(vite@6.3.5(@types/node@22.13.1)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.86.3)(yaml@2.5.1)):
dependencies:
- '@babel/core': 7.27.4
- '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.27.4)
- '@babel/plugin-syntax-import-attributes': 7.25.6(@babel/core@7.27.4)
- '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.27.4)
- '@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.4)
- '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.27.4)
+ '@babel/core': 7.27.7
+ '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.27.7)
+ '@babel/plugin-syntax-import-attributes': 7.25.6(@babel/core@7.27.7)
+ '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.27.7)
+ '@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.7)
+ '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.27.7)
'@vue/compiler-dom': 3.5.17
kolorist: 1.8.0
magic-string: 0.30.17
@@ -21229,7 +21235,7 @@ snapshots:
'@cloudflare/workerd-linux-arm64': 1.20250428.0
'@cloudflare/workerd-windows-64': 1.20250428.0
- wrangler@4.14.1(@cloudflare/workers-types@4.20250607.0):
+ wrangler@4.14.1(@cloudflare/workers-types@4.20250507.0):
dependencies:
'@cloudflare/kv-asset-handler': 0.4.0
'@cloudflare/unenv-preset': 2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250428.0)
@@ -21240,7 +21246,7 @@ snapshots:
unenv: 2.0.0-rc.15
workerd: 1.20250428.0
optionalDependencies:
- '@cloudflare/workers-types': 4.20250607.0
+ '@cloudflare/workers-types': 4.20250507.0
fsevents: 2.3.3
sharp: 0.33.5
transitivePeerDependencies: