diff --git a/.agent/workflows/openspec-apply.md b/.agent/workflows/openspec-apply.md
new file mode 100644
index 000000000..b0154dd9d
--- /dev/null
+++ b/.agent/workflows/openspec-apply.md
@@ -0,0 +1,20 @@
+---
+description: Implement an approved OpenSpec change and keep tasks in sync.
+---
+
+**Guardrails**
+- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
+- Keep changes tightly scoped to the requested outcome.
+- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
+
+**Steps**
+Track these steps as TODOs and complete them one by one.
+1. Read `changes//proposal.md`, `design.md` (if present), and `tasks.md` to confirm scope and acceptance criteria.
+2. Work through tasks sequentially, keeping edits minimal and focused on the requested change.
+3. Confirm completion before updating statuses—make sure every item in `tasks.md` is finished.
+4. Update the checklist after all work is done so each task is marked `- [x]` and reflects reality.
+5. Reference `openspec list` or `openspec show ` when additional context is required.
+
+**Reference**
+- Use `openspec show --json --deltas-only` if you need additional context from the proposal while implementing.
+
diff --git a/.agent/workflows/openspec-archive.md b/.agent/workflows/openspec-archive.md
new file mode 100644
index 000000000..38dcc8174
--- /dev/null
+++ b/.agent/workflows/openspec-archive.md
@@ -0,0 +1,24 @@
+---
+description: Archive a deployed OpenSpec change and update specs.
+---
+
+**Guardrails**
+- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
+- Keep changes tightly scoped to the requested outcome.
+- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
+
+**Steps**
+1. Determine the change ID to archive:
+ - If this prompt already includes a specific change ID (for example inside a `` block populated by slash-command arguments), use that value after trimming whitespace.
+ - If the conversation references a change loosely (for example by title or summary), run `openspec list` to surface likely IDs, share the relevant candidates, and confirm which one the user intends.
+ - Otherwise, review the conversation, run `openspec list`, and ask the user which change to archive; wait for a confirmed change ID before proceeding.
+ - If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet.
+2. Validate the change ID by running `openspec list` (or `openspec show `) and stop if the change is missing, already archived, or otherwise not ready to archive.
+3. Run `openspec archive --yes` so the CLI moves the change and applies spec updates without prompts (use `--skip-specs` only for tooling-only work).
+4. Review the command output to confirm the target specs were updated and the change landed in `changes/archive/`.
+5. Validate with `openspec validate --strict` and inspect with `openspec show ` if anything looks off.
+
+**Reference**
+- Use `openspec list` to confirm change IDs before archiving.
+- Inspect refreshed specs with `openspec list --specs` and address any validation issues before handing off.
+
diff --git a/.agent/workflows/openspec-proposal.md b/.agent/workflows/openspec-proposal.md
new file mode 100644
index 000000000..db8a95ad0
--- /dev/null
+++ b/.agent/workflows/openspec-proposal.md
@@ -0,0 +1,25 @@
+---
+description: Scaffold a new OpenSpec change and validate strictly.
+---
+
+**Guardrails**
+- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
+- Keep changes tightly scoped to the requested outcome.
+- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
+- Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files.
+- Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval.
+
+**Steps**
+1. Review `openspec/project.md`, run `openspec list` and `openspec list --specs`, and inspect related code or docs (e.g., via `rg`/`ls`) to ground the proposal in current behaviour; note any gaps that require clarification.
+2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, and `design.md` (when needed) under `openspec/changes//`.
+3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing.
+4. Capture architectural reasoning in `design.md` when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs.
+5. Draft spec deltas in `changes//specs//spec.md` (one folder per capability) using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement and cross-reference related capabilities when relevant.
+6. Draft `tasks.md` as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work.
+7. Validate with `openspec validate --strict` and resolve every issue before sharing the proposal.
+
+**Reference**
+- Use `openspec show --json --deltas-only` or `openspec show --type spec` to inspect details when validation fails.
+- Search existing requirements with `rg -n "Requirement:|Scenario:" openspec/specs` before writing new ones.
+- Explore the codebase with `rg `, `ls`, or direct file reads so proposals align with current implementation realities.
+
diff --git a/.changeset/bun-plugin.md b/.changeset/bun-plugin.md
new file mode 100644
index 000000000..f650d64d4
--- /dev/null
+++ b/.changeset/bun-plugin.md
@@ -0,0 +1,6 @@
+---
+"@arkenv/bun-plugin": minor
+---
+
+Add Bun plugin for build-time environment variable validation and type-safe access, similar to the Vite plugin.
+
diff --git a/.cursor/commands/openspec-proposal.md b/.cursor/commands/openspec-proposal.md
index 2d7ed7e93..25f1a3f57 100644
--- a/.cursor/commands/openspec-proposal.md
+++ b/.cursor/commands/openspec-proposal.md
@@ -10,6 +10,7 @@ description: Scaffold a new OpenSpec change and validate strictly.
- Keep changes tightly scoped to the requested outcome.
- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
- Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files.
+- Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval.
**Steps**
1. Review `openspec/project.md`, run `openspec list` and `openspec list --specs`, and inspect related code or docs (e.g., via `rg`/`ls`) to ground the proposal in current behaviour; note any gaps that require clarification.
diff --git a/apps/playgrounds/bun-react/.env.production b/apps/playgrounds/bun-react/.env.production
new file mode 100644
index 000000000..2cce42ed5
--- /dev/null
+++ b/apps/playgrounds/bun-react/.env.production
@@ -0,0 +1,2 @@
+BUN_PUBLIC_API_URL=https://api.example.com
+BUN_PUBLIC_DEBUG=true
diff --git a/apps/playgrounds/bun-react/bin/build.ts b/apps/playgrounds/bun-react/bin/build.ts
new file mode 100644
index 000000000..409918899
--- /dev/null
+++ b/apps/playgrounds/bun-react/bin/build.ts
@@ -0,0 +1,20 @@
+import arkenv from "@arkenv/bun-plugin";
+
+const result = await Bun.build({
+ entrypoints: ["./src/index.html"],
+ outdir: "./dist",
+ sourcemap: true,
+ target: "browser",
+ minify: true,
+ plugins: [arkenv],
+});
+
+if (!result.success) {
+ console.error("Build failed:");
+ for (const log of result.logs) {
+ console.error(log);
+ }
+ process.exit(1);
+}
+
+console.log(`✓ Build succeeded: ${result.outputs.length} files generated`);
diff --git a/apps/playgrounds/bun-react/bun-env.d.ts b/apps/playgrounds/bun-react/bun-env.d.ts
index 809de985d..6270f7509 100644
--- a/apps/playgrounds/bun-react/bun-env.d.ts
+++ b/apps/playgrounds/bun-react/bun-env.d.ts
@@ -1,17 +1,23 @@
-// Generated by `bun init`
+///
+
+// Import the Env schema type from env.ts
+type ProcessEnvAugmented = import("@arkenv/bun-plugin").ProcessEnvAugmented<
+ typeof import("./src/env").default
+>;
+
+declare namespace NodeJS {
+ interface ProcessEnv extends ProcessEnvAugmented {
+ BUN_PUBLIC_API_URL: string;
+ BUN_PUBLIC_DEBUG: boolean;
+ }
+}
declare module "*.svg" {
- /**
- * A path to the SVG file
- */
- const path: `${string}.svg`;
- export = path;
+ const content: string;
+ export default content;
}
declare module "*.module.css" {
- /**
- * A record of class names to their corresponding CSS module classes
- */
const classes: { readonly [key: string]: string };
- export = classes;
+ export default classes;
}
diff --git a/apps/playgrounds/bun-react/bunfig.toml b/apps/playgrounds/bun-react/bunfig.toml
index 9819bf6de..339d48643 100644
--- a/apps/playgrounds/bun-react/bunfig.toml
+++ b/apps/playgrounds/bun-react/bunfig.toml
@@ -1,2 +1,3 @@
[serve.static]
-env = "BUN_PUBLIC_*"
\ No newline at end of file
+env = "BUN_PUBLIC_*"
+plugins = ["@arkenv/bun-plugin"]
diff --git a/apps/playgrounds/bun-react/package.json b/apps/playgrounds/bun-react/package.json
index 0b0282048..4d29842f7 100644
--- a/apps/playgrounds/bun-react/package.json
+++ b/apps/playgrounds/bun-react/package.json
@@ -5,11 +5,15 @@
"type": "module",
"scripts": {
"dev": "bun --hot src/index.tsx",
- "build": "bun build ./src/index.html --outdir=dist --sourcemap --target=browser --minify --define:process.env.NODE_ENV='\"production\"' --env='BUN_PUBLIC_*'",
+ "build": "NODE_ENV=production bun bin/build.ts",
+ "preview": "bun dist/index.html",
"start": "NODE_ENV=production bun src/index.tsx",
"clean": "rimraf dist node_modules"
},
"dependencies": {
+ "@arkenv/bun-plugin": "workspace:*",
+ "arkenv": "workspace:*",
+ "arktype": "catalog:",
"react": "catalog:",
"react-dom": "catalog:"
},
diff --git a/apps/playgrounds/bun-react/src/App.tsx b/apps/playgrounds/bun-react/src/App.tsx
index 5c178f495..0aa16de31 100644
--- a/apps/playgrounds/bun-react/src/App.tsx
+++ b/apps/playgrounds/bun-react/src/App.tsx
@@ -17,6 +17,29 @@ export function App() {
Edit src/App.tsx and save to test HMR
+
+
+
+
Variable
+
Value
+
Type
+
+
+
+
+
BUN_PUBLIC_API_URL
+
{process.env.BUN_PUBLIC_API_URL}
+
{typeof process.env.BUN_PUBLIC_API_URL}
+
+
+
BUN_PUBLIC_DEBUG
+
{String(process.env.BUN_PUBLIC_DEBUG)}
+
{typeof process.env.BUN_PUBLIC_DEBUG}
+
+
+
+ {/* Print whether we are in "build" or in the dev server */}
+
Mode: {process.env.NODE_ENV}
);
}
diff --git a/apps/playgrounds/bun-react/src/env.ts b/apps/playgrounds/bun-react/src/env.ts
new file mode 100644
index 000000000..beb7155b6
--- /dev/null
+++ b/apps/playgrounds/bun-react/src/env.ts
@@ -0,0 +1,6 @@
+import { type } from "arkenv";
+
+export default type({
+ BUN_PUBLIC_API_URL: "string",
+ BUN_PUBLIC_DEBUG: "boolean",
+});
diff --git a/apps/playgrounds/bun-react/src/index.css b/apps/playgrounds/bun-react/src/index.css
index 09eaa7e9c..593d4ddfd 100644
--- a/apps/playgrounds/bun-react/src/index.css
+++ b/apps/playgrounds/bun-react/src/index.css
@@ -185,3 +185,37 @@ code {
animation: none !important;
}
}
+
+.env-table {
+ width: 100%;
+ max-width: 600px;
+ margin: 2rem auto;
+ border-collapse: separate;
+ border-spacing: 0;
+ background: #1a1a1a;
+ border-radius: 12px;
+ overflow: hidden;
+ border: 2px solid #fbf0df;
+}
+
+.env-table th,
+.env-table td {
+ padding: 1rem;
+ text-align: left;
+ border-bottom: 1px solid rgba(251, 240, 223, 0.1);
+}
+
+.env-table th {
+ background: rgba(251, 240, 223, 0.1);
+ color: #fbf0df;
+ font-weight: 600;
+}
+
+.env-table td {
+ color: #e0e0e0;
+ font-family: monospace;
+}
+
+.env-table tr:last-child td {
+ border-bottom: none;
+}
diff --git a/apps/playgrounds/bun-react/src/index.tsx b/apps/playgrounds/bun-react/src/index.tsx
index bd8df61e4..05980fe74 100644
--- a/apps/playgrounds/bun-react/src/index.tsx
+++ b/apps/playgrounds/bun-react/src/index.tsx
@@ -7,13 +7,13 @@ const server = serve({
"/*": index,
"/api/hello": {
- async GET(req) {
+ async GET() {
return Response.json({
message: "Hello, world!",
method: "GET",
});
},
- async PUT(req) {
+ async PUT() {
return Response.json({
message: "Hello, world!",
method: "PUT",
diff --git a/apps/www/app/layout.tsx b/apps/www/app/layout.tsx
index a51daff8d..967b317d6 100644
--- a/apps/www/app/layout.tsx
+++ b/apps/www/app/layout.tsx
@@ -1,4 +1,4 @@
-import { Banner } from "fumadocs-ui/components/banner";
+import { Banner } from "~/components/banner";
import "./globals.css";
import { Analytics } from "@vercel/analytics/next";
import { SpeedInsights } from "@vercel/speed-insights/next";
@@ -48,18 +48,7 @@ export default function Layout({ children }: { children: ReactNode }) {
enableSystem: true,
}}
>
-
- 🎉 Announcing Vite support: check out the
-
- new docs
-
- !
-
+
{children}
diff --git a/apps/www/components/banner.tsx b/apps/www/components/banner.tsx
new file mode 100644
index 000000000..cd79057b6
--- /dev/null
+++ b/apps/www/components/banner.tsx
@@ -0,0 +1,19 @@
+"use client";
+
+import { Banner as FumadocsBanner } from "fumadocs-ui/components/banner";
+import { useRouter } from "next/navigation";
+
+export function Banner() {
+ const router = useRouter();
+ return (
+ router.push("/docs/bun-plugin")}
+ className="cursor-pointer"
+ >
+ 🎉 Official Bun support is here: ArkEnv at build time, fullstack dev
+ server
+
+ );
+}
diff --git a/apps/www/components/docs/install-button.tsx b/apps/www/components/docs/install-button.tsx
index 278d10014..60387bdd0 100644
--- a/apps/www/components/docs/install-button.tsx
+++ b/apps/www/components/docs/install-button.tsx
@@ -8,18 +8,24 @@ import { Button } from "~/components/ui/button";
export function InstallButton() {
const pathname = usePathname();
const isVitePluginPage = pathname?.includes("/docs/vite-plugin");
+ const isBunPluginPage = pathname?.includes("/docs/bun-plugin");
+
+ let href = "/docs/arkenv/quickstart#install";
+ let label = "Install ArkEnv";
+
+ if (isVitePluginPage) {
+ href = "/docs/vite-plugin#installation";
+ label = "Install ArkEnv Vite plugin";
+ } else if (isBunPluginPage) {
+ href = "/docs/bun-plugin#installation";
+ label = "Install ArkEnv Bun plugin";
+ }
return (
);
diff --git a/apps/www/content/docs/bun-plugin/index.mdx b/apps/www/content/docs/bun-plugin/index.mdx
new file mode 100644
index 000000000..2002288b2
--- /dev/null
+++ b/apps/www/content/docs/bun-plugin/index.mdx
@@ -0,0 +1,78 @@
+---
+title: Introduction
+icon: Album
+---
+
+## What is this?
+
+The Bun plugin for ArkEnv lets you validate environment variables at build-time and runtime with ArkEnv.
+
+It supports **zero-config** usage for most projects, automatically discovering your schema from `./src/env.ts` or `./env.ts`.
+
+## Usage
+
+### Zero-Config (Recommended)
+
+Add the plugin to your `bunfig.toml`. This works for both `bun run dev` and `bun run build`.
+
+```toml title="bunfig.toml"
+[serve.static]
+plugins = ["@arkenv/bun-plugin"]
+```
+
+Create your schema in `src/env.ts` (or `env.ts`):
+
+```ts title="src/env.ts"
+import { type } from "arkenv";
+
+export default type({
+ BUN_PUBLIC_API_URL: "string",
+ BUN_PUBLIC_DEBUG: "boolean",
+});
+```
+
+### Manual Configuration
+
+If you prefer explicit configuration or need to customize the schema location, you can use the plugin in your build script:
+
+```ts title="build.ts"
+import arkenv from "@arkenv/bun-plugin";
+import { type } from "arkenv";
+
+const env = type({
+ BUN_PUBLIC_API_URL: "string",
+ BUN_PUBLIC_DEBUG: "boolean",
+});
+
+await Bun.build({
+ entrypoints: ["./app.tsx"],
+ outdir: "./dist",
+ plugins: [arkenv(env)],
+});
+```
+
+### Zero-Config in Build Scripts
+
+You can also use the zero-config pattern in build scripts by passing the plugin object directly:
+
+```ts title="build.ts"
+import arkenv from "@arkenv/bun-plugin";
+
+await Bun.build({
+ // ...
+ plugins: [arkenv], // Auto-discovers src/env.ts
+});
+```
+
+## Features
+
+- **Static Analysis**: Automatically replaces `process.env.VARIABLE` with validated values during the build.
+- **Type Safety**: Ensures your code only accesses variables defined in your schema.
+- **Hot Reloading**: Automatically reloads your schema when `env.ts` changes (in `bun --hot` mode).
+- **Secure Defaults**: Only exposes variables prefixed with `BUN_PUBLIC_` to the client bundle. You can customize this prefix by setting the `env` option in your `Bun.build()` configuration (e.g., `env: "MY_PUBLIC_*"` to use `MY_PUBLIC_` instead). See [Bun's bundler documentation](https://bun.sh/docs/bundler#env) for more details.
+
+## Installation
+
+```package-install
+@arkenv/bun-plugin arkenv arktype
+```
diff --git a/apps/www/content/docs/bun-plugin/meta.json b/apps/www/content/docs/bun-plugin/meta.json
new file mode 100644
index 000000000..c8e4e0eb6
--- /dev/null
+++ b/apps/www/content/docs/bun-plugin/meta.json
@@ -0,0 +1,7 @@
+{
+ "title": "@arkenv/bun-plugin",
+ "description": "The Bun plugin",
+ "root": true,
+ "icon": "Bun",
+ "pages": ["---Guide---", "index"]
+}
diff --git a/apps/www/content/docs/meta.json b/apps/www/content/docs/meta.json
index 1f4b8cd3a..6f40ecac2 100644
--- a/apps/www/content/docs/meta.json
+++ b/apps/www/content/docs/meta.json
@@ -1,3 +1,3 @@
{
- "pages": ["arkenv", "vite-plugin"]
+ "pages": ["arkenv", "vite-plugin", "bun-plugin"]
}
diff --git a/arkenv.code-workspace b/arkenv.code-workspace
index 1aa8973aa..f4a2299ef 100644
--- a/arkenv.code-workspace
+++ b/arkenv.code-workspace
@@ -32,6 +32,10 @@
"path": "packages/vite-plugin",
"name": " @arkenv/vite-plugin"
},
+ {
+ "path": "packages/bun-plugin",
+ "name": " @arkenv/bun-plugin"
+ },
{
"path": "packages/internal/types",
"name": " @repo/types"
diff --git a/openspec/changes/add-bun-plugin/design.md b/openspec/changes/add-bun-plugin/design.md
new file mode 100644
index 000000000..3ffff2123
--- /dev/null
+++ b/openspec/changes/add-bun-plugin/design.md
@@ -0,0 +1,144 @@
+
+### Requirement: Bun Plugin Configuration Patterns
+
+The Bun plugin SHALL support two primary configuration patterns depending on the usage context:
+
+1. **Direct Reference (Bun.build)**: The plugin SHALL be configurable by passing a configured plugin instance directly in the `plugins` array when using `Bun.build()`.
+2. **Package Reference (Bun.serve)**: The plugin SHALL be configurable via a package name in `bunfig.toml` when using `Bun.serve()` for full-stack applications, with convention-based schema discovery.
+
+A future, more advanced configuration pattern using a custom static file MAY be supported, but is not required for the initial version.
+
+#### Scenario: Plugin configuration with Bun.build
+
+- **WHEN** a user wants to build an application using `Bun.build()`
+- **AND** they configure the plugin with an environment variable schema
+- **THEN** they can pass a configured plugin instance directly in the `plugins` array
+- **AND** the plugin validates and transforms environment variables during the build process
+
+#### Scenario: Plugin configuration with Bun.serve via package reference
+
+- **WHEN** a user wants to use `Bun.serve()` for a full-stack application
+- **AND** they configure `bunfig.toml` with:
+ - a `[serve.static]` section
+ - a `plugins` array that includes the package name `@arkenv/bun-plugin`
+- **AND** their project contains an ArkEnv schema file in one of the supported default locations (for example, `./src/env.arkenv.ts`, `./src/env.ts`, `./env.arkenv.ts`, `./env.ts`)
+- **AND** that schema file exports a schema using `type` from arktype (via a default export or an `env` named export)
+- **THEN** the plugin SHALL locate the schema file via this convention-based search
+- **AND** it SHALL load the schema at startup
+- **AND** it SHALL use that schema to validate and transform environment variables during the bundling phase
+
+#### Scenario: Bun.serve configuration fails when no schema file is found
+
+- **WHEN** a user configures `bunfig.toml` with `[serve.static].plugins = ["@arkenv/bun-plugin"]`
+- **AND** there is no schema file in any of the supported default locations
+- **THEN** the plugin SHALL fail fast with a clear, descriptive error message
+- **AND** the error message SHALL list the paths that were checked
+- **AND** the error message SHALL show an example of a minimal `env` schema file the user can create
+
+
+
+### Decision: Configuration Modes and Schema Discovery
+
+**What**: The plugin supports two core configuration modes:
+
+1. **Direct Reference (Bun.build)** – pass a configured plugin instance directly in the `plugins` array.
+2. **Package Reference with Convention (Bun.serve)** – declare `@arkenv/bun-plugin` in `bunfig.toml` and let the plugin discover the ArkEnv schema file using a set of well-known paths.
+
+A third, more advanced mode using a custom static plugin file may be added later for projects with non-standard layouts, but is not required for the initial release.
+
+#### Why
+
+- `Bun.build()` accepts plugins directly as JavaScript objects, which is ideal for explicit, programmatic configuration.
+- `Bun.serve()` uses `bunfig.toml` where `plugins` is a list of strings (module specifiers) and does not support passing options inline.
+- By using a package name (`"@arkenv/bun-plugin"`) plus convention-based schema discovery, we avoid forcing users to create extra “config glue” files for the common case, while still keeping an escape hatch for advanced setups.
+
+#### Implementation
+
+### Pattern 1: Bun.build (Direct Reference)
+
+```ts
+// build.ts
+import arkenv from "@arkenv/bun-plugin";
+import { type } from "arktype";
+
+const env = type({
+ BUN_PUBLIC_API_URL: "string",
+ BUN_PUBLIC_DEBUG: "boolean",
+});
+
+await Bun.build({
+ entrypoints: ["./app.tsx"],
+ outdir: "./dist",
+ plugins: [arkenv(env)],
+});
+```
+
+### Pattern 2: Bun.serve (Package Reference with Convention)
+
+```toml
+# bunfig.toml
+[serve.static]
+env = "BUN_PUBLIC_*"
+plugins = ["@arkenv/bun-plugin"]
+```
+
+With a schema file at a conventional path, for example:
+
+```ts
+// src/env.ts
+import { type } from "arktype";
+
+const env = type({
+ BUN_PUBLIC_API_URL: "string",
+ BUN_PUBLIC_DEBUG: "boolean",
+});
+
+export default env;
+```
+
+At startup, `@arkenv/bun-plugin`:
+
+- Searches for a schema file in a small set of well-known locations (for example: `./src/env.arkenv.ts`, `./src/env.ts`, `./env.arkenv.ts`, `./env.ts`).
+- Imports the first one it finds.
+- Reads the default export (or an `env` named export) as the ArkEnv schema.
+- Creates a Bun plugin and registers it with `Bun.plugin(...)`.
+
+If no schema file is found, or the module does not export a usable schema, the plugin fails fast with a clear error message that lists the paths checked and shows a minimal example.
+
+### Future / Advanced Mode (Custom Static File)
+
+In future iterations we MAY support a custom plugin entry file pattern for advanced layouts, for example:
+
+```toml
+[serve.static]
+plugins = ["./arkenv.bun-plugin.ts"]
+```
+
+```ts
+// arkenv.bun-plugin.ts
+import { Bun } from "bun";
+import { buildArkEnvBunPlugin } from "@arkenv/bun-plugin";
+
+Bun.plugin(
+ await buildArkEnvBunPlugin({
+ schemaPath: "./config/env/app.env.ts",
+ // future options (prefix overrides, strictness, etc.)
+ }),
+);
+```
+
+This keeps the default experience zero-config for most users, while still allowing power users to override the schema location and other options when needed.
+
+#### Alternatives considered
+
+- **Static file reference as the only pattern** (previous design): Forces every project to create a separate `bun-plugin-config.ts` file even in simple setups, increasing boilerplate.
+- **Schema definition via JSON/YAML or bunfig.toml**: Reduces type safety and breaks the “define once in TypeScript” story that ArkEnv aims for.
+- **Only programmatic configuration** (no bunfig path): Would make full-stack `Bun.serve()` setups awkward compared to other Bun plugins that integrate via `bunfig.toml`.
+
+
+
+### Usage Patterns
+- **Bun.build**: Pass a configured plugin instance directly in the `plugins` array (standard Bun plugin API), for example `plugins: [arkenv(env)]`.
+- **Bun.serve (default)**: Configure `bunfig.toml` with `[serve.static].plugins = ["@arkenv/bun-plugin"]`. The plugin discovers the ArkEnv schema file from a small set of conventional locations (for example `./src/env.arkenv.ts`, `./src/env.ts`, `./env.arkenv.ts`, `./env.ts`) and uses it automatically.
+- **Bun.serve (advanced, future)**: Optionally support a custom plugin entry file referenced from `bunfig.toml` (for example `plugins = ["./arkenv.bun-plugin.ts"]`) for projects that need a non-standard schema location or additional configuration.
+
diff --git a/openspec/changes/add-bun-plugin/proposal.md b/openspec/changes/add-bun-plugin/proposal.md
new file mode 100644
index 000000000..03c0334d4
--- /dev/null
+++ b/openspec/changes/add-bun-plugin/proposal.md
@@ -0,0 +1,182 @@
+
+### Requirement: Bun Plugin Configuration Patterns
+
+The Bun plugin SHALL support two primary configuration patterns depending on the usage context:
+
+1. **Direct Reference (Bun.build)**: The plugin SHALL be configurable by passing a configured plugin instance directly in the `plugins` array when using `Bun.build()`.
+2. **Package Reference (Bun.serve)**: The plugin SHALL be configurable via a package name in `bunfig.toml` when using `Bun.serve()` for full-stack applications, with convention-based schema discovery.
+
+A future, more advanced configuration pattern using a custom static file MAY be supported, but is not required for the initial version.
+
+#### Scenario: Plugin configuration with Bun.build
+
+- **WHEN** a user wants to build an application using `Bun.build()`
+- **AND** they configure the plugin with an environment variable schema
+- **THEN** they can pass a configured plugin instance directly in the `plugins` array
+- **AND** the plugin validates and transforms environment variables during the build process
+
+#### Scenario: Plugin configuration with Bun.serve via package reference
+
+- **WHEN** a user wants to use `Bun.serve()` for a full-stack application
+- **AND** they configure `bunfig.toml` with:
+ - a `[serve.static]` section
+ - a `plugins` array that includes the package name `@arkenv/bun-plugin`
+- **AND** their project contains an ArkEnv schema file in one of the supported default locations (for example, `./src/env.arkenv.ts`, `./src/env.ts`, `./env.arkenv.ts`, `./env.ts`)
+- **AND** that schema file exports a schema using `type` from arktype (via a default export or an `env` named export)
+- **THEN** the plugin SHALL locate the schema file via this convention-based search
+- **AND** it SHALL load the schema at startup
+- **AND** it SHALL use that schema to validate and transform environment variables during the bundling phase
+
+#### Scenario: Bun.serve configuration fails when no schema file is found
+
+- **WHEN** a user configures `bunfig.toml` with `[serve.static].plugins = ["@arkenv/bun-plugin"]`
+- **AND** there is no schema file in any of the supported default locations
+- **THEN** the plugin SHALL fail fast with a clear, descriptive error message
+- **AND** the error message SHALL list the paths that were checked
+- **AND** the error message SHALL show an example of a minimal `env` schema file the user can create
+
+
+
+### Decision: Configuration Modes and Schema Discovery
+
+**What**: The plugin supports two core configuration modes:
+
+1. **Direct Reference (Bun.build)** – pass a configured plugin instance directly in the `plugins` array.
+2. **Package Reference with Convention (Bun.serve)** – declare `@arkenv/bun-plugin` in `bunfig.toml` and let the plugin discover the ArkEnv schema file using a set of well-known paths.
+
+A third, more advanced mode using a custom static plugin file may be added later for projects with non-standard layouts, but is not required for the initial release.
+
+**Why**:
+
+- `Bun.build()` accepts plugins directly as JavaScript objects, which is ideal for explicit, programmatic configuration.
+- `Bun.serve()` uses `bunfig.toml` where `plugins` is a list of strings (module specifiers) and does not support passing options inline.
+- By using a package name (`"@arkenv/bun-plugin"`) plus convention-based schema discovery, we avoid forcing users to create extra “config glue” files for the common case, while still keeping an escape hatch for advanced setups.
+
+**Implementation**:
+
+**Pattern 1: Bun.build (Direct Reference)**
+
+```ts
+// build.ts
+import arkenv from "@arkenv/bun-plugin";
+import { type } from "arktype";
+
+const env = type({
+ BUN_PUBLIC_API_URL: "string",
+ BUN_PUBLIC_DEBUG: "boolean",
+});
+
+await Bun.build({
+ entrypoints: ["./app.tsx"],
+ outdir: "./dist",
+ plugins: [arkenv(env)],
+});
+```
+
+**Pattern 2: Bun.serve (Package Reference with Convention)**
+
+```toml
+# bunfig.toml
+[serve.static]
+env = "BUN_PUBLIC_*"
+plugins = ["@arkenv/bun-plugin"]
+```
+
+With a schema file at a conventional path, for example:
+
+```ts
+// src/env.ts
+import { type } from "arktype";
+
+const env = type({
+ BUN_PUBLIC_API_URL: "string",
+ BUN_PUBLIC_DEBUG: "boolean",
+});
+
+export default env;
+```
+
+At startup, `@arkenv/bun-plugin`:
+
+- Searches for a schema file in a small set of well-known locations (for example: `./src/env.arkenv.ts`, `./src/env.ts`, `./env.arkenv.ts`, `./env.ts`).
+- Imports the first one it finds.
+- Reads the default export (or an `env` named export) as the ArkEnv schema.
+- Creates a Bun plugin and registers it with `Bun.plugin(...)`.
+
+If no schema file is found, or the module does not export a usable schema, the plugin fails fast with a clear error message that lists the paths checked and shows a minimal example.
+
+**Future / Advanced Mode (Custom Static File)**
+
+In future iterations we MAY support a custom plugin entry file pattern for advanced layouts, for example:
+
+```toml
+[serve.static]
+plugins = ["./arkenv.bun-plugin.ts"]
+```
+
+```ts
+// arkenv.bun-plugin.ts
+import { Bun } from "bun";
+import { buildArkEnvBunPlugin } from "@arkenv/bun-plugin";
+
+Bun.plugin(
+ await buildArkEnvBunPlugin({
+ schemaPath: "./config/env/app.env.ts",
+ // future options (prefix overrides, strictness, etc.)
+ }),
+);
+```
+
+This keeps the default experience zero-config for most users, while still allowing power users to override the schema location and other options when needed.
+
+**Alternatives considered**:
+
+- **Static file reference as the only pattern** (previous design): Forces every project to create a separate `bun-plugin-config.ts` file even in simple setups, increasing boilerplate.
+- **Schema definition via JSON/YAML or bunfig.toml**: Reduces type safety and breaks the “define once in TypeScript” story that ArkEnv aims for.
+- **Only programmatic configuration** (no bunfig path): Would make full-stack `Bun.serve()` setups awkward compared to other Bun plugins that integrate via `bunfig.toml`.
+
+
+
+# Change: Add Bun Plugin for ArkEnv
+
+## Why
+
+ArkEnv currently provides a Vite plugin for build-time environment variable validation and type-safe access in client code. However, Bun users (especially those building full-stack React applications with Bun's `serve` function) need similar functionality.
+
+Bun's bundler statically replaces `process.env` variables during build, which means:
+- Environment variables must be validated and transformed at build-time
+- Only variables matching Bun's prefix (defaults to `BUN_PUBLIC_*`) should be exposed to client code
+- Type augmentation is needed for type-safe access to `process.env` in client code
+- The plugin must work within Bun's serve function for full-stack React apps
+
+Without a Bun plugin, users must manually validate environment variables or risk runtime errors, and they lose the type safety and build-time validation benefits that ArkEnv provides.
+
+## What Changes
+
+- **ADDED**: New `@arkenv/bun-plugin` package that provides Bun plugin integration
+- **ADDED**: Build-time environment variable validation using Bun's plugin API
+- **ADDED**: Automatic filtering of environment variables based on Bun's prefix (defaults to `BUN_PUBLIC_*`)
+- **ADDED**: Static replacement of `process.env` variables with validated, transformed values during bundling
+- **ADDED**: Type augmentation for `process.env` similar to Vite plugin's `ImportMetaEnvAugmented`
+- **ADDED**: Support for Bun's serve function in full-stack React applications
+- **ADDED**: Documentation and examples for using the Bun plugin
+
+The plugin will work very similarly to the Vite plugin:
+- Uses Bun's `onLoad` hook to intercept and transform environment variable access
+- Validates environment variables using ArkEnv's schema validation
+- Filters variables to only expose those matching the configured prefix
+- Replaces `process.env.VARIABLE` with validated, transformed values (e.g., string to boolean, default values)
+- Provides TypeScript type augmentation for type-safe access
+
+### Usage Patterns
+- **Bun.build**: Pass a configured plugin instance directly in the `plugins` array (standard Bun plugin API), for example `plugins: [arkenv(env)]`.
+- **Bun.serve (default)**: Configure `bunfig.toml` with `[serve.static].plugins = ["@arkenv/bun-plugin"]`. The plugin discovers the ArkEnv schema file from a small set of conventional locations (for example `./src/env.arkenv.ts`, `./src/env.ts`, `./env.arkenv.ts`, `./env.ts`) and uses it automatically.
+- **Bun.serve (advanced, future)**: Optionally support a custom plugin entry file referenced from `bunfig.toml` (for example `plugins = ["./arkenv.bun-plugin.ts"]`) for projects that need a non-standard schema location or additional configuration.
+
+## Impact
+
+- **New opt-in feature**: The Bun plugin is an entirely new package (@arkenv/bun-plugin) and does not affect existing arkenv users or workflows.
+- **No breaking changes**: This is a pure addition and does not modify any public APIs or existing behavior.
+- **Backward compatible**: All existing code continues to work unchanged. Bun users simply gain access to new functionality.
+- **New dependency**: Projects using @arkenv/bun-plugin will add a new dev dependency to their package.json.
+
diff --git a/openspec/changes/add-bun-plugin/specs/bun-plugin/spec.md b/openspec/changes/add-bun-plugin/specs/bun-plugin/spec.md
new file mode 100644
index 000000000..009ef520e
--- /dev/null
+++ b/openspec/changes/add-bun-plugin/specs/bun-plugin/spec.md
@@ -0,0 +1,103 @@
+# bun-plugin Specification
+
+## ADDED Requirements
+
+### Requirement: Bun Plugin Configuration Patterns
+
+The Bun plugin SHALL support two primary configuration patterns depending on the usage context:
+
+1. **Direct Reference (Bun.build)**: The plugin SHALL be configurable by passing a configured plugin instance directly in the `plugins` array when using `Bun.build()`.
+2. **Package Reference (Bun.serve)**: The plugin SHALL be configurable via a package name in `bunfig.toml` when using `Bun.serve()` for full-stack applications, with convention-based schema discovery.
+
+A future, more advanced configuration pattern using a custom static file MAY be supported, but is not required for the initial version.
+
+#### Scenario: Plugin configuration with Bun.build
+
+- **WHEN** a user wants to build an application using `Bun.build()`
+- **AND** they configure the plugin with an environment variable schema
+- **THEN** they can pass a configured plugin instance directly in the `plugins` array
+- **AND** the plugin validates and transforms environment variables during the build process
+
+#### Scenario: Plugin configuration with Bun.serve via package reference
+
+- **WHEN** a user wants to use `Bun.serve()` for a full-stack application
+- **AND** they configure `bunfig.toml` with:
+ - a `[serve.static]` section
+ - a `plugins` array that includes the package name `@arkenv/bun-plugin`
+- **AND** their project contains an ArkEnv schema file in one of the supported default locations (for example, `./src/env.arkenv.ts`, `./src/env.ts`, `./env.arkenv.ts`, `./env.ts`)
+- **AND** that schema file exports a schema using `type` from arktype (via a default export or an `env` named export)
+- **THEN** the plugin SHALL locate the schema file via this convention-based search
+- **AND** it SHALL load the schema at startup
+- **AND** it SHALL use that schema to validate and transform environment variables during the bundling phase
+
+#### Scenario: Bun.serve configuration fails when no schema file is found
+
+- **WHEN** a user configures `bunfig.toml` with `[serve.static].plugins = ["@arkenv/bun-plugin"]`
+- **AND** there is no schema file in any of the supported default locations
+- **THEN** the plugin SHALL fail fast with a clear, descriptive error message
+- **AND** the error message SHALL list the paths that were checked
+- **AND** the error message SHALL show an example of a minimal `env` schema file the user can create
+
+### Requirement: Bun Plugin Environment Variable Validation and Transformation
+
+The Bun plugin SHALL validate environment variables at build-time using ArkEnv's schema validation and statically replace `process.env.VARIABLE` access with validated, transformed values during bundling. The plugin SHALL transform values according to the schema (e.g., string to boolean, apply default values).
+
+#### Scenario: Plugin validates and transforms environment variables
+- **WHEN** a user configures the Bun plugin with a schema containing environment variables
+- **AND** the schema includes variables with various types (e.g., `BUN_PUBLIC_API_URL: "string"`, `BUN_PUBLIC_DEBUG: "boolean"`)
+- **THEN** the plugin validates all variables in the schema at build-time
+- **AND** the plugin transforms values according to the schema (e.g., `"true"` string to `true` boolean)
+- **AND** the plugin statically replaces `process.env.VARIABLE` with the validated, transformed value
+- **AND** default values are applied when variables are missing
+
+#### Scenario: Plugin handles various process.env access patterns
+- **WHEN** a user accesses environment variables via different patterns (e.g., `process.env.VAR`, `process.env["VAR"]`, destructuring)
+- **AND** the plugin is configured with a schema
+- **THEN** the plugin transforms all access patterns to use validated values
+- **AND** the transformed code uses the validated, transformed values instead of raw `process.env` access
+
+### Requirement: Bun Plugin Environment Variable Filtering
+
+The Bun plugin SHALL automatically filter environment variables to only expose those matching Bun's configured prefix (defaults to `BUN_PUBLIC_*`) to client code. Server-only environment variables without the prefix SHALL NOT be exposed to the client bundle.
+
+#### Scenario: Only prefixed variables are exposed to client
+- **WHEN** a user passes a schema containing both prefixed (`BUN_PUBLIC_*`) and unprefixed variables to the Bun plugin
+- **AND** the schema includes server-only variables like `PORT` and client-safe variables like `BUN_PUBLIC_API_URL`
+- **THEN** only variables starting with the Bun prefix are validated and exposed to client code via `process.env.*`
+- **AND** server-only variables are not included in the client bundle
+- **AND** the plugin respects Bun's prefix configuration (from bunfig.toml or defaults to `BUN_PUBLIC_*`)
+
+#### Scenario: Default prefix behavior
+- **WHEN** a user does not configure a prefix in bunfig.toml
+- **AND** they pass a schema to the Bun plugin
+- **THEN** the plugin defaults to `"BUN_PUBLIC_"` as the prefix
+- **AND** only variables starting with `BUN_PUBLIC_` are exposed to client code
+
+### Requirement: Bun Plugin Type Augmentation
+
+The Bun plugin SHALL provide TypeScript type augmentation for `process.env` similar to the Vite plugin's `ImportMetaEnvAugmented`, enabling type-safe access to environment variables in client code.
+
+#### Scenario: Type augmentation enables type-safe access
+- **WHEN** a user configures the Bun plugin with a schema
+- **AND** they augment `process.env` types using `ProcessEnvAugmented`
+- **THEN** TypeScript provides type checking and autocomplete for environment variables
+- **AND** only variables matching the configured prefix are included in the type
+- **AND** types reflect the validated, transformed values (e.g., `boolean` instead of `string`)
+
+#### Scenario: Type augmentation filters by prefix
+- **WHEN** a user defines a schema with both prefixed and unprefixed variables
+- **AND** they use `ProcessEnvAugmented` for type augmentation
+- **THEN** the type only includes variables matching the configured prefix
+- **AND** server-only variables are excluded from the type
+
+### Requirement: Bun Plugin Integration with Bun's Serve Function
+
+The Bun plugin SHALL work correctly with Bun's `serve` function for full-stack React applications, validating and transforming environment variables during the bundling phase before the server starts.
+
+#### Scenario: Plugin works with Bun serve in full-stack React app
+- **WHEN** a user uses Bun's `serve` function with a full-stack React application
+- **AND** they configure the Bun plugin with a schema
+- **THEN** the plugin validates environment variables during bundling
+- **AND** the plugin transforms `process.env` access in both server and client code
+- **AND** only prefixed variables are exposed to client code
+- **AND** the server starts successfully with validated environment variables
diff --git a/openspec/changes/add-bun-plugin/tasks.md b/openspec/changes/add-bun-plugin/tasks.md
new file mode 100644
index 000000000..6c03b2844
--- /dev/null
+++ b/openspec/changes/add-bun-plugin/tasks.md
@@ -0,0 +1,10 @@
+# Implementation Checklist
+
+- [x] Implement Direct Reference (Bun.build)
+- [x] Implement Package Reference (Bun.serve) with convention-based schema discovery
+- [x] Add schema file path resolution for default locations
+- [x] Implement error handling when schema file is not found
+- [x] Add unit tests
+- [x] Add integration tests
+- [x] Update docs
+- [x] Setup playground app
diff --git a/package.json b/package.json
index 10bb79725..00841a9f7 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
"@sentry/cli",
"@tailwindcss/oxide",
"@vercel/speed-insights",
+ "bun",
"esbuild",
"sharp"
]
diff --git a/packages/bun-plugin/.gitignore b/packages/bun-plugin/.gitignore
new file mode 100644
index 000000000..a14702c40
--- /dev/null
+++ b/packages/bun-plugin/.gitignore
@@ -0,0 +1,34 @@
+# dependencies (bun install)
+node_modules
+
+# output
+out
+dist
+*.tgz
+
+# code coverage
+coverage
+*.lcov
+
+# logs
+logs
+_.log
+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
+
+# dotenv environment variable files
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# caches
+.eslintcache
+.cache
+*.tsbuildinfo
+
+# IntelliJ based IDEs
+.idea
+
+# Finder (MacOS) folder config
+.DS_Store
diff --git a/packages/bun-plugin/README.md b/packages/bun-plugin/README.md
new file mode 100644
index 000000000..ab4aa5ce7
--- /dev/null
+++ b/packages/bun-plugin/README.md
@@ -0,0 +1,98 @@
+# `@arkenv/bun-plugin`
+
+[Bun](https://bun.sh/) plugin to validate environment variables at build-time with ArkEnv.
+
+
+
+
+
+## [Read the docs →](https://arkenv.js.org/docs/bun-plugin)
+
+
+
+
+## Features
+
+- Build-time validation - app won't start if environment variables are invalid
+- Typesafe environment variables backed by TypeScript
+- Access to ArkType's powerful type system
+- Automatic filtering of client-exposed variables (defaults to `BUN_PUBLIC_*`)
+
+## Installation
+
+
+pnpm
+
+```sh
+pnpm add @arkenv/bun-plugin arktype
+```
+
+
+
+npm
+
+```sh
+npm install @arkenv/bun-plugin arktype
+```
+
+
+
+Yarn
+
+```sh
+yarn add @arkenv/bun-plugin arktype
+```
+
+
+
+Bun
+
+```sh
+bun add @arkenv/bun-plugin arktype
+```
+
+
+## Usage
+
+### Basic Example
+
+```ts
+// bun.config.ts or in Bun.build()
+import arkenv from '@arkenv/bun-plugin';
+
+await Bun.build({
+ entrypoints: ['./app.tsx'],
+ outdir: './dist',
+ plugins: [
+ arkenv({
+ BUN_PUBLIC_API_URL: 'string',
+ BUN_PUBLIC_DEBUG: 'boolean',
+ }),
+ ],
+});
+```
+
+### With Type Augmentation
+
+```ts
+// src/env.d.ts
+///
+
+import type { ProcessEnvAugmented } from '@arkenv/bun-plugin';
+
+declare global {
+ namespace NodeJS {
+ // Note: This assumes your env schema is the default export from "./env"
+ interface ProcessEnv extends ProcessEnvAugmented {}
+ }
+}
+```
+
+## Examples
+
+* [bun-react](https://github.com/yamcodes/arkenv/tree/main/apps/playgrounds/bun-react)
+
+## Related
+
+- [ArkEnv](https://arkenv.js.org) - Core library and docs
+- [ArkType](https://arktype.io/) - Underlying validator / type system
diff --git a/packages/bun-plugin/package.json b/packages/bun-plugin/package.json
new file mode 100644
index 000000000..8709bc115
--- /dev/null
+++ b/packages/bun-plugin/package.json
@@ -0,0 +1,68 @@
+{
+ "name": "@arkenv/bun-plugin",
+ "version": "0.0.1",
+ "author": "Yam Borodetsky ",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/yamcodes/arkenv.git"
+ },
+ "main": "./dist/index.cjs",
+ "module": "./dist/index.js",
+ "dependencies": {
+ "arkenv": "workspace:*"
+ },
+ "devDependencies": {
+ "@repo/types": "workspace:*",
+ "@size-limit/preset-small-lib": "11.2.0",
+ "@types/bun": "1.3.2",
+ "arktype": "2.1.27",
+ "bun": "1.1.0",
+ "size-limit": "11.2.0",
+ "tsdown": "0.16.5",
+ "typescript": "5.9.3",
+ "vitest": "4.0.10"
+ },
+ "peerDependencies": {
+ "arktype": "^2.1.22",
+ "bun": "^1.0.0"
+ },
+ "exports": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js",
+ "require": "./dist/index.cjs"
+ },
+ "bugs": "https://github.com/yamcodes/arkenv/labels/%40arkenv%2Fbun-plugin",
+ "description": "Bun plugin for ArkEnv",
+ "files": [
+ "dist"
+ ],
+ "homepage": "https://arkenv.js.org",
+ "keywords": [
+ "arktype",
+ "arkenv",
+ "environment",
+ "variables",
+ "bun",
+ "plugin",
+ "bun-plugin"
+ ],
+ "license": "MIT",
+ "scripts": {
+ "build": "tsdown",
+ "typecheck": "tsc --noEmit",
+ "clean": "rimraf dist node_modules",
+ "test": "vitest",
+ "fix": "pnpm -w run fix",
+ "changeset": "pnpm -w run changeset",
+ "size": "size-limit"
+ },
+ "type": "module",
+ "types": "./dist/index.d.ts",
+ "size-limit": [
+ {
+ "path": "dist/index.js",
+ "limit": "2 kB",
+ "import": "*"
+ }
+ ]
+}
diff --git a/packages/bun-plugin/src/__mocks__/bun.ts b/packages/bun-plugin/src/__mocks__/bun.ts
new file mode 100644
index 000000000..6da02df2d
--- /dev/null
+++ b/packages/bun-plugin/src/__mocks__/bun.ts
@@ -0,0 +1,23 @@
+// Mock Bun plugin API for testing
+export function plugin(pluginConfig: {
+ name: string;
+ setup: (build: {
+ onLoad: (
+ args: { filter: RegExp },
+ callback: (args: { path: string }) => Promise<
+ | {
+ loader?: string;
+ contents?: string;
+ }
+ | undefined
+ >,
+ ) => void;
+ }) => void;
+}) {
+ return {
+ name: pluginConfig.name,
+ setup: pluginConfig.setup,
+ };
+}
+
+export type BunPlugin = ReturnType;
diff --git a/packages/bun-plugin/src/index.test.ts b/packages/bun-plugin/src/index.test.ts
new file mode 100644
index 000000000..96a576a63
--- /dev/null
+++ b/packages/bun-plugin/src/index.test.ts
@@ -0,0 +1,69 @@
+import { afterEach, beforeEach, describe, expect, it } from "vitest";
+import arkenvPlugin, { processEnvSchema } from "./index.js";
+
+describe("Bun Plugin", () => {
+ let originalEnv: NodeJS.ProcessEnv;
+
+ beforeEach(() => {
+ originalEnv = { ...process.env };
+ });
+
+ afterEach(() => {
+ process.env = originalEnv;
+ });
+
+ it("should create a plugin function", () => {
+ expect(typeof arkenvPlugin).toBe("function");
+ });
+
+ it("should return a Bun plugin object", () => {
+ // Set up a valid environment variable
+ process.env.BUN_PUBLIC_TEST = "test-value";
+
+ const pluginInstance = arkenvPlugin({ BUN_PUBLIC_TEST: "string" });
+
+ expect(pluginInstance).toHaveProperty("name", "@arkenv/bun-plugin");
+ expect(pluginInstance).toHaveProperty("setup");
+ expect(typeof pluginInstance.setup).toBe("function");
+ });
+
+ it("should validate environment variables at plugin creation", () => {
+ // Set up a valid environment variable
+ process.env.BUN_PUBLIC_TEST = "test-value";
+
+ expect(() => {
+ arkenvPlugin({ BUN_PUBLIC_TEST: "string" });
+ }).not.toThrow();
+ });
+
+ it("should throw if environment variable validation fails", () => {
+ // Don't set the required environment variable
+ delete process.env.BUN_PUBLIC_REQUIRED;
+
+ expect(() => {
+ arkenvPlugin({ BUN_PUBLIC_REQUIRED: "string" });
+ }).toThrow();
+ });
+
+ it("should filter out non-prefixed variables", () => {
+ process.env.BUN_PUBLIC_API_URL = "https://api.example.com";
+ process.env.PORT = "3000";
+ process.env.DATABASE_URL = "postgres://localhost/db";
+
+ const envMap = processEnvSchema({
+ BUN_PUBLIC_API_URL: "string",
+ PORT: "number.port",
+ DATABASE_URL: "string",
+ });
+
+ // Check that prefixed variables are present
+ expect(envMap.has("BUN_PUBLIC_API_URL")).toBe(true);
+ expect(envMap.get("BUN_PUBLIC_API_URL")).toBe(
+ JSON.stringify("https://api.example.com"),
+ );
+
+ // Check that non-prefixed variables are filtered out
+ expect(envMap.has("PORT")).toBe(false);
+ expect(envMap.has("DATABASE_URL")).toBe(false);
+ });
+});
diff --git a/packages/bun-plugin/src/index.ts b/packages/bun-plugin/src/index.ts
new file mode 100644
index 000000000..3153ae79c
--- /dev/null
+++ b/packages/bun-plugin/src/index.ts
@@ -0,0 +1,241 @@
+import { join } from "node:path";
+import type { EnvSchema } from "arkenv";
+import { createEnv } from "arkenv";
+import type { type } from "arktype";
+import type { BunPlugin, Loader, PluginBuilder } from "bun";
+
+export type { ProcessEnvAugmented } from "./types";
+
+/**
+ * Helper to process env schema and return envMap
+ */
+export function processEnvSchema(options: EnvSchema | type.Any) {
+ // Validate environment variables
+ const env = createEnv(options, process.env);
+
+ // Get Bun's prefix for client-exposed environment variables
+ const prefix = "BUN_PUBLIC_";
+
+ // Filter to only include environment variables matching the prefix
+ const filteredEnv = Object.fromEntries(
+ Object.entries(>env).filter(([key]) =>
+ key.startsWith(prefix),
+ ),
+ );
+
+ // Create a map of variable names to their JSON-stringified values
+ const envMap = new Map();
+ for (const [key, value] of Object.entries(filteredEnv)) {
+ envMap.set(key, JSON.stringify(value));
+ }
+ return envMap;
+}
+
+/**
+ * Helper to register the onLoad handler
+ */
+function registerLoader(build: PluginBuilder, envMap: Map) {
+ build.onLoad({ filter: /\.(js|jsx|ts|tsx|mjs|cjs)$/ }, async (args) => {
+ // Skip node_modules and other non-source files
+ if (args.path.includes("node_modules")) {
+ return undefined;
+ }
+
+ try {
+ // Read the file contents
+ const file = Bun.file(args.path);
+ const contents = await file.text();
+
+ // Replace process.env.VARIABLE patterns with validated values
+ let transformed = contents;
+
+ // Pattern 1: process.env.VARIABLE
+ // Pattern 2: process.env["VARIABLE"]
+ // Pattern 3: process.env['VARIABLE']
+ for (const [key, value] of envMap.entries()) {
+ // Replace process.env.KEY (word boundary to avoid partial matches)
+ const dotPattern = new RegExp(
+ `process\\.env\\.${key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`,
+ "g",
+ );
+ transformed = transformed.replace(dotPattern, value);
+
+ // Replace process.env["KEY"] and process.env['KEY']
+ const bracketPattern = new RegExp(
+ `process\\.env\\[(["'])${key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\1\\]`,
+ "g",
+ );
+ transformed = transformed.replace(bracketPattern, value);
+ }
+
+ // Determine loader based on file extension
+ const loader = (
+ args.path.endsWith(".tsx") || args.path.endsWith(".jsx")
+ ? "tsx"
+ : args.path.endsWith(".ts") || args.path.endsWith(".mts")
+ ? "ts"
+ : "js"
+ ) as Loader;
+
+ return {
+ loader,
+ contents: transformed,
+ };
+ } catch (error) {
+ // If file can't be read, return undefined to let Bun handle it
+ return undefined;
+ }
+ });
+}
+
+/**
+ * Bun plugin to validate environment variables using ArkEnv and expose prefixed variables to client code.
+ *
+ * You can use this in one of two ways:
+ *
+ * 1. **Zero-config (Static Analysis)**:
+ * Automatically looks for `./src/env.ts` or `./env.ts`.
+ *
+ * In `bunfig.toml`:
+ * ```toml
+ * [serve.static]
+ * plugins = ["@arkenv/bun-plugin"]
+ * ```
+ * and in `Bun.build`:
+ * ```ts
+ * import arkenv from "@arkenv/bun-plugin";
+ * Bun.build({
+ * plugins: [arkenv]
+ * })
+ * ```
+ *
+ * 2. **Manual Configuration**:
+ * Call it as a function in `Bun.build` with your schema.
+ * ```ts
+ * import arkenv from "@arkenv/bun-plugin";
+ * import { Env } from "./src/env";
+ * Bun.build({
+ * plugins: [arkenv(Env)]
+ * })
+ * ```
+ */
+export function arkenv>(
+ options: EnvSchema,
+): BunPlugin;
+export function arkenv(options: type.Any): BunPlugin;
+export function arkenv>(
+ options: EnvSchema | type.Any,
+): BunPlugin {
+ const envMap = processEnvSchema(options);
+
+ return {
+ name: "@arkenv/bun-plugin",
+ setup(build) {
+ registerLoader(build, envMap);
+ },
+ } satisfies BunPlugin;
+}
+
+// Attach static analysis properties to the function to make it a valid BunPlugin object
+// This allows it to be used in bunfig.toml as `plugins = ["@arkenv/bun-plugin"]`
+/**
+ * Bun plugin to validate environment variables using ArkEnv and expose prefixed variables to client code.
+ *
+ * You can use this in one of two ways:
+ *
+ * 1. **Zero-config (Static Analysis)**:
+ * Automatically looks for `./src/env.ts` or `./env.ts`.
+ *
+ * In `bunfig.toml`:
+ * ```toml
+ * [serve.static]
+ * plugins = ["@arkenv/bun-plugin"]
+ * ```
+ * and in `Bun.build`:
+ * ```ts
+ * import arkenv from "@arkenv/bun-plugin";
+ * Bun.build({
+ * plugins: [arkenv]
+ * })
+ * ```
+ *
+ * 2. **Manual Configuration**:
+ * Call it as a function in `Bun.build` with your schema.
+ * ```ts
+ * import arkenv from "@arkenv/bun-plugin";
+ * import { Env } from "./src/env";
+ * Bun.build({
+ * plugins: [arkenv(Env)]
+ * })
+ * ```
+ */
+const hybrid = arkenv as typeof arkenv & BunPlugin;
+
+Object.defineProperty(hybrid, "name", {
+ value: "@arkenv/bun-plugin",
+ writable: false,
+});
+
+hybrid.setup = (build) => {
+ const envMap = new Map();
+
+ build.onStart(async () => {
+ const cwd = process.cwd();
+ let schema: any;
+
+ const possiblePaths = [join(cwd, "src", "env.ts"), join(cwd, "env.ts")];
+
+ for (const p of possiblePaths) {
+ if (await Bun.file(p).exists()) {
+ try {
+ // Invalidate cache to support hot reloading of the schema file itself
+ // Note: Bun's require cache invalidation might be needed if using require
+ // For ESM import(), we might need a cache busting query param or similar if Bun caches it aggressively
+ // However, for now, we'll try standard import.
+ // To truly support hot reload of config, we might need to rely on Bun's watcher restarting the process
+ // when bunfig.toml or dependencies change.
+ const mod = await import(p);
+ if (mod.default) {
+ schema = mod.default;
+ break;
+ }
+ if (mod.env) {
+ schema = mod.env;
+ break;
+ }
+ } catch (e) {
+ console.error(`Failed to load env schema from ${p}:`, e);
+ }
+ }
+ }
+
+ if (!schema) {
+ const pathsList = possiblePaths.map((p) => ` - ${p}`).join("\n");
+ const example = `
+Example \`src/env.ts\`:
+\`\`\`ts
+import { type } from "arktype";
+
+export default type({
+ BUN_PUBLIC_API_URL: "string",
+ BUN_PUBLIC_DEBUG: "boolean"
+});
+\`\`\`
+`;
+ throw new Error(
+ `@arkenv/bun-plugin: No environment schema found.\n\nChecked paths:\n${pathsList}\n\nPlease create a schema file at one of these locations exporting your environment definition.\n${example}`,
+ );
+ }
+
+ // Update the shared envMap with new values
+ const newEnvMap = processEnvSchema(schema);
+ envMap.clear();
+ for (const [k, v] of newEnvMap) {
+ envMap.set(k, v);
+ }
+ });
+
+ registerLoader(build, envMap);
+};
+
+export default hybrid;
diff --git a/packages/bun-plugin/src/types.ts b/packages/bun-plugin/src/types.ts
new file mode 100644
index 000000000..d17d16e86
--- /dev/null
+++ b/packages/bun-plugin/src/types.ts
@@ -0,0 +1,61 @@
+import type { InferType } from "@repo/types";
+import type { type } from "arktype";
+
+/**
+ * Filter environment variables to only include those that start with the given prefix.
+ * This ensures only client-exposed variables (e.g., BUN_PUBLIC_*) are included in process.env.
+ */
+type FilterByPrefix<
+ T extends Record,
+ Prefix extends string = "BUN_PUBLIC_",
+> = {
+ [K in keyof T as K extends `${Prefix}${string}` ? K : never]: T[K];
+};
+
+/**
+ * Augment the `process.env` object with typesafe environment variables
+ * based on the schema validator.
+ *
+ * This type extracts the inferred type from the schema (result of `type()` from arkenv),
+ * filters it to only include variables matching the Bun prefix (defaults to "BUN_PUBLIC_"),
+ * and makes them available on `process.env`.
+ *
+ * @template TSchema - The environment variable schema (result of `type()` from arkenv)
+ * @template Prefix - The prefix to filter by (defaults to "BUN_PUBLIC_")
+ *
+ * @example
+ * ```ts
+ * // bun.config.ts or similar
+ * import arkenv from '@arkenv/bun-plugin';
+ * import { type } from 'arkenv';
+ *
+ * export const Env = type({
+ * BUN_PUBLIC_API_URL: 'string',
+ * BUN_PUBLIC_DEBUG: 'boolean',
+ * PORT: 'number.port', // Server-only, won't be in ProcessEnvAugmented
+ * });
+ *
+ * export default {
+ * plugins: [arkenv(Env)],
+ * };
+ * ```
+ *
+ * @example
+ * ```ts
+ * // src/env.d.ts
+ * ///
+ *
+ * import type { ProcessEnvAugmented } from '@arkenv/bun-plugin';
+ * import type { Env } from './env'; // or from bun.config.ts
+ *
+ * declare global {
+ * namespace NodeJS {
+ * interface ProcessEnv extends ProcessEnvAugmented {}
+ * }
+ * }
+ * ```
+ */
+export type ProcessEnvAugmented<
+ TSchema extends type.Any,
+ Prefix extends string = "BUN_PUBLIC_",
+> = FilterByPrefix, Prefix>;
diff --git a/packages/bun-plugin/tsconfig.json b/packages/bun-plugin/tsconfig.json
new file mode 100644
index 000000000..0288a3e60
--- /dev/null
+++ b/packages/bun-plugin/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "target": "es2020",
+ "module": "esnext",
+ "strict": true,
+ "esModuleInterop": true,
+ "moduleResolution": "bundler",
+ "skipLibCheck": true,
+ "noUnusedLocals": true,
+ "noImplicitAny": true,
+ "emitDeclarationOnly": true,
+ "outDir": "dist",
+ "resolveJsonModule": true,
+ "declaration": true,
+ "declarationMap": true
+ }
+}
diff --git a/packages/bun-plugin/tsdown.config.ts b/packages/bun-plugin/tsdown.config.ts
new file mode 100644
index 000000000..4bee4f713
--- /dev/null
+++ b/packages/bun-plugin/tsdown.config.ts
@@ -0,0 +1,11 @@
+import { defineConfig } from "tsdown";
+
+export default defineConfig({
+ format: ["esm", "cjs"],
+ minify: true,
+ fixedExtension: false,
+ sourcemap: true,
+ dts: {
+ resolve: ["@repo/types"],
+ },
+});
diff --git a/packages/bun-plugin/turbo.json b/packages/bun-plugin/turbo.json
new file mode 100644
index 000000000..3e34e8a2f
--- /dev/null
+++ b/packages/bun-plugin/turbo.json
@@ -0,0 +1,10 @@
+{
+ "extends": ["//"],
+ "tasks": {
+ // Defined here and not in the root turbo.json to avoid building all packages when running `turbo run size`.
+ "size": {
+ "dependsOn": ["build"],
+ "cache": false
+ }
+ }
+}
diff --git a/packages/bun-plugin/vitest.config.ts b/packages/bun-plugin/vitest.config.ts
new file mode 100644
index 000000000..53978c91b
--- /dev/null
+++ b/packages/bun-plugin/vitest.config.ts
@@ -0,0 +1,14 @@
+import { defineConfig } from "vitest/config";
+
+export default defineConfig({
+ test: {
+ environment: "node",
+ },
+ resolve: {
+ alias: {
+ // Mock bun module for testing
+ bun: new URL("./src/__mocks__/bun.ts", import.meta.url).pathname,
+ arkenv: new URL("../arkenv/src/index.ts", import.meta.url).pathname,
+ },
+ },
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 057d2a2b3..f12eb7717 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -128,6 +128,15 @@ importers:
apps/playgrounds/bun-react:
dependencies:
+ '@arkenv/bun-plugin':
+ specifier: workspace:*
+ version: link:../../../packages/bun-plugin
+ arkenv:
+ specifier: workspace:*
+ version: link:../../../packages/arkenv
+ arktype:
+ specifier: 'catalog:'
+ version: 2.1.27
react:
specifier: 'catalog:'
version: 19.2.0
@@ -418,6 +427,40 @@ importers:
specifier: 'catalog:'
version: 4.0.14(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/ui@4.0.14)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)
+ packages/bun-plugin:
+ dependencies:
+ arkenv:
+ specifier: workspace:*
+ version: link:../arkenv
+ devDependencies:
+ '@repo/types':
+ specifier: workspace:*
+ version: link:../internal/types
+ '@size-limit/preset-small-lib':
+ specifier: 11.2.0
+ version: 11.2.0(size-limit@11.2.0)
+ '@types/bun':
+ specifier: 1.3.2
+ version: 1.3.2(@types/react@19.2.7)
+ arktype:
+ specifier: 2.1.27
+ version: 2.1.27
+ bun:
+ specifier: 1.1.0
+ version: 1.1.0
+ size-limit:
+ specifier: 11.2.0
+ version: 11.2.0
+ tsdown:
+ specifier: 0.16.5
+ version: 0.16.5(typescript@5.9.3)
+ typescript:
+ specifier: 5.9.3
+ version: 5.9.3
+ vitest:
+ specifier: 4.0.10
+ version: 4.0.10(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@4.0.14)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)
+
packages/internal/types:
devDependencies:
arktype:
@@ -1817,6 +1860,46 @@ packages:
resolution: {integrity: sha512-scSmQBD8eANlMUOglxHrN1JdSW8tDghsPuS83otqealBiIeMukCQMOf/wc0JJjDXomqwNdEQFLXLGHrU6PGxuA==}
engines: {node: '>= 20.0.0'}
+ '@oven/bun-darwin-aarch64@1.1.0':
+ resolution: {integrity: sha512-8hDDBdQVHfFJ1KHXeHIB78SFs7rYG1Ff4n8SDv006ENc3uEIqynFVbHCKbqa5aE7zLkdBizoBzL50W76zAPmCQ==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@oven/bun-darwin-x64-baseline@1.1.0':
+ resolution: {integrity: sha512-61rkVhpzU3PfoXRLrIpgKzLys4Qk9bvCI5DVM5cZgVxGq62jR+FwldCVcCoyfMdblGg07x3aUY9BXMwtSxvN0A==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@oven/bun-darwin-x64@1.1.0':
+ resolution: {integrity: sha512-KNEtlnEok6LB9ZNMe2aSxRVO8ps22hn4qTTjJc/s0josPNlIk4PvV2xusbUEGQS4XSNGcEH/Gh7VYE/W3u1gjg==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@oven/bun-linux-aarch64@1.1.0':
+ resolution: {integrity: sha512-UZhZU2mkC+OnbDB/Lq8MTJWiwhDMrnZvcW99cc+fymU5w/bOvpSuFOhpC/IeI1Dp8WGlkjDGyottSr++juWXOw==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@oven/bun-linux-x64-baseline@1.1.0':
+ resolution: {integrity: sha512-eAxK+x5dEzoVGR0f4FiiLYgtzHu8xB8uWB+Uc9h/6C46vODlOPsBT2Pwv6y5uPAX+dyKGHeMQsP+r2OFBkbkTA==}
+ cpu: [x64]
+ os: [linux]
+
+ '@oven/bun-linux-x64@1.1.0':
+ resolution: {integrity: sha512-o2D9LGXyJqHTQ5tTF4GSctL20ZFw0EGwrhhCLPM4cGzHrhji3EP9euz28aREM+iYUqAWC6BOGz77up5yeMbBQw==}
+ cpu: [x64]
+ os: [linux]
+
+ '@oven/bun-windows-x64-baseline@1.1.0':
+ resolution: {integrity: sha512-PqQToENBnHkzdcUnkCYI86397oNvs8Z7PZT8iyQEMSr/oYTMNCSArgrpFSEG6seN5HBPkSyhbj0fuU3U5oOhtQ==}
+ cpu: [x64]
+ os: [win32]
+
+ '@oven/bun-windows-x64@1.1.0':
+ resolution: {integrity: sha512-SStu+4Zq0S/nfwaSz9QcBnk9CYjlSckzkzChoFt+vdIXfiaCT+uq0I57OXifRb67uOVtXl6N3PqmCivJPTh/kw==}
+ cpu: [x64]
+ os: [win32]
+
'@oxc-project/runtime@0.96.0':
resolution: {integrity: sha512-34lh4o9CcSw09Hx6fKihPu85+m+4pmDlkXwJrLvN5nMq5JrcGhhihVM415zDqT8j8IixO1PYYdQZRN4SwQCncg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1825,6 +1908,9 @@ packages:
resolution: {integrity: sha512-8iE5/4OK0SLHqWzRxSvI1gjFPmIH6718s8iwkuco95rBZsCZIHq+5wy4lYsASxnH+8FOhbGndiUrcwsVG5i2zw==}
engines: {node: ^20.19.0 || >=22.12.0}
+ '@oxc-project/types@0.97.0':
+ resolution: {integrity: sha512-lxmZK4xFrdvU0yZiDwgVQTCvh2gHWBJCBk5ALsrtsBWhs0uDIi+FTOnXRQeQfs304imdvTdaakT/lqwQ8hkOXQ==}
+
'@oxc-project/types@0.98.0':
resolution: {integrity: sha512-Vzmd6FsqVuz5HQVcRC/hrx7Ujo3WEVeQP7C2UNP5uy1hUY4SQvMB+93jxkI1KRHz9a/6cni3glPOtvteN+zpsw==}
@@ -2385,6 +2471,12 @@ packages:
'@radix-ui/rect@1.1.1':
resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==}
+ '@rolldown/binding-android-arm64@1.0.0-beta.50':
+ resolution: {integrity: sha512-XlEkrOIHLyGT3avOgzfTFSjG+f+dZMw+/qd+Y3HLN86wlndrB/gSimrJCk4gOhr1XtRtEKfszpadI3Md4Z4/Ag==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [android]
+
'@rolldown/binding-android-arm64@1.0.0-beta.51':
resolution: {integrity: sha512-Ctn8FUXKWWQI9pWC61P1yumS9WjQtelNS9riHwV7oCkknPGaAry4o7eFx2KgoLMnI2BgFJYpW7Im8/zX3BuONg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2397,6 +2489,12 @@ packages:
cpu: [arm64]
os: [android]
+ '@rolldown/binding-darwin-arm64@1.0.0-beta.50':
+ resolution: {integrity: sha512-+JRqKJhoFlt5r9q+DecAGPLZ5PxeLva+wCMtAuoFMWPoZzgcYrr599KQ+Ix0jwll4B4HGP43avu9My8KtSOR+w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [darwin]
+
'@rolldown/binding-darwin-arm64@1.0.0-beta.51':
resolution: {integrity: sha512-EL1aRW2Oq15ShUEkBPsDtLMO8GTqfb/ktM/dFaVzXKQiEE96Ss6nexMgfgQrg8dGnNpndFyffVDb5IdSibsu1g==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2409,6 +2507,12 @@ packages:
cpu: [arm64]
os: [darwin]
+ '@rolldown/binding-darwin-x64@1.0.0-beta.50':
+ resolution: {integrity: sha512-fFXDjXnuX7/gQZQm/1FoivVtRcyAzdjSik7Eo+9iwPQ9EgtA5/nB2+jmbzaKtMGG3q+BnZbdKHCtOacmNrkIDA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [darwin]
+
'@rolldown/binding-darwin-x64@1.0.0-beta.51':
resolution: {integrity: sha512-uGtYKlFen9pMIPvkHPWZVDtmYhMQi5g5Ddsndg1gf3atScKYKYgs5aDP4DhHeTwGXQglhfBG7lEaOIZ4UAIWww==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2421,6 +2525,12 @@ packages:
cpu: [x64]
os: [darwin]
+ '@rolldown/binding-freebsd-x64@1.0.0-beta.50':
+ resolution: {integrity: sha512-F1b6vARy49tjmT/hbloplzgJS7GIvwWZqt+tAHEstCh0JIh9sa8FAMVqEmYxDviqKBaAI8iVvUREm/Kh/PD26Q==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [freebsd]
+
'@rolldown/binding-freebsd-x64@1.0.0-beta.51':
resolution: {integrity: sha512-JRoVTQtHYbZj1P07JLiuTuXjiBtIa7ag7/qgKA6CIIXnAcdl4LrOf7nfDuHPJcuRKaP5dzecMgY99itvWfmUFQ==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2433,6 +2543,12 @@ packages:
cpu: [x64]
os: [freebsd]
+ '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.50':
+ resolution: {integrity: sha512-U6cR76N8T8M6lHj7EZrQ3xunLPxSvYYxA8vJsBKZiFZkT8YV4kjgCO3KwMJL0NOjQCPGKyiXO07U+KmJzdPGRw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.51':
resolution: {integrity: sha512-BKATVnpPZ0TYBW9XfDwyd4kPGgvf964HiotIwUgpMrFOFYWqpZ+9ONNzMV4UFAYC7Hb5C2qgYQk/qj2OnAd4RQ==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2445,6 +2561,12 @@ packages:
cpu: [arm]
os: [linux]
+ '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50':
+ resolution: {integrity: sha512-ONgyjofCrrE3bnh5GZb8EINSFyR/hmwTzZ7oVuyUB170lboza1VMCnb8jgE6MsyyRgHYmN8Lb59i3NKGrxrYjw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+
'@rolldown/binding-linux-arm64-gnu@1.0.0-beta.51':
resolution: {integrity: sha512-xLd7da5jkfbVsBCm1buIRdWtuXY8+hU3+6ESXY/Tk5X5DPHaifrUblhYDgmA34dQt6WyNC2kfXGgrduPEvDI6Q==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2457,6 +2579,12 @@ packages:
cpu: [arm64]
os: [linux]
+ '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50':
+ resolution: {integrity: sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+
'@rolldown/binding-linux-arm64-musl@1.0.0-beta.51':
resolution: {integrity: sha512-EQFXTgHxxTzv3t5EmjUP/DfxzFYx9sMndfLsYaAY4DWF6KsK1fXGYsiupif6qPTViPC9eVmRm78q0pZU/kuIPg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2469,6 +2597,12 @@ packages:
cpu: [arm64]
os: [linux]
+ '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50':
+ resolution: {integrity: sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+
'@rolldown/binding-linux-x64-gnu@1.0.0-beta.51':
resolution: {integrity: sha512-p5P6Xpa68w3yFaAdSzIZJbj+AfuDnMDqNSeglBXM7UlJT14Q4zwK+rV+8Mhp9MiUb4XFISZtbI/seBprhkQbiQ==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2481,6 +2615,12 @@ packages:
cpu: [x64]
os: [linux]
+ '@rolldown/binding-linux-x64-musl@1.0.0-beta.50':
+ resolution: {integrity: sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+
'@rolldown/binding-linux-x64-musl@1.0.0-beta.51':
resolution: {integrity: sha512-sNVVyLa8HB8wkFipdfz1s6i0YWinwpbMWk5hO5S+XAYH2UH67YzUT13gs6wZTKg2x/3gtgXzYnHyF5wMIqoDAw==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2493,6 +2633,12 @@ packages:
cpu: [x64]
os: [linux]
+ '@rolldown/binding-openharmony-arm64@1.0.0-beta.50':
+ resolution: {integrity: sha512-eZUssog7qljrrRU9Mi0eqYEPm3Ch0UwB+qlWPMKSUXHNqhm3TvDZarJQdTevGEfu3EHAXJvBIe0YFYr0TPVaMA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [openharmony]
+
'@rolldown/binding-openharmony-arm64@1.0.0-beta.51':
resolution: {integrity: sha512-e/JMTz9Q8+T3g/deEi8DK44sFWZWGKr9AOCW5e8C8SCVWzAXqYXAG7FXBWBNzWEZK0Rcwo9TQHTQ9Q0gXgdCaA==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2505,6 +2651,11 @@ packages:
cpu: [arm64]
os: [openharmony]
+ '@rolldown/binding-wasm32-wasi@1.0.0-beta.50':
+ resolution: {integrity: sha512-nmCN0nIdeUnmgeDXiQ+2HU6FT162o+rxnF7WMkBm4M5Ds8qTU7Dzv2Wrf22bo4ftnlrb2hKK6FSwAJSAe2FWLg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+
'@rolldown/binding-wasm32-wasi@1.0.0-beta.51':
resolution: {integrity: sha512-We3LWqSu6J9s5Y0MK+N7fUiiu37aBGPG3Pc347EoaROuAwkCS2u9xJ5dpIyLW4B49CIbS3KaPmn4kTgPb3EyPw==}
engines: {node: '>=14.0.0'}
@@ -2515,6 +2666,12 @@ packages:
engines: {node: '>=14.0.0'}
cpu: [wasm32]
+ '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.50':
+ resolution: {integrity: sha512-7kcNLi7Ua59JTTLvbe1dYb028QEPaJPJQHqkmSZ5q3tJueUeb6yjRtx8mw4uIqgWZcnQHAR3PrLN4XRJxvgIkA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [win32]
+
'@rolldown/binding-win32-arm64-msvc@1.0.0-beta.51':
resolution: {integrity: sha512-fj56buHRuMM+r/cb6ZYfNjNvO/0xeFybI6cTkTROJatdP4fvmQ1NS8D/Lm10FCSDEOkqIz8hK3TGpbAThbPHsA==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2527,6 +2684,12 @@ packages:
cpu: [arm64]
os: [win32]
+ '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.50':
+ resolution: {integrity: sha512-lL70VTNvSCdSZkDPPVMwWn/M2yQiYvSoXw9hTLgdIWdUfC3g72UaruezusR6ceRuwHCY1Ayu2LtKqXkBO5LIwg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [ia32]
+ os: [win32]
+
'@rolldown/binding-win32-ia32-msvc@1.0.0-beta.51':
resolution: {integrity: sha512-fkqEqaeEx8AySXiDm54b/RdINb3C0VovzJA3osMhZsbn6FoD73H0AOIiaVAtGr6x63hefruVKTX8irAm4Jkt2w==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2539,6 +2702,12 @@ packages:
cpu: [ia32]
os: [win32]
+ '@rolldown/binding-win32-x64-msvc@1.0.0-beta.50':
+ resolution: {integrity: sha512-4qU4x5DXWB4JPjyTne/wBNPqkbQU8J45bl21geERBKtEittleonioACBL1R0PsBu0Aq21SwMK5a9zdBkWSlQtQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [win32]
+
'@rolldown/binding-win32-x64-msvc@1.0.0-beta.51':
resolution: {integrity: sha512-CWuLG/HMtrVcjKGa0C4GnuxONrku89g0+CsH8nT0SNhOtREXuzwgjIXNJImpE/A/DMf9JF+1Xkrq/YRr+F/rCg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2554,6 +2723,9 @@ packages:
'@rolldown/pluginutils@1.0.0-beta.47':
resolution: {integrity: sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==}
+ '@rolldown/pluginutils@1.0.0-beta.50':
+ resolution: {integrity: sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==}
+
'@rolldown/pluginutils@1.0.0-beta.51':
resolution: {integrity: sha512-51/8cNXMrqWqX3o8DZidhwz1uYq0BhHDDSfVygAND1Skx5s1TDw3APSSxCMcFFedwgqGcx34gRouwY+m404BBQ==}
@@ -3350,6 +3522,9 @@ packages:
'@types/braces@3.0.5':
resolution: {integrity: sha512-SQFof9H+LXeWNz8wDe7oN5zu7ket0qwMu5vZubW4GCJ8Kkeh6nBWUz87+KTz/G3Kqsrp0j/W253XJb3KMEeg3w==}
+ '@types/bun@1.3.2':
+ resolution: {integrity: sha512-t15P7k5UIgHKkxwnMNkJbWlh/617rkDGEdSsDbu+qNHTaz9SKf7aC8fiIlUdD5RPpH6GEkP0cK7WlvmrEBRtWg==}
+
'@types/bun@1.3.3':
resolution: {integrity: sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g==}
@@ -3522,9 +3697,23 @@ packages:
peerDependencies:
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
+ '@vitest/expect@4.0.10':
+ resolution: {integrity: sha512-3QkTX/lK39FBNwARCQRSQr0TP9+ywSdxSX+LgbJ2M1WmveXP72anTbnp2yl5fH+dU6SUmBzNMrDHs80G8G2DZg==}
+
'@vitest/expect@4.0.14':
resolution: {integrity: sha512-RHk63V3zvRiYOWAV0rGEBRO820ce17hz7cI2kDmEdfQsBjT2luEKB5tCOc91u1oSQoUOZkSv3ZyzkdkSLD7lKw==}
+ '@vitest/mocker@4.0.10':
+ resolution: {integrity: sha512-e2OfdexYkjkg8Hh3L9NVEfbwGXq5IZbDovkf30qW2tOh7Rh9sVtmSr2ztEXOFbymNxS4qjzLXUQIvATvN4B+lg==}
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^6.0.0 || ^7.0.0-0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
'@vitest/mocker@4.0.14':
resolution: {integrity: sha512-RzS5NujlCzeRPF1MK7MXLiEFpkIXeMdQ+rN3Kk3tDI9j0mtbr7Nmuq67tpkOJQpgyClbOltCXMjLZicJHsH5Cg==}
peerDependencies:
@@ -3536,15 +3725,27 @@ packages:
vite:
optional: true
+ '@vitest/pretty-format@4.0.10':
+ resolution: {integrity: sha512-99EQbpa/zuDnvVjthwz5bH9o8iPefoQZ63WV8+bsRJZNw3qQSvSltfut8yu1Jc9mqOYi7pEbsKxYTi/rjaq6PA==}
+
'@vitest/pretty-format@4.0.14':
resolution: {integrity: sha512-SOYPgujB6TITcJxgd3wmsLl+wZv+fy3av2PpiPpsWPZ6J1ySUYfScfpIt2Yv56ShJXR2MOA6q2KjKHN4EpdyRQ==}
+ '@vitest/runner@4.0.10':
+ resolution: {integrity: sha512-EXU2iSkKvNwtlL8L8doCpkyclw0mc/t4t9SeOnfOFPyqLmQwuceMPA4zJBa6jw0MKsZYbw7kAn+gl7HxrlB8UQ==}
+
'@vitest/runner@4.0.14':
resolution: {integrity: sha512-BsAIk3FAqxICqREbX8SetIteT8PiaUL/tgJjmhxJhCsigmzzH8xeadtp7LRnTpCVzvf0ib9BgAfKJHuhNllKLw==}
+ '@vitest/snapshot@4.0.10':
+ resolution: {integrity: sha512-2N4X2ZZl7kZw0qeGdQ41H0KND96L3qX1RgwuCfy6oUsF2ISGD/HpSbmms+CkIOsQmg2kulwfhJ4CI0asnZlvkg==}
+
'@vitest/snapshot@4.0.14':
resolution: {integrity: sha512-aQVBfT1PMzDSA16Y3Fp45a0q8nKexx6N5Amw3MX55BeTeZpoC08fGqEZqVmPcqN0ueZsuUQ9rriPMhZ3Mu19Ag==}
+ '@vitest/spy@4.0.10':
+ resolution: {integrity: sha512-AsY6sVS8OLb96GV5RoG8B6I35GAbNrC49AO+jNRF9YVGb/g9t+hzNm1H6kD0NDp8tt7VJLs6hb7YMkDXqu03iw==}
+
'@vitest/spy@4.0.14':
resolution: {integrity: sha512-JmAZT1UtZooO0tpY3GRyiC/8W7dCs05UOq9rfsUUgEZEdq+DuHLmWhPsrTt0TiW7WYeL/hXpaE07AZ2RCk44hg==}
@@ -3553,6 +3754,9 @@ packages:
peerDependencies:
vitest: 4.0.14
+ '@vitest/utils@4.0.10':
+ resolution: {integrity: sha512-kOuqWnEwZNtQxMKg3WmPK1vmhZu9WcoX69iwWjVz+jvKTsF1emzsv3eoPcDr6ykA3qP2bsCQE7CwqfNtAVzsmg==}
+
'@vitest/utils@4.0.14':
resolution: {integrity: sha512-hLqXZKAWNg8pI+SQXyXxWCTOpA3MvsqcbVeNgSi8x/CSN2wi26dSzn1wrOhmCmFjEvN9p8/kLFRHa6PI8jHazw==}
@@ -3893,9 +4097,20 @@ packages:
buffer@6.0.3:
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
+ bun-types@1.3.2:
+ resolution: {integrity: sha512-i/Gln4tbzKNuxP70OWhJRZz1MRfvqExowP7U6JKoI8cntFrtxg7RJK3jvz7wQW54UuvNC8tbKHHri5fy74FVqg==}
+ peerDependencies:
+ '@types/react': ^19
+
bun-types@1.3.3:
resolution: {integrity: sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ==}
+ bun@1.1.0:
+ resolution: {integrity: sha512-vEfq5NXOWriLzVtA/gMC69MR/W48KE0G7SarZUbu7H89KH9u7FFozTvn8noyLKqpI1sRa2qu/laE21K+htFxCQ==}
+ cpu: [arm64, x64]
+ os: [darwin, linux, win32]
+ hasBin: true
+
bundle-name@4.1.0:
resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
engines: {node: '>=18'}
@@ -6271,6 +6486,25 @@ packages:
engines: {node: 20 || >=22}
hasBin: true
+ rolldown-plugin-dts@0.17.8:
+ resolution: {integrity: sha512-76EEBlhF00yeY6M7VpMkWKI4r9WjuoMiOGey7j4D6zf3m0BR+ZrrY9hvSXdueJ3ljxSLq4DJBKFpX/X9+L7EKw==}
+ engines: {node: '>=20.19.0'}
+ peerDependencies:
+ '@ts-macro/tsc': ^0.3.6
+ '@typescript/native-preview': '>=7.0.0-dev.20250601.1'
+ rolldown: ^1.0.0-beta.44
+ typescript: ^5.0.0
+ vue-tsc: ~3.1.0
+ peerDependenciesMeta:
+ '@ts-macro/tsc':
+ optional: true
+ '@typescript/native-preview':
+ optional: true
+ typescript:
+ optional: true
+ vue-tsc:
+ optional: true
+
rolldown-plugin-dts@0.18.1:
resolution: {integrity: sha512-uIgNMix6OI+6bSkw0nw6O+G/ydPRCWKwvvcEyL6gWkVkSFVGWWO23DX4ZYVOqC7w5u2c8uPY9Q74U0QCKvegFA==}
engines: {node: '>=20.19.0'}
@@ -6330,6 +6564,11 @@ packages:
yaml:
optional: true
+ rolldown@1.0.0-beta.50:
+ resolution: {integrity: sha512-JFULvCNl/anKn99eKjOSEubi0lLmNqQDAjyEMME2T4CwezUDL0i6t1O9xZsu2OMehPnV2caNefWpGF+8TnzB6A==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+
rolldown@1.0.0-beta.51:
resolution: {integrity: sha512-ZRLgPlS91l4JztLYEZnmMcd3Umcla1hkXJgiEiR4HloRJBBoeaX8qogTu5Jfu36rRMVLndzqYv0h+M5gJAkUfg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -6834,6 +7073,31 @@ packages:
typescript:
optional: true
+ tsdown@0.16.5:
+ resolution: {integrity: sha512-jo/2MmJI1uNJ+QvwEfF/2DcICd2Bc/Gc/XIVJS9Gvfns7ji5TgUeu3kYfG8nA/mGgWXU8REpTNweIcVJQoSLAQ==}
+ engines: {node: '>=20.19.0'}
+ hasBin: true
+ peerDependencies:
+ '@arethetypeswrong/core': ^0.18.1
+ '@vitejs/devtools': ^0.0.0-alpha.17
+ publint: ^0.3.0
+ typescript: ^5.0.0
+ unplugin-lightningcss: ^0.4.0
+ unplugin-unused: ^0.5.0
+ peerDependenciesMeta:
+ '@arethetypeswrong/core':
+ optional: true
+ '@vitejs/devtools':
+ optional: true
+ publint:
+ optional: true
+ typescript:
+ optional: true
+ unplugin-lightningcss:
+ optional: true
+ unplugin-unused:
+ optional: true
+
tsdown@0.16.7:
resolution: {integrity: sha512-3rGG74MGc16rJ70ID7WyKnJBM5TIqGX5uYbmUCdiFIc2c3+KXka4nCeji3RRxhBw/hL7Xbs8pCY8x2cn0J+O0w==}
engines: {node: '>=20.19.0'}
@@ -7257,6 +7521,40 @@ packages:
vite:
optional: true
+ vitest@4.0.10:
+ resolution: {integrity: sha512-2Fqty3MM9CDwOVet/jaQalYlbcjATZwPYGcqpiYQqgQ/dLC7GuHdISKgTYIVF/kaishKxLzleKWWfbSDklyIKg==}
+ engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@types/debug': ^4.1.12
+ '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
+ '@vitest/browser-playwright': 4.0.10
+ '@vitest/browser-preview': 4.0.10
+ '@vitest/browser-webdriverio': 4.0.10
+ '@vitest/ui': 4.0.10
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@types/debug':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser-playwright':
+ optional: true
+ '@vitest/browser-preview':
+ optional: true
+ '@vitest/browser-webdriverio':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
vitest@4.0.14:
resolution: {integrity: sha512-d9B2J9Cm9dN9+6nxMnnNJKJCtcyKfnHj15N6YNJfaFHRLua/d3sRKU9RuKmO9mB0XdFtUizlxfz/VPbd3OxGhw==}
engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
@@ -9241,10 +9539,36 @@ snapshots:
'@orama/orama@3.1.16': {}
+ '@oven/bun-darwin-aarch64@1.1.0':
+ optional: true
+
+ '@oven/bun-darwin-x64-baseline@1.1.0':
+ optional: true
+
+ '@oven/bun-darwin-x64@1.1.0':
+ optional: true
+
+ '@oven/bun-linux-aarch64@1.1.0':
+ optional: true
+
+ '@oven/bun-linux-x64-baseline@1.1.0':
+ optional: true
+
+ '@oven/bun-linux-x64@1.1.0':
+ optional: true
+
+ '@oven/bun-windows-x64-baseline@1.1.0':
+ optional: true
+
+ '@oven/bun-windows-x64@1.1.0':
+ optional: true
+
'@oxc-project/runtime@0.96.0': {}
'@oxc-project/runtime@0.99.0': {}
+ '@oxc-project/types@0.97.0': {}
+
'@oxc-project/types@0.98.0': {}
'@oxc-project/types@0.99.0': {}
@@ -9784,66 +10108,101 @@ snapshots:
'@radix-ui/rect@1.1.1': {}
+ '@rolldown/binding-android-arm64@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-android-arm64@1.0.0-beta.51':
optional: true
'@rolldown/binding-android-arm64@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-darwin-arm64@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-darwin-arm64@1.0.0-beta.51':
optional: true
'@rolldown/binding-darwin-arm64@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-darwin-x64@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-darwin-x64@1.0.0-beta.51':
optional: true
'@rolldown/binding-darwin-x64@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-freebsd-x64@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-freebsd-x64@1.0.0-beta.51':
optional: true
'@rolldown/binding-freebsd-x64@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.51':
optional: true
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-linux-arm64-gnu@1.0.0-beta.51':
optional: true
'@rolldown/binding-linux-arm64-gnu@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-linux-arm64-musl@1.0.0-beta.51':
optional: true
'@rolldown/binding-linux-arm64-musl@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-linux-x64-gnu@1.0.0-beta.51':
optional: true
'@rolldown/binding-linux-x64-gnu@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-linux-x64-musl@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-linux-x64-musl@1.0.0-beta.51':
optional: true
'@rolldown/binding-linux-x64-musl@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-openharmony-arm64@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-openharmony-arm64@1.0.0-beta.51':
optional: true
'@rolldown/binding-openharmony-arm64@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-wasm32-wasi@1.0.0-beta.50':
+ dependencies:
+ '@napi-rs/wasm-runtime': 1.0.7
+ optional: true
+
'@rolldown/binding-wasm32-wasi@1.0.0-beta.51':
dependencies:
'@napi-rs/wasm-runtime': 1.0.7
@@ -9854,18 +10213,27 @@ snapshots:
'@napi-rs/wasm-runtime': 1.0.7
optional: true
+ '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-win32-arm64-msvc@1.0.0-beta.51':
optional: true
'@rolldown/binding-win32-arm64-msvc@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-win32-ia32-msvc@1.0.0-beta.51':
optional: true
'@rolldown/binding-win32-ia32-msvc@1.0.0-beta.52':
optional: true
+ '@rolldown/binding-win32-x64-msvc@1.0.0-beta.50':
+ optional: true
+
'@rolldown/binding-win32-x64-msvc@1.0.0-beta.51':
optional: true
@@ -9874,6 +10242,8 @@ snapshots:
'@rolldown/pluginutils@1.0.0-beta.47': {}
+ '@rolldown/pluginutils@1.0.0-beta.50': {}
+
'@rolldown/pluginutils@1.0.0-beta.51': {}
'@rolldown/pluginutils@1.0.0-beta.52': {}
@@ -10883,6 +11253,12 @@ snapshots:
'@types/braces@3.0.5': {}
+ '@types/bun@1.3.2(@types/react@19.2.7)':
+ dependencies:
+ bun-types: 1.3.2(@types/react@19.2.7)
+ transitivePeerDependencies:
+ - '@types/react'
+
'@types/bun@1.3.3':
dependencies:
bun-types: 1.3.3
@@ -11097,6 +11473,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@vitest/expect@4.0.10':
+ dependencies:
+ '@standard-schema/spec': 1.0.0
+ '@types/chai': 5.2.3
+ '@vitest/spy': 4.0.10
+ '@vitest/utils': 4.0.10
+ chai: 6.2.1
+ tinyrainbow: 3.0.3
+
'@vitest/expect@4.0.14':
dependencies:
'@standard-schema/spec': 1.0.0
@@ -11106,6 +11491,14 @@ snapshots:
chai: 6.2.1
tinyrainbow: 3.0.3
+ '@vitest/mocker@4.0.10(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6))':
+ dependencies:
+ '@vitest/spy': 4.0.10
+ estree-walker: 3.0.3
+ magic-string: 0.30.21
+ optionalDependencies:
+ vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)
+
'@vitest/mocker@4.0.14(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6))':
dependencies:
'@vitest/spy': 4.0.14
@@ -11114,21 +11507,38 @@ snapshots:
optionalDependencies:
vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)
+ '@vitest/pretty-format@4.0.10':
+ dependencies:
+ tinyrainbow: 3.0.3
+
'@vitest/pretty-format@4.0.14':
dependencies:
tinyrainbow: 3.0.3
+ '@vitest/runner@4.0.10':
+ dependencies:
+ '@vitest/utils': 4.0.10
+ pathe: 2.0.3
+
'@vitest/runner@4.0.14':
dependencies:
'@vitest/utils': 4.0.14
pathe: 2.0.3
+ '@vitest/snapshot@4.0.10':
+ dependencies:
+ '@vitest/pretty-format': 4.0.10
+ magic-string: 0.30.21
+ pathe: 2.0.3
+
'@vitest/snapshot@4.0.14':
dependencies:
'@vitest/pretty-format': 4.0.14
magic-string: 0.30.21
pathe: 2.0.3
+ '@vitest/spy@4.0.10': {}
+
'@vitest/spy@4.0.14': {}
'@vitest/ui@4.0.14(vitest@4.0.14)':
@@ -11142,6 +11552,11 @@ snapshots:
tinyrainbow: 3.0.3
vitest: 4.0.14(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/ui@4.0.14)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)
+ '@vitest/utils@4.0.10':
+ dependencies:
+ '@vitest/pretty-format': 4.0.10
+ tinyrainbow: 3.0.3
+
'@vitest/utils@4.0.14':
dependencies:
'@vitest/pretty-format': 4.0.14
@@ -11500,10 +11915,26 @@ snapshots:
base64-js: 1.5.1
ieee754: 1.2.1
+ bun-types@1.3.2(@types/react@19.2.7):
+ dependencies:
+ '@types/node': 24.10.1
+ '@types/react': 19.2.7
+
bun-types@1.3.3:
dependencies:
'@types/node': 24.10.1
+ bun@1.1.0:
+ optionalDependencies:
+ '@oven/bun-darwin-aarch64': 1.1.0
+ '@oven/bun-darwin-x64': 1.1.0
+ '@oven/bun-darwin-x64-baseline': 1.1.0
+ '@oven/bun-linux-aarch64': 1.1.0
+ '@oven/bun-linux-x64': 1.1.0
+ '@oven/bun-linux-x64-baseline': 1.1.0
+ '@oven/bun-windows-x64': 1.1.0
+ '@oven/bun-windows-x64-baseline': 1.1.0
+
bundle-name@4.1.0:
dependencies:
run-applescript: 7.1.0
@@ -14301,6 +14732,23 @@ snapshots:
glob: 13.0.0
package-json-from-dist: 1.0.1
+ rolldown-plugin-dts@0.17.8(rolldown@1.0.0-beta.50)(typescript@5.9.3):
+ dependencies:
+ '@babel/generator': 7.28.5
+ '@babel/parser': 7.28.5
+ '@babel/types': 7.28.5
+ ast-kit: 2.2.0
+ birpc: 2.8.0
+ dts-resolver: 2.1.3
+ get-tsconfig: 4.13.0
+ magic-string: 0.30.21
+ obug: 2.1.1
+ rolldown: 1.0.0-beta.50
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - oxc-resolver
+
rolldown-plugin-dts@0.18.1(rolldown@1.0.0-beta.51)(typescript@5.9.3):
dependencies:
'@babel/generator': 7.28.5
@@ -14335,6 +14783,26 @@ snapshots:
terser: 5.44.1
tsx: 4.20.6
+ rolldown@1.0.0-beta.50:
+ dependencies:
+ '@oxc-project/types': 0.97.0
+ '@rolldown/pluginutils': 1.0.0-beta.50
+ optionalDependencies:
+ '@rolldown/binding-android-arm64': 1.0.0-beta.50
+ '@rolldown/binding-darwin-arm64': 1.0.0-beta.50
+ '@rolldown/binding-darwin-x64': 1.0.0-beta.50
+ '@rolldown/binding-freebsd-x64': 1.0.0-beta.50
+ '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.50
+ '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.50
+ '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.50
+ '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.50
+ '@rolldown/binding-linux-x64-musl': 1.0.0-beta.50
+ '@rolldown/binding-openharmony-arm64': 1.0.0-beta.50
+ '@rolldown/binding-wasm32-wasi': 1.0.0-beta.50
+ '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.50
+ '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.50
+ '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.50
+
rolldown@1.0.0-beta.51:
dependencies:
'@oxc-project/types': 0.98.0
@@ -14910,6 +15378,32 @@ snapshots:
optionalDependencies:
typescript: 5.9.3
+ tsdown@0.16.5(typescript@5.9.3):
+ dependencies:
+ ansis: 4.2.0
+ cac: 6.7.14
+ chokidar: 4.0.3
+ diff: 8.0.2
+ empathic: 2.0.0
+ hookable: 5.5.3
+ obug: 2.1.1
+ rolldown: 1.0.0-beta.50
+ rolldown-plugin-dts: 0.17.8(rolldown@1.0.0-beta.50)(typescript@5.9.3)
+ semver: 7.7.3
+ tinyexec: 1.0.2
+ tinyglobby: 0.2.15
+ tree-kill: 1.2.2
+ unconfig-core: 7.4.1
+ unrun: 0.2.11
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - '@ts-macro/tsc'
+ - '@typescript/native-preview'
+ - oxc-resolver
+ - synckit
+ - vue-tsc
+
tsdown@0.16.7(typescript@5.9.3):
dependencies:
ansis: 4.2.0
@@ -15365,6 +15859,47 @@ snapshots:
optionalDependencies:
vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)
+ vitest@4.0.10(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/ui@4.0.14)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6):
+ dependencies:
+ '@vitest/expect': 4.0.10
+ '@vitest/mocker': 4.0.10(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6))
+ '@vitest/pretty-format': 4.0.10
+ '@vitest/runner': 4.0.10
+ '@vitest/snapshot': 4.0.10
+ '@vitest/spy': 4.0.10
+ '@vitest/utils': 4.0.10
+ debug: 4.4.3
+ es-module-lexer: 1.7.0
+ expect-type: 1.2.2
+ magic-string: 0.30.21
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ std-env: 3.10.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.15
+ tinyrainbow: 3.0.3
+ vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/debug': 4.1.12
+ '@types/node': 24.10.1
+ '@vitest/ui': 4.0.14(vitest@4.0.14)
+ jsdom: 27.2.0
+ transitivePeerDependencies:
+ - jiti
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
vitest@4.0.14(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(@vitest/ui@4.0.14)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6):
dependencies:
'@vitest/expect': 4.0.14