+
SvelteKit
-
-
-
Astro
+
+
NestJS
Coming soon
diff --git a/package.json b/package.json
index 5e80e2d39..f5e934c8e 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,8 @@
"packageManager": "pnpm@10.20.0+sha512.cf9998222162dd85864d0a8102e7892e7ba4ceadebbf5a31f9c2fce48dfce317a9c53b9f6464d1ef9042cba2e02ae02a9f7c143a2b438cd93c91840f0192b9dd",
"pnpm": {
"overrides": {
- "rfc6902": "5.1.2"
+ "rfc6902": "5.1.2",
+ "path-to-regexp": "6.3.0"
},
"onlyBuiltDependencies": [
"bun"
diff --git a/packages/astro/LICENSE.md b/packages/astro/LICENSE.md
new file mode 100644
index 000000000..c4d680f55
--- /dev/null
+++ b/packages/astro/LICENSE.md
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2025 Vercel Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/astro/README.md b/packages/astro/README.md
new file mode 100644
index 000000000..17a1b2eab
--- /dev/null
+++ b/packages/astro/README.md
@@ -0,0 +1,3 @@
+# workflow/astro
+
+The docs have moved! Refer to them [here](https://useworkflow.dev/)
diff --git a/packages/astro/package.json b/packages/astro/package.json
new file mode 100644
index 000000000..dfd49b7ce
--- /dev/null
+++ b/packages/astro/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "@workflow/astro",
+ "version": "4.0.0-beta.1",
+ "description": "Astro integration for Workflow DevKit",
+ "type": "module",
+ "main": "dist/index.js",
+ "files": [
+ "dist"
+ ],
+ "publishConfig": {
+ "access": "public"
+ },
+ "license": "Apache-2.0",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/vercel/workflow.git",
+ "directory": "packages/astro"
+ },
+ "exports": {
+ ".": "./dist/index.js"
+ },
+ "scripts": {
+ "build": "tsc",
+ "dev": "tsc --watch",
+ "clean": "tsc --build --clean && rm -rf dist"
+ },
+ "dependencies": {
+ "@swc/core": "1.11.24",
+ "@workflow/builders": "workspace:*",
+ "@workflow/swc-plugin": "workspace:*",
+ "exsolve": "^1.0.7",
+ "pathe": "^2.0.3"
+ },
+ "devDependencies": {
+ "@types/node": "catalog:",
+ "@workflow/tsconfig": "workspace:*",
+ "astro": "5.16.0"
+ }
+}
diff --git a/packages/astro/src/builder.ts b/packages/astro/src/builder.ts
new file mode 100644
index 000000000..94f9852df
--- /dev/null
+++ b/packages/astro/src/builder.ts
@@ -0,0 +1,260 @@
+import { mkdir, readFile, writeFile } from 'node:fs/promises';
+import { join, resolve } from 'node:path';
+import {
+ BaseBuilder,
+ VercelBuildOutputAPIBuilder,
+ createBaseBuilderConfig,
+ type AstroConfig,
+} from '@workflow/builders';
+
+// NOTE: This is the same as SvelteKit request converter, should merge
+const NORMALIZE_REQUEST_CONVERTER = `
+async function normalizeRequestConverter(request) {
+ const options = {
+ method: request.method,
+ headers: new Headers(request.headers)
+ };
+ if (!['GET', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT'].includes(request.method)) {
+ options.body = await request.arrayBuffer();
+ }
+ return new Request(request.url, options);
+}
+`;
+
+const WORKFLOW_ROUTES = [
+ {
+ src: '^/\\.well-known/workflow/v1/flow/?$',
+ dest: '/.well-known/workflow/v1/flow',
+ },
+ {
+ src: '^/\\.well-known/workflow/v1/step/?$',
+ dest: '/.well-known/workflow/v1/step',
+ },
+ {
+ src: '^/\\.well-known/workflow/v1/webhook/([^/]+?)/?$',
+ dest: '/.well-known/workflow/v1/webhook/[token]',
+ },
+];
+
+export class LocalBuilder extends BaseBuilder {
+ constructor() {
+ super({
+ dirs: ['src/pages', 'src/workflows'],
+ buildTarget: 'astro' as const,
+ stepsBundlePath: '', // unused in base
+ workflowsBundlePath: '', // unused in base
+ webhookBundlePath: '', // unused in base
+ workingDir: process.cwd(),
+ debugFilePrefix: '_', // Prefix with underscore so Astro ignores debug files
+ });
+ }
+
+ override async build(): Promise
{
+ const pagesDir = resolve(this.config.workingDir, 'src/pages');
+ const workflowGeneratedDir = join(pagesDir, '.well-known/workflow/v1');
+
+ // Ensure output directories exist
+ await mkdir(workflowGeneratedDir, { recursive: true });
+
+ // Add .gitignore to exclude generated files from version control
+ if (process.env.VERCEL_DEPLOYMENT_ID === undefined) {
+ await writeFile(join(workflowGeneratedDir, '.gitignore'), '*');
+ }
+
+ // Get workflow and step files to bundle
+ const inputFiles = await this.getInputFiles();
+ const tsConfig = await this.getTsConfigOptions();
+
+ const options = {
+ inputFiles,
+ workflowGeneratedDir,
+ tsBaseUrl: tsConfig.baseUrl,
+ tsPaths: tsConfig.paths,
+ };
+
+ // Generate the three Astro route handlers
+ await this.buildStepsRoute(options);
+ await this.buildWorkflowsRoute(options);
+ await this.buildWebhookRoute({ workflowGeneratedDir });
+ }
+
+ private async buildStepsRoute({
+ inputFiles,
+ workflowGeneratedDir,
+ tsPaths,
+ tsBaseUrl,
+ }: {
+ inputFiles: string[];
+ workflowGeneratedDir: string;
+ tsBaseUrl?: string;
+ tsPaths?: Record;
+ }) {
+ // Create steps route: .well-known/workflow/v1/step.js
+ const stepsRouteFile = join(workflowGeneratedDir, 'step.js');
+ await this.createStepsBundle({
+ format: 'esm',
+ inputFiles,
+ outfile: stepsRouteFile,
+ externalizeNonSteps: true,
+ tsBaseUrl,
+ tsPaths,
+ });
+
+ let stepsRouteContent = await readFile(stepsRouteFile, 'utf-8');
+
+ // Normalize request, needed for preserving request through astro
+ stepsRouteContent = stepsRouteContent.replace(
+ /export\s*\{\s*stepEntrypoint\s+as\s+POST\s*\}\s*;?$/m,
+ `${NORMALIZE_REQUEST_CONVERTER}
+export const POST = async ({request}) => {
+ const normalRequest = await normalizeRequestConverter(request);
+ return stepEntrypoint(normalRequest);
+}
+
+export const prerender = false;`
+ );
+ await writeFile(stepsRouteFile, stepsRouteContent);
+ }
+
+ private async buildWorkflowsRoute({
+ inputFiles,
+ workflowGeneratedDir,
+ tsPaths,
+ tsBaseUrl,
+ }: {
+ inputFiles: string[];
+ workflowGeneratedDir: string;
+ tsBaseUrl?: string;
+ tsPaths?: Record;
+ }) {
+ // Create workflows route: .well-known/workflow/v1/flow.js
+ const workflowsRouteFile = join(workflowGeneratedDir, 'flow.js');
+ await this.createWorkflowsBundle({
+ format: 'esm',
+ outfile: workflowsRouteFile,
+ bundleFinalOutput: false,
+ inputFiles,
+ tsBaseUrl,
+ tsPaths,
+ });
+
+ let workflowsRouteContent = await readFile(workflowsRouteFile, 'utf-8');
+
+ // Normalize request, needed for preserving request through astro
+ workflowsRouteContent = workflowsRouteContent.replace(
+ /export const POST = workflowEntrypoint\(workflowCode\);?$/m,
+ `${NORMALIZE_REQUEST_CONVERTER}
+export const POST = async ({request}) => {
+ const normalRequest = await normalizeRequestConverter(request);
+ return workflowEntrypoint(workflowCode)(normalRequest);
+}
+
+export const prerender = false;`
+ );
+ await writeFile(workflowsRouteFile, workflowsRouteContent);
+ }
+
+ private async buildWebhookRoute({
+ workflowGeneratedDir,
+ }: {
+ workflowGeneratedDir: string;
+ }) {
+ // Create webhook route: .well-known/workflow/v1/webhook/[token].js
+ const webhookRouteFile = join(workflowGeneratedDir, 'webhook/[token].js');
+
+ await this.createWebhookBundle({
+ outfile: webhookRouteFile,
+ bundle: false,
+ });
+
+ // Post-process the generated file to wrap with Astro request converter
+ let webhookRouteContent = await readFile(webhookRouteFile, 'utf-8');
+
+ // Update handler signature to accept token as parameter
+ webhookRouteContent = webhookRouteContent.replace(
+ /async function handler\(request\) \{[\s\S]*?const token = decodeURIComponent\(pathParts\[pathParts\.length - 1\]\);/,
+ `async function handler(request, token) {`
+ );
+
+ // Remove the URL parsing code since we get token from params
+ webhookRouteContent = webhookRouteContent.replace(
+ /const url = new URL\(request\.url\);[\s\S]*?const pathParts = url\.pathname\.split\('\/'\);[\s\S]*?\n/,
+ ''
+ );
+
+ // Normalize request, needed for preserving request through astro
+ webhookRouteContent = webhookRouteContent.replace(
+ /export const GET = handler;\nexport const POST = handler;\nexport const PUT = handler;\nexport const PATCH = handler;\nexport const DELETE = handler;\nexport const HEAD = handler;\nexport const OPTIONS = handler;/,
+ `${NORMALIZE_REQUEST_CONVERTER}
+const createHandler = (method) => async ({ request, params, platform }) => {
+ const normalRequest = await normalizeRequestConverter(request);
+ const response = await handler(normalRequest, params.token);
+ return response;
+};
+
+export const GET = createHandler('GET');
+export const POST = createHandler('POST');
+export const PUT = createHandler('PUT');
+export const PATCH = createHandler('PATCH');
+export const DELETE = createHandler('DELETE');
+export const HEAD = createHandler('HEAD');
+export const OPTIONS = createHandler('OPTIONS');
+
+export const prerender = false;`
+ );
+
+ await writeFile(webhookRouteFile, webhookRouteContent);
+ }
+}
+
+export class VercelBuilder extends VercelBuildOutputAPIBuilder {
+ constructor(config?: Partial) {
+ const workingDir = config?.workingDir || process.cwd();
+ super({
+ ...createBaseBuilderConfig({
+ workingDir,
+ dirs: ['src/pages', 'src/workflows'],
+ }),
+ buildTarget: 'vercel-build-output-api',
+ debugFilePrefix: '_',
+ });
+ }
+
+ override async build(): Promise {
+ const configPath = join(
+ this.config.workingDir,
+ '.vercel/output/config.json'
+ );
+
+ // The config output by astro
+ const config = JSON.parse(await readFile(configPath, 'utf-8'));
+
+ // Filter out existing workflow routes (wrong `dest` mapping)
+ config.routes = config.routes.filter(
+ (route: { src?: string; dest: string }) =>
+ !route.src?.includes('.well-known/workflow')
+ );
+
+ // Find the index right after the "filesystem" handler and "continue: true" routes
+ let insertIndex = config.routes.findIndex(
+ (route: any) => route.handle === 'filesystem'
+ );
+
+ // Move past any routes with "continue: true" (like _astro cache headers)
+ while (
+ insertIndex < config.routes.length - 1 &&
+ config.routes[insertIndex + 1]?.continue === true
+ ) {
+ insertIndex++;
+ }
+
+ // Insert workflow routes right after
+ config.routes.splice(insertIndex + 1, 0, ...WORKFLOW_ROUTES);
+
+ // Bundles workflows for vercel
+ await super.build();
+
+ // Use old astro config with updated routes
+ await writeFile(configPath, JSON.stringify(config, null, 2));
+ }
+}
diff --git a/packages/astro/src/index.ts b/packages/astro/src/index.ts
new file mode 100644
index 000000000..0aee8949f
--- /dev/null
+++ b/packages/astro/src/index.ts
@@ -0,0 +1 @@
+export { workflow } from './plugin.js';
diff --git a/packages/astro/src/plugin.ts b/packages/astro/src/plugin.ts
new file mode 100644
index 000000000..b96506ab8
--- /dev/null
+++ b/packages/astro/src/plugin.ts
@@ -0,0 +1,196 @@
+import { relative } from 'node:path';
+import { transform } from '@swc/core';
+import { resolveModulePath } from 'exsolve';
+import type { AstroIntegration, HookParameters } from 'astro';
+import { LocalBuilder, VercelBuilder } from './builder.js';
+
+export function workflow(): AstroIntegration {
+ const builder = new LocalBuilder();
+
+ return {
+ name: 'workflow:astro',
+ hooks: {
+ 'astro:config:setup': async ({
+ updateConfig,
+ }: HookParameters<'astro:config:setup'>) => {
+ // Use local builder
+ if (!process.env.VERCEL_DEPLOYMENT_ID) {
+ try {
+ await builder.build();
+ } catch (buildError) {
+ // Build might fail due to invalid workflow files or missing dependencies
+ // Log the error and rethrow to properly propagate to Astro
+ console.error('Build failed during config setup:', buildError);
+ throw buildError;
+ }
+ }
+ updateConfig({
+ vite: {
+ plugins: [
+ {
+ name: 'workflow:vite',
+
+ // TODO: Move this to @workflow/vite or something since this is vite specific
+ // Transform workflow files with SWC
+ async transform(code: string, id: string) {
+ // Only apply the transform if file needs it
+ if (!code.match(/(use step|use workflow)/)) {
+ return null;
+ }
+
+ const isTypeScript =
+ id.endsWith('.ts') || id.endsWith('.tsx');
+ const isTsx = id.endsWith('.tsx');
+
+ const swcPlugin = resolveModulePath('@workflow/swc-plugin', {
+ from: [import.meta.url],
+ });
+
+ // Calculate relative filename for SWC plugin
+ // The SWC plugin uses filename to generate workflowId, so it must be relative
+ const workingDir = process.cwd();
+ const normalizedWorkingDir = workingDir
+ .replace(/\\/g, '/')
+ .replace(/\/$/, '');
+ const normalizedFilepath = id.replace(/\\/g, '/');
+
+ // Windows fix: Use case-insensitive comparison to work around drive letter casing issues
+ const lowerWd = normalizedWorkingDir.toLowerCase();
+ const lowerPath = normalizedFilepath.toLowerCase();
+
+ let relativeFilename: string;
+ if (lowerPath.startsWith(lowerWd + '/')) {
+ // File is under working directory - manually calculate relative path
+ relativeFilename = normalizedFilepath.substring(
+ normalizedWorkingDir.length + 1
+ );
+ } else if (lowerPath === lowerWd) {
+ // File IS the working directory (shouldn't happen)
+ relativeFilename = '.';
+ } else {
+ // Use relative() for files outside working directory
+ relativeFilename = relative(workingDir, id).replace(
+ /\\/g,
+ '/'
+ );
+
+ if (relativeFilename.startsWith('../')) {
+ relativeFilename = relativeFilename
+ .split('/')
+ .filter((part) => part !== '..')
+ .join('/');
+ }
+ }
+
+ // Final safety check - ensure we never pass an absolute path to SWC
+ if (
+ relativeFilename.includes(':') ||
+ relativeFilename.startsWith('/')
+ ) {
+ // This should rarely happen, but use filename split as last resort
+ relativeFilename =
+ normalizedFilepath.split('/').pop() || 'unknown.ts';
+ }
+
+ // Transform with SWC
+ const result = await transform(code, {
+ filename: relativeFilename,
+ jsc: {
+ parser: {
+ syntax: isTypeScript ? 'typescript' : 'ecmascript',
+ tsx: isTsx,
+ },
+ target: 'es2022',
+ experimental: {
+ plugins: [[swcPlugin, { mode: 'client' }]],
+ },
+ },
+ minify: false,
+ sourceMaps: true,
+ inlineSourcesContent: true,
+ });
+
+ return {
+ code: result.code,
+ map: result.map ? JSON.parse(result.map) : null,
+ };
+ },
+
+ // TODO: Move this to @workflow/vite or something since this is vite specific
+ async hotUpdate(options) {
+ const { file, server, read } = options;
+
+ // Check if this is a TS/JS file that might contain workflow directives
+ const jsTsRegex = /\.(ts|tsx|js|jsx|mjs|cjs)$/;
+ if (!jsTsRegex.test(file)) {
+ return;
+ }
+
+ // Read the file to check for workflow/step directives
+ let content: string;
+ try {
+ content = await read();
+ } catch {
+ // File might have been deleted - trigger rebuild to update generated routes
+ console.log(
+ 'Workflow file deleted, regenerating routes...'
+ );
+ try {
+ await builder.build();
+ } catch (buildError) {
+ // Build might fail if files are being deleted during test cleanup
+ // Log but don't crash - the next successful change will trigger a rebuild
+ console.error(
+ 'Build failed during file deletion:',
+ buildError
+ );
+ }
+
+ server.ws.send({ type: 'full-reload', path: '*' });
+ return [];
+ }
+
+ const useWorkflowPattern = /^\s*(['"])use workflow\1;?\s*$/m;
+ const useStepPattern = /^\s*(['"])use step\1;?\s*$/m;
+
+ if (
+ !useWorkflowPattern.test(content) &&
+ !useStepPattern.test(content)
+ ) {
+ return;
+ }
+
+ // Rebuild everything - simpler and more reliable than tracking individual files
+ console.log('Workflow file changed, regenerating routes...');
+ try {
+ await builder.build();
+ } catch (buildError) {
+ // Build might fail if files are being modified/deleted during test cleanup
+ // Log but don't crash - the next successful change will trigger a rebuild
+ console.error('Build failed during HMR:', buildError);
+ return [];
+ }
+
+ // Trigger full reload of workflow routes
+ server.ws.send({
+ type: 'full-reload',
+ path: '*',
+ });
+
+ // Prevent Vite from processing this HMR update
+ return [];
+ },
+ },
+ ],
+ },
+ });
+ },
+ 'astro:build:done': async () => {
+ if (process.env.VERCEL_DEPLOYMENT_ID) {
+ const vercelBuilder = new VercelBuilder();
+ await vercelBuilder.build();
+ }
+ },
+ },
+ };
+}
diff --git a/packages/astro/tsconfig.json b/packages/astro/tsconfig.json
new file mode 100644
index 000000000..ba5d9aec0
--- /dev/null
+++ b/packages/astro/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "extends": "@workflow/tsconfig/base.json",
+ "compilerOptions": {
+ "outDir": "dist",
+ "target": "es2022",
+ "module": "preserve",
+ "baseUrl": ".",
+ "moduleResolution": "bundler"
+ },
+ "include": ["src"],
+ "exclude": ["node_modules", "**/*.test.ts"]
+}
diff --git a/packages/builders/src/base-builder.ts b/packages/builders/src/base-builder.ts
index 4319251d2..21d1c0000 100644
--- a/packages/builders/src/base-builder.ts
+++ b/packages/builders/src/base-builder.ts
@@ -1,5 +1,5 @@
import { mkdir, readFile, writeFile } from 'node:fs/promises';
-import { dirname, join, relative, resolve } from 'node:path';
+import { basename, dirname, join, relative, resolve } from 'node:path';
import { promisify } from 'node:util';
import chalk from 'chalk';
import { parse } from 'comment-json';
@@ -184,14 +184,17 @@ export abstract class BaseBuilder {
merge?: boolean
): Promise {
try {
+ const prefix = this.config.debugFilePrefix || '';
+ const debugFileName = `${dirname(outfile)}/${prefix}${basename(outfile)}.debug.json`;
+
let existing = {};
if (merge) {
existing = JSON.parse(
- await readFile(`${outfile}.debug.json`, 'utf8').catch(() => '{}')
+ await readFile(debugFileName, 'utf8').catch(() => '{}')
);
}
await writeFile(
- `${outfile}.debug.json`,
+ debugFileName,
JSON.stringify(
{
...existing,
diff --git a/packages/builders/src/index.ts b/packages/builders/src/index.ts
index 1301c5461..d949717b6 100644
--- a/packages/builders/src/index.ts
+++ b/packages/builders/src/index.ts
@@ -8,6 +8,7 @@ export { createNodeModuleErrorPlugin } from './node-module-esbuild-plugin.js';
export { StandaloneBuilder } from './standalone.js';
export { createSwcPlugin } from './swc-esbuild-plugin.js';
export type {
+ AstroConfig,
BuildTarget,
NextConfig,
StandaloneConfig,
@@ -15,8 +16,5 @@ export type {
VercelBuildOutputConfig,
WorkflowConfig,
} from './types.js';
-export {
- isValidBuildTarget,
- validBuildTargets,
-} from './types.js';
+export { isValidBuildTarget, validBuildTargets } from './types.js';
export { VercelBuildOutputAPIBuilder } from './vercel-build-output-api.js';
diff --git a/packages/builders/src/types.ts b/packages/builders/src/types.ts
index 5c514142f..87c0d5428 100644
--- a/packages/builders/src/types.ts
+++ b/packages/builders/src/types.ts
@@ -3,6 +3,7 @@ export const validBuildTargets = [
'vercel-build-output-api',
'next',
'sveltekit',
+ 'astro',
] as const;
export type BuildTarget = (typeof validBuildTargets)[number];
@@ -22,6 +23,9 @@ interface BaseWorkflowConfig {
externalPackages?: string[];
workflowManifestPath?: string;
+
+ // Optional prefix for debug files (e.g., "_" for Astro to ignore them)
+ debugFilePrefix?: string;
}
/**
@@ -66,6 +70,17 @@ export interface SvelteKitConfig extends BaseWorkflowConfig {
webhookBundlePath: string;
}
+/**
+ * Configuration for Astro builds.
+ */
+export interface AstroConfig extends BaseWorkflowConfig {
+ buildTarget: 'astro';
+ // Astro builder computes paths dynamically, so these are not used
+ stepsBundlePath: string;
+ workflowsBundlePath: string;
+ webhookBundlePath: string;
+}
+
/**
* Discriminated union of all builder configuration types.
*/
@@ -73,7 +88,8 @@ export type WorkflowConfig =
| StandaloneConfig
| VercelBuildOutputConfig
| NextConfig
- | SvelteKitConfig;
+ | SvelteKitConfig
+ | AstroConfig;
export function isValidBuildTarget(
target: string | undefined
diff --git a/packages/core/e2e/e2e.test.ts b/packages/core/e2e/e2e.test.ts
index 27cfaeba3..0ac6e71dc 100644
--- a/packages/core/e2e/e2e.test.ts
+++ b/packages/core/e2e/e2e.test.ts
@@ -600,7 +600,8 @@ describe('e2e', () => {
// TODO: Investigate esbuild source map generation for bundled modules
const isViteBasedFrameworkDevMode =
(process.env.APP_NAME === 'sveltekit' ||
- process.env.APP_NAME === 'vite') &&
+ process.env.APP_NAME === 'vite' ||
+ process.env.APP_NAME === 'astro') &&
isLocalDeployment();
if (!isViteBasedFrameworkDevMode) {
diff --git a/packages/core/e2e/local-build.test.ts b/packages/core/e2e/local-build.test.ts
index 4daca2b01..b65b64e96 100644
--- a/packages/core/e2e/local-build.test.ts
+++ b/packages/core/e2e/local-build.test.ts
@@ -14,6 +14,7 @@ describe.each([
'nuxt',
'hono',
'express',
+ 'astro',
])('e2e', (project) => {
test('builds without errors', { timeout: 180_000 }, async () => {
// skip if we're targeting specific app to test
diff --git a/packages/workflow/package.json b/packages/workflow/package.json
index 2b4fa5c9c..db3957002 100644
--- a/packages/workflow/package.json
+++ b/packages/workflow/package.json
@@ -41,6 +41,7 @@
"./nitro": "./dist/nitro.js",
"./nuxt": "./dist/nuxt.js",
"./sveltekit": "./dist/sveltekit.js",
+ "./astro": "./dist/astro.js",
"./rollup": "./dist/rollup.js",
"./vite": "./dist/vite.js",
"./runtime": "./dist/runtime.js"
@@ -53,6 +54,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
+ "@workflow/astro": "workspace:*",
"@workflow/cli": "workspace:*",
"@workflow/core": "workspace:*",
"@workflow/errors": "workspace:*",
diff --git a/packages/workflow/src/astro.ts b/packages/workflow/src/astro.ts
new file mode 100644
index 000000000..7caf16677
--- /dev/null
+++ b/packages/workflow/src/astro.ts
@@ -0,0 +1 @@
+export * from '@workflow/astro';
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 78e318255..4f48126c1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -45,6 +45,7 @@ catalogs:
overrides:
rfc6902: 5.1.2
+ path-to-regexp: 6.3.0
importers:
@@ -314,6 +315,34 @@ importers:
specifier: workspace:*
version: link:../workflow
+ packages/astro:
+ dependencies:
+ '@swc/core':
+ specifier: 1.11.24
+ version: 1.11.24
+ '@workflow/builders':
+ specifier: workspace:*
+ version: link:../builders
+ '@workflow/swc-plugin':
+ specifier: workspace:*
+ version: link:../swc-plugin-workflow
+ exsolve:
+ specifier: ^1.0.7
+ version: 1.0.7
+ pathe:
+ specifier: ^2.0.3
+ version: 2.0.3
+ devDependencies:
+ '@types/node':
+ specifier: 'catalog:'
+ version: 22.19.0
+ '@workflow/tsconfig':
+ specifier: workspace:*
+ version: link:../tsconfig
+ astro:
+ specifier: 5.16.0
+ version: 5.16.0(@netlify/blobs@9.1.2)(@types/node@22.19.0)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.1)(rollup@4.53.2)(terser@5.44.0)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1)
+
packages/builders:
dependencies:
'@swc/core':
@@ -875,6 +904,9 @@ importers:
'@opentelemetry/api':
specifier: '1'
version: 1.9.0
+ '@workflow/astro':
+ specifier: workspace:*
+ version: link:../astro
'@workflow/cli':
specifier: workspace:*
version: link:../cli
@@ -1091,6 +1123,36 @@ importers:
specifier: 3.2.0
version: 3.2.0
+ workbench/astro:
+ dependencies:
+ '@astrojs/node':
+ specifier: 9.5.0
+ version: 9.5.0(astro@5.16.0(@netlify/blobs@9.1.2)(@types/node@24.6.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.1)(rollup@4.53.2)(terser@5.44.0)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))
+ '@astrojs/vercel':
+ specifier: ^9.0.0
+ version: 9.0.1(@aws-sdk/credential-provider-web-identity@3.844.0)(@sveltejs/kit@2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.1.12(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(svelte@5.43.3)(vite@7.1.12(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(astro@5.16.0(@netlify/blobs@9.1.2)(@types/node@24.6.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.1)(rollup@4.53.2)(terser@5.44.0)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(next@16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)(rollup@4.53.2)(svelte@5.43.3)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3))
+ '@workflow/world-postgres':
+ specifier: workspace:*
+ version: link:../../packages/world-postgres
+ ai:
+ specifier: 'catalog:'
+ version: 5.0.76(zod@4.1.11)
+ astro:
+ specifier: ^5.15.6
+ version: 5.16.0(@netlify/blobs@9.1.2)(@types/node@24.6.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.1)(rollup@4.53.2)(terser@5.44.0)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1)
+ lodash.chunk:
+ specifier: ^4.2.0
+ version: 4.2.0
+ openai:
+ specifier: 6.9.0
+ version: 6.9.0(ws@8.18.3)(zod@4.1.11)
+ workflow:
+ specifier: workspace:*
+ version: link:../../packages/workflow
+ zod:
+ specifier: 'catalog:'
+ version: 4.1.11
+
workbench/example:
dependencies:
'@vercel/functions':
@@ -1598,6 +1660,36 @@ packages:
'@antfu/utils@9.3.0':
resolution: {integrity: sha512-9hFT4RauhcUzqOE4f1+frMKLZrgNog5b06I7VmZQV1BkvwvqrbC8EBZf3L1eEL2AKb6rNKjER0sEvJiSP1FXEA==}
+ '@astrojs/compiler@2.13.0':
+ resolution: {integrity: sha512-mqVORhUJViA28fwHYaWmsXSzLO9osbdZ5ImUfxBarqsYdMlPbqAqGJCxsNzvppp1BEzc1mJNjOVvQqeDN8Vspw==}
+
+ '@astrojs/internal-helpers@0.7.4':
+ resolution: {integrity: sha512-lDA9MqE8WGi7T/t2BMi+EAXhs4Vcvr94Gqx3q15cFEz8oFZMO4/SFBqYr/UcmNlvW+35alowkVj+w9VhLvs5Cw==}
+
+ '@astrojs/internal-helpers@0.7.5':
+ resolution: {integrity: sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA==}
+
+ '@astrojs/markdown-remark@6.3.9':
+ resolution: {integrity: sha512-hX2cLC/KW74Io1zIbn92kI482j9J7LleBLGCVU9EP3BeH5MVrnFawOnqD0t/q6D1Z+ZNeQG2gNKMslCcO36wng==}
+
+ '@astrojs/node@9.5.0':
+ resolution: {integrity: sha512-x1whLIatmCefaqJA8FjfI+P6FStF+bqmmrib0OUGM1M3cZhAXKLgPx6UF2AzQ3JgpXgCWYM24MHtraPvZhhyLQ==}
+ peerDependencies:
+ astro: ^5.14.3
+
+ '@astrojs/prism@3.3.0':
+ resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==}
+ engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
+
+ '@astrojs/telemetry@3.3.0':
+ resolution: {integrity: sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==}
+ engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
+
+ '@astrojs/vercel@9.0.1':
+ resolution: {integrity: sha512-wdDcRygD7hnFy4c+5ynCZ43lsSXaAeTr7d3A2VedDf/vNrSmT6ZNIECUHzbizrraTqKk8eFC9RQf5aKouSdirw==}
+ peerDependencies:
+ astro: ^5.0.0
+
'@aws-crypto/sha256-browser@5.2.0':
resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==}
@@ -1909,6 +2001,10 @@ packages:
'@braintree/sanitize-url@7.1.1':
resolution: {integrity: sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==}
+ '@capsizecss/unpack@3.0.1':
+ resolution: {integrity: sha512-8XqW8xGn++Eqqbz3e9wKuK7mxryeRjs4LOHLxbh2lwKeSbuNR4NFifDZT4KzvjU6HMOPbiNTsWpniK5EJfTWkg==}
+ engines: {node: '>=18'}
+
'@cbor-extract/cbor-extract-darwin-arm64@2.2.0':
resolution: {integrity: sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==}
cpu: [arm64]
@@ -3515,6 +3611,9 @@ packages:
resolution: {integrity: sha512-scSmQBD8eANlMUOglxHrN1JdSW8tDghsPuS83otqealBiIeMukCQMOf/wc0JJjDXomqwNdEQFLXLGHrU6PGxuA==}
engines: {node: '>= 20.0.0'}
+ '@oslojs/encoding@1.1.0':
+ resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
+
'@oven/bun-darwin-aarch64@1.3.0':
resolution: {integrity: sha512-WeXSaL29ylJEZMYHHW28QZ6rgAbxQ1KuNSZD9gvd3fPlo0s6s2PglvPArjjP07nmvIK9m4OffN0k4M98O7WmAg==}
cpu: [arm64]
@@ -6133,6 +6232,9 @@ packages:
'@types/express@5.0.5':
resolution: {integrity: sha512-LuIQOcb6UmnF7C1PCFmEU1u2hmiHL43fgFQX67sN3H4Z+0Yk0Neo++mFsBjhOAuLzvlQeqAAkeDOZrJs9rzumQ==}
+ '@types/fontkit@2.0.8':
+ resolution: {integrity: sha512-wN+8bYxIpJf+5oZdrdtaX04qUuWHcKxcDEgRS9Qm9ZClSHjzEn13SxUC+5eRM+4yXIeTYk8mTzLAWGF64847ew==}
+
'@types/fs-extra@11.0.4':
resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==}
@@ -6181,6 +6283,9 @@ packages:
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+ '@types/nlcst@2.0.3':
+ resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==}
+
'@types/node@12.20.55':
resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
@@ -6334,6 +6439,15 @@ packages:
'@opentelemetry/api':
optional: true
+ '@vercel/functions@2.2.13':
+ resolution: {integrity: sha512-14ArBSIIcOBx9nrEgaJb4Bw+en1gl6eSoJWh8qjifLl5G3E4dRXCFOT8HP+w66vb9Wqyd1lAQBrmRhRwOj9X9A==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ '@aws-sdk/credential-provider-web-identity': '*'
+ peerDependenciesMeta:
+ '@aws-sdk/credential-provider-web-identity':
+ optional: true
+
'@vercel/functions@3.1.4':
resolution: {integrity: sha512-1dEfZkb7qxsA+ilo+1uBUCEgr7e90vHcimpDYkUB84DM051wQ5amJDk9x+cnaI29paZb5XukXwGl8yk3Udb/DQ==}
engines: {node: '>= 20'}
@@ -6353,6 +6467,10 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ '@vercel/oidc@2.0.2':
+ resolution: {integrity: sha512-59PBFx3T+k5hLTEWa3ggiMpGRz1OVvl9eN8SUai+A43IsqiOuAe7qPBf+cray/Fj6mkgnxm/D7IAtjc8zSHi7g==}
+ engines: {node: '>= 18'}
+
'@vercel/oidc@3.0.3':
resolution: {integrity: sha512-yNEQvPcVrK9sIe637+I0jD6leluPxzwJKx/Haw6F4H77CdDsszUn5V3o96LPziXkSNE2B83+Z3mjqGKBK/R6Gg==}
engines: {node: '>= 20'}
@@ -6378,6 +6496,9 @@ packages:
engines: {node: '>=20.0.0'}
hasBin: true
+ '@vercel/routing-utils@5.3.0':
+ resolution: {integrity: sha512-gKsPSGc/hBMSHiAXTjTcbSa9egy7wCogrLctx8bJUS21w2OppWzrd5ZqUMqvnrfdKzLMpGIJ2bZMxBQ9xjGkaA==}
+
'@vercel/speed-insights@1.2.0':
resolution: {integrity: sha512-y9GVzrUJ2xmgtQlzFP2KhVRoCglwfRQgjyfY607aU0hh0Un6d0OUyrJkjuAlsV18qR4zfoFPs/BiIj9YDS6Wzw==}
peerDependencies:
@@ -6675,6 +6796,9 @@ packages:
resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
engines: {node: '>= 0.4'}
+ array-iterate@2.0.1:
+ resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==}
+
array-timsort@1.0.3:
resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==}
@@ -6708,6 +6832,11 @@ packages:
resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
hasBin: true
+ astro@5.16.0:
+ resolution: {integrity: sha512-GaDRs2Mngpw3dr2vc085GnORh98NiXxwIjg/EoQQQl/icZt3Z7s0BRsYHDZ8swkZbOA6wZsqWJdrNirl+iKcDg==}
+ engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'}
+ hasBin: true
+
async-lock@1.4.1:
resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==}
@@ -6780,6 +6909,9 @@ packages:
bare-url@2.3.0:
resolution: {integrity: sha512-c+RCqMSZbkz97Mw1LWR0gcOqwK82oyYKfLoHJ8k13ybi1+I80ffdDzUy0TdAburdrR/kI0/VuN8YgEnJqX+Nyw==}
+ base-64@1.0.0:
+ resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==}
+
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
@@ -6845,6 +6977,9 @@ packages:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
+ brotli@1.3.3:
+ resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==}
+
browserslist@4.27.0:
resolution: {integrity: sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
@@ -7008,6 +7143,10 @@ packages:
resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
engines: {node: '>=8'}
+ ci-info@4.3.1:
+ resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==}
+ engines: {node: '>=8'}
+
citty@0.1.6:
resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
@@ -7056,6 +7195,10 @@ packages:
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
engines: {node: '>=0.8'}
+ clone@2.1.2:
+ resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==}
+ engines: {node: '>=0.8'}
+
cloudflare-video-element@1.3.4:
resolution: {integrity: sha512-F9g+tXzGEXI6v6L48qXxr8vnR8+L6yy7IhpJxK++lpzuVekMHTixxH7/dzLuq6OacVGziU4RB5pzZYJ7/LYtJg==}
@@ -7145,6 +7288,9 @@ packages:
resolution: {integrity: sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==}
engines: {node: '>= 6'}
+ common-ancestor-path@1.0.1:
+ resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==}
+
common-path-prefix@3.0.0:
resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==}
@@ -7666,6 +7812,10 @@ packages:
peerDependencies:
typescript: ^5.4.4
+ deterministic-object-hash@2.0.2:
+ resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==}
+ engines: {node: '>=18'}
+
devalue@5.5.0:
resolution: {integrity: sha512-69sM5yrHfFLJt0AZ9QqZXGCPfJ7fQjvpln3Rq5+PS03LD32Ost1Q9N+eEnaQwGRIriKkMImXD56ocjQmfjbV3w==}
@@ -7682,6 +7832,13 @@ packages:
dexie@4.2.1:
resolution: {integrity: sha512-Ckej0NS6jxQ4Po3OrSQBFddayRhTCic2DoCAG5zacOfOVB9P2Q5Xc5uL/nVa7ZVs+HdMnvUPzLFCB/JwpB6Csg==}
+ dfa@1.2.0:
+ resolution: {integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==}
+
+ diff@5.2.0:
+ resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==}
+ engines: {node: '>=0.3.1'}
+
diff@8.0.2:
resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==}
engines: {node: '>=0.3.1'}
@@ -7690,6 +7847,9 @@ packages:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
+ dlv@1.1.3:
+ resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+
docker-compose@1.3.0:
resolution: {integrity: sha512-7Gevk/5eGD50+eMD+XDnFnOrruFkL0kSd7jEG4cjmqweDSUhB7i0g8is/nBdVpl+Bx338SqIB2GLKm32M+Vs6g==}
engines: {node: '>= 6.0.0'}
@@ -7837,6 +7997,10 @@ packages:
sqlite3:
optional: true
+ dset@3.1.4:
+ resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
+ engines: {node: '>=4'}
+
dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
@@ -8258,9 +8422,19 @@ packages:
flatted@3.3.3:
resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
+ flattie@1.1.1:
+ resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==}
+ engines: {node: '>=8'}
+
fn.name@1.1.0:
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
+ fontace@0.3.1:
+ resolution: {integrity: sha512-9f5g4feWT1jWT8+SbL85aLIRLIXUaDygaM2xPXRmzPYxrOMNok79Lr3FGJoKVNKibE0WCunNiEVG2mwuE+2qEg==}
+
+ fontkit@2.0.4:
+ resolution: {integrity: sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==}
+
foreground-child@3.3.1:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
@@ -8682,12 +8856,18 @@ packages:
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+ html-escaper@3.0.3:
+ resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}
+
html-url-attributes@3.0.1:
resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+ http-cache-semantics@4.2.0:
+ resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
+
http-errors@2.0.0:
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
engines: {node: '>= 0.8'}
@@ -8761,6 +8941,9 @@ packages:
import-in-the-middle@1.15.0:
resolution: {integrity: sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==}
+ import-meta-resolve@4.2.0:
+ resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==}
+
impound@1.0.0:
resolution: {integrity: sha512-8lAJ+1Arw2sMaZ9HE2ZmL5zOcMnt18s6+7Xqgq2aUVy4P1nlzAyPtzCDxsk51KVFwHEEdc6OWvUyqwHwhRYaug==}
@@ -9046,6 +9229,10 @@ packages:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
hasBin: true
+ js-yaml@4.1.1:
+ resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
+ hasBin: true
+
jsesc@3.1.0:
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
engines: {node: '>=6'}
@@ -9361,6 +9548,9 @@ packages:
magicast@0.3.5:
resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
+ magicast@0.5.1:
+ resolution: {integrity: sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==}
+
make-dir@4.0.0:
resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
engines: {node: '>=10'}
@@ -9381,6 +9571,9 @@ packages:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
+ mdast-util-definitions@6.0.0:
+ resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==}
+
mdast-util-find-and-replace@3.0.2:
resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
@@ -9772,6 +9965,10 @@ packages:
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
engines: {node: '>= 0.6'}
+ neotraverse@0.6.18:
+ resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==}
+ engines: {node: '>= 10'}
+
netlify@13.3.5:
resolution: {integrity: sha512-Nc3loyVASW59W+8fLDZT1lncpG7llffyZ2o0UQLx/Fr20i7P8oP+lE7+TEcFvXj9IUWU6LjB9P3BH+iFGyp+mg==}
engines: {node: ^14.16.0 || >=16.0.0}
@@ -9890,6 +10087,9 @@ packages:
xml2js:
optional: true
+ nlcst-to-string@4.0.0:
+ resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==}
+
node-abi@3.78.0:
resolution: {integrity: sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ==}
engines: {node: '>=10'}
@@ -10095,6 +10295,18 @@ packages:
zod:
optional: true
+ openai@6.9.0:
+ resolution: {integrity: sha512-n2sJRYmM+xfJ0l3OfH8eNnIyv3nQY7L08gZQu3dw6wSdfPtKAk92L83M2NIP5SS8Cl/bsBBG3yKzEOjkx0O+7A==}
+ hasBin: true
+ peerDependencies:
+ ws: ^8.18.0
+ zod: ^3.25 || ^4.0
+ peerDependenciesMeta:
+ ws:
+ optional: true
+ zod:
+ optional: true
+
optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
@@ -10176,6 +10388,10 @@ packages:
resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ p-limit@6.2.0:
+ resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==}
+ engines: {node: '>=18'}
+
p-locate@4.1.0:
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
engines: {node: '>=8'}
@@ -10196,6 +10412,10 @@ packages:
resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==}
engines: {node: '>=18'}
+ p-queue@8.1.1:
+ resolution: {integrity: sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==}
+ engines: {node: '>=18'}
+
p-timeout@6.1.4:
resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==}
engines: {node: '>=14.16'}
@@ -10217,6 +10437,9 @@ packages:
package-manager-detector@1.5.0:
resolution: {integrity: sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw==}
+ pako@0.2.9:
+ resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
+
parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
@@ -10239,6 +10462,9 @@ packages:
resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==}
engines: {node: '>=18'}
+ parse-latin@7.0.0:
+ resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==}
+
parse-ms@4.0.0:
resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
engines: {node: '>=18'}
@@ -10290,8 +10516,8 @@ packages:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'}
- path-to-regexp@8.3.0:
- resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==}
+ path-to-regexp@6.3.0:
+ resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
@@ -10358,6 +10584,9 @@ packages:
pgpass@1.0.5:
resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
+ piccolore@0.1.3:
+ resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==}
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -10633,6 +10862,10 @@ packages:
resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==}
engines: {node: '>=18'}
+ prismjs@1.30.0:
+ resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
+ engines: {node: '>=6'}
+
process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
@@ -10921,12 +11154,21 @@ packages:
rehype-katex@7.0.1:
resolution: {integrity: sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==}
+ rehype-parse@9.0.1:
+ resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==}
+
rehype-raw@7.0.0:
resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==}
rehype-recma@1.0.0:
resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==}
+ rehype-stringify@10.0.1:
+ resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==}
+
+ rehype@13.0.2:
+ resolution: {integrity: sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==}
+
remark-gfm@4.0.1:
resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
@@ -10942,6 +11184,10 @@ packages:
remark-rehype@11.1.2:
resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
+ remark-smartypants@3.0.2:
+ resolution: {integrity: sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==}
+ engines: {node: '>=16.0.0'}
+
remark-stringify@11.0.0:
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
@@ -10990,6 +11236,21 @@ packages:
resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==}
engines: {node: '>=18'}
+ restructure@3.0.2:
+ resolution: {integrity: sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==}
+
+ retext-latin@4.0.0:
+ resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==}
+
+ retext-smartypants@6.2.0:
+ resolution: {integrity: sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==}
+
+ retext-stringify@4.0.0:
+ resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==}
+
+ retext@9.0.0:
+ resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==}
+
retry@0.12.0:
resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
engines: {node: '>= 4'}
@@ -11123,6 +11384,9 @@ packages:
resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==}
engines: {node: '>= 18'}
+ server-destroy@1.0.1:
+ resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==}
+
set-cookie-parser@2.7.2:
resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
@@ -11215,6 +11479,10 @@ packages:
smob@1.5.0:
resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==}
+ smol-toml@1.5.2:
+ resolution: {integrity: sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ==}
+ engines: {node: '>= 18'}
+
sonner@2.0.7:
resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==}
peerDependencies:
@@ -11537,6 +11805,9 @@ packages:
tiktok-video-element@0.1.1:
resolution: {integrity: sha512-BaiVzvNz2UXDKTdSrXzrNf4q6Ecc+/utYUh7zdEu2jzYcJVDoqYbVfUl0bCfMoOeeAqg28vD/yN63Y3E9jOrlA==}
+ tiny-inflate@1.0.3:
+ resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
+
tiny-invariant@1.3.3:
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
@@ -11783,6 +12054,12 @@ packages:
unhead@2.0.19:
resolution: {integrity: sha512-gEEjkV11Aj+rBnY6wnRfsFtF2RxKOLaPN4i+Gx3UhBxnszvV6ApSNZbGk7WKyy/lErQ6ekPN63qdFL7sa1leow==}
+ unicode-properties@1.4.1:
+ resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==}
+
+ unicode-trie@2.0.0:
+ resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==}
+
unicorn-magic@0.1.0:
resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==}
engines: {node: '>=18'}
@@ -11794,6 +12071,9 @@ packages:
unified@11.0.5:
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
+ unifont@0.6.0:
+ resolution: {integrity: sha512-5Fx50fFQMQL5aeHyWnZX9122sSLckcDvcfFiBf3QYeHa7a1MKJooUy52b67moi2MJYkrfo/TWY+CoLdr/w0tTA==}
+
unimport@5.5.0:
resolution: {integrity: sha512-/JpWMG9s1nBSlXJAQ8EREFTFy3oy6USFd8T6AoBaw1q2GGcF4R9yp3ofg32UODZlYEO5VD0EWE1RpI9XDWyPYg==}
engines: {node: '>=18.12.0'}
@@ -11804,6 +12084,9 @@ packages:
unist-util-is@6.0.0:
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
+ unist-util-modify-children@4.0.0:
+ resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==}
+
unist-util-position-from-estree@2.0.0:
resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==}
@@ -11816,9 +12099,15 @@ packages:
unist-util-stringify-position@4.0.0:
resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+ unist-util-visit-children@3.0.0:
+ resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==}
+
unist-util-visit-parents@6.0.1:
resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
+ unist-util-visit-parents@6.0.2:
+ resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
+
unist-util-visit@5.0.0:
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
@@ -11936,6 +12225,68 @@ packages:
uploadthing:
optional: true
+ unstorage@1.17.3:
+ resolution: {integrity: sha512-i+JYyy0DoKmQ3FximTHbGadmIYb8JEpq7lxUjnjeB702bCPum0vzo6oy5Mfu0lpqISw7hCyMW2yj4nWC8bqJ3Q==}
+ peerDependencies:
+ '@azure/app-configuration': ^1.8.0
+ '@azure/cosmos': ^4.2.0
+ '@azure/data-tables': ^13.3.0
+ '@azure/identity': ^4.6.0
+ '@azure/keyvault-secrets': ^4.9.0
+ '@azure/storage-blob': ^12.26.0
+ '@capacitor/preferences': ^6.0.3 || ^7.0.0
+ '@deno/kv': '>=0.9.0'
+ '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0
+ '@planetscale/database': ^1.19.0
+ '@upstash/redis': ^1.34.3
+ '@vercel/blob': '>=0.27.1'
+ '@vercel/functions': ^2.2.12 || ^3.0.0
+ '@vercel/kv': ^1.0.1
+ aws4fetch: ^1.0.20
+ db0: '>=0.2.1'
+ idb-keyval: ^6.2.1
+ ioredis: ^5.4.2
+ uploadthing: ^7.4.4
+ peerDependenciesMeta:
+ '@azure/app-configuration':
+ optional: true
+ '@azure/cosmos':
+ optional: true
+ '@azure/data-tables':
+ optional: true
+ '@azure/identity':
+ optional: true
+ '@azure/keyvault-secrets':
+ optional: true
+ '@azure/storage-blob':
+ optional: true
+ '@capacitor/preferences':
+ optional: true
+ '@deno/kv':
+ optional: true
+ '@netlify/blobs':
+ optional: true
+ '@planetscale/database':
+ optional: true
+ '@upstash/redis':
+ optional: true
+ '@vercel/blob':
+ optional: true
+ '@vercel/functions':
+ optional: true
+ '@vercel/kv':
+ optional: true
+ aws4fetch:
+ optional: true
+ db0:
+ optional: true
+ idb-keyval:
+ optional: true
+ ioredis:
+ optional: true
+ uploadthing:
+ optional: true
+
unstorage@2.0.0-alpha.4:
resolution: {integrity: sha512-ywXZMZRfrvmO1giJeMTCw6VUn0ALYxVl8pFqJPStiyQUvgJImejtAHrKvXPj4QGJAoS/iLGcVGF6ljN/lkh1bw==}
peerDependencies:
@@ -12215,6 +12566,46 @@ packages:
vite: ^6.0.0 || ^7.0.0
vue: ^3.5.0
+ vite@6.4.1:
+ resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ jiti: '>=1.21.0'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
vite@7.1.11:
resolution: {integrity: sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -12408,6 +12799,10 @@ packages:
whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+ which-pm-runs@1.1.0:
+ resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==}
+ engines: {node: '>=4'}
+
which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
@@ -12500,6 +12895,9 @@ packages:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
+ xxhash-wasm@1.1.0:
+ resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==}
+
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
@@ -12540,6 +12938,10 @@ packages:
resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==}
engines: {node: '>=12.20'}
+ yocto-spinner@0.2.3:
+ resolution: {integrity: sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==}
+ engines: {node: '>=18.19'}
+
yoctocolors@2.1.2:
resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==}
engines: {node: '>=18'}
@@ -12564,6 +12966,17 @@ packages:
resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==}
engines: {node: '>= 14'}
+ zod-to-json-schema@3.25.0:
+ resolution: {integrity: sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==}
+ peerDependencies:
+ zod: ^3.25 || ^4
+
+ zod-to-ts@1.2.0:
+ resolution: {integrity: sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==}
+ peerDependencies:
+ typescript: ^4.9.4 || ^5.0.2
+ zod: ^3
+
zod@3.25.76:
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
@@ -12630,23 +13043,103 @@ snapshots:
'@antfu/utils@9.3.0': {}
- '@aws-crypto/sha256-browser@5.2.0':
- dependencies:
- '@aws-crypto/sha256-js': 5.2.0
- '@aws-crypto/supports-web-crypto': 5.2.0
- '@aws-crypto/util': 5.2.0
- '@aws-sdk/types': 3.840.0
- '@aws-sdk/util-locate-window': 3.893.0
- '@smithy/util-utf8': 2.3.0
- tslib: 2.8.1
+ '@astrojs/compiler@2.13.0': {}
- '@aws-crypto/sha256-js@5.2.0':
- dependencies:
- '@aws-crypto/util': 5.2.0
- '@aws-sdk/types': 3.840.0
- tslib: 2.8.1
+ '@astrojs/internal-helpers@0.7.4': {}
- '@aws-crypto/supports-web-crypto@5.2.0':
+ '@astrojs/internal-helpers@0.7.5': {}
+
+ '@astrojs/markdown-remark@6.3.9':
+ dependencies:
+ '@astrojs/internal-helpers': 0.7.5
+ '@astrojs/prism': 3.3.0
+ github-slugger: 2.0.0
+ hast-util-from-html: 2.0.3
+ hast-util-to-text: 4.0.2
+ import-meta-resolve: 4.2.0
+ js-yaml: 4.1.1
+ mdast-util-definitions: 6.0.0
+ rehype-raw: 7.0.0
+ rehype-stringify: 10.0.1
+ remark-gfm: 4.0.1
+ remark-parse: 11.0.0
+ remark-rehype: 11.1.2
+ remark-smartypants: 3.0.2
+ shiki: 3.13.0
+ smol-toml: 1.5.2
+ unified: 11.0.5
+ unist-util-remove-position: 5.0.0
+ unist-util-visit: 5.0.0
+ unist-util-visit-parents: 6.0.2
+ vfile: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@astrojs/node@9.5.0(astro@5.16.0(@netlify/blobs@9.1.2)(@types/node@24.6.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.1)(rollup@4.53.2)(terser@5.44.0)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))':
+ dependencies:
+ '@astrojs/internal-helpers': 0.7.4
+ astro: 5.16.0(@netlify/blobs@9.1.2)(@types/node@24.6.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.1)(rollup@4.53.2)(terser@5.44.0)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1)
+ send: 1.2.0
+ server-destroy: 1.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@astrojs/prism@3.3.0':
+ dependencies:
+ prismjs: 1.30.0
+
+ '@astrojs/telemetry@3.3.0':
+ dependencies:
+ ci-info: 4.3.1
+ debug: 4.4.3(supports-color@8.1.1)
+ dlv: 1.1.3
+ dset: 3.1.4
+ is-docker: 3.0.0
+ is-wsl: 3.1.0
+ which-pm-runs: 1.1.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@astrojs/vercel@9.0.1(@aws-sdk/credential-provider-web-identity@3.844.0)(@sveltejs/kit@2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.1.12(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(svelte@5.43.3)(vite@7.1.12(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(astro@5.16.0(@netlify/blobs@9.1.2)(@types/node@24.6.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.1)(rollup@4.53.2)(terser@5.44.0)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(next@16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)(rollup@4.53.2)(svelte@5.43.3)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3))':
+ dependencies:
+ '@astrojs/internal-helpers': 0.7.5
+ '@vercel/analytics': 1.5.0(@sveltejs/kit@2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.1.12(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(svelte@5.43.3)(vite@7.1.12(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(next@16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)(svelte@5.43.3)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3))
+ '@vercel/functions': 2.2.13(@aws-sdk/credential-provider-web-identity@3.844.0)
+ '@vercel/nft': 0.30.3(rollup@4.53.2)
+ '@vercel/routing-utils': 5.3.0
+ astro: 5.16.0(@netlify/blobs@9.1.2)(@types/node@24.6.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.1)(rollup@4.53.2)(terser@5.44.0)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1)
+ esbuild: 0.25.12
+ tinyglobby: 0.2.15
+ transitivePeerDependencies:
+ - '@aws-sdk/credential-provider-web-identity'
+ - '@remix-run/react'
+ - '@sveltejs/kit'
+ - encoding
+ - next
+ - react
+ - rollup
+ - supports-color
+ - svelte
+ - vue
+ - vue-router
+
+ '@aws-crypto/sha256-browser@5.2.0':
+ dependencies:
+ '@aws-crypto/sha256-js': 5.2.0
+ '@aws-crypto/supports-web-crypto': 5.2.0
+ '@aws-crypto/util': 5.2.0
+ '@aws-sdk/types': 3.840.0
+ '@aws-sdk/util-locate-window': 3.893.0
+ '@smithy/util-utf8': 2.3.0
+ tslib: 2.8.1
+
+ '@aws-crypto/sha256-js@5.2.0':
+ dependencies:
+ '@aws-crypto/util': 5.2.0
+ '@aws-sdk/types': 3.840.0
+ tslib: 2.8.1
+
+ '@aws-crypto/supports-web-crypto@5.2.0':
dependencies:
tslib: 2.8.1
@@ -13211,6 +13704,10 @@ snapshots:
'@braintree/sanitize-url@7.1.1': {}
+ '@capsizecss/unpack@3.0.1':
+ dependencies:
+ fontkit: 2.0.4
+
'@cbor-extract/cbor-extract-darwin-arm64@2.2.0':
optional: true
@@ -13770,7 +14267,7 @@ snapshots:
globals: 14.0.0
ignore: 5.3.2
import-fresh: 3.3.1
- js-yaml: 4.1.0
+ js-yaml: 4.1.1
minimatch: 3.1.2
strip-json-comments: 3.1.1
transitivePeerDependencies:
@@ -14744,7 +15241,7 @@ snapshots:
consola: 3.4.2
cssnano: 7.1.1(postcss@8.5.6)
defu: 6.1.4
- esbuild: 0.25.11
+ esbuild: 0.25.12
escape-string-regexp: 5.0.0
exsolve: 1.0.7
get-port-please: 3.2.0
@@ -15019,6 +15516,8 @@ snapshots:
'@orama/orama@3.1.16': {}
+ '@oslojs/encoding@1.1.0': {}
+
'@oven/bun-darwin-aarch64@1.3.0':
optional: true
@@ -17678,6 +18177,10 @@ snapshots:
'@types/express-serve-static-core': 5.1.0
'@types/serve-static': 1.15.10
+ '@types/fontkit@2.0.8':
+ dependencies:
+ '@types/node': 24.6.2
+
'@types/fs-extra@11.0.4':
dependencies:
'@types/jsonfile': 6.1.4
@@ -17726,6 +18229,10 @@ snapshots:
'@types/ms@2.1.0': {}
+ '@types/nlcst@2.0.3':
+ dependencies:
+ '@types/unist': 3.0.3
+
'@types/node@12.20.55': {}
'@types/node@18.19.130':
@@ -17866,6 +18373,15 @@ snapshots:
vue: 3.5.22(typescript@5.9.3)
vue-router: 4.6.3(vue@3.5.22(typescript@5.9.3))
+ '@vercel/analytics@1.5.0(@sveltejs/kit@2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.1.12(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(svelte@5.43.3)(vite@7.1.12(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(next@16.0.3(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)(svelte@5.43.3)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3))':
+ optionalDependencies:
+ '@sveltejs/kit': 2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.1.12(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(svelte@5.43.3)(vite@7.1.12(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ next: 16.0.3(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ react: 19.2.0
+ svelte: 5.43.3
+ vue: 3.5.22(typescript@5.9.3)
+ vue-router: 4.6.3(vue@3.5.22(typescript@5.9.3))
+
'@vercel/edge-config-fs@0.1.0': {}
'@vercel/edge-config@1.4.0(@opentelemetry/api@1.9.0)':
@@ -17874,6 +18390,12 @@ snapshots:
optionalDependencies:
'@opentelemetry/api': 1.9.0
+ '@vercel/functions@2.2.13(@aws-sdk/credential-provider-web-identity@3.844.0)':
+ dependencies:
+ '@vercel/oidc': 2.0.2
+ optionalDependencies:
+ '@aws-sdk/credential-provider-web-identity': 3.844.0
+
'@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.609.0(@aws-sdk/client-sts@3.844.0))':
dependencies:
'@vercel/oidc': 3.0.3
@@ -17924,6 +18446,11 @@ snapshots:
- rollup
- supports-color
+ '@vercel/oidc@2.0.2':
+ dependencies:
+ '@types/ms': 2.1.0
+ ms: 2.1.3
+
'@vercel/oidc@3.0.3': {}
'@vercel/oidc@3.0.5': {}
@@ -17943,6 +18470,13 @@ snapshots:
'@vercel/oidc': 3.0.5
mixpart: 0.0.5-alpha.1
+ '@vercel/routing-utils@5.3.0':
+ dependencies:
+ path-to-regexp: 6.3.0
+ path-to-regexp-updated: path-to-regexp@6.3.0
+ optionalDependencies:
+ ajv: 6.12.6
+
'@vercel/speed-insights@1.2.0(@sveltejs/kit@2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.1.12(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(svelte@5.43.3)(vite@7.1.12(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(next@16.0.3(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)(svelte@5.43.3)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3))':
optionalDependencies:
'@sveltejs/kit': 2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.1.12(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(svelte@5.43.3)(vite@7.1.12(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
@@ -18341,6 +18875,8 @@ snapshots:
aria-query@5.3.2: {}
+ array-iterate@2.0.1: {}
+
array-timsort@1.0.3: {}
array-union@2.1.0: {}
@@ -18371,6 +18907,210 @@ snapshots:
astring@1.9.0: {}
+ astro@5.16.0(@netlify/blobs@9.1.2)(@types/node@22.19.0)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.1)(rollup@4.53.2)(terser@5.44.0)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1):
+ dependencies:
+ '@astrojs/compiler': 2.13.0
+ '@astrojs/internal-helpers': 0.7.5
+ '@astrojs/markdown-remark': 6.3.9
+ '@astrojs/telemetry': 3.3.0
+ '@capsizecss/unpack': 3.0.1
+ '@oslojs/encoding': 1.1.0
+ '@rollup/pluginutils': 5.3.0(rollup@4.53.2)
+ acorn: 8.15.0
+ aria-query: 5.3.2
+ axobject-query: 4.1.0
+ boxen: 8.0.1
+ ci-info: 4.3.1
+ clsx: 2.1.1
+ common-ancestor-path: 1.0.1
+ cookie: 1.0.2
+ cssesc: 3.0.0
+ debug: 4.4.3(supports-color@8.1.1)
+ deterministic-object-hash: 2.0.2
+ devalue: 5.5.0
+ diff: 5.2.0
+ dlv: 1.1.3
+ dset: 3.1.4
+ es-module-lexer: 1.7.0
+ esbuild: 0.25.12
+ estree-walker: 3.0.3
+ flattie: 1.1.1
+ fontace: 0.3.1
+ github-slugger: 2.0.0
+ html-escaper: 3.0.3
+ http-cache-semantics: 4.2.0
+ import-meta-resolve: 4.2.0
+ js-yaml: 4.1.1
+ magic-string: 0.30.21
+ magicast: 0.5.1
+ mrmime: 2.0.1
+ neotraverse: 0.6.18
+ p-limit: 6.2.0
+ p-queue: 8.1.1
+ package-manager-detector: 1.5.0
+ piccolore: 0.1.3
+ picomatch: 4.0.3
+ prompts: 2.4.2
+ rehype: 13.0.2
+ semver: 7.7.3
+ shiki: 3.15.0
+ smol-toml: 1.5.2
+ svgo: 4.0.0
+ tinyexec: 1.0.2
+ tinyglobby: 0.2.15
+ tsconfck: 3.1.6(typescript@5.9.3)
+ ultrahtml: 1.6.0
+ unifont: 0.6.0
+ unist-util-visit: 5.0.0
+ unstorage: 1.17.3(@netlify/blobs@9.1.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)
+ vfile: 6.0.3
+ vite: 6.4.1(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vitefu: 1.1.1(vite@6.4.1(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ xxhash-wasm: 1.1.0
+ yargs-parser: 21.1.1
+ yocto-spinner: 0.2.3
+ zod: 3.25.76
+ zod-to-json-schema: 3.25.0(zod@3.25.76)
+ zod-to-ts: 1.2.0(typescript@5.9.3)(zod@3.25.76)
+ optionalDependencies:
+ sharp: 0.34.4
+ transitivePeerDependencies:
+ - '@azure/app-configuration'
+ - '@azure/cosmos'
+ - '@azure/data-tables'
+ - '@azure/identity'
+ - '@azure/keyvault-secrets'
+ - '@azure/storage-blob'
+ - '@capacitor/preferences'
+ - '@deno/kv'
+ - '@netlify/blobs'
+ - '@planetscale/database'
+ - '@types/node'
+ - '@upstash/redis'
+ - '@vercel/blob'
+ - '@vercel/functions'
+ - '@vercel/kv'
+ - aws4fetch
+ - db0
+ - idb-keyval
+ - ioredis
+ - jiti
+ - less
+ - lightningcss
+ - rollup
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - typescript
+ - uploadthing
+ - yaml
+
+ astro@5.16.0(@netlify/blobs@9.1.2)(@types/node@24.6.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.1)(rollup@4.53.2)(terser@5.44.0)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1):
+ dependencies:
+ '@astrojs/compiler': 2.13.0
+ '@astrojs/internal-helpers': 0.7.5
+ '@astrojs/markdown-remark': 6.3.9
+ '@astrojs/telemetry': 3.3.0
+ '@capsizecss/unpack': 3.0.1
+ '@oslojs/encoding': 1.1.0
+ '@rollup/pluginutils': 5.3.0(rollup@4.53.2)
+ acorn: 8.15.0
+ aria-query: 5.3.2
+ axobject-query: 4.1.0
+ boxen: 8.0.1
+ ci-info: 4.3.1
+ clsx: 2.1.1
+ common-ancestor-path: 1.0.1
+ cookie: 1.0.2
+ cssesc: 3.0.0
+ debug: 4.4.3(supports-color@8.1.1)
+ deterministic-object-hash: 2.0.2
+ devalue: 5.5.0
+ diff: 5.2.0
+ dlv: 1.1.3
+ dset: 3.1.4
+ es-module-lexer: 1.7.0
+ esbuild: 0.25.12
+ estree-walker: 3.0.3
+ flattie: 1.1.1
+ fontace: 0.3.1
+ github-slugger: 2.0.0
+ html-escaper: 3.0.3
+ http-cache-semantics: 4.2.0
+ import-meta-resolve: 4.2.0
+ js-yaml: 4.1.1
+ magic-string: 0.30.21
+ magicast: 0.5.1
+ mrmime: 2.0.1
+ neotraverse: 0.6.18
+ p-limit: 6.2.0
+ p-queue: 8.1.1
+ package-manager-detector: 1.5.0
+ piccolore: 0.1.3
+ picomatch: 4.0.3
+ prompts: 2.4.2
+ rehype: 13.0.2
+ semver: 7.7.3
+ shiki: 3.15.0
+ smol-toml: 1.5.2
+ svgo: 4.0.0
+ tinyexec: 1.0.2
+ tinyglobby: 0.2.15
+ tsconfck: 3.1.6(typescript@5.9.3)
+ ultrahtml: 1.6.0
+ unifont: 0.6.0
+ unist-util-visit: 5.0.0
+ unstorage: 1.17.3(@netlify/blobs@9.1.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)
+ vfile: 6.0.3
+ vite: 6.4.1(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+ vitefu: 1.1.1(vite@6.4.1(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))
+ xxhash-wasm: 1.1.0
+ yargs-parser: 21.1.1
+ yocto-spinner: 0.2.3
+ zod: 3.25.76
+ zod-to-json-schema: 3.25.0(zod@3.25.76)
+ zod-to-ts: 1.2.0(typescript@5.9.3)(zod@3.25.76)
+ optionalDependencies:
+ sharp: 0.34.4
+ transitivePeerDependencies:
+ - '@azure/app-configuration'
+ - '@azure/cosmos'
+ - '@azure/data-tables'
+ - '@azure/identity'
+ - '@azure/keyvault-secrets'
+ - '@azure/storage-blob'
+ - '@capacitor/preferences'
+ - '@deno/kv'
+ - '@netlify/blobs'
+ - '@planetscale/database'
+ - '@types/node'
+ - '@upstash/redis'
+ - '@vercel/blob'
+ - '@vercel/functions'
+ - '@vercel/kv'
+ - aws4fetch
+ - db0
+ - idb-keyval
+ - ioredis
+ - jiti
+ - less
+ - lightningcss
+ - rollup
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - typescript
+ - uploadthing
+ - yaml
+
async-lock@1.4.1: {}
async-sema@3.1.1: {}
@@ -18432,6 +19172,8 @@ snapshots:
bare-path: 3.0.0
optional: true
+ base-64@1.0.0: {}
+
base64-js@1.5.1: {}
baseline-browser-mapping@2.8.19: {}
@@ -18521,6 +19263,10 @@ snapshots:
dependencies:
fill-range: 7.1.1
+ brotli@1.3.3:
+ dependencies:
+ base64-js: 1.5.1
+
browserslist@4.27.0:
dependencies:
baseline-browser-mapping: 2.8.19
@@ -18697,6 +19443,8 @@ snapshots:
ci-info@3.9.0: {}
+ ci-info@4.3.1: {}
+
citty@0.1.6:
dependencies:
consola: 3.4.2
@@ -18748,6 +19496,8 @@ snapshots:
clone@1.0.4:
optional: true
+ clone@2.1.2: {}
+
cloudflare-video-element@1.3.4: {}
clsx@2.1.1: {}
@@ -18821,6 +19571,8 @@ snapshots:
has-own-prop: 2.0.0
repeat-string: 1.6.1
+ common-ancestor-path@1.0.1: {}
+
common-path-prefix@3.0.0: {}
commondir@1.0.1: {}
@@ -19352,6 +20104,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ deterministic-object-hash@2.0.2:
+ dependencies:
+ base-64: 1.0.0
+
devalue@5.5.0: {}
devlop@1.1.0:
@@ -19366,12 +20122,18 @@ snapshots:
dexie@4.2.1: {}
+ dfa@1.2.0: {}
+
+ diff@5.2.0: {}
+
diff@8.0.2: {}
dir-glob@3.0.1:
dependencies:
path-type: 4.0.0
+ dlv@1.1.3: {}
+
docker-compose@1.3.0:
dependencies:
yaml: 2.8.1
@@ -19454,6 +20216,8 @@ snapshots:
pg: 8.16.3
postgres: 3.4.7
+ dset@3.1.4: {}
+
dunder-proto@1.0.1:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -20045,8 +20809,27 @@ snapshots:
flatted@3.3.3:
optional: true
+ flattie@1.1.1: {}
+
fn.name@1.1.0: {}
+ fontace@0.3.1:
+ dependencies:
+ '@types/fontkit': 2.0.8
+ fontkit: 2.0.4
+
+ fontkit@2.0.4:
+ dependencies:
+ '@swc/helpers': 0.5.15
+ brotli: 1.3.3
+ clone: 2.1.2
+ dfa: 1.2.0
+ fast-deep-equal: 3.1.3
+ restructure: 3.0.2
+ tiny-inflate: 1.0.3
+ unicode-properties: 1.4.1
+ unicode-trie: 2.0.0
+
foreground-child@3.3.1:
dependencies:
cross-spawn: 7.0.6
@@ -20107,7 +20890,7 @@ snapshots:
image-size: 2.0.2
negotiator: 1.0.0
npm-to-yarn: 3.0.1
- path-to-regexp: 8.3.0
+ path-to-regexp: 6.3.0
remark: 15.0.1
remark-gfm: 4.0.1
remark-rehype: 11.1.2
@@ -20136,7 +20919,7 @@ snapshots:
image-size: 2.0.2
negotiator: 1.0.0
npm-to-yarn: 3.0.1
- path-to-regexp: 8.3.0
+ path-to-regexp: 6.3.0
remark: 15.0.1
remark-gfm: 4.0.1
remark-rehype: 11.1.2
@@ -20592,10 +21375,14 @@ snapshots:
html-escaper@2.0.2: {}
+ html-escaper@3.0.3: {}
+
html-url-attributes@3.0.1: {}
html-void-elements@3.0.0: {}
+ http-cache-semantics@4.2.0: {}
+
http-errors@2.0.0:
dependencies:
depd: 2.0.0
@@ -20659,6 +21446,8 @@ snapshots:
cjs-module-lexer: 1.4.3
module-details-from-path: 1.0.4
+ import-meta-resolve@4.2.0: {}
+
impound@1.0.0:
dependencies:
exsolve: 1.0.7
@@ -20889,6 +21678,10 @@ snapshots:
dependencies:
argparse: 2.0.1
+ js-yaml@4.1.1:
+ dependencies:
+ argparse: 2.0.1
+
jsesc@3.1.0: {}
json-buffer@3.0.1:
@@ -21207,6 +22000,12 @@ snapshots:
'@babel/types': 7.28.5
source-map-js: 1.2.1
+ magicast@0.5.1:
+ dependencies:
+ '@babel/parser': 7.28.5
+ '@babel/types': 7.28.5
+ source-map-js: 1.2.1
+
make-dir@4.0.0:
dependencies:
semver: 7.7.3
@@ -21219,6 +22018,12 @@ snapshots:
math-intrinsics@1.1.0: {}
+ mdast-util-definitions@6.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ unist-util-visit: 5.0.0
+
mdast-util-find-and-replace@3.0.2:
dependencies:
'@types/mdast': 4.0.4
@@ -21866,6 +22671,8 @@ snapshots:
negotiator@1.0.0: {}
+ neotraverse@0.6.18: {}
+
netlify@13.3.5:
dependencies:
'@netlify/open-api': 2.43.1
@@ -22296,6 +23103,10 @@ snapshots:
- supports-color
- uploadthing
+ nlcst-to-string@4.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+
node-abi@3.78.0:
dependencies:
semver: 7.7.3
@@ -22716,6 +23527,11 @@ snapshots:
ws: 8.18.3
zod: 4.1.11
+ openai@6.9.0(ws@8.18.3)(zod@4.1.11):
+ optionalDependencies:
+ ws: 8.18.3
+ zod: 4.1.11
+
optionator@0.9.4:
dependencies:
deep-is: 0.1.4
@@ -22924,6 +23740,10 @@ snapshots:
dependencies:
yocto-queue: 1.2.1
+ p-limit@6.2.0:
+ dependencies:
+ yocto-queue: 1.2.1
+
p-locate@4.1.0:
dependencies:
p-limit: 2.3.0
@@ -22941,6 +23761,11 @@ snapshots:
p-map@7.0.4: {}
+ p-queue@8.1.1:
+ dependencies:
+ eventemitter3: 5.0.1
+ p-timeout: 6.1.4
+
p-timeout@6.1.4: {}
p-try@2.2.0: {}
@@ -22957,6 +23782,8 @@ snapshots:
package-manager-detector@1.5.0: {}
+ pako@0.2.9: {}
+
parent-module@1.0.1:
dependencies:
callsites: 3.1.0
@@ -22990,6 +23817,15 @@ snapshots:
index-to-position: 1.2.0
type-fest: 4.41.0
+ parse-latin@7.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ '@types/unist': 3.0.3
+ nlcst-to-string: 4.0.0
+ unist-util-modify-children: 4.0.0
+ unist-util-visit-children: 3.0.0
+ vfile: 6.0.3
+
parse-ms@4.0.0: {}
parse-path@7.1.0:
@@ -23028,7 +23864,7 @@ snapshots:
lru-cache: 10.4.3
minipass: 7.1.2
- path-to-regexp@8.3.0: {}
+ path-to-regexp@6.3.0: {}
path-type@4.0.0: {}
@@ -23089,6 +23925,8 @@ snapshots:
dependencies:
split2: 4.2.0
+ piccolore@0.1.3: {}
+
picocolors@1.1.1: {}
picomatch@2.3.1: {}
@@ -23365,6 +24203,8 @@ snapshots:
dependencies:
parse-ms: 4.0.0
+ prismjs@1.30.0: {}
+
process-nextick-args@2.0.1: {}
process@0.11.10: {}
@@ -23825,6 +24665,12 @@ snapshots:
unist-util-visit-parents: 6.0.1
vfile: 6.0.3
+ rehype-parse@9.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-from-html: 2.0.3
+ unified: 11.0.5
+
rehype-raw@7.0.0:
dependencies:
'@types/hast': 3.0.4
@@ -23839,6 +24685,19 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ rehype-stringify@10.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-to-html: 9.0.5
+ unified: 11.0.5
+
+ rehype@13.0.2:
+ dependencies:
+ '@types/hast': 3.0.4
+ rehype-parse: 9.0.1
+ rehype-stringify: 10.0.1
+ unified: 11.0.5
+
remark-gfm@4.0.1:
dependencies:
'@types/mdast': 4.0.4
@@ -23883,6 +24742,13 @@ snapshots:
unified: 11.0.5
vfile: 6.0.3
+ remark-smartypants@3.0.2:
+ dependencies:
+ retext: 9.0.0
+ retext-smartypants: 6.2.0
+ unified: 11.0.5
+ unist-util-visit: 5.0.0
+
remark-stringify@11.0.0:
dependencies:
'@types/mdast': 4.0.4
@@ -23937,6 +24803,33 @@ snapshots:
onetime: 7.0.0
signal-exit: 4.1.0
+ restructure@3.0.2: {}
+
+ retext-latin@4.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ parse-latin: 7.0.0
+ unified: 11.0.5
+
+ retext-smartypants@6.2.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ nlcst-to-string: 4.0.0
+ unist-util-visit: 5.0.0
+
+ retext-stringify@4.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ nlcst-to-string: 4.0.0
+ unified: 11.0.5
+
+ retext@9.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ retext-latin: 4.0.0
+ retext-stringify: 4.0.0
+ unified: 11.0.5
+
retry@0.12.0: {}
reusify@1.1.0: {}
@@ -24005,7 +24898,7 @@ snapshots:
depd: 2.0.0
is-promise: 4.0.0
parseurl: 1.3.3
- path-to-regexp: 8.3.0
+ path-to-regexp: 6.3.0
transitivePeerDependencies:
- supports-color
@@ -24093,6 +24986,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ server-destroy@1.0.1: {}
+
set-cookie-parser@2.7.2: {}
setprototypeof@1.2.0: {}
@@ -24235,6 +25130,8 @@ snapshots:
smob@1.5.0: {}
+ smol-toml@1.5.2: {}
+
sonner@2.0.7(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
react: 19.1.0
@@ -24637,6 +25534,8 @@ snapshots:
tiktok-video-element@0.1.1: {}
+ tiny-inflate@1.0.3: {}
+
tiny-invariant@1.3.3: {}
tinybench@2.9.0: {}
@@ -24863,6 +25762,16 @@ snapshots:
dependencies:
hookable: 5.5.3
+ unicode-properties@1.4.1:
+ dependencies:
+ base64-js: 1.5.1
+ unicode-trie: 2.0.0
+
+ unicode-trie@2.0.0:
+ dependencies:
+ pako: 0.2.9
+ tiny-inflate: 1.0.3
+
unicorn-magic@0.1.0: {}
unicorn-magic@0.3.0: {}
@@ -24877,6 +25786,12 @@ snapshots:
trough: 2.2.0
vfile: 6.0.3
+ unifont@0.6.0:
+ dependencies:
+ css-tree: 3.1.0
+ ofetch: 1.5.1
+ ohash: 2.0.11
+
unimport@5.5.0:
dependencies:
acorn: 8.15.0
@@ -24903,6 +25818,11 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
+ unist-util-modify-children@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ array-iterate: 2.0.1
+
unist-util-position-from-estree@2.0.0:
dependencies:
'@types/unist': 3.0.3
@@ -24920,11 +25840,20 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
+ unist-util-visit-children@3.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
unist-util-visit-parents@6.0.1:
dependencies:
'@types/unist': 3.0.3
unist-util-is: 6.0.0
+ unist-util-visit-parents@6.0.2:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.0
+
unist-util-visit@5.0.0:
dependencies:
'@types/unist': 3.0.3
@@ -25025,6 +25954,22 @@ snapshots:
db0: 0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7))
ioredis: 5.8.2
+ unstorage@1.17.3(@netlify/blobs@9.1.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2):
+ dependencies:
+ anymatch: 3.1.3
+ chokidar: 4.0.3
+ destr: 2.0.5
+ h3: 1.15.4
+ lru-cache: 10.4.3
+ node-fetch-native: 1.6.7
+ ofetch: 1.5.1
+ ufo: 1.6.1
+ optionalDependencies:
+ '@netlify/blobs': 9.1.2
+ '@vercel/functions': 3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0)
+ db0: 0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7))
+ ioredis: 5.8.2
+
unstorage@2.0.0-alpha.4(@netlify/blobs@9.1.2)(@vercel/functions@3.1.4(@aws-sdk/credential-provider-web-identity@3.844.0))(chokidar@4.0.3)(db0@0.3.4(better-sqlite3@11.10.0)(drizzle-orm@0.44.7(@opentelemetry/api@1.9.0)(better-sqlite3@11.10.0)(pg@8.16.3)(postgres@3.4.7)))(ioredis@5.8.2)(lru-cache@11.2.2)(ofetch@2.0.0-alpha.3):
optionalDependencies:
'@netlify/blobs': 9.1.2
@@ -25298,9 +26243,43 @@ snapshots:
vite: 7.1.12(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
vue: 3.5.22(typescript@5.9.3)
+ vite@6.4.1(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1):
+ dependencies:
+ esbuild: 0.25.12
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.53.2
+ tinyglobby: 0.2.14
+ optionalDependencies:
+ '@types/node': 22.19.0
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.30.1
+ terser: 5.44.0
+ tsx: 4.20.6
+ yaml: 2.8.1
+
+ vite@6.4.1(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1):
+ dependencies:
+ esbuild: 0.25.12
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.53.2
+ tinyglobby: 0.2.14
+ optionalDependencies:
+ '@types/node': 24.6.2
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.30.1
+ terser: 5.44.0
+ tsx: 4.20.6
+ yaml: 2.8.1
+
vite@7.1.11(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1):
dependencies:
- esbuild: 0.25.11
+ esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
postcss: 8.5.6
@@ -25349,6 +26328,14 @@ snapshots:
tsx: 4.20.6
yaml: 2.8.1
+ vitefu@1.1.1(vite@6.4.1(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
+ optionalDependencies:
+ vite: 6.4.1(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+
+ vitefu@1.1.1(vite@6.4.1(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
+ optionalDependencies:
+ vite: 6.4.1(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
+
vitefu@1.1.1(vite@7.1.12(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)):
optionalDependencies:
vite: 7.1.12(@types/node@22.19.0)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)
@@ -25514,6 +26501,8 @@ snapshots:
tr46: 0.0.3
webidl-conversions: 3.0.1
+ which-pm-runs@1.1.0: {}
+
which@2.0.2:
dependencies:
isexe: 2.0.0
@@ -25609,6 +26598,8 @@ snapshots:
xtend@4.0.2: {}
+ xxhash-wasm@1.1.0: {}
+
y18n@5.0.8: {}
yallist@3.1.1: {}
@@ -25641,6 +26632,10 @@ snapshots:
yocto-queue@1.2.1: {}
+ yocto-spinner@0.2.3:
+ dependencies:
+ yoctocolors: 2.1.2
+
yoctocolors@2.1.2: {}
youch-core@0.3.3:
@@ -25674,6 +26669,15 @@ snapshots:
compress-commons: 6.0.2
readable-stream: 4.7.0
+ zod-to-json-schema@3.25.0(zod@3.25.76):
+ dependencies:
+ zod: 3.25.76
+
+ zod-to-ts@1.2.0(typescript@5.9.3)(zod@3.25.76):
+ dependencies:
+ typescript: 5.9.3
+ zod: 3.25.76
+
zod@3.25.76: {}
zod@4.1.11: {}
diff --git a/scripts/create-test-matrix.mjs b/scripts/create-test-matrix.mjs
index 369ec344d..fb07f268c 100644
--- a/scripts/create-test-matrix.mjs
+++ b/scripts/create-test-matrix.mjs
@@ -49,6 +49,13 @@ const DEV_TEST_CONFIGS = {
apiFilePath: './src/index.ts',
apiFileImportPath: '..',
},
+ astro: {
+ generatedStepPath: 'src/pages/.well-known/workflow/v1/step.js',
+ generatedWorkflowPath: 'src/pages/.well-known/workflow/v1/flow.js',
+ apiFilePath: 'src/pages/api/chat.ts',
+ apiFileImportPath: '../..',
+ workflowsDir: 'src/workflows',
+ },
};
const matrix = {
@@ -112,4 +119,10 @@ matrix.app.push({
...DEV_TEST_CONFIGS.express,
});
+matrix.app.push({
+ name: 'astro',
+ project: 'workbench-astro-workflow',
+ ...DEV_TEST_CONFIGS.astro,
+});
+
console.log(JSON.stringify(matrix));
diff --git a/workbench/astro/.gitignore b/workbench/astro/.gitignore
new file mode 100644
index 000000000..185adda60
--- /dev/null
+++ b/workbench/astro/.gitignore
@@ -0,0 +1,27 @@
+# build output
+dist/
+# generated types
+.astro/
+
+# dependencies
+node_modules/
+
+# logs
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+
+# environment variables
+.env
+.env.production
+
+# macOS-specific files
+.DS_Store
+
+# jetbrains setting folder
+.idea/
+
+# Workflow
+src/lib/_workflows.ts
diff --git a/workbench/astro/.npmrc b/workbench/astro/.npmrc
new file mode 100644
index 000000000..b6f27f135
--- /dev/null
+++ b/workbench/astro/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/workbench/astro/README.md b/workbench/astro/README.md
new file mode 100644
index 000000000..87b813ae7
--- /dev/null
+++ b/workbench/astro/README.md
@@ -0,0 +1,43 @@
+# Astro Starter Kit: Minimal
+
+```sh
+npm create astro@latest -- --template minimal
+```
+
+> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
+
+## 🚀 Project Structure
+
+Inside of your Astro project, you'll see the following folders and files:
+
+```text
+/
+├── public/
+├── src/
+│ └── pages/
+│ └── index.astro
+└── package.json
+```
+
+Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
+
+There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
+
+Any static assets, like images, can be placed in the `public/` directory.
+
+## 🧞 Commands
+
+All commands are run from the root of the project, from a terminal:
+
+| Command | Action |
+| :------------------------ | :----------------------------------------------- |
+| `npm install` | Installs dependencies |
+| `npm run dev` | Starts local dev server at `localhost:4321` |
+| `npm run build` | Build your production site to `./dist/` |
+| `npm run preview` | Preview your build locally, before deploying |
+| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
+| `npm run astro -- --help` | Get help using the Astro CLI |
+
+## 👀 Want to learn more?
+
+Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
diff --git a/workbench/astro/astro.config.mjs b/workbench/astro/astro.config.mjs
new file mode 100644
index 000000000..5087a1f12
--- /dev/null
+++ b/workbench/astro/astro.config.mjs
@@ -0,0 +1,25 @@
+import { defineConfig } from 'astro/config';
+import { workflow } from 'workflow/astro';
+import node from '@astrojs/node';
+import vercel from '@astrojs/vercel';
+
+// Node adapter needed for ci tests
+const adapter = process.env.VERCEL_DEPLOYMENT_ID
+ ? vercel()
+ : node({
+ mode: 'standalone',
+ });
+
+// https://astro.build/config
+export default defineConfig({
+ output: 'server',
+ integrations: [workflow()],
+ adapter: adapter,
+ // WARNING: CSRF protection is disabled for testing/development purposes.
+ // This configuration trusts all origins and should NOT be used in production.
+ // In production, specify only trusted origins or remove this configuration
+ // to use Astro's default CSRF protection.
+ security: {
+ checkOrigin: false,
+ },
+});
diff --git a/workbench/astro/package.json b/workbench/astro/package.json
new file mode 100644
index 000000000..e1b132bf5
--- /dev/null
+++ b/workbench/astro/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "@workflow/example-astro",
+ "type": "module",
+ "version": "0.0.0",
+ "scripts": {
+ "generate:workflows": "node ../scripts/generate-workflows-registry.js ./src/workflows src/lib/_workflows.ts",
+ "predev": "pnpm generate:workflows",
+ "prebuild": "pnpm generate:workflows",
+ "dev": "astro dev",
+ "build": "astro build",
+ "preview": "astro preview",
+ "astro": "astro",
+ "start": "node scripts/start-with-pg.mjs"
+ },
+ "dependencies": {
+ "@astrojs/node": "9.5.0",
+ "@astrojs/vercel": "^9.0.0",
+ "ai": "catalog:",
+ "astro": "^5.15.6",
+ "lodash.chunk": "^4.2.0",
+ "openai": "6.9.0",
+ "workflow": "workspace:*",
+ "@workflow/world-postgres": "workspace:*",
+ "zod": "catalog:"
+ }
+}
diff --git a/workbench/astro/public/favicon.svg b/workbench/astro/public/favicon.svg
new file mode 100644
index 000000000..f157bd1c5
--- /dev/null
+++ b/workbench/astro/public/favicon.svg
@@ -0,0 +1,9 @@
+
diff --git a/workbench/astro/scripts/start-with-pg.mjs b/workbench/astro/scripts/start-with-pg.mjs
new file mode 100644
index 000000000..c6c506090
--- /dev/null
+++ b/workbench/astro/scripts/start-with-pg.mjs
@@ -0,0 +1,21 @@
+#!/usr/bin/env node
+
+// Start the Postgres World before starting the Astro server
+// Needed since we test this in CI
+// Astro doesn't have a hook for starting the Postgres World in production
+
+async function main() {
+ if (process.env.WORKFLOW_TARGET_WORLD === '@workflow/world-postgres') {
+ console.log('Starting Postgres World...');
+ const { getWorld } = await import('workflow/runtime');
+ await getWorld().start?.();
+ }
+
+ // Now start the Astro server
+ await import('../dist/server/entry.mjs');
+}
+
+main().catch((error) => {
+ console.error('Failed to start server:', error);
+ process.exit(1);
+});
diff --git a/workbench/astro/src/lib/.gitkeep b/workbench/astro/src/lib/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/workbench/astro/src/pages/api/chat.ts b/workbench/astro/src/pages/api/chat.ts
new file mode 100644
index 000000000..420339e43
--- /dev/null
+++ b/workbench/astro/src/pages/api/chat.ts
@@ -0,0 +1,12 @@
+// THIS FILE IS JUST FOR TESTING HMR AS AN ENTRY NEEDS
+// TO IMPORT THE WORKFLOWS TO DISCOVER THEM AND WATCH
+
+import type { APIRoute } from 'astro';
+import * as workflows from '../../workflows/3_streams';
+
+export const POST: APIRoute = async ({ request }: { request: Request }) => {
+ console.log(workflows);
+ return Response.json('hello world');
+};
+
+export const prerender = false;
diff --git a/workbench/astro/src/pages/api/hook.ts b/workbench/astro/src/pages/api/hook.ts
new file mode 100644
index 000000000..afaa46ddc
--- /dev/null
+++ b/workbench/astro/src/pages/api/hook.ts
@@ -0,0 +1,27 @@
+import type { APIRoute } from 'astro';
+import { getHookByToken, resumeHook } from 'workflow/api';
+
+export const POST: APIRoute = async ({ request }: { request: Request }) => {
+ const { token, data } = await request.json();
+
+ let hook: Awaited>;
+ try {
+ hook = await getHookByToken(token);
+ console.log('hook', hook);
+ } catch (error) {
+ console.log('error during getHookByToken', error);
+ // TODO: `WorkflowAPIError` is not exported, so for now
+ // we'll return 404 assuming it's the "invalid" token test case
+ return Response.json(null, { status: 404 });
+ }
+
+ await resumeHook(hook.token, {
+ ...data,
+ // @ts-expect-error metadata is not typed
+ customData: hook.metadata?.customData,
+ });
+
+ return Response.json(hook);
+};
+
+export const prerender = false;
diff --git a/workbench/astro/src/pages/api/test-direct-step-call.ts b/workbench/astro/src/pages/api/test-direct-step-call.ts
new file mode 100644
index 000000000..205dff6c5
--- /dev/null
+++ b/workbench/astro/src/pages/api/test-direct-step-call.ts
@@ -0,0 +1,19 @@
+import { add } from '../../workflows/99_e2e';
+
+export async function POST({ request }: { request: Request }) {
+ // This route tests calling step functions directly outside of any workflow context
+ // After the SWC compiler changes, step functions in client mode have their directive removed
+ // and keep their original implementation, allowing them to be called as regular async functions
+ const body = await request.json();
+ const { x, y } = body;
+
+ console.log(`Calling step function directly with x=${x}, y=${y}`);
+
+ // Call step function directly as a regular async function (no workflow context)
+ const result = await add(x, y);
+ console.log(`add(${x}, ${y}) = ${result}`);
+
+ return Response.json({ result });
+}
+
+export const prerender = false;
diff --git a/workbench/astro/src/pages/api/trigger.ts b/workbench/astro/src/pages/api/trigger.ts
new file mode 100644
index 000000000..fe54124d5
--- /dev/null
+++ b/workbench/astro/src/pages/api/trigger.ts
@@ -0,0 +1,153 @@
+import { getRun, start } from 'workflow/api';
+import {
+ WorkflowRunFailedError,
+ WorkflowRunNotCompletedError,
+} from 'workflow/internal/errors';
+import { hydrateWorkflowArguments } from 'workflow/internal/serialization';
+import { allWorkflows } from '../../lib/_workflows';
+import type { APIRoute } from 'astro';
+
+export async function POST({ request }: { request: Request }) {
+ const url = new URL(request.url);
+ const workflowFile =
+ url.searchParams.get('workflowFile') || 'workflows/99_e2e.ts';
+ if (!workflowFile) {
+ return new Response('No workflowFile query parameter provided', {
+ status: 400,
+ });
+ }
+ const workflows = allWorkflows[workflowFile as keyof typeof allWorkflows];
+ if (!workflows) {
+ return new Response(`Workflow file "${workflowFile}" not found`, {
+ status: 400,
+ });
+ }
+
+ const workflowFn = url.searchParams.get('workflowFn') || 'simple';
+ if (!workflowFn) {
+ return new Response('No workflow query parameter provided', {
+ status: 400,
+ });
+ }
+ const workflow = workflows[workflowFn as keyof typeof workflows];
+ if (!workflow) {
+ return new Response(`Workflow "${workflowFn}" not found`, { status: 400 });
+ }
+
+ let args: any[] = [];
+
+ // Args from query string
+ const argsParam = url.searchParams.get('args');
+ if (argsParam) {
+ args = argsParam.split(',').map((arg) => {
+ const num = parseFloat(arg);
+ return Number.isNaN(num) ? arg.trim() : num;
+ });
+ } else {
+ // Args from body
+ const body = await request.text();
+ if (body) {
+ args = hydrateWorkflowArguments(JSON.parse(body), globalThis);
+ } else {
+ args = [42];
+ }
+ }
+ console.log(`Starting "${workflowFn}" workflow with args: ${args}`);
+
+ try {
+ const run = await start(workflow as any, args as any);
+ console.log('Run:', run);
+ return Response.json(run);
+ } catch (err) {
+ console.error(`Failed to start!!`, err);
+ throw err;
+ }
+}
+
+export const GET: APIRoute = async ({ request }: { request: Request }) => {
+ const url = new URL(request.url);
+ const runId = url.searchParams.get('runId');
+ if (!runId) {
+ return new Response('No runId provided', { status: 400 });
+ }
+
+ const outputStreamParam = url.searchParams.get('output-stream');
+ if (outputStreamParam) {
+ const namespace = outputStreamParam === '1' ? undefined : outputStreamParam;
+ const run = getRun(runId);
+ const stream = run.getReadable({
+ namespace,
+ });
+ // Add JSON framing to the stream, wrapping binary data in base64
+ const streamWithFraming = new TransformStream({
+ transform(chunk, controller) {
+ const data =
+ chunk instanceof Uint8Array
+ ? { data: Buffer.from(chunk).toString('base64') }
+ : chunk;
+ controller.enqueue(`${JSON.stringify(data)}\n`);
+ },
+ });
+ return new Response(stream.pipeThrough(streamWithFraming), {
+ headers: {
+ 'Content-Type': 'application/octet-stream',
+ },
+ });
+ }
+
+ try {
+ const run = getRun(runId);
+ const returnValue = await run.returnValue;
+ console.log('Return value:', returnValue);
+ return returnValue instanceof ReadableStream
+ ? new Response(returnValue, {
+ headers: {
+ 'Content-Type': 'application/octet-stream',
+ },
+ })
+ : Response.json(returnValue);
+ } catch (error) {
+ if (error instanceof Error) {
+ if (WorkflowRunNotCompletedError.is(error)) {
+ return Response.json(
+ {
+ ...error,
+ name: error.name,
+ message: error.message,
+ },
+ { status: 202 }
+ );
+ }
+
+ if (WorkflowRunFailedError.is(error)) {
+ const cause = error.cause;
+ return Response.json(
+ {
+ ...error,
+ name: error.name,
+ message: error.message,
+ cause: {
+ message: cause.message,
+ stack: cause.stack,
+ code: cause.code,
+ },
+ },
+ { status: 400 }
+ );
+ }
+ }
+
+ console.error(
+ 'Unexpected error while getting workflow return value:',
+ error
+ );
+ return Response.json(
+ {
+ error: 'Internal server error',
+ },
+ { status: 500 }
+ );
+ }
+};
+
+export const prerender = false;
diff --git a/workbench/astro/src/pages/index.astro b/workbench/astro/src/pages/index.astro
new file mode 100644
index 000000000..45a53644c
--- /dev/null
+++ b/workbench/astro/src/pages/index.astro
@@ -0,0 +1,138 @@
+---
+// No server-side code needed for this page
+---
+
+
+
+
+
+ Workflow DevKit + Astro Example
+
+
+
+
+ Workflow DevKit + Nitro Example
+
+
+
+
+
+
diff --git a/workbench/astro/src/workflows b/workbench/astro/src/workflows
new file mode 120000
index 000000000..8a9aab9c9
--- /dev/null
+++ b/workbench/astro/src/workflows
@@ -0,0 +1 @@
+../../sveltekit/src/workflows
\ No newline at end of file
diff --git a/workbench/astro/tsconfig.json b/workbench/astro/tsconfig.json
new file mode 100644
index 000000000..8bf91d3bb
--- /dev/null
+++ b/workbench/astro/tsconfig.json
@@ -0,0 +1,5 @@
+{
+ "extends": "astro/tsconfigs/strict",
+ "include": [".astro/types.d.ts", "**/*"],
+ "exclude": ["dist"]
+}