Conversation
… for standard and core modes
🦋 Changeset detectedLatest commit: 02704b4 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. WalkthroughRefactors ArkEnv export surface into three tiers: root Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Consumer
participant Root as "arkenv (root)"
participant Standard as "arkenv/standard"
participant ArkType as "src/arktype/index.ts"
participant Core as "arkenv/core"
Consumer->>Root: import { createEnv, type } from "arkenv"
Root->>ArkType: static parse(def, config)
Consumer->>Standard: import { createEnv } from "arkenv/standard"
Standard->>Standard: run guards (assertNotArkTypeDsl, assertStandardSchema)
Standard->>Standard: parseStandard(def, config) -> validated output
Any->>Core: import { ArkEnvError, ValidationIssue } from "arkenv/core"
Core-->>Any: structured error primitives / formatted messages
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…d entries for standard and core modes
… for standard and core modes
…new source files and updated tests
|
Documentation Updates 3 document(s) were updated by changes in this PR: CHANGELOGView Changes@@ -1,4 +1,51 @@
# ArkEnv
+
+## 0.10.0
+
+### Minor Changes
+
+- #### Add `arkenv/standard` import for non-ArkType consumers _[`#806`](https://github.com/yamcodes/arkenv/pull/806) [@yamcodes](https://github.com/yamcodes)_
+
+ ArkEnv now provides three separate entry points to better serve different use cases:
+
+ - **`arkenv`** (main): ArkType-first. Includes `createEnv`, `type`, and `ArkEnvError`. The `type` helper has moved here from `arkenv/arktype`.
+ - **`arkenv/standard`**: ArkType-free. A standalone `createEnv` for Standard Schema validators (Zod, Valibot, etc.) with zero ArkType in the bundle.
+ - **`arkenv/core`**: Mode-agnostic primitives - `ArkEnvError` and `ValidationIssue`.
+
+ **For Standard Schema users** (Zod, Valibot, etc.), import from `arkenv/standard` directly, without passing `{ validator: "standard" }` on every call:
+
+ ```ts
+ // ❌ Before
+ import { createEnv } from "arkenv";
+ import { z } from "zod";
+
+ const env = createEnv(
+ { PORT: z.coerce.number() },
+ { validator: "standard" }
+ );
+
+ // ✅ After
+ import { createEnv } from "arkenv/standard";
+ import { z } from "zod";
+
+ const env = createEnv({ PORT: z.coerce.number() });
+ ```
+
+ **For `arkenv/arktype` users**, the `type` helper has moved to the main entry:
+
+ ```ts
+ // ❌ Before
+ import { type } from "arkenv/arktype";
+
+ // ✅ After
+ import { type } from "arkenv";
+ ```
+
+ **Breaking Changes:**
+
+ - Removed `arkenv/arktype` sub-path. Import the `type` helper from the main `arkenv` entry point instead.
+ - The `validator` config option has been removed. For Standard Schema flows, use the new `arkenv/standard` entry point instead.
+ - For access to core primitives like `ArkEnvError`, use `import { ArkEnvError } from "arkenv/core"`.
## 0.9.3
copilot-instructionsView Changes@@ -51,47 +51,124 @@
### Main Package (`packages/arkenv`)
-The core package provides:
-
-1. **`createEnv(schema)`** - Main function to create validated environment objects. Also available as the default export, typically imported as `arkenv`.
-2. **Built-in validators** - Common validators like `host`, `port`, `url`, etc.
-3. **ArkType integration** - Uses ArkType for schema definition and validation
-4. **Type inference** - Full TypeScript type inference from schemas
+The core package provides three entry points:
+
+1. **`arkenv`** (main entry) - ArkType-first `createEnv` with built-in validators and `type` helper
+2. **`arkenv/standard`** - ArkType-free `createEnv` for Standard Schema validators (Zod, Valibot, etc.)
+3. **`arkenv/core`** - Core primitives like `ArkEnvError` and `ValidationIssue`, usable without ArkType
+
+#### Main Entry (`arkenv`)
+- **`createEnv(schema)`** - Main function to create validated environment objects (also available as default export `arkenv`)
+- **`type`** - Helper for ArkType schemas, re-exported from ArkType with ArkEnv's built-in validators
+- **Built-in validators** - Common validators like `host`, `port`, `url`, etc.
+- **Type inference** - Full TypeScript type inference from schemas
+
+#### Standard Entry (`arkenv/standard`)
+- **`createEnv(schema)`** - ArkType-free validator for Standard Schema implementations
+- No ArkType dependency - perfect for projects using only Zod, Valibot, or other Standard Schema validators
+
+#### Core Entry (`arkenv/core`)
+- **`ArkEnvError`** - Error class for validation failures
+- **`ValidationIssue`** - Type for individual validation errors
+- Mode-agnostic primitives usable in any context
### Key Files
+- `src/index.ts` - Main ArkType entry point exporting `createEnv` and `type` helper
+- `src/standard.ts` - Standard Schema entry point with ArkType-free `createEnv`
+- `src/core.ts` - Core primitives (`ArkEnvError`, `ValidationIssue`)
- `src/create-env.ts` - Core `createEnv` implementation
-- `src/types.ts` - Built-in type validators (host, port, url, etc.)
-- `src/errors.ts` - Error handling and formatting
+- `src/arktype/index.ts` - ArkType-specific validation logic and `parse` function
+- `src/parse-standard.ts` - Standard Schema validation logic
+- `src/guards.ts` - Type guards for runtime validation
- `src/utils.ts` - Utility functions
## Coding Patterns
-### Environment Schema Definition
-```typescript
-import arkenv from 'arkenv';
+### Import Structure
+
+ArkEnv has three main entry points for different use cases:
+
+#### Using ArkType (Default)
+```typescript
+import arkenv, { type } from 'arkenv';
const env = arkenv({
HOST: "string.host", // Built-in validator
PORT: "number.port", // Built-in validator
- NODE_ENV: "'development' | 'production' | 'test'", // ArkType string literal
- DATABASE_URL: "string", // Simple ArkType schema
- FEATURE_FLAG: "boolean = false", // Default value
-});
-```
+ NODE_ENV: "'development' | 'production' | 'test'", // ArkType string literal
+ DATABASE_URL: "string", // Simple ArkType schema
+ FEATURE_FLAG: "boolean = false", // Default value
+});
+
+// Using the type helper for reusable schemas
+const portSchema = type("number.port");
+const env2 = arkenv({
+ API_PORT: portSchema,
+ DB_PORT: portSchema,
+});
+```
+
+#### Using Standard Schema Only (Zod, Valibot, etc.)
+```typescript
+import arkenv from 'arkenv/standard';
+import { z } from 'zod';
+
+const env = arkenv({
+ PORT: z.coerce.number().int().min(0).max(65535),
+ DATABASE_URL: z.string().url(),
+ DEBUG: z.coerce.boolean().default(false),
+});
+```
+
+#### Importing Core Primitives
+```typescript
+import { ArkEnvError } from 'arkenv/core';
+
+try {
+ // validation logic
+} catch (error) {
+ if (error instanceof ArkEnvError) {
+ console.error('Environment validation failed:', error.message);
+ }
+}
+```
+
+### Environment Schema Definition
+
+The main entry (`arkenv`) uses ArkType's DSL for schema definition with built-in validators:
### Built-in Validators
-The library provides common validators in `src/types.ts`:
-- `host` - Valid IP address or hostname
-- `port` - Valid port number (0-65535)
-- `url` - Valid URL
-- `email` - Valid email address
+
+The library provides common validators accessible via the ArkType DSL:
+- `string.host` - Valid IP address or hostname
+- `number.port` - Valid port number (0-65535)
+- `string.url` - Valid URL
+- `string.email` - Valid email address
+
+These validators are available when using the main `arkenv` entry with ArkType.
### Error Handling
-Environment validation errors are thrown early with descriptive messages showing:
+
+Validation errors are thrown as `ArkEnvError` (importable from `arkenv` or `arkenv/core`) with descriptive messages showing:
- Which variables are missing or invalid
- Expected vs actual values
- Helpful suggestions for fixing issues
+```typescript
+import arkenv, { ArkEnvError } from 'arkenv';
+
+try {
+ const env = arkenv({
+ PORT: "number.port",
+ HOST: "string.host",
+ });
+} catch (error) {
+ if (error instanceof ArkEnvError) {
+ console.error('Environment validation failed:', error.message);
+ }
+}
+```
+
## Testing Guidelines
### Test Structure
@@ -102,9 +179,11 @@
**What:** Test individual functions, components, and hooks in isolation with mocked dependencies.
Tests are located alongside source files with `.test.ts` suffix:
-- `create-env.test.ts` - Tests for main `createEnv` functionality
-- `types.test.ts` - Tests for built-in validators
+- `create-env.test.ts` - Tests for `createEnv` functionality
+- `arktype/create-env.test.ts` - Tests for ArkType-specific parsing
+- `standard-mode.test.ts` - Tests for Standard Schema mode
- `errors.test.ts` - Tests for error handling
+- `guards.test.ts` - Tests for type guards
- `utils.test.ts` - Tests for utility functions
- `copy-button.test.tsx` - Tests `CopyButton` component with mocked dependencies
@@ -146,6 +225,9 @@
### Unit Test Example
```typescript
import { beforeEach, afterEach, it, expect } from 'vitest';
+import arkenv from 'arkenv';
+
+let originalEnv: NodeJS.ProcessEnv;
beforeEach(() => {
// Save original env
@@ -258,18 +340,77 @@
## Best Practices
-1. **Use built-in validators** when available (host, port, url, etc.)
-2. **Provide defaults** for optional environment variables
-3. **Group related variables** in logical schemas
-4. **Document environment requirements** in README files
-5. **Test edge cases** including invalid and missing values
-6. **Use descriptive variable names** that indicate purpose and format
+1. **Choose the right entry point**:
+ - Use `arkenv` for ArkType DSL and built-in validators
+ - Use `arkenv/standard` for Standard Schema-only workflows (Zod, Valibot)
+ - Use `arkenv/core` for importing error types without validation logic
+2. **Use built-in validators** when available (`string.host`, `number.port`, `string.url`, etc.)
+3. **Provide defaults** for optional environment variables
+4. **Group related variables** in logical schemas
+5. **Document environment requirements** in README files
+6. **Test edge cases** including invalid and missing values
+7. **Use descriptive variable names** that indicate purpose and format
+
+## Migration Guide
+
+### From arkenv < 1.0 (arkenv/arktype sub-path)
+
+The `arkenv/arktype` sub-path has been removed. Update your imports:
+
+**Before:**
+```typescript
+import { type } from 'arkenv/arktype';
+import arkenv from 'arkenv';
+
+const env = arkenv({
+ PORT: type("number.port"),
+});
+```
+
+**After:**
+```typescript
+import arkenv, { type } from 'arkenv';
+
+const env = arkenv({
+ PORT: type("number.port"),
+});
+```
+
+### From validator option to entry point
+
+The `validator` configuration option has been removed. Use the appropriate entry point instead:
+
+**Before:**
+```typescript
+import arkenv from 'arkenv';
+import { z } from 'zod';
+
+const env = arkenv(
+ {
+ PORT: z.coerce.number(),
+ },
+ { validator: "standard" }
+);
+```
+
+**After:**
+```typescript
+import arkenv from 'arkenv/standard';
+import { z } from 'zod';
+
+const env = arkenv({
+ PORT: z.coerce.number(),
+});
+```
## Examples Reference
Check the `examples/` directory for practical usage patterns:
-- `basic/` - Simple Node.js application
+- `basic/` - Simple Node.js application with ArkType
- `with-bun/` - Bun runtime integration
+- `with-standard-schema/` - Using Standard Schema validators without ArkType
+- `with-vite-react/` - Vite + React integration
+- `with-solid-start/` - SolidStart integration
These examples demonstrate real-world usage and can serve as templates for new integrations.
@@ -285,7 +426,7 @@
### Security Considerations
- Always validate user input in examples and documentation
-- Use `ArkEnvError` for environment variable errors, not generic errors
+- Use `ArkEnvError` (from `arkenv` or `arkenv/core`) for environment variable errors, not generic errors
- Never log environment variable values in production code
- Ensure examples demonstrate secure default practices
READMEView Changes@@ -1,4 +1,6 @@
# ArkType Land
+
+> **⚠️ Breaking Change:** The `arkenv/arktype` sub-path has been **removed**. The `type` helper is now exported from the main **`arkenv`** entry point. Import from `"arkenv"` instead of `"arkenv/arktype"`.
This module **assumes that the user has `arktype` installed** in their project. It is intentionally isolated from the core of `arkenv` to allow for optional and lazy loading of the ArkType library.
@@ -8,7 +10,7 @@
This directory contains the ArkType-specific validator logic for `arkenv`.
-- `index.ts`: The main entry point for the ArkType validator, which integrates with `@repo/scope`.
+- `index.ts`: The implementation of the ArkType validator, including the `parse` function and `type` helper. While this was previously exposed as `arkenv/arktype`, it is now an internal module. The `type` helper is re-exported from the main `arkenv` entry.
- `coercion/`: Logic for introspecting ArkType schemas and applying automatic type coercion (e.g., parsing "3000" as a number).
## How it works
@@ -16,3 +18,25 @@
When `createEnv` is called in ArkType-mode (the default), `arkenv` dynamically loads this module. This ensures that:
1. `arkenv` can be used without `arktype` (e.g., for Standard Schema only projects).
2. `arktype` is only loaded if and when environment validation is actually performed.
+
+## Public API
+
+`arkenv` now has **three public entry points**:
+
+- **`arkenv`** (main): ArkType-first. Exports `createEnv` (with ArkType support), `type` (the ArkEnv helper with extra keywords like `string.host`), and `ArkEnvError`.
+- **`arkenv/standard`**: ArkType-free. A standalone `createEnv` for Standard Schema validators (Zod, Valibot, etc.) with zero ArkType in the bundle.
+- **`arkenv/core`**: Mode-agnostic primitives (`ArkEnvError`, `ValidationIssue`).
+
+The `arkenv/arktype` sub-path no longer exists. This module (`src/arktype/`) is now an internal implementation detail, and its exports are re-exported from the main `arkenv` entry.
+
+## Migration
+
+For developers referencing this internal module:
+
+```ts
+// ❌ Before
+import { type } from "arkenv/arktype";
+
+// ✅ After
+import { type } from "arkenv";
+``` |
📦 Bundle Size Report
✅ All size limits passed! |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/arkenv/src/utils/bundling-interop.test.ts (1)
83-141:⚠️ Potential issue | 🟡 MinorThe test doesn't actually enforce the "no ArkType needed" guarantee.
The comment on Line 124 says "arktype must NOT be required", but the test only checks
output.trim() === "SUCCESS". Ifarkenv/standard's dist were to importarktype, esbuild would resolve it via the workspace's ownnode_modules(the temp dir is a subdirectory of the workspace), bundle it transparently, and the test would still pass. The ArkType-free invariant is never enforced.The simplest fix is to assert the bundle output contains no
arktypereference:🧪 Proposed verification step
+ // Verify the bundle does not reference arktype (ArkType-free guarantee) + const { readFileSync } = await import("node:fs"); + const bundleSource = readFileSync(outFile, "utf-8"); + expect(bundleSource).not.toContain("arktype"); // Run the bundled output — arktype must NOT be required for this to work try {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/arkenv/src/utils/bundling-interop.test.ts` around lines 83 - 141, The test "should work when arkenv/standard is external in an ESM bundle (no ArkType needed)" does not assert that arktype is not referenced; after bundling (the execSync call using esbuildPath that writes outFile), read the generated bundle file (outFile) and assert it does not contain any "arktype" references (e.g., import "arktype", require("arktype"), or the string 'arktype') before running the bundled output; update the test to fail if such a reference is found so the ArkType-free invariant is actually enforced.
🧹 Nitpick comments (3)
openspec/changes/refactor-export-surface/specs/validator-mode/spec.md (1)
1-20: Consider adding a scenario for the ArkType-free runtime invariant.The three scenarios cover happy-path validation and the two error modes, but the headline requirement — "without requiring ArkType" — has no corresponding
#### Scenario. Consumers adoptingarkenv/standardspecifically for ArkType-free bundles would benefit from a normative scenario capturing this guarantee (e.g., WHEN imported in a bundle without ArkType installed, THEN it MUST function without errors). This would also drive better test coverage (see note onbundling-interop.test.ts).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@openspec/changes/refactor-export-surface/specs/validator-mode/spec.md` around lines 1 - 20, Add a fourth Scenario under the "Dedicated Standard Entry Point" requirement that captures the ArkType-free runtime invariant: when createEnv is imported from "arkenv/standard" and run in a runtime/bundle where ArkType is not present or installed, it MUST still validate and return the Standard Schema output without throwing errors; reference the arkenv/standard createEnv symbol and mention that no ArkType runtime/DLS strings may be required, and add a corresponding test note (e.g., in bundling-interop.test.ts) to exercise this case to ensure the bundle works without ArkType.packages/arkenv/src/standard.ts (1)
55-63: Outer schema-shape validation is duplicated betweenstandard.tsandcreate-env.ts.The identical
!def || typeof def !== "object" || Array.isArray(def)guard +ArkEnvErrorthrow block (including the same error message) appears in bothsrc/standard.ts(lines 55–62) andsrc/create-env.ts(lines 117–126). TheassertNotArkTypeDsl/assertStandardSchemaguards were correctly extracted toguards.ts, but this outer check was not. Consider extracting it intoguards.tsas well:♻️ Suggested refactor
In
src/guards.ts, add:export function assertStandardSchemaMap(def: unknown): asserts def is Record<string, unknown> { if (!def || typeof def !== "object" || Array.isArray(def)) { throw new ArkEnvError([ { path: "", message: 'Invalid schema: expected an object mapping in "standard" mode.', }, ]); } }Then in both
standard.tsandcreate-env.ts, replace the duplicated block with a single call:-if (!def || typeof def !== "object" || Array.isArray(def)) { - throw new ArkEnvError([{ path: "", message: 'Invalid schema: expected an object mapping in "standard" mode.' }]); -} +assertStandardSchemaMap(def);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/arkenv/src/standard.ts` around lines 55 - 63, Extract the duplicated outer-schema check into a new guard in guards.ts named assertStandardSchemaMap(def: unknown): asserts def is Record<string, unknown> that throws the existing ArkEnvError with message 'Invalid schema: expected an object mapping in "standard" mode.' when !def || typeof def !== "object" || Array.isArray(def); then replace the duplicated if-blocks in standard.ts (the current guard before using def) and create-env.ts (the identical guard around schema handling) with a single call to assertStandardSchemaMap(def) so both files use the shared guard.packages/arkenv/package.json (1)
84-93: Consider addingsize-limitentries for the two new sub-paths.
dist/standard.mjsanddist/core.mjsare new public entries that will contribute to install weight but are not currently measured. The design doc notes this as "worth doing but out of scope" — worth tracking.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/arkenv/package.json` around lines 84 - 93, Update the "size-limit" configuration in package.json to add entries for the two new public build outputs so they are measured: add objects analogous to the existing entry for "dist/index.mjs" for "dist/standard.mjs" and "dist/core.mjs" (using the same "limit", "import" and "ignore" values as the current size-limit entry) so the new sub-paths are tracked by size-limit.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@openspec/changes/refactor-export-surface/design.md`:
- Line 63: The sentence currently implies a dependency chain "create-env.ts (via
src/standard.ts) → parseStandard" which is incorrect; update the phrasing in
design.md so it clearly states that both create-env.ts and src/standard.ts
independently call parseStandard (or simply drop the parenthetical), and ensure
the line names create-env.ts, src/standard.ts and parseStandard are mentioned to
make it explicit there is no create-env.ts → src/standard.ts dependency.
In `@packages/arkenv/package.json`:
- Around line 18-33: The package arkenv removed the ./arktype export which is a
breaking change; add a changeset for the arkenv package that documents this as a
major bump so releases are versioned correctly. Create a new file under
.changeset (e.g., a .md or .mdx file named uniquely) that lists the package name
"arkenv" and sets the bump type to "major", include a brief note referencing the
refactor/export-surface change, and commit it alongside the package.json change
so the release tooling will pick up the breaking change.
In `@packages/arkenv/src/core.ts`:
- Line 1: Rename the exported type InternalValidationError to a public-friendly
name (e.g., ValidationIssue or EnvValidationError) and update all internal
references and public re-exports to use the new identifier; specifically, change
the export statement that currently exports InternalValidationError and adjust
any usages in types, function signatures, error handling code, and other export
lists so they import/export the new name consistently (ensure any tests or docs
referencing InternalValidationError are updated or aliased if backwards
compatibility is required).
In `@packages/arkenv/src/guards.ts`:
- Around line 23-32: assertStandardSchema currently only checks that the
"~standard" property exists but not that its validate field is a function, so
malformed validators like { "~standard": null } escape and later cause
TypeError; update assertStandardSchema to verify that value["~standard"] is an
object and that ("validate" in value["~standard"]) and typeof
value["~standard"].validate === "function", and if not throw an ArkEnvError
(same shape as existing error) so parse-standard.ts will receive a structured
error instead of a runtime TypeError.
In `@packages/arkenv/src/isolation.test.ts`:
- Around line 35-39: The test "loads ArkType statically when importing from
arktype/index.ts" currently only does an import with no assertions; update it to
explicitly assert that the expected export from "./arktype/index.ts" is present
(e.g., import the module as const mod = await import("./arktype/index.ts") and
add an expect that mod.ArkType or mod.default is defined or matches the expected
shape), so the test documents the contract and fails if the export isn't
available.
---
Outside diff comments:
In `@packages/arkenv/src/utils/bundling-interop.test.ts`:
- Around line 83-141: The test "should work when arkenv/standard is external in
an ESM bundle (no ArkType needed)" does not assert that arktype is not
referenced; after bundling (the execSync call using esbuildPath that writes
outFile), read the generated bundle file (outFile) and assert it does not
contain any "arktype" references (e.g., import "arktype", require("arktype"), or
the string 'arktype') before running the bundled output; update the test to fail
if such a reference is found so the ArkType-free invariant is actually enforced.
---
Nitpick comments:
In `@openspec/changes/refactor-export-surface/specs/validator-mode/spec.md`:
- Around line 1-20: Add a fourth Scenario under the "Dedicated Standard Entry
Point" requirement that captures the ArkType-free runtime invariant: when
createEnv is imported from "arkenv/standard" and run in a runtime/bundle where
ArkType is not present or installed, it MUST still validate and return the
Standard Schema output without throwing errors; reference the arkenv/standard
createEnv symbol and mention that no ArkType runtime/DLS strings may be
required, and add a corresponding test note (e.g., in bundling-interop.test.ts)
to exercise this case to ensure the bundle works without ArkType.
In `@packages/arkenv/package.json`:
- Around line 84-93: Update the "size-limit" configuration in package.json to
add entries for the two new public build outputs so they are measured: add
objects analogous to the existing entry for "dist/index.mjs" for
"dist/standard.mjs" and "dist/core.mjs" (using the same "limit", "import" and
"ignore" values as the current size-limit entry) so the new sub-paths are
tracked by size-limit.
In `@packages/arkenv/src/standard.ts`:
- Around line 55-63: Extract the duplicated outer-schema check into a new guard
in guards.ts named assertStandardSchemaMap(def: unknown): asserts def is
Record<string, unknown> that throws the existing ArkEnvError with message
'Invalid schema: expected an object mapping in "standard" mode.' when !def ||
typeof def !== "object" || Array.isArray(def); then replace the duplicated
if-blocks in standard.ts (the current guard before using def) and create-env.ts
(the identical guard around schema handling) with a single call to
assertStandardSchemaMap(def) so both files use the shared guard.
There was a problem hiding this comment.
🧹 Nitpick comments (2)
apps/www/content/docs/arkenv/quickstart.mdx (1)
59-60: Merge the two imports from'arkenv'into one statement.Lines 59–60 both import from the same specifier; combining them avoids redundancy in the doc sample.
♻️ Proposed merge
-import arkenv from 'arkenv'; -import { type } from 'arkenv'; +import arkenv, { type } from 'arkenv';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/www/content/docs/arkenv/quickstart.mdx` around lines 59 - 60, Merge the two import statements that both import from 'arkenv' into a single import declaration by combining the default import arkenv and the named import type (e.g., import arkenv, { type } from 'arkenv';) so the example no longer has redundant separate imports for arkenv and type.apps/www/content/docs/arkenv/how-to/reuse-schemas.mdx (1)
27-28: Merge the two'arkenv'imports into one statement.Having separate
importdeclarations for the same module is non-idiomatic and adds cognitive overhead for readers copying this example.♻️ Suggested consolidation
-import arkenv from 'arkenv'; -import { type } from 'arkenv'; +import arkenv, { type } from 'arkenv';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/www/content/docs/arkenv/how-to/reuse-schemas.mdx` around lines 27 - 28, The file has two imports from the same module ("import arkenv from 'arkenv';" and "import { type } from 'arkenv';"); consolidate them into a single import statement that imports the default export and the named export together (reference the symbols arkenv and type) so there's only one import declaration from 'arkenv'.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@apps/playgrounds/bun-react/src/env.ts`:
- Line 1: The import statement currently reads 'import { type } from "arkenv";'
and the reviewer approved the change (no modifications required); leave the
import as-is in env.ts (the existing symbol 'type' from the arkenv module should
remain unchanged).
In `@apps/playgrounds/solid-start/README.md`:
- Line 16: Remove the stray/incorrect import statement "import { type } from
\"arkenv\";" found in apps/playgrounds/solid-start/README.md; locate the literal
"import { type } from \"arkenv\";" and delete it (or replace it with the
intended example/code snippet) so the README no longer contains a dangling or
invalid import reference to the symbol "type".
In `@apps/playgrounds/vite-legacy/vite.config.ts`:
- Line 3: The import statement currently reads "import arkenv, { type } from
'arkenv';" and there is no change needed—leave the import as-is (keeping the
default export arkenv and the named export type) since the reviewer approved the
code; no edits to the import line or symbols (arkenv, type) are required.
---
Nitpick comments:
In `@apps/www/content/docs/arkenv/how-to/reuse-schemas.mdx`:
- Around line 27-28: The file has two imports from the same module ("import
arkenv from 'arkenv';" and "import { type } from 'arkenv';"); consolidate them
into a single import statement that imports the default export and the named
export together (reference the symbols arkenv and type) so there's only one
import declaration from 'arkenv'.
In `@apps/www/content/docs/arkenv/quickstart.mdx`:
- Around line 59-60: Merge the two import statements that both import from
'arkenv' into a single import declaration by combining the default import arkenv
and the named import type (e.g., import arkenv, { type } from 'arkenv';) so the
example no longer has redundant separate imports for arkenv and type.
- Clarify `./arktype` sub-path removal - Promote `type` export to root entry - Document hard ArkType dependency
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/www/content/docs/vite-plugin/arkenv-in-viteconfig.mdx (1)
15-15:⚠️ Potential issue | 🟡 MinorMissing space before the backtick causes a rendering artifact.
ArkEnv's\type()`should beArkEnv's `type()`` — the missing space before the backtick fuses the apostrophe into the inline-code span.✏️ Proposed fix
-Here's how to validate those variables with ArkEnv. The key is defining your schema *once* with ArkEnv's`type()` and reusing it for both server-side config variables and client-exposed `VITE_*` variables: +Here's how to validate those variables with ArkEnv. The key is defining your schema *once* with ArkEnv's `type()` and reusing it for both server-side config variables and client-exposed `VITE_*` variables:🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/www/content/docs/vite-plugin/arkenv-in-viteconfig.mdx` at line 15, The inline code snippet "ArkEnv's`type()`" is missing a space before the backtick causing a rendering artifact; update the MDX text so there is a space between the apostrophe and the inline code (i.e., change to "ArkEnv's `type()`") where the phrase referencing ArkEnv and its type() helper appears to fix the inline-code rendering.
🧹 Nitpick comments (1)
apps/www/content/docs/arkenv/quickstart.mdx (1)
17-27: Consider surfacingarkenv/standardimport path in the Standard Schema accordion.The PR introduces
arkenv/standardas the dedicated ArkType-free entry point, but the "Install ArkEnv only" accordion only links to the Standard Schema guide without mentioning which import path to use. A Standard Schema user who doesn't follow the link might default toimport from 'arkenv'(the ArkType-dependent entry). A one-liner like:Use this if you already rely on a [Standard Schema](https://standardschema.dev) validator like Zod or Valibot. + + ```ts + import { createEnv } from 'arkenv/standard'; + ``` > The examples in this guide use ArkType. See the [Standard Schema guide](/docs/arkenv/integrations/standard-schema) for alternative setups.…would make the distinction immediately clear at the install step.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/www/content/docs/arkenv/quickstart.mdx` around lines 17 - 27, Add a one-line example showing the ArkType-free import path so Standard Schema users know to use the dedicated entry point: insert a short code snippet inside the "Install ArkEnv only" Accordion demonstrating "import { createEnv } from 'arkenv/standard';" (or similar named export used elsewhere) directly above or below the existing install snippet, and keep the existing note about ArkType and the link to the Standard Schema guide unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@apps/www/content/docs/vite-plugin/arkenv-in-viteconfig.mdx`:
- Line 15: The inline code snippet "ArkEnv's`type()`" is missing a space before
the backtick causing a rendering artifact; update the MDX text so there is a
space between the apostrophe and the inline code (i.e., change to "ArkEnv's
`type()`") where the phrase referencing ArkEnv and its type() helper appears to
fix the inline-code rendering.
---
Nitpick comments:
In `@apps/www/content/docs/arkenv/quickstart.mdx`:
- Around line 17-27: Add a one-line example showing the ArkType-free import path
so Standard Schema users know to use the dedicated entry point: insert a short
code snippet inside the "Install ArkEnv only" Accordion demonstrating "import {
createEnv } from 'arkenv/standard';" (or similar named export used elsewhere)
directly above or below the existing install snippet, and keep the existing note
about ArkType and the link to the Standard Schema guide unchanged.
openspec/changes/refactor-export-surface/specs/validator-mode/spec.md
Outdated
Show resolved
Hide resolved
commit: |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/www/content/docs/arkenv/validator-mode.mdx (1)
6-7:⚠️ Potential issue | 🟡 MinorStale introduction: validator mode is no longer selected via a
validatoroption.Line 7 says "You select the mode via the
validatoroption in thearkenvconfiguration." With the new three-tier export surface, Standard mode is selected by importing fromarkenv/standard—not via an option. Consider updating the intro paragraph to reflect this.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/www/content/docs/arkenv/validator-mode.mdx` around lines 6 - 7, Update the stale intro sentence that says "You select the mode via the `validator` option in the `arkenv` configuration": instead explain that validator modes are selected by importing the appropriate export (e.g., import from `arkenv/standard` to use Standard mode) as part of the new three-tier export surface; replace or reword the line in validator-mode.mdx to reference importing `arkenv/standard` (and the equivalent import names for other modes) instead of using a `validator` option.packages/arkenv/src/arktype/index.ts (1)
1-1:⚠️ Potential issue | 🟠 MajorCI failure: sync the
with-standard-schemaexample.The
sync-examplespipeline reportswith-standard-schemais out of sync (Modified: index.ts). The example needs to be updated to use the newarkenv/standardimport path introduced by this PR.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/arkenv/src/arktype/index.ts` at line 1, Update the import in the arktype module: replace the existing import statement that reads import { $ } from "@repo/scope"; with the new package path import { $ } from "arkenv/standard"; so the example uses the new arkenv/standard export. Ensure the symbol $ remains imported from "arkenv/standard" exactly as shown.
🧹 Nitpick comments (4)
apps/playgrounds/standard-schema/index.ts (1)
19-19: Redundantstr: stringtype annotation — TypeScript infers it from thez.string()chain.Per coding guidelines, explicit types inferrable by TypeScript should be omitted.
♻️ Remove the redundant type annotation
- .transform((str: string) => str.split(",")) + .transform((str) => str.split(","))As per coding guidelines: "Avoid explicit types when TypeScript can infer them (
noInferrableTypeserror)."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/playgrounds/standard-schema/index.ts` at line 19, The transform callback on the z.string() schema includes a redundant parameter type annotation "str: string"; remove the explicit ": string" so the transform reads (.transform((str) => ...)) to rely on TypeScript's inferred type and satisfy the noInferrableTypes guideline in the transform call on the z.string() chain.packages/arkenv/src/standard-mode.test.ts (1)
36-36: Movevi.unstubAllEnvs()toafterEachto prevent env leaks on assertion failures.If any assertion throws before the inline
vi.unstubAllEnvs()call, stubs accumulate and can cause false positives or failures in subsequent tests. As per coding guidelines, useafterEachfor cleanup.♻️ Proposed refactor
+import { afterEach, describe, expect, expectTypeOf, it, vi } from "vitest"; -import { describe, expect, expectTypeOf, it, vi } from "vitest"; describe("Standard Mode Type Inference", () => { + afterEach(() => { + vi.unstubAllEnvs(); + }); + it("should infer correct types from Standard Schema validators", () => { vi.stubEnv("STRING_VAR", "test"); vi.stubEnv("NUMBER_VAR", "42"); vi.stubEnv("BOOLEAN_VAR", "true"); // ... - vi.unstubAllEnvs(); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/arkenv/src/standard-mode.test.ts` at line 36, The test currently calls vi.unstubAllEnvs() inline which can be skipped if an assertion throws; move the cleanup into a global teardown by adding an afterEach hook that calls vi.unstubAllEnvs(), ensuring it runs after every test; update the test file (standard-mode.test.ts) to remove the inline vi.unstubAllEnvs() call and add afterEach(() => vi.unstubAllEnvs()) near the other test setup/teardown code so environment stubs are always cleared even on failures.packages/arkenv/src/arktype/index.ts (1)
7-7: Explicit.tsextension onstyle-text.tsimport is inconsistent with the rest of the file.Lines 6 and 8 use extension-less imports (
../create-env,./coercion/coerce), while line 7 retains../utils/style-text.ts. This is a nit.🔧 Proposed fix
-import { styleText } from "../utils/style-text.ts"; +import { styleText } from "../utils/style-text";🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/arkenv/src/arktype/index.ts` at line 7, The import for styleText uses an explicit .ts extension while the surrounding imports (e.g., ../create-env and ./coercion/coerce) are extension-less; change the import of styleText (symbol: styleText) to the extension-less form (../utils/style-text) so it matches the project's import style and remains consistent with the other imports in this module (arktype/index.ts).openspec/changes/refactor-export-surface/design.md (1)
61-61:$.type.raw()is documented in ArkType's FAQ — no action needed, but worth a stabilization note.The ArkType FAQ explicitly demonstrates
type.raw()for generic wrappers, confirming this is a semi-public, intentionally exposed API rather than a private internal. Calling it on a custom scope instance ($.type.raw()) is the expected extension of that pattern.Since this design doc hard-codes the call signature, consider adding a one-line note along the lines of "verified against ArkType vX.Y" so future maintainers know which version the assumption was validated against, without needing to re-investigate.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@openspec/changes/refactor-export-surface/design.md` at line 61, Add a one-line stabilization note stating which ArkType version the `$.type.raw()` call signature was verified against (e.g., "Verified against ArkType vX.Y") to the design doc so future maintainers know the assumption backing `createEnv`'s use of `$.type.raw()` is validated; mention `createEnv`, the `$.type.raw()` call, and that parsing/validation is delegated to `parse` in `src/arktype/index.ts` so the note clearly ties the verification to the relevant symbols.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/playgrounds/standard-schema/index.ts`:
- Around line 1-4: The example file is out of sync: replace its current env
import and call with the updated pattern by importing createEnv as arkenv from
"arkenv/standard" and updating the createEnv call-site to the single-argument
form arkenv({...}); ensure the zod import (import * as z from "zod") remains and
that the symbol arkenv is used where the previous createEnv call was so the
example matches the new playground usage.
In `@apps/www/content/docs/arkenv/how-to/load-environment-variables.mdx`:
- Around line 218-221: The schema uses z.url() which exists only in Zod v4;
update the DATABASE_URL validator in the createEnv call (symbol: env2 and
function createEnv) to use z.string().url() instead of z.url(), leaving PORT as
z.coerce.number().int().min(0).max(65535); this ensures compatibility with the
current Zod version while preserving URL validation.
In `@apps/www/content/docs/arkenv/integrations/standard-schema.mdx`:
- Line 57: Update the prose to stop referencing the deprecated validator:
"standard" option and instead describe the new import-based pattern: explain
that to run ArkEnv in Standard-only mode you import from 'arkenv/standard'
(e.g., using the dedicated import) and remove or replace the phrase `validator:
"standard"` so the text matches the example that uses the import-based approach;
update the sentence around the example to mention the dedicated import (from
'arkenv/standard') and that no validator option is required.
- Around line 64-66: The schema uses z.url() which is a Zod v4 API and will
break for zod@^3.24.0; replace the DATABASE_URL schema definition from using
z.url() to the Zod v3-compatible form z.string().url() so the constant
DATABASE_URL in the object (near PORT and DEBUG) validates as a URL with Zod v3.
In `@apps/www/content/docs/arkenv/validator-mode.mdx`:
- Around line 67-70: The schema in createEnv uses z.url() (for DATABASE_URL)
which is Zod v4-only; update the DATABASE_URL entry in the createEnv call to use
z.string().url() instead (leave the PORT definition as-is) so the validator
works with Zod v3—look for the createEnv invocation that defines PORT and
DATABASE_URL and replace z.url() with z.string().url().
In `@packages/arkenv/src/arktype/index.ts`:
- Around line 34-37: Replace the regex-based path stripping (variables
escapedPath and pathRegex) with deterministic string operations to avoid ReDoS
and RegExp overhead: trim leading whitespace from the input, optionally strip a
single leading separator character if it's one of ':', '.', or '-', then trim
any following whitespace, and perform a case-insensitive startsWith check
against the path string (use .toLowerCase() on both sides) and slice off the
matched prefix; update the code around escapedPath/pathRegex in arktype/index.ts
accordingly.
In `@packages/arkenv/src/index.ts`:
- Line 1: The examples check failed because
examples/with-standard-schema/index.ts is out of sync with the updated
packages/arkenv/src/index.ts; open packages/arkenv/src/index.ts to see the
intended change (the import of $ from "@repo/scope") then update
examples/with-standard-schema/index.ts to match that change (ensure the same
imports/exports and any API usage are identical), run the repo's sync or
formatting script (or re-run the fd/rg check) to validate, then commit and push
the updated examples/with-standard-schema/index.ts so the sync-examples CI gate
passes.
---
Outside diff comments:
In `@apps/www/content/docs/arkenv/validator-mode.mdx`:
- Around line 6-7: Update the stale intro sentence that says "You select the
mode via the `validator` option in the `arkenv` configuration": instead explain
that validator modes are selected by importing the appropriate export (e.g.,
import from `arkenv/standard` to use Standard mode) as part of the new
three-tier export surface; replace or reword the line in validator-mode.mdx to
reference importing `arkenv/standard` (and the equivalent import names for other
modes) instead of using a `validator` option.
In `@packages/arkenv/src/arktype/index.ts`:
- Line 1: Update the import in the arktype module: replace the existing import
statement that reads import { $ } from "@repo/scope"; with the new package path
import { $ } from "arkenv/standard"; so the example uses the new arkenv/standard
export. Ensure the symbol $ remains imported from "arkenv/standard" exactly as
shown.
---
Duplicate comments:
In `@packages/arkenv/package.json`:
- Around line 18-33: The package removed the ./arktype export but no changeset
was added; create a major-bump changeset documenting the breaking change
(removal of the ./arktype export) and include it in the repository's changesets
folder so CI/release tooling will publish a major version; reference the removed
export name ("./arktype") and the affected package ("packages/arkenv" / its
package.json exports) in the changeset description.
---
Nitpick comments:
In `@apps/playgrounds/standard-schema/index.ts`:
- Line 19: The transform callback on the z.string() schema includes a redundant
parameter type annotation "str: string"; remove the explicit ": string" so the
transform reads (.transform((str) => ...)) to rely on TypeScript's inferred type
and satisfy the noInferrableTypes guideline in the transform call on the
z.string() chain.
In `@openspec/changes/refactor-export-surface/design.md`:
- Line 61: Add a one-line stabilization note stating which ArkType version the
`$.type.raw()` call signature was verified against (e.g., "Verified against
ArkType vX.Y") to the design doc so future maintainers know the assumption
backing `createEnv`'s use of `$.type.raw()` is validated; mention `createEnv`,
the `$.type.raw()` call, and that parsing/validation is delegated to `parse` in
`src/arktype/index.ts` so the note clearly ties the verification to the relevant
symbols.
In `@packages/arkenv/src/arktype/index.ts`:
- Line 7: The import for styleText uses an explicit .ts extension while the
surrounding imports (e.g., ../create-env and ./coercion/coerce) are
extension-less; change the import of styleText (symbol: styleText) to the
extension-less form (../utils/style-text) so it matches the project's import
style and remains consistent with the other imports in this module
(arktype/index.ts).
In `@packages/arkenv/src/standard-mode.test.ts`:
- Line 36: The test currently calls vi.unstubAllEnvs() inline which can be
skipped if an assertion throws; move the cleanup into a global teardown by
adding an afterEach hook that calls vi.unstubAllEnvs(), ensuring it runs after
every test; update the test file (standard-mode.test.ts) to remove the inline
vi.unstubAllEnvs() call and add afterEach(() => vi.unstubAllEnvs()) near the
other test setup/teardown code so environment stubs are always cleared even on
failures.
apps/www/content/docs/arkenv/how-to/load-environment-variables.mdx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
🧹 Nitpick comments (2)
examples/with-standard-schema/index.ts (2)
17-20: Redundant explicit type annotation on transform parameter.TypeScript can infer
strasstringfrom the precedingz.string()schema; the: stringannotation is superfluous.As per coding guidelines, "Avoid explicit types when TypeScript can infer them (
noInferrableTypeserror)."♻️ Proposed fix
- ALLOWED_ORIGINS: z - .string() - .transform((str: string) => str.split(",")) - .pipe(z.array(z.url())), + ALLOWED_ORIGINS: z + .string() + .transform((str) => str.split(",")) + .pipe(z.array(z.url())),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/with-standard-schema/index.ts` around lines 17 - 20, Remove the redundant explicit type annotation from the transform callback on ALLOWED_ORIGINS: locate the ALLOWED_ORIGINS schema where you call z.string().transform((str: string) => str.split(",")) and change the callback to use an unannotated parameter (e.g. (str) => str.split(",")) so TypeScript can infer the type from z.string(); keep the subsequent .pipe(z.array(z.url())) unchanged.
25-28:z.boolean()branch in theDEBUGunion is unreachable for env var inputs.Environment variables are always strings, so the
z.boolean()arm of the union will never match at runtime — thez.enum(["true", "false", "1", "0"])branch handles all real cases. If this example is meant to be illustrative of programmatic (non-env) usage, a short comment would help; otherwise, consider dropping the dead branch to avoid confusion.♻️ Proposed simplification (env-var-only path)
- DEBUG: z - .union([z.boolean(), z.enum(["true", "false", "1", "0"])]) - .transform((v) => v === true || v === "true" || v === "1") - .default(false), + DEBUG: z + .enum(["true", "false", "1", "0"]) + .transform((v) => v === "true" || v === "1") + .default("false"),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/with-standard-schema/index.ts` around lines 25 - 28, The DEBUG schema's union includes z.boolean() which is unreachable for env-var inputs (env vars are strings); update the DEBUG definition (the union containing z.boolean(), z.enum(["true","false","1","0"]), .transform(...), .default(false)) by either removing the z.boolean() branch to avoid dead code for env-var parsing, or add a concise comment above DEBUG stating the union includes z.boolean() only for programmatic (non-env) usage so readers understand intent; keep the existing .transform(...) and .default(false) logic unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@examples/with-standard-schema/index.ts`:
- Around line 17-20: Remove the redundant explicit type annotation from the
transform callback on ALLOWED_ORIGINS: locate the ALLOWED_ORIGINS schema where
you call z.string().transform((str: string) => str.split(",")) and change the
callback to use an unannotated parameter (e.g. (str) => str.split(",")) so
TypeScript can infer the type from z.string(); keep the subsequent
.pipe(z.array(z.url())) unchanged.
- Around line 25-28: The DEBUG schema's union includes z.boolean() which is
unreachable for env-var inputs (env vars are strings); update the DEBUG
definition (the union containing z.boolean(), z.enum(["true","false","1","0"]),
.transform(...), .default(false)) by either removing the z.boolean() branch to
avoid dead code for env-var parsing, or add a concise comment above DEBUG
stating the union includes z.boolean() only for programmatic (non-env) usage so
readers understand intent; keep the existing .transform(...) and .default(false)
logic unchanged.
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
packages/bun-plugin/src/plugin.test.ts (1)
24-27:⚠️ Potential issue | 🟠 MajorReplace
mockReset()withmockClear()inafterEachto preserve the wrappedcreateEnvimplementation across test runs.When
vi.fn(actual.createEnv)wraps the real implementation,mockReset()removes that implementation entirely, causing all subsequent tests to receiveundefined. SincebeforeEachonly callsmockClear(), the implementation is never restored. This causes tests 2–5 (which invokearkenv()and triggercreateEnv) to fail withTypeErrorwhenprocessEnvSchematries to callObject.entries()onundefined.Proposed fix
afterEach(() => { process.env = originalEnv; - mockCreateEnv.mockReset(); + mockCreateEnv.mockClear(); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/bun-plugin/src/plugin.test.ts` around lines 24 - 27, The test teardown currently calls mockCreateEnv.mockReset() which clears the wrapped real implementation of createEnv and causes later tests to get undefined; change mockCreateEnv.mockReset() to mockCreateEnv.mockClear() in the afterEach so the vi.fn wrapper around actual.createEnv is preserved across tests; ensure this change is made in the afterEach block that mirrors the beforeEach (which already uses mockClear), so arkenv()/processEnvSchema callers receive the real createEnv implementation instead of undefined.apps/www/content/docs/arkenv/validator-mode.mdx (1)
37-41:⚠️ Potential issue | 🟡 Minor
z.url()is Zod v4-only; the requirements section referenceszod@^3.24.0.Line 74 lists
zod@^3.24.0as a supported version, butz.url()was introduced in Zod v4. Usez.string().url()for v3 compatibility.🐛 Proposed fix
- DATABASE_URL: z.url(), + DATABASE_URL: z.string().url(),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/www/content/docs/arkenv/validator-mode.mdx` around lines 37 - 41, The example uses z.url() (Zod v4-only) inside the arkenv schema; replace that call with the v3-compatible z.string().url() expression so the example and the listed requirement zod@^3.24.0 are consistent—update the const env = arkenv({ ... DATABASE_URL: ... }) example to use z.string().url() instead of z.url() (ensure any references to z.url() in the surrounding docs/examples are changed similarly).apps/www/content/docs/vite-plugin/index.mdx (1)
36-49:⚠️ Potential issue | 🟡 Minor
z.url()is Zod v4-only — usez.string().url()for v3 compatibility.The documentation in
validator-mode.mdxreferenceszod@^3.24.0, which usesz.string().url()syntax. Thez.url()shorthand was introduced in Zod v4. For compatibility with both versions, usez.string().url().Proposed fix
- VITE_API_URL: z.url(), + VITE_API_URL: z.string().url(),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/www/content/docs/vite-plugin/index.mdx` around lines 36 - 49, The example uses Zod's v4-only shorthand z.url(); update the arkenv plugin config so the VITE_API_URL schema uses z.string().url() instead: locate the arkenv({...}) plugin block and replace z.url() for the VITE_API_URL entry with z.string().url() (leave VITE_API_KEY and VITE_DEBUG as-is) to restore compatibility with Zod v3.
🧹 Nitpick comments (2)
packages/vite-plugin/src/index.test.ts (1)
122-134: Optional: extract sharedmockContextinto a factory to eliminate duplication.The
mockContextobject (withmeta,error,warn,info,debug) is constructed identically in 10+ test cases. Extracting it reduces noise and makes future Vite API changes a single-point fix.♻️ Proposed refactor
+const createMockContext = () => + ({ + meta: { + framework: "vite", + version: "1.0.0", + rollupVersion: "4.0.0", + viteVersion: "5.0.0", + }, + error: vi.fn(), + warn: vi.fn(), + info: vi.fn(), + debug: vi.fn(), + }) as any;Then replace each inline object with
createMockContext(), e.g.:- const mockContext = { - meta: { - framework: "vite", - version: "1.0.0", - rollupVersion: "4.0.0", - viteVersion: "5.0.0", - }, - error: vi.fn(), - warn: vi.fn(), - info: vi.fn(), - debug: vi.fn(), - } as any; + const mockContext = createMockContext();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/vite-plugin/src/index.test.ts` around lines 122 - 134, Extract the repeated mockContext construction into a factory function (e.g., createMockContext) that returns the object with meta and stubbed methods (error, warn, info, debug) used across tests; replace each inline instantiation (the object passed into pluginInstance.config checks and other places) with calls to createMockContext(), keep the same shape and typing (cast as any or appropriate type) and place the factory at the top of the test file (or export from a shared test-helpers file) so all 10+ tests reuse it and a single change to meta or method names updates all tests.examples/without-arktype/src/index.ts (1)
7-7: Considerz.hostname()instead ofz.url()for the HOST field.
z.url()uses thenew URL()constructor and is permissive — it accepts full URI strings with a scheme (e.g.,"mailto:[email protected]","https://example.com"). For aHOSTenvironment variable,z.hostname()more accurately validates bare hostnames (e.g.,"example.com","192.168.1.1").♻️ Suggested refinement
- HOST: z.literal("localhost").or(z.url()), + HOST: z.literal("localhost").or(z.hostname()),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/without-arktype/src/index.ts` at line 7, The HOST schema currently allows z.url() which accepts full URIs; change it to use z.hostname() (keeping z.literal("localhost") or) so HOST validates bare hostnames/IPs rather than full URLs—update the HOST entry that currently reads HOST: z.literal("localhost").or(z.url()) to use z.hostname() instead of z.url() and ensure the combined schema still permits "localhost" and valid hostnames/IPs via the HOST symbol.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/www/content/docs/bun-plugin/index.mdx`:
- Line 93: Update the closing sentence that still uses the deprecated phrase
"validator mode" to match the renamed section "Using Standard Schema validators
(Zod, Valibot)"; replace the phrase with something like "default validator" or
"built-in validator implementation" and keep the guidance about installing
arktype (i.e., change the sentence that currently reads 'If you intend to use
the default **validator mode**, you should also install `arktype`:' to a wording
such as 'If you intend to use the default validator, you should also install
`arktype`:'), ensuring the wording no longer references "validator mode" but
preserves the arktype installation recommendation.
In `@openspec/specs/validator-mode/spec.md`:
- Around line 12-13: Lines stating "**THEN** it SHOULD use ArkType for
validation" and "**AND** it SHOULD support ArkType-specific features like string
DSL and `type()`" downgrade mandatory behavior; update these two normative
statements to use MUST (or SHALL) instead of SHOULD so the arkenv default entry
is required to use ArkType for validation and must expose ArkType features
(string DSL and `type()`); edit the two phrases referencing "ArkType", "string
DSL", and "`type()`" accordingly to maintain consistency with the rest of the
spec.
In `@packages/arkenv/src/parse-standard.ts`:
- Around line 54-70: The error messages in parse-standard.ts duplicate the key
name because formatInternalErrors already prepends the path; update the
ArkEnvError messages thrown in the StandardSchemaV1 path so they do not include
the key string. Specifically, in the block that throws new ArkEnvError when the
validator is invalid and in the block that throws for async validation, remove
the `"${key}"` inclusion from the message text (leave a generic, descriptive
message like "Invalid schema: expected a Standard Schema 1.0 validator in
'standard' mode." and "Async validation is not supported. ArkEnv is
synchronous."). Keep the path field as-is so formatInternalErrors can add the
key.
---
Outside diff comments:
In `@apps/www/content/docs/arkenv/validator-mode.mdx`:
- Around line 37-41: The example uses z.url() (Zod v4-only) inside the arkenv
schema; replace that call with the v3-compatible z.string().url() expression so
the example and the listed requirement zod@^3.24.0 are consistent—update the
const env = arkenv({ ... DATABASE_URL: ... }) example to use z.string().url()
instead of z.url() (ensure any references to z.url() in the surrounding
docs/examples are changed similarly).
In `@apps/www/content/docs/vite-plugin/index.mdx`:
- Around line 36-49: The example uses Zod's v4-only shorthand z.url(); update
the arkenv plugin config so the VITE_API_URL schema uses z.string().url()
instead: locate the arkenv({...}) plugin block and replace z.url() for the
VITE_API_URL entry with z.string().url() (leave VITE_API_KEY and VITE_DEBUG
as-is) to restore compatibility with Zod v3.
In `@packages/bun-plugin/src/plugin.test.ts`:
- Around line 24-27: The test teardown currently calls mockCreateEnv.mockReset()
which clears the wrapped real implementation of createEnv and causes later tests
to get undefined; change mockCreateEnv.mockReset() to mockCreateEnv.mockClear()
in the afterEach so the vi.fn wrapper around actual.createEnv is preserved
across tests; ensure this change is made in the afterEach block that mirrors the
beforeEach (which already uses mockClear), so arkenv()/processEnvSchema callers
receive the real createEnv implementation instead of undefined.
---
Duplicate comments:
In `@apps/www/content/docs/arkenv/validator-mode.mdx`:
- Around line 67-70: The docs use z.url() which is only available in Zod v4
whereas the project pins zod@^3.24.0; update the validator example to be
compatible with Zod v3 by replacing z.url() with a v3-safe alternative (e.g.,
z.string().url() or a custom validator) in the createEnv call so the
DATABASE_URL schema uses z.string().url() (or equivalent) alongside the existing
PORT definition; ensure the symbols referenced are createEnv, PORT,
DATABASE_URL, and z.url() when making the change.
---
Nitpick comments:
In `@examples/without-arktype/src/index.ts`:
- Line 7: The HOST schema currently allows z.url() which accepts full URIs;
change it to use z.hostname() (keeping z.literal("localhost") or) so HOST
validates bare hostnames/IPs rather than full URLs—update the HOST entry that
currently reads HOST: z.literal("localhost").or(z.url()) to use z.hostname()
instead of z.url() and ensure the combined schema still permits "localhost" and
valid hostnames/IPs via the HOST symbol.
In `@packages/vite-plugin/src/index.test.ts`:
- Around line 122-134: Extract the repeated mockContext construction into a
factory function (e.g., createMockContext) that returns the object with meta and
stubbed methods (error, warn, info, debug) used across tests; replace each
inline instantiation (the object passed into pluginInstance.config checks and
other places) with calls to createMockContext(), keep the same shape and typing
(cast as any or appropriate type) and place the factory at the top of the test
file (or export from a shared test-helpers file) so all 10+ tests reuse it and a
single change to meta or method names updates all tests.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## arkenv@0.10.0 ### Minor Changes - #### `arkenv/standard` import _[`#806`](#806) [`f9010d0`](f9010d0) [@yamcodes](https://github.com/yamcodes)_ `arkenv` now ships three separate entry points: - **`arkenv`** (main): ArkType-first. Includes `createEnv` (aliased to `arkenv` default import), `type`, and `ArkEnvError`. Importing from this entry requires you to have ArkType installed. - **`arkenv/standard`**: ArkType-free. A standalone `createEnv` (aliased to `arkenv` default import) for Standard Schema validators (Zod, Valibot, etc.), not requiring ArkType. - **`arkenv/core`**: Mode-agnostic primitives - `ArkEnvError` and `ValidationIssue`. #### Breaking changes **1. `validator: "standard"` option removed; `arkenv` now statically requires ArkType.** The `validator` config option has been removed - ArkType is now always required when importing from `arkenv`. For a zero-ArkType bundle, use `arkenv/standard`: ```ts // ❌ Before import arkenv from "arkenv"; import { z } from "zod"; const env = arkenv({ PORT: z.coerce.number() }, { validator: "standard" }); // ✅ After import arkenv from "arkenv/standard"; import { z } from "zod"; const env = arkenv({ PORT: z.coerce.number() }); ``` **2. `type` moved from `arkenv/arktype` to `arkenv`.** The `type` helper is now exported from the main entry. The `arkenv/arktype` sub-path is no longer public: ```ts // ❌ Before import { type } from "arkenv/arktype"; // ✅ After import { type } from "arkenv"; // 'type' is the ArkEnv helper, not a TS type modifier ``` ## @arkenv/bun-plugin@0.1.4 ### Patch Changes <details><summary>Updated 1 dependency</summary> <small> [`f9010d0`](f9010d0) </small> - `arkenv@0.10.0` </details> ## @arkenv/vite-plugin@0.0.31 ### Patch Changes - #### `arkenv/standard` import _[`#806`](#806) [`f9010d0`](f9010d0) [@yamcodes](https://github.com/yamcodes)_ `arkenv` now ships three separate entry points: - **`arkenv`** (main): ArkType-first. Includes `createEnv` (aliased to `arkenv` default import), `type`, and `ArkEnvError`. Importing from this entry requires you to have ArkType installed. - **`arkenv/standard`**: ArkType-free. A standalone `createEnv` (aliased to `arkenv` default import) for Standard Schema validators (Zod, Valibot, etc.), not requiring ArkType. - **`arkenv/core`**: Mode-agnostic primitives - `ArkEnvError` and `ValidationIssue`. #### Breaking changes **1. `validator: "standard"` option removed; `arkenv` now statically requires ArkType.** The `validator` config option has been removed - ArkType is now always required when importing from `arkenv`. For a zero-ArkType bundle, use `arkenv/standard`: ```ts // ❌ Before import arkenv from "arkenv"; import { z } from "zod"; const env = arkenv({ PORT: z.coerce.number() }, { validator: "standard" }); // ✅ After import arkenv from "arkenv/standard"; import { z } from "zod"; const env = arkenv({ PORT: z.coerce.number() }); ``` **2. `type` moved from `arkenv/arktype` to `arkenv`.** The `type` helper is now exported from the main entry. The `arkenv/arktype` sub-path is no longer public: ```ts // ❌ Before import { type } from "arkenv/arktype"; // ✅ After import { type } from "arkenv"; // 'type' is the ArkEnv helper, not a TS type modifier ``` <details><summary>Updated 1 dependency</summary> <small> [`f9010d0`](f9010d0) </small> - `arkenv@0.10.0` </details> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Summary by CodeRabbit
New Features
Breaking Changes
Documentation