Skip to content

Coercion through preprocessing PoC#465

Closed
yamcodes wants to merge 17 commits intomainfrom
228-coercion-stringnumber-stringboolean-etc
Closed

Coercion through preprocessing PoC#465
yamcodes wants to merge 17 commits intomainfrom
228-coercion-stringnumber-stringboolean-etc

Conversation

@yamcodes
Copy link
Owner

@yamcodes yamcodes commented Nov 29, 2025

Closes #228

Summary by CodeRabbit

New Features

  • Environment variables are now automatically coerced to their target types before validation
  • Numeric strings are parsed as numbers, including specialized subtypes like port numbers
  • Boolean strings ("true"/"false") are parsed as boolean values
  • Values that cannot be coerced remain unchanged for validation to catch errors

✏️ Tip: You can customize this high-level summary in your review settings.

@yamcodes yamcodes linked an issue Nov 29, 2025 that may be closed by this pull request
@changeset-bot
Copy link

changeset-bot bot commented Nov 29, 2025

⚠️ No Changeset found

Latest commit: 1551753

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Nov 29, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
arkenv Ready Ready Preview Comment Dec 10, 2025 3:55pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 29, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR implements automatic coercion of environment variables from strings to target types (numbers and booleans) before ArkType validation. It adds a new coerce utility function, integrates it into createEnv with logic to detect compiled types, updates the port keyword to accept string or number input, and includes comprehensive tests and documentation.

Changes

Cohort / File(s) Summary
Core Coercion Implementation
packages/arkenv/src/coerce.ts, packages/arkenv/src/create-env.ts
Adds coerce function to transform string env values to numbers/booleans based on schema definitions. Integrates coercion into createEnv with compiled type detection and conditional coercion application.
Coercion Tests
packages/arkenv/src/coerce.test.ts, packages/arkenv/src/coercion.integration.test.ts
Introduces unit tests for coerce logic (numeric, boolean, passthrough, undefined handling) and integration tests verifying coercion with ArkEnv schema validation and subtype constraints.
Design & Documentation
openspec/changes/add-coercion/design.md, openspec/changes/add-coercion/proposal.md, openspec/changes/add-coercion/specs/coercion/spec.md, openspec/changes/add-coercion/tasks.md, packages/arkenv/README.md
Documents the coercion design approach, problem statement, detailed behavioral specs (number subtypes, boolean strings), implementation tasks, and README documentation of coercion feature.
Keywords & Examples
packages/internal/keywords/src/index.ts, examples/basic/index.ts, apps/playgrounds/node/index.ts
Updates port keyword to accept string | number input and adjusts parsing logic. Adds example usage of MY_STRING_AS_NUMBER environment variable in basic and playground examples.

Sequence Diagram

sequenceDiagram
    participant User
    participant createEnv
    participant Coerce
    participant ArkType
    participant Validation

    User->>createEnv: createEnv(def, env)
    createEnv->>createEnv: Check if def is compiled type
    alt def is raw schema
        createEnv->>Coerce: coerce(def, env)
        Coerce->>Coerce: Iterate def entries
        Coerce->>Coerce: Coerce number/boolean strings<br/>based on type signature
        Coerce-->>createEnv: coercedEnv
    else def is compiled type
        createEnv-->>createEnv: Use env unchanged
    end
    
    createEnv->>ArkType: Validate coercedEnv against schema
    ArkType->>Validation: Schema validation
    Validation-->>ArkType: Validated result or errors
    ArkType-->>createEnv: Result or throws ArkEnvError
    createEnv-->>User: Typed environment object
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • coerce.ts implementation: Review the type detection logic (string prefix checks for "number"/"boolean") and string-to-primitive conversion correctness
  • create-env.ts integration: Verify the compiled type detection (isCompiledType) flag and conditional flow between coerced and raw environments are sound
  • port keyword changes: Confirm the updated input type constraint (string | number) and dual-path parsing logic (direct number vs. string parse) maintain validation integrity
  • Test coverage: Validate that test cases cover edge cases (undefined values, non-coercible inputs, subtype constraints like port ranges)

Possibly related PRs

Poem

🐰 A string hops in, a number bounds out,
"true" becomes true—no doubt, no doubt!
Coercion's the magic we needed to find,
Less piping, more parsing, much cleaner by design!
Environment variables now dancing with glee, 💫

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Coercion through preprocessing PoC' accurately describes the main change: implementing a proof-of-concept for environment variable coercion using a preprocessing approach.
Linked Issues check ✅ Passed The PR implements Solution A from issue #228: a preprocessing coercion layer that converts string env vars to primitives (numbers, booleans) before ArkType validation, meeting the core requirement to enable shorthand type declarations without manual conversion.
Out of Scope Changes check ✅ Passed All changes are within scope: coerce utility implementation, integration into createEnv, comprehensive tests, design/proposal documentation, README updates, and example files demonstrating the feature.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 228-coercion-stringnumber-stringboolean-etc

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the docs Improvements or additions to documentation label Nov 29, 2025
@yamcodes yamcodes requested review from Copilot and removed request for Copilot November 29, 2025 20:20
@yamcodes yamcodes changed the title feat: add specification, design, and tasks for automatic environment … Coercion from ArkEnv side PoC Nov 29, 2025
@yamcodes yamcodes changed the title Coercion from ArkEnv side PoC Coercion through preprocessing PoC Nov 29, 2025
@github-actions github-actions bot added arkenv Changes to the `arkenv` npm package. tests This issue or PR is about adding, removing or changing tests labels Nov 29, 2025
@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 29, 2025

Open in StackBlitz

npm i https://pkg.pr.new/arkenv@465
npm i https://pkg.pr.new/@arkenv/bun-plugin@465
npm i https://pkg.pr.new/@arkenv/vite-plugin@465

commit: 1551753

@yamcodes yamcodes marked this pull request as ready for review November 29, 2025 20:47
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

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/types.ts (1)

3-14: Update port JSDoc to reflect new string | number input

The implementation now accepts both strings and numbers (type("string | number", ...)), but the comment still describes only “A string that can be parsed into a number…”. Consider updating the doc to something like “A string or number representing a port in the range 0–65535” so it matches the actual type.

🧹 Nitpick comments (9)
packages/arkenv/src/coerce.ts (1)

1-31: Coercion logic matches spec; consider supporting boolean subtypes/defaults

The implementation is clean and side‑effect free. To mirror the number handling (which supports number.* and number = ... styles via startsWith("number")), you could also treat boolean subtypes/defaults by checking typeDef.startsWith("boolean") instead of strict equality. That would automatically coerce definitions like "boolean?" or "boolean = false" as well, and keep behavior consistent.

-			} else if (typeDef === "boolean") {
+			} else if (typeDef.startsWith("boolean")) {
openspec/changes/add-coercion/specs/coercion/spec.md (1)

1-42: Spec content matches behavior; consider WHEN/THEN bullets and a failure scenario

The requirements and examples line up with the implementation (number.* and boolean coercion plus pass‑through). To match the openspec guidelines more closely, you could:

  • Rewrite scenario bodies as bullet lists with **WHEN** / **THEN** items instead of freeform Given/When/Then lines.
  • Optionally add a scenario for a non‑coercible value (e.g. PORT: "number" with "not-a-number") being passed through unchanged and rejected by ArkType.

As per coding guidelines, openspec specs should use the standardized scenario format.

openspec/changes/add-coercion/design.md (1)

1-66: Align design pseudo-code and paths with the final implementation

The high‑level architecture matches the code, but a few details in the examples are now slightly out of sync:

  • Flow step 3 mentions Number() or parseFloat(), but coerce.ts currently uses Number() only.
  • The coerce sample lives in src/utils.ts in the doc, while the actual implementation is in packages/arkenv/src/coerce.ts.
  • The integration snippet uses isPlainObject(def), whereas the code distinguishes compiled types via an isCompiledType check.

Updating these snippets to mirror coerce.ts and create-env.ts will reduce confusion for future readers.

apps/playgrounds/node/index.ts (1)

3-28: Playground still shows manual coercion rather than the new automatic coercion

MY_STRING_AS_NUMBER is defined via type("string").pipe((value) => Number(value)), which is essentially what the new preprocessing coerce step now does for "number" schemas. Because Env here is a compiled type passed to arkenv(Env, process.env), the new coerce hook in createEnv will not run for this example.

If you intend this playground to showcase the new feature, consider either:

  • Using a raw schema with arkenv({ MY_STRING_AS_NUMBER: "number", ... }) so the automatic coercion path is exercised, or
  • Adding a short comment that this example intentionally demonstrates a custom pipe beyond the built‑in coercion behavior.

Based on learnings, examples should highlight the recommended ergonomics around createEnv/arkenv.

openspec/changes/add-coercion/tasks.md (1)

1-7: Update task paths (and optionally numbering) to match the codebase

The checklist accurately reflects what was done, but the referenced locations are now slightly off:

  • coerce lives in packages/arkenv/src/coerce.ts, not src/utils.ts.
  • Integration tests are in packages/arkenv/src/coercion.integration.test.ts, not tests/coercion.test.ts.

Consider updating these paths so future readers can quickly find the implementation and tests. You may also want to prefix the items with explicit numbers to align with the openspec/changes/*/tasks.md “numbered checklist” convention.

As per coding guidelines, tasks.md should serve as an accurate, navigable map of the change.

packages/arkenv/README.md (1)

60-72: Coercion docs look good; consider briefly explaining failure behavior

The new Coercion section is clear and aligns with coerce.ts (numbers and number.*number, "true"/"false"boolean). To help users debug misconfigured env vars, you might add a short note that:

  • Non‑coercible values (e.g. PORT="abc") are left as strings, and
  • ArkType/ArkEnv will then surface these as ArkEnvError validation failures.

This ties the feature back to the error story emphasized elsewhere in the README.

openspec/changes/add-coercion/proposal.md (1)

1-28: Align proposal sections with openspec conventions and fix minor grammar

The proposal content matches the implemented behavior, but the structure doesn’t fully follow the openspec/changes/*/proposal.md pattern:

  • Consider organizing sections under ## Why, ## What Changes (marking any BREAKING aspects), and ## Impact instead of ## Problem / ## Solution.
  • LanguageTool also flagged “native feeling” – changing this to “native-feeling” would fix the hyphenation nit.

As per coding guidelines, proposals should follow the standard section layout to keep the changes consistently scannable.

packages/arkenv/src/coerce.test.ts (1)

61-67: Consider renaming test to clarify behavior for extra keys

The body asserts that EXTRA is preserved ("foo"), so “ignore keys not in definition” could be read as “drop them entirely.” A name like should_not_coerce_keys_not_in_definition or should_preserve_extra_keys_unchanged would better document the intended behavior.

packages/arkenv/src/coercion.integration.test.ts (1)

26-37: Optionally assert on ArkEnvError type/message for failure cases

For the failing scenarios you currently use a bare toThrow(). To lock in the public error contract, consider asserting on the specific error type (e.g. ArkEnvError) or key parts of the message (missing/invalid var name + expected type), in line with the guideline that env validation errors should be surfaced via ArkEnvError with clear messaging.

Based on learnings, error handling is a first‑class API surface and worth pinning down here.

Also applies to: 57-61

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea7d4e0 and f88d25c.

📒 Files selected for processing (11)
  • apps/playgrounds/node/index.ts (2 hunks)
  • openspec/changes/add-coercion/design.md (1 hunks)
  • openspec/changes/add-coercion/proposal.md (1 hunks)
  • openspec/changes/add-coercion/specs/coercion/spec.md (1 hunks)
  • openspec/changes/add-coercion/tasks.md (1 hunks)
  • packages/arkenv/README.md (1 hunks)
  • packages/arkenv/src/coerce.test.ts (1 hunks)
  • packages/arkenv/src/coerce.ts (1 hunks)
  • packages/arkenv/src/coercion.integration.test.ts (1 hunks)
  • packages/arkenv/src/create-env.ts (2 hunks)
  • packages/arkenv/src/types.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (15)
openspec/changes/*/tasks.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Create tasks.md with numbered implementation checklist items as checkboxes (- [ ] format)

Files:

  • openspec/changes/add-coercion/tasks.md
packages/arkenv/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/arktype.mdc)

packages/arkenv/**/*.ts: Use ArkType's type() function to define schemas in environment variable definitions
Leverage ArkType's type inference for TypeScript types instead of manual type definitions
Use the scoped $ type system for custom types defined in scope.ts
Keep environment variable schemas readable and TypeScript-like using ArkType syntax
Use union types for enums in ArkType schemas (e.g., "'dev' | 'prod'") instead of separate enum definitions
Leverage ArkType's built-in types (e.g., string.host, number.port) where possible in environment schemas
Convert ArkType validation errors to ArkEnvError for user-friendly error messages that include variable name and expected type

Files:

  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coerce.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

Files:

  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coerce.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • apps/playgrounds/node/index.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Co-locate tests with components: Component.tsx next to Component.test.tsx

**/*.test.{ts,tsx}: Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests
Keep unit tests fast with execution under 100ms per test
Co-locate unit tests with source files using naming convention: source.tssource.test.ts
Focus component tests on public API, user behavior, state transitions, and accessibility rather than styling or implementation details
Query component tests by role, name, label, and text using accessibility-first selectors
Use Vitest as the test framework for unit and integration tests
Use Testing Library with user-event for real user simulation in component tests

Unit tests should be fast (< 100ms per test) and located alongside source files with .test.ts suffix, with mocked external dependencies

Files:

  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx}: Use the main function createEnv(schema) or default import arkenv to create validated environment objects with TypeScript type inference from ArkType schemas
Use built-in validators (host, port, url, email) from src/types.ts when available instead of writing custom validation logic
Provide descriptive variable names that indicate purpose and format in environment schema definitions
Group related environment variables in logical schemas for better organization and maintainability
Provide default values for optional environment variables using ArkType's default value syntax (e.g., "boolean = false")

Files:

  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coerce.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • apps/playgrounds/node/index.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
**/*.{test,integration.test}.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use Vitest's describe/it structure with both success and failure test cases in all test files

Files:

  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
**/packages/**/*.{test,integration.test}.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Mock process.env in tests to simulate different environment scenarios with both valid and invalid values

Files:

  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
**/packages/arkenv/**/*.{test,integration.test}.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Save and restore original process.env in beforeEach/afterEach hooks to avoid test pollution

Files:

  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
**/packages/arkenv/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Ensure environment validation errors display missing variables, expected types/formats, and helpful suggestions for fixing issues

Files:

  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coerce.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
**/*.{test,integration.test}.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use TypeScript types directly in test files to verify both runtime behavior and TypeScript type correctness

Files:

  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
**/*.integration.test.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/test-patterns.mdc)

**/*.integration.test.{ts,tsx}: Test how multiple units (components, hooks, functions) work together without mocking their interactions in integration tests
Keep integration tests slower but comprehensive (100ms - 2000ms per test) with real interactions between units
Use *.integration.test.ts suffix to distinguish integration tests from unit tests

Integration tests should use .integration.test.ts suffix, test real interactions between units without mocking their interactions, and may take 100ms - 2000ms per test

Files:

  • packages/arkenv/src/coercion.integration.test.ts
openspec/changes/*/specs/**/spec.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

openspec/changes/*/specs/**/spec.md: Use ## ADDED|MODIFIED|REMOVED|RENAMED Requirements as delta headers in spec.md files under changes
Ensure change proposals contain delta specs for each affected capability under changes/[change-id]/specs/[capability]/spec.md

Files:

  • openspec/changes/add-coercion/specs/coercion/spec.md
openspec/**/spec.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

openspec/**/spec.md: Include at least one scenario per requirement using #### Scenario: header format with WHEN and THEN bullet points
Use SHALL/MUST for normative requirements rather than should/may unless intentionally non-normative

Files:

  • openspec/changes/add-coercion/specs/coercion/spec.md
**/index.ts

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Use barrel exports (index.ts) for package entry points

Files:

  • apps/playgrounds/node/index.ts
openspec/changes/*/proposal.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Create proposal.md with sections: Why, What Changes (with BREAKING markers), and Impact

Files:

  • openspec/changes/add-coercion/proposal.md
🧠 Learnings (27)
📓 Common learnings
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Provide default values for optional environment variables using ArkType's default value syntax (e.g., `"boolean = false"`)
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use the main function `createEnv(schema)` or default import `arkenv` to create validated environment objects with TypeScript type inference from ArkType schemas
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: ArkType validates environment variables at runtime and TypeScript types are inferred from the schema definition
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use ArkType's `type()` function to define schemas in environment variable definitions
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/packages/arkenv/**/*.{ts,tsx} : Ensure environment validation errors display missing variables, expected types/formats, and helpful suggestions for fixing issues
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax

Applied to files:

  • packages/arkenv/README.md
  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coerce.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • openspec/changes/add-coercion/specs/coercion/spec.md
  • apps/playgrounds/node/index.ts
  • openspec/changes/add-coercion/proposal.md
  • openspec/changes/add-coercion/design.md
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas

Applied to files:

  • packages/arkenv/README.md
  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coerce.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • openspec/changes/add-coercion/specs/coercion/spec.md
  • apps/playgrounds/node/index.ts
  • openspec/changes/add-coercion/proposal.md
  • openspec/changes/add-coercion/design.md
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
📚 Learning: 2025-11-29T07:59:59.399Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/packages/arkenv/**/*.{ts,tsx} : Ensure environment validation errors display missing variables, expected types/formats, and helpful suggestions for fixing issues

Applied to files:

  • packages/arkenv/README.md
  • openspec/changes/add-coercion/tasks.md
  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coerce.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • openspec/changes/add-coercion/proposal.md
  • openspec/changes/add-coercion/design.md
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type

Applied to files:

  • packages/arkenv/README.md
  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coerce.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • openspec/changes/add-coercion/proposal.md
  • openspec/changes/add-coercion/design.md
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use union types for enums in ArkType schemas (e.g., `"'dev' | 'prod'"`) instead of separate enum definitions

Applied to files:

  • packages/arkenv/README.md
  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coerce.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • openspec/changes/add-coercion/proposal.md
  • openspec/changes/add-coercion/design.md
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's type inference for TypeScript types instead of manual type definitions

Applied to files:

  • packages/arkenv/README.md
  • packages/arkenv/src/coerce.ts
  • openspec/changes/add-coercion/proposal.md
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use ArkType's `type()` function to define schemas in environment variable definitions

Applied to files:

  • packages/arkenv/README.md
  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coerce.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • openspec/changes/add-coercion/specs/coercion/spec.md
  • apps/playgrounds/node/index.ts
  • openspec/changes/add-coercion/proposal.md
  • openspec/changes/add-coercion/design.md
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
📚 Learning: 2025-11-29T07:59:59.399Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Provide default values for optional environment variables using ArkType's default value syntax (e.g., `"boolean = false"`)

Applied to files:

  • packages/arkenv/README.md
  • packages/arkenv/src/coerce.ts
  • openspec/changes/add-coercion/specs/coercion/spec.md
  • apps/playgrounds/node/index.ts
  • openspec/changes/add-coercion/proposal.md
  • openspec/changes/add-coercion/design.md
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors

Applied to files:

  • packages/arkenv/README.md
  • apps/playgrounds/node/index.ts
  • openspec/changes/add-coercion/proposal.md
  • openspec/changes/add-coercion/design.md
  • packages/arkenv/src/create-env.ts
📚 Learning: 2025-11-29T07:59:59.399Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use the main function `createEnv(schema)` or default import `arkenv` to create validated environment objects with TypeScript type inference from ArkType schemas

Applied to files:

  • packages/arkenv/README.md
  • openspec/changes/add-coercion/tasks.md
  • packages/arkenv/src/coerce.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • openspec/changes/add-coercion/specs/coercion/spec.md
  • apps/playgrounds/node/index.ts
  • openspec/changes/add-coercion/proposal.md
  • openspec/changes/add-coercion/design.md
  • packages/arkenv/src/create-env.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: ArkType validates environment variables at runtime and TypeScript types are inferred from the schema definition

Applied to files:

  • packages/arkenv/README.md
  • openspec/changes/add-coercion/specs/coercion/spec.md
  • openspec/changes/add-coercion/proposal.md
  • openspec/changes/add-coercion/design.md
  • packages/arkenv/src/create-env.ts
📚 Learning: 2025-11-24T16:04:36.939Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-11-24T16:04:36.939Z
Learning: Achieve coverage goals: environment variable parsing and validation, type checking and error handling, default value handling, custom type validation, plugin integration with Vite, and real project build testing using examples as fixtures

Applied to files:

  • openspec/changes/add-coercion/tasks.md
  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
📚 Learning: 2025-11-29T07:59:59.399Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/packages/**/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in tests to simulate different environment scenarios with both valid and invalid values

Applied to files:

  • openspec/changes/add-coercion/tasks.md
  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-24T16:04:36.939Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-11-24T16:04:36.939Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Test how multiple units (components, hooks, functions) work together without mocking their interactions in integration tests

Applied to files:

  • openspec/changes/add-coercion/tasks.md
  • packages/arkenv/src/coercion.integration.test.ts
📚 Learning: 2025-11-29T07:59:59.399Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/packages/arkenv/**/*.{test,integration.test}.{ts,tsx} : Save and restore original `process.env` in `beforeEach`/`afterEach` hooks to avoid test pollution

Applied to files:

  • openspec/changes/add-coercion/tasks.md
  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
📚 Learning: 2025-11-24T16:04:36.939Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-11-24T16:04:36.939Z
Learning: Applies to **/*.test.{ts,tsx} : Co-locate unit tests with source files using naming convention: `source.ts` → `source.test.ts`

Applied to files:

  • openspec/changes/add-coercion/tasks.md
  • packages/arkenv/src/coerce.test.ts
📚 Learning: 2025-11-29T07:59:59.399Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/*.{test,integration.test}.ts : Use TypeScript types directly in test files to verify both runtime behavior and TypeScript type correctness

Applied to files:

  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
📚 Learning: 2025-11-29T07:59:59.399Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Use Vitest's `describe`/`it` structure with both success and failure test cases in all test files

Applied to files:

  • packages/arkenv/src/coerce.test.ts
  • packages/arkenv/src/coercion.integration.test.ts
📚 Learning: 2025-11-29T08:57:24.044Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: examples/with-bun-react/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-29T08:57:24.044Z
Learning: Applies to examples/with-bun-react/**/*.test.{ts,tsx,js,jsx} : Use test syntax from `bun:test` with `test` and `expect` functions

Applied to files:

  • packages/arkenv/src/coerce.test.ts
📚 Learning: 2025-11-29T07:59:59.399Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use built-in validators (`host`, `port`, `url`, `email`) from `src/types.ts` when available instead of writing custom validation logic

Applied to files:

  • packages/arkenv/src/coercion.integration.test.ts
  • apps/playgrounds/node/index.ts
  • packages/arkenv/src/types.ts
📚 Learning: 2025-11-24T16:04:36.939Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-11-24T16:04:36.939Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest as the test framework for unit and integration tests

Applied to files:

  • packages/arkenv/src/coercion.integration.test.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use UPPER_SNAKE_CASE for environment variables and constants

Applied to files:

  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-29T07:59:59.399Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T07:59:59.399Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Provide descriptive variable names that indicate purpose and format in environment schema definitions

Applied to files:

  • apps/playgrounds/node/index.ts
  • openspec/changes/add-coercion/design.md
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use the scoped `$` type system for custom types defined in `scope.ts`

Applied to files:

  • packages/arkenv/src/create-env.ts
  • packages/arkenv/src/types.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/scope.ts : Define custom types in `scope.ts` using ArkType's scoped type system for reusability across schemas

Applied to files:

  • packages/arkenv/src/create-env.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Prefer `Number.parseInt` over global `parseInt` (`useNumberNamespace` error)

Applied to files:

  • packages/arkenv/src/types.ts
🧬 Code graph analysis (5)
packages/arkenv/README.md (2)
packages/arkenv/src/type.test.ts (9)
  • envType (86-108)
  • envType (129-129)
  • envType (171-190)
  • envType (83-83)
  • envType (67-84)
  • envType (127-127)
  • envType (11-15)
  • envType (118-118)
  • envType (29-47)
packages/arkenv/src/custom-types.integration.test.ts (1)
  • env (199-205)
apps/playgrounds/node/index.ts (4)
packages/arkenv/src/type.ts (1)
  • type (3-3)
examples/with-bun-react/src/env.ts (1)
  • env (9-9)
packages/arkenv/src/create-env.test.ts (2)
  • env (87-98)
  • process (128-145)
packages/arkenv/src/type.test.ts (2)
  • envType (11-15)
  • envType (118-118)
openspec/changes/add-coercion/proposal.md (1)
packages/arkenv/src/type.test.ts (9)
  • envType (29-47)
  • envType (86-108)
  • envType (202-217)
  • envType (171-190)
  • envType (11-15)
  • envType (118-118)
  • envType (127-127)
  • envType (116-116)
  • envType (128-128)
openspec/changes/add-coercion/design.md (2)
packages/arkenv/src/type.test.ts (7)
  • envType (86-108)
  • envType (29-47)
  • envType (171-190)
  • envType (23-27)
  • envType (202-217)
  • envType (5-9)
  • envType (116-116)
packages/arkenv/src/create-env.test.ts (1)
  • envSchema (172-187)
packages/arkenv/src/create-env.ts (2)
packages/arkenv/src/scope.ts (1)
  • $ (9-19)
packages/arkenv/src/coerce.ts (1)
  • coerce (1-31)
🪛 LanguageTool
openspec/changes/add-coercion/proposal.md

[grammar] ~28-~28: Use a hyphen to join words.
Context: ...oach allows arkenv to support "native" feeling environment variables while leve...

(QB_NEW_EN_HYPHEN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: test-e2e (e2e)
  • GitHub Check: test-e2e (a11y)
  • GitHub Check: test-build (lts/*)
  • GitHub Check: test-build (latest)
  • GitHub Check: test-typesafety
🔇 Additional comments (3)
packages/arkenv/src/create-env.ts (1)

3-51: Coercion integration and compiled-type detection look solid

The isCompiledType guard cleanly separates compiled ArkType inputs from raw schema objects and only applies coerce to the latter, which matches the documented limitation around pre‑compiled types. Passing coercedEnv into schema(...) while preserving the existing instanceof type.errorsArkEnvError flow keeps backwards compatibility for error handling while enabling the new coercion behavior.

packages/arkenv/src/coerce.test.ts (1)

4-59: Comprehensive unit coverage for coercion behavior looks good

This suite cleanly exercises numeric/boolean coercion, failure pass-through, undefined handling, and subtype support; nothing blocking from my side here.

packages/arkenv/src/coercion.integration.test.ts (1)

5-55: Solid integration coverage of coercion and validation

These tests nicely cover end‑to‑end behavior: primitive coercion, subtype validation (number.port), mixed schemas, and failure paths when coercion can’t satisfy the schema. This gives good confidence that createEnv and coerce work together as intended.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements automatic coercion of environment variables from strings to their target primitive types (numbers and booleans), eliminating the need for manual type conversion. The feature uses a preprocessing approach that inspects raw schema definitions and converts string values before ArkType validation, making environment variable handling more intuitive while maintaining backward compatibility.

Key Changes

  • Added a coerce() function that converts string environment variables to numbers and booleans before validation
  • Integrated coercion into createEnv() as a preprocessing step (only for raw schema objects, not compiled types)
  • Updated the port type to accept both strings and numbers for backward compatibility with compiled types where coercion doesn't apply

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
packages/arkenv/src/coerce.ts New coercion utility that converts string env vars to numbers (including subtypes like number.port) and booleans ("true"/"false")
packages/arkenv/src/create-env.ts Integrates coercion preprocessing before validation; only applies to raw schemas, not compiled types
packages/arkenv/src/types.ts Updated port validator to accept string | number for backward compatibility
packages/arkenv/src/coerce.test.ts Unit tests for coercion logic covering basic cases and error pass-through
packages/arkenv/src/coercion.integration.test.ts Integration tests verifying end-to-end coercion with validation
packages/arkenv/README.md Documents coercion feature with examples
openspec/changes/add-coercion/proposal.md Defines the problem statement and desired behavior
openspec/changes/add-coercion/design.md Explains architectural decisions and preprocessing approach
openspec/changes/add-coercion/specs/coercion/spec.md Formal specification with scenarios for number and boolean coercion
openspec/changes/add-coercion/tasks.md Task checklist for implementation (all completed)
apps/playgrounds/node/index.ts Added example showing manual .pipe() for compiled types
Comments suppressed due to low confidence (1)

apps/playgrounds/node/index.ts:10

  • This playground uses a compiled type (type({...})), which means automatic coercion will NOT work according to the implementation in create-env.ts (lines 44-48). The added example MY_STRING_AS_NUMBER with manual .pipe() is good, but consider adding a comment explaining why manual piping is necessary when using compiled types, or provide a second example using a raw schema object to demonstrate automatic coercion.
const Env = type({
	HOST: "string.host",
	MY_STRING_AS_NUMBER: type("string").pipe((value) => Number(value)),
	PORT: "number.port",
	NODE_ENV: "'development' | 'production' | 'test' = 'development'",
	ALLOWED_ORIGINS: type("string[]").default(() => []),
	DEBUG: "boolean = true",
});

Comment on lines +60 to +73
## Coercion

Environment variables are always strings, but ArkEnv automatically coerces them to their target types when possible:

- `number` and subtypes (`number.port`, `number.epoch`) are parsed as numbers.
- `boolean` strings ("true", "false") are parsed as booleans.

```ts
const env = arkenv({
PORT: "number", // "3000" → 3000
DEBUG: "boolean", // "true" → true
TIMESTAMP: "number.epoch" // "1640995200000" → 1640995200000
});
```
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The coercion documentation should clarify an important limitation: coercion only works with raw schema objects (e.g., arkenv({ PORT: "number" })), not with pre-compiled types (e.g., arkenv(type({ PORT: "number" }))). This is mentioned in the integration test but should be prominently documented here.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +19
if (typeDef.startsWith("number")) {
const asNumber = Number(value);
if (!Number.isNaN(asNumber)) {
coerced[key] = asNumber;
}
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Number(value) for coercion can produce unexpected results for edge cases:

  • Empty strings: Number("") returns 0, which may not be the intended behavior
  • Whitespace: Number(" ") returns 0
  • Scientific notation: Number("1e3") returns 1000 (might be acceptable)

Consider using Number.parseFloat() or adding explicit validation to reject empty/whitespace-only strings to avoid silent conversion of invalid inputs to 0.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +31
it("should coerce boolean 'true'", () => {
const def = { DEBUG: "boolean" };
const env = { DEBUG: "true" };
const result = coerce(def, env);
expect(result.DEBUG).toBe(true);
});

it("should coerce boolean 'false'", () => {
const def = { DEBUG: "boolean" };
const env = { DEBUG: "false" };
const result = coerce(def, env);
expect(result.DEBUG).toBe(false);
});
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing test coverage for additional boolean edge cases:

  • Case sensitivity: What happens with "True", "FALSE", "TRUE"?
  • Numeric booleans: "0", "1"
  • Other truthy/falsy strings commonly used in env vars: "yes", "no", "on", "off"

While the current implementation only accepts exact "true"/"false", tests should verify these other values are properly rejected or document why only these two values are supported.

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +27
if (typeof typeDef === "string") {
if (typeDef.startsWith("number")) {
const asNumber = Number(value);
if (!Number.isNaN(asNumber)) {
coerced[key] = asNumber;
}
} else if (typeDef === "boolean") {
if (value === "true") {
coerced[key] = true;
} else if (value === "false") {
coerced[key] = false;
}
}
}
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The coercion logic only handles simple string type definitions. It doesn't account for:

  1. Union types: "number | string" - will try to coerce even though string is acceptable
  2. Optional types: "number?" - will coerce, but the ? suffix might not be handled
  3. Types with defaults: "number = 3000" - will coerce, but the = 3000 suffix needs testing

Consider adding logic to parse these modifiers or adding tests to verify current behavior with these patterns.

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +55
it("should work with mixed coerced and non-coerced values", () => {
const env = createEnv(
{
PORT: "number",
HOST: "string",
DEBUG: "boolean",
},
{
PORT: "3000",
HOST: "localhost",
DEBUG: "true",
},
);
expect(env.PORT).toBe(3000);
expect(env.HOST).toBe("localhost");
expect(env.DEBUG).toBe(true);
});
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Missing test coverage for the case where a non-string primitive (e.g., actual number or boolean) is passed in the environment object. While typically environment variables are strings, the function signature accepts Record<string, string | undefined>, and in test scenarios someone might pass actual primitives. Add a test to verify that already-coerced values (numbers, booleans) are passed through unchanged.

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +5
): Record<string, unknown> {
const coerced: Record<string, unknown> = { ...env };
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The return type Record<string, unknown> doesn't match the input parameter constraint. The function accepts env: Record<string, string | undefined> but returns Record<string, unknown>, which correctly reflects that values can be coerced to numbers/booleans. However, for better type safety, consider making the return type more explicit: Record<string, string | number | boolean | undefined> to document exactly what types can be returned.

Suggested change
): Record<string, unknown> {
const coerced: Record<string, unknown> = { ...env };
): Record<string, string | number | boolean | undefined> {
const coerced: Record<string, string | number | boolean | undefined> = { ...env };

Copilot uses AI. Check for mistakes.
Comment on lines +61 to +68
it("should ignore keys not in definition", () => {
const def = { PORT: "number" };
const env = { PORT: "3000", EXTRA: "foo" };
const result = coerce(def, env);
expect(result.PORT).toBe(3000);
expect(result.EXTRA).toBe("foo");
});
});
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Add test coverage for coercion with ArkType modifiers in raw schema definitions:

  • Optional types: { PORT: "number?" } with missing value
  • Types with pipe operators: { VALUE: "number | string" } to ensure it doesn't incorrectly coerce strings that are valid
  • Union types with boolean: { FLAG: "boolean | string" }

The current string-based detection (typeDef.startsWith("number")) might have unintended behavior with these patterns.

Copilot uses AI. Check for mistakes.
@yamcodes yamcodes self-assigned this Dec 9, 2025
@arkenv-bot
Copy link
Contributor

arkenv-bot bot commented Dec 10, 2025

📦 Bundle Size Report

Package Size Limit Diff Status
arkenv 848 B 2 kB +16.5%

All size limits passed!

@github-actions github-actions bot added the example Issues or Pull Requests concerning at least one ArkEnv example. (Found in the `examples/` directory) label Dec 10, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/internal/keywords/src/index.ts (1)

1-29: Pipeline failure: Examples out of sync.

The CI pipeline is failing because the examples are out of sync. Run pnpm sync:examples to update them before merging.

#!/bin/bash
# Run this command to sync the examples
pnpm sync:examples
apps/playgrounds/node/index.ts (1)

1-32: Pipeline failure: Examples out of sync.

The CI pipeline is failing because the examples are out of sync. Run pnpm sync:examples to update them before merging.

#!/bin/bash
# Run this command to sync the examples
pnpm sync:examples
♻️ Duplicate comments (1)
packages/internal/keywords/src/index.ts (1)

4-4: Update the documentation comment.

The documentation is outdated and doesn't reflect that the type now accepts both string and number inputs.

As noted in the previous review, update to:

-/**
- * A `string` that can be parsed into a number between 0 and 65535
- */
+/**
+ * A string or number between 0 and 65535
+ */
🧹 Nitpick comments (1)
apps/playgrounds/node/index.ts (1)

28-28: Consider a clearer console label.

The label myString doesn't convey that the value has been transformed to a number. Consider using myNumber or myStringAsNumber for clarity.

-	myString: env.MY_STRING_AS_NUMBER,
+	myNumber: env.MY_STRING_AS_NUMBER,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f88d25c and 5a90cd2.

📒 Files selected for processing (4)
  • apps/playgrounds/node/index.ts (2 hunks)
  • packages/arkenv/README.md (1 hunks)
  • packages/arkenv/src/create-env.ts (2 hunks)
  • packages/internal/keywords/src/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/arkenv/src/create-env.ts
  • packages/arkenv/README.md
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

**/*.{ts,tsx}: Use createEnv(schema) as the main function for validated environment objects, available as the default export
Use built-in validators (host, port, url, email) from src/types.ts when available instead of custom validation
Use ArkEnvError for environment variable errors, not generic errors
Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern
Use logical grouping for related environment variables in schemas
Use descriptive env...

Files:

  • apps/playgrounds/node/index.ts
  • packages/internal/keywords/src/index.ts
**/index.ts

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Use barrel exports (index.ts) for package entry points

Files:

  • apps/playgrounds/node/index.ts
  • packages/internal/keywords/src/index.ts
**/*.{ts,tsx,json,md}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use Biome for linting and formatting instead of ESLint and Prettier

Files:

  • apps/playgrounds/node/index.ts
  • packages/internal/keywords/src/index.ts
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-11-24T16:04:36.939Z
Learning: Achieve coverage goals: environment variable parsing and validation, type checking and error handling, default value handling, custom type validation, plugin integration with Vite, and real project build testing using examples as fixtures
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use descriptive environment variable names that indicate purpose and format

Applied to files:

  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use UPPER_SNAKE_CASE for environment variables and constants

Applied to files:

  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas

Applied to files:

  • apps/playgrounds/node/index.ts
  • packages/internal/keywords/src/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax

Applied to files:

  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use ArkType's `type()` function to define schemas in environment variable definitions

Applied to files:

  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors

Applied to files:

  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable errors, not generic errors

Applied to files:

  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: ArkType validates environment variables at runtime and TypeScript types are inferred from the schema definition

Applied to files:

  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type

Applied to files:

  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern

Applied to files:

  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use union types for enums in ArkType schemas (e.g., `"'dev' | 'prod'"`) instead of separate enum definitions

Applied to files:

  • apps/playgrounds/node/index.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Prefer `Number.parseInt` over global `parseInt` (`useNumberNamespace` error)

Applied to files:

  • packages/internal/keywords/src/index.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use built-in validators (host, port, url, email) from `src/types.ts` when available instead of custom validation

Applied to files:

  • packages/internal/keywords/src/index.ts
🧬 Code graph analysis (1)
packages/internal/keywords/src/index.ts (1)
packages/arkenv/src/type.ts (1)
  • type (3-3)
🪛 GitHub Actions: sync-examples
apps/playgrounds/node/index.ts

[error] 1-1: Examples out of sync: Modified: index.ts. Run 'pnpm sync:examples' to update them. Command 'pnpm sync:examples:check' failed with exit code 1.

packages/internal/keywords/src/index.ts

[error] 1-1: Examples out of sync: Modified: index.ts. Run 'pnpm sync:examples' to update them. Command 'pnpm sync:examples:check' failed with exit code 1.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test-e2e (e2e)
  • GitHub Check: test-e2e (a11y)
🔇 Additional comments (2)
packages/internal/keywords/src/index.ts (1)

6-14: LGTM! Implementation correctly handles both string and number inputs.

The updated port validator appropriately expands the input type to string | number and handles both cases correctly:

  • String inputs are parsed using Number.parseInt
  • Number inputs are used directly
  • Validation logic for integer check and range (0-65535) is preserved

This dual-input design allows the validator to work both standalone and with the upstream coercion layer introduced in this PR.

apps/playgrounds/node/index.ts (1)

6-6: Replace manual transformation with automatic coercion to demonstrate the new feature.

Automatic coercion for the "number" type is built into the system and handles string-to-number conversion. Simplify this to:

MY_STRING_AS_NUMBER: "number",

This demonstrates the automatic coercion feature instead of manual .pipe() transformation and keeps the example concise.

⛔ Skipped due to learnings
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Prefer `Number.parseInt` over global `parseInt` (`useNumberNamespace` error)
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
examples/basic/index.ts (1)

28-28: Consider using a more descriptive property name for clarity.

The environment variable is named MY_STRING_AS_NUMBER, but the console output property is named myString. For better readability in examples, consider using a name that better reflects the variable's purpose.

Apply this diff:

-	myString: env.MY_STRING_AS_NUMBER,
+	myStringAsNumber: env.MY_STRING_AS_NUMBER,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5a90cd2 and 2e79e95.

⛔ Files ignored due to path filters (1)
  • examples/basic/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • apps/playgrounds/bun-react/bin/build.ts (0 hunks)
  • examples/basic/index.ts (2 hunks)
  • examples/with-bun-react/bin/build.ts (0 hunks)
💤 Files with no reviewable changes (2)
  • apps/playgrounds/bun-react/bin/build.ts
  • examples/with-bun-react/bin/build.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

**/*.{ts,tsx}: Use createEnv(schema) as the main function for validated environment objects, available as the default export
Use built-in validators (host, port, url, email) from src/types.ts when available instead of custom validation
Use ArkEnvError for environment variable errors, not generic errors
Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern
Use logical grouping for related environment variables in schemas
Use descriptive env...

Files:

  • examples/basic/index.ts
{bin,examples,playgrounds}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Console usage is allowed in bin/ and example/playground directories, otherwise treated as warning

Files:

  • examples/basic/index.ts
**/index.ts

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Use barrel exports (index.ts) for package entry points

Files:

  • examples/basic/index.ts
examples/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

examples/**/*.{ts,tsx}: Ensure examples demonstrate secure default practices
Add examples in the examples/ directory for new functionality, demonstrating real-world usage patterns

Files:

  • examples/basic/index.ts
**/*.{ts,tsx,json,md}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use Biome for linting and formatting instead of ESLint and Prettier

Files:

  • examples/basic/index.ts
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas

Applied to files:

  • examples/basic/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax

Applied to files:

  • examples/basic/index.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable errors, not generic errors

Applied to files:

  • examples/basic/index.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors

Applied to files:

  • examples/basic/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use ArkType's `type()` function to define schemas in environment variable definitions

Applied to files:

  • examples/basic/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type

Applied to files:

  • examples/basic/index.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use descriptive environment variable names that indicate purpose and format

Applied to files:

  • examples/basic/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use union types for enums in ArkType schemas (e.g., `"'dev' | 'prod'"`) instead of separate enum definitions

Applied to files:

  • examples/basic/index.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern

Applied to files:

  • examples/basic/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: ArkType validates environment variables at runtime and TypeScript types are inferred from the schema definition

Applied to files:

  • examples/basic/index.ts
🧬 Code graph analysis (1)
examples/basic/index.ts (2)
packages/arkenv/src/type.ts (1)
  • type (3-3)
packages/arkenv/src/type.test.ts (4)
  • envType (11-15)
  • envType (118-118)
  • envType (127-127)
  • envType (86-108)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test-e2e (a11y)
  • GitHub Check: test-e2e (e2e)


const env = arkenv({
HOST: "string.host",
MY_STRING_AS_NUMBER: type("string").pipe((value) => Number(value)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the coerce utility implementation
find . -name "coerce.ts" -o -name "coerce.js" | head -20

Repository: yamcodes/arkenv

Length of output: 90


🏁 Script executed:

#!/bin/bash
# Also check the types.ts to see available built-in types
cat packages/arkenv/src/types.ts 2>/dev/null | head -100

Repository: yamcodes/arkenv

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Check create-env implementation to understand the recommended patterns
rg -n "coerce|pipe|Number\(" packages/arkenv/src/create-env.ts -A3 -B3

Repository: yamcodes/arkenv

Length of output: 794


🏁 Script executed:

#!/bin/bash
# Check if there are other examples using number coercion
rg -n "type.*pipe.*Number|\.pipe.*number" examples/ -A5 -B5

Repository: yamcodes/arkenv

Length of output: 2431


🏁 Script executed:

#!/bin/bash
# Check test files for how string->number coercion should work
rg -n "string.*number|Number.*isNaN" packages/arkenv/src/*.test.ts -A3 -B3

Repository: yamcodes/arkenv

Length of output: 643


🏁 Script executed:

#!/bin/bash
# Read the coerce.ts file
cat packages/arkenv/src/coerce.ts

Repository: yamcodes/arkenv

Length of output: 752


🏁 Script executed:

#!/bin/bash
# Check what the pipe validation does in ArkType - search for pipe error handling
rg -n "pipe.*issue|pipe.*error" packages/arkenv/src/ -A3 -B3

Repository: yamcodes/arkenv

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Understand the relationship between coerce and .pipe approaches
rg -n "\.pipe" packages/arkenv/src/ -B2 -A2

Repository: yamcodes/arkenv

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Verify when coerce runs relative to .pipe() transformations
# Check create-env.ts flow
sed -n '40,55p' packages/arkenv/src/create-env.ts

Repository: yamcodes/arkenv

Length of output: 671


🏁 Script executed:

#!/bin/bash
# Check if there are tests showing the expected behavior of .pipe() with NaN
rg -n "pipe.*Number|MY_STRING|coerce.*number" packages/arkenv/src/*.test.ts -B3 -A5

Repository: yamcodes/arkenv

Length of output: 2613


🏁 Script executed:

#!/bin/bash
# Verify the learning about Number.parseInt preference
rg -n "Number\.parseInt|useNumberNamespace" .cursor/rules/ -B2 -A2

Repository: yamcodes/arkenv

Length of output: 654


🏁 Script executed:

#!/bin/bash
# Check if "number" string type can be used in place of type("string").pipe(Number)
# Look at type definitions and tests
rg -n '"number"' packages/arkenv/src/coercion.integration.test.ts -B2 -A2 | head -40

Repository: yamcodes/arkenv

Length of output: 874


🏁 Script executed:

#!/bin/bash
# Verify what happens with invalid input to the current .pipe(Number) implementation
# Check if there are any guards in place
rg -n "pipe.*validate|pipe.*check" packages/arkenv/src/ -B3 -A3

Repository: yamcodes/arkenv

Length of output: 41


Use the built-in "number" type instead of custom Number() conversion.

Replace the manual .pipe((value) => Number(value)) with ArkType's built-in "number" type, which handles string-to-number coercion safely with proper NaN validation:

-	MY_STRING_AS_NUMBER: type("string").pipe((value) => Number(value)),
+	MY_STRING_AS_NUMBER: "number",

The built-in "number" type already coerces valid numeric strings (e.g., "3000"3000) and rejects invalid ones (e.g., "abc") during validation. This follows the guideline to leverage ArkType's built-in types where possible and keeps the schema readable and consistent with other fields like PORT: "number.port".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
MY_STRING_AS_NUMBER: type("string").pipe((value) => Number(value)),
MY_STRING_AS_NUMBER: "number",
🤖 Prompt for AI Agents
In examples/basic/index.ts around line 6, the field currently uses a custom pipe
to coerce strings to numbers (MY_STRING_AS_NUMBER: type("string").pipe((value)
=> Number(value))), replace this with ArkType's built-in "number" type (e.g.,
MY_STRING_AS_NUMBER: "number") so valid numeric strings are coerced and invalid
ones rejected; update the schema entry to use the built-in type for consistency
with other fields like PORT ("number.port") and remove the custom .pipe
conversion.

@vercel
Copy link

vercel bot commented Dec 12, 2025

Deployment failed with the following error:

Resource is limited - try again in 7 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/yamcodes?upgradeToPro=build-rate-limit

@vercel
Copy link

vercel bot commented Dec 12, 2025

Deployment failed with the following error:

Resource is limited - try again in 6 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/yamcodes?upgradeToPro=build-rate-limit

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/arkenv/README.md (1)

62-75: Docs: clarify compiled-schema limitation + avoid potentially unsupported number.epoch example
Coercion appears to apply only when passing a raw schema object (e.g., arkenv({ PORT: "number" })) and not when passing a compiled schema (e.g., arkenv(type({ PORT: "number" }))). Also, the README example uses number.epoch; if that type isn’t actually defined/registered in ArkEnv’s scope, the example will mislead.

Suggested doc tweak (keep examples to known built-ins unless number.epoch is confirmed):

 ## Coercion

 Environment variables are always strings, but ArkEnv automatically coerces them to their target types when possible:
 
 - `number` and subtypes (`number.port`, `number.epoch`) are parsed as numbers.
 - `boolean` strings ("true", "false") are parsed as booleans.

+> Note: coercion currently applies to *raw schema objects* passed to `arkenv(...)`.
+> If you pass a pre-compiled ArkType (created with `type(...)`), ArkEnv can’t reliably inspect it to know what to coerce.

 ```ts
 const env = arkenv({
   PORT: "number",           // "3000" → 3000
   DEBUG: "boolean",        // "true" → true
-  TIMESTAMP: "number.epoch" // "1640995200000" → 1640995200000
+  // Example subtype (if supported in ArkEnv scope):
+  // TIMESTAMP: "number.epoch" // "1640995200000" → 1640995200000
 });

To verify `number.epoch` exists in-repo, run:

```shell
#!/bin/bash
rg -n --hidden --glob '!**/node_modules/**' '\bepoch\b' packages/arkenv
rg -n --hidden --glob '!**/node_modules/**' 'number\.epoch' packages/arkenv
🧹 Nitpick comments (1)
packages/arkenv/src/create-env.ts (1)

4-4: Consider a more explicit type check for compiled validators (optional improvement)

The detection typeof def === "function" && "assert" in def works correctly in practice, but checking that assert is actually a function would be more defensive. Your test suite comprehensively covers both code paths (raw schemas and compiled types), and both work correctly, so this is a nice-to-have for stricter type checking rather than a critical fix.

If preferred, you can make the check more explicit:

- const isCompiledType = typeof def === "function" && "assert" in def;
+ const isCompiledType =
+ 	typeof def === "function" && typeof (def as { assert?: unknown }).assert === "function";

Or extract to a named predicate:

+ function isArkTypeCompiledType(x: unknown): x is EnvSchemaWithType {
+ 	return typeof x === "function" && typeof (x as { assert?: unknown }).assert === "function";
+ }
+ ...
- const isCompiledType = isArkTypeCompiledType(def);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e79e95 and 50c91b4.

📒 Files selected for processing (2)
  • packages/arkenv/README.md (1 hunks)
  • packages/arkenv/src/create-env.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
packages/arkenv/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/arktype.mdc)

packages/arkenv/**/*.ts: Use ArkType's type() function to define schemas in environment variable definitions
Leverage ArkType's type inference for TypeScript types instead of manual type definitions
Use the scoped $ type system for custom types defined in scope.ts
Keep environment variable schemas readable and TypeScript-like using ArkType syntax
Use union types for enums in ArkType schemas (e.g., "'dev' | 'prod'") instead of separate enum definitions
Leverage ArkType's built-in types (e.g., string.host, number.port) where possible in environment schemas
Convert ArkType validation errors to ArkEnvError for user-friendly error messages that include variable name and expected type

Files:

  • packages/arkenv/src/create-env.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

**/*.{ts,tsx}: Use createEnv(schema) as the main function for validated environment objects, available as the default export
Use built-in validators (host, port, url, email) from src/types.ts when available instead of custom validation
Use ArkEnvError for environment variable errors, not generic errors
Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern
Use logical grouping for related environment variables in schemas
Use descriptive env...

Files:

  • packages/arkenv/src/create-env.ts
packages/arkenv/src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Main library implementation should be in src/create-env.ts, built-in validators in src/types.ts, error handling in src/errors.ts, and utilities in src/utils.ts

Files:

  • packages/arkenv/src/create-env.ts
**/*.{ts,tsx,json,md}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use Biome for linting and formatting instead of ESLint and Prettier

Files:

  • packages/arkenv/src/create-env.ts
  • packages/arkenv/README.md
**/README.md

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Document environment requirements in README files

Files:

  • packages/arkenv/README.md
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use ArkType's `type()` function to define schemas in environment variable definitions
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: ArkType validates environment variables at runtime and TypeScript types are inferred from the schema definition
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable errors, not generic errors
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use union types for enums in ArkType schemas (e.g., `"'dev' | 'prod'"`) instead of separate enum definitions
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's type inference for TypeScript types instead of manual type definitions
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax

Applied to files:

  • packages/arkenv/src/create-env.ts
  • packages/arkenv/README.md
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use ArkType's `type()` function to define schemas in environment variable definitions

Applied to files:

  • packages/arkenv/src/create-env.ts
  • packages/arkenv/README.md
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type

Applied to files:

  • packages/arkenv/src/create-env.ts
  • packages/arkenv/README.md
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas

Applied to files:

  • packages/arkenv/src/create-env.ts
  • packages/arkenv/README.md
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use union types for enums in ArkType schemas (e.g., `"'dev' | 'prod'"`) instead of separate enum definitions

Applied to files:

  • packages/arkenv/src/create-env.ts
  • packages/arkenv/README.md
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use `createEnv(schema)` as the main function for validated environment objects, available as the default export

Applied to files:

  • packages/arkenv/src/create-env.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors

Applied to files:

  • packages/arkenv/src/create-env.ts
  • packages/arkenv/README.md
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Environment schema definitions should use built-in validators, ArkType string literals, and support default values in the schema pattern

Applied to files:

  • packages/arkenv/src/create-env.ts
  • packages/arkenv/README.md
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: ArkType validates environment variables at runtime and TypeScript types are inferred from the schema definition

Applied to files:

  • packages/arkenv/src/create-env.ts
  • packages/arkenv/README.md
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's type inference for TypeScript types instead of manual type definitions

Applied to files:

  • packages/arkenv/src/create-env.ts
  • packages/arkenv/README.md
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/scope.ts : Define custom types in `scope.ts` using ArkType's scoped type system for reusability across schemas

Applied to files:

  • packages/arkenv/src/create-env.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use the scoped `$` type system for custom types defined in `scope.ts`

Applied to files:

  • packages/arkenv/src/create-env.ts
📚 Learning: 2025-11-29T22:11:39.931Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T22:11:39.931Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable errors, not generic errors

Applied to files:

  • packages/arkenv/README.md
📚 Learning: 2025-09-09T17:37:19.650Z
Learnt from: yamcodes
Repo: yamcodes/arkenv PR: 132
File: packages/arkenv/README.md:13-14
Timestamp: 2025-09-09T17:37:19.650Z
Learning: For yamcodes/arkenv project: Runtime support documentation should link to specific examples: Node.js (examples/basic), Bun (examples/with-bun), Vite (examples/with-vite-react-ts).

Applied to files:

  • packages/arkenv/README.md
🧬 Code graph analysis (1)
packages/arkenv/src/create-env.ts (1)
packages/arkenv/src/coerce.ts (1)
  • coerce (1-31)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: test-e2e (a11y)
  • GitHub Check: test-e2e (e2e)
  • GitHub Check: test-build (lts/*)
  • GitHub Check: test-typesafety
  • GitHub Check: test-build (latest)

@vercel
Copy link

vercel bot commented Dec 12, 2025

Deployment failed with the following error:

Resource is limited - try again in 5 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/yamcodes?upgradeToPro=build-rate-limit

@yamcodes
Copy link
Owner Author

This implementation is unacceptable. With this implementation, coercion only works with raw schema objects (e.g., arkenv({ PORT: "number" })), not with pre-compiled types (e.g., arkenv(type({ PORT: "number" }))).

This is a big no-no. Coercion should work either through the 'type' function (supplied via arkenv), or directly via createEnv.

Closing.

@yamcodes yamcodes closed this Dec 12, 2025
@yamcodes yamcodes deleted the 228-coercion-stringnumber-stringboolean-etc branch December 12, 2025 15:41
@yamcodes yamcodes restored the 228-coercion-stringnumber-stringboolean-etc branch December 12, 2025 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arkenv Changes to the `arkenv` npm package. docs Improvements or additions to documentation example Issues or Pull Requests concerning at least one ArkEnv example. (Found in the `examples/` directory) tests This issue or PR is about adding, removing or changing tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Coercion (string→number, string→boolean, etc.)

2 participants