Conversation
…variable coercion.
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Other AI code review bot(s) detectedCodeRabbit 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. WalkthroughThis PR implements automatic coercion of environment variables from strings to target types (numbers and booleans) before ArkType validation. It adds a new Changes
Sequence DiagramsequenceDiagram
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…or using preprocessing for coercion.
…aw schema definitions.
commit: |
There was a problem hiding this comment.
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 newstring | numberinputThe implementation now accepts both strings and numbers (
type("string | number", ...)), but the comment still describes only “Astringthat can be parsed into a number…”. Consider updating the doc to something like “Astringornumberrepresenting 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/defaultsThe implementation is clean and side‑effect free. To mirror the
numberhandling (which supportsnumber.*andnumber = ...styles viastartsWith("number")), you could also treat boolean subtypes/defaults by checkingtypeDef.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 scenarioThe requirements and examples line up with the implementation (
number.*andbooleancoercion 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 implementationThe high‑level architecture matches the code, but a few details in the examples are now slightly out of sync:
- Flow step 3 mentions
Number()orparseFloat(), butcoerce.tscurrently usesNumber()only.- The
coercesample lives insrc/utils.tsin the doc, while the actual implementation is inpackages/arkenv/src/coerce.ts.- The integration snippet uses
isPlainObject(def), whereas the code distinguishes compiled types via anisCompiledTypecheck.Updating these snippets to mirror
coerce.tsandcreate-env.tswill 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_NUMBERis defined viatype("string").pipe((value) => Number(value)), which is essentially what the new preprocessingcoercestep now does for"number"schemas. BecauseEnvhere is a compiled type passed toarkenv(Env, process.env), the newcoercehook increateEnvwill 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 codebaseThe checklist accurately reflects what was done, but the referenced locations are now slightly off:
coercelives inpackages/arkenv/src/coerce.ts, notsrc/utils.ts.- Integration tests are in
packages/arkenv/src/coercion.integration.test.ts, nottests/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 behaviorThe new Coercion section is clear and aligns with
coerce.ts(numbers andnumber.*→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
ArkEnvErrorvalidation 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 grammarThe proposal content matches the implemented behavior, but the structure doesn’t fully follow the
openspec/changes/*/proposal.mdpattern:
- Consider organizing sections under
## Why,## What Changes(marking any BREAKING aspects), and## Impactinstead 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 keysThe body asserts that
EXTRAis preserved ("foo"), so “ignore keys not in definition” could be read as “drop them entirely.” A name likeshould_not_coerce_keys_not_in_definitionorshould_preserve_extra_keys_unchangedwould better document the intended behavior.packages/arkenv/src/coercion.integration.test.ts (1)
26-37: Optionally assert on ArkEnvError type/message for failure casesFor 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 viaArkEnvErrorwith 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
📒 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'stype()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 inscope.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 toArkEnvErrorfor user-friendly error messages that include variable name and expected type
Files:
packages/arkenv/src/coerce.test.tspackages/arkenv/src/coerce.tspackages/arkenv/src/coercion.integration.test.tspackages/arkenv/src/create-env.tspackages/arkenv/src/types.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)
**/*.{ts,tsx}: Prefertypeoverinterfacefor type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverageconsttype 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 (noInferrableTypeserror)
Useas constwhere appropriate for immutable values (useAsConstAssertionerror)
Don't reassign function parameters (noParameterAssignerror)
Place default parameters last in function signatures (useDefaultParameterLasterror)
Always initialize enum values (useEnumInitializerserror)
Declare one variable per statement (useSingleVarDeclaratorerror)
Avoid unnecessary template literals (noUnusedTemplateLiteralerror)
PreferNumber.parseIntover globalparseInt(useNumberNamespaceerror)
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
UseArkEnvErrorfor environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type
Files:
packages/arkenv/src/coerce.test.tspackages/arkenv/src/coerce.tspackages/arkenv/src/coercion.integration.test.tsapps/playgrounds/node/index.tspackages/arkenv/src/create-env.tspackages/arkenv/src/types.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)
Co-locate tests with components:
Component.tsxnext toComponent.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.ts→source.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 withuser-eventfor real user simulation in component testsUnit tests should be fast (< 100ms per test) and located alongside source files with
.test.tssuffix, with mocked external dependencies
Files:
packages/arkenv/src/coerce.test.tspackages/arkenv/src/coercion.integration.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx,js,jsx}: Use the main functioncreateEnv(schema)or default importarkenvto create validated environment objects with TypeScript type inference from ArkType schemas
Use built-in validators (host,port,url,src/types.tswhen 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.tspackages/arkenv/src/coerce.tspackages/arkenv/src/coercion.integration.test.tsapps/playgrounds/node/index.tspackages/arkenv/src/create-env.tspackages/arkenv/src/types.ts
**/*.{test,integration.test}.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use Vitest's
describe/itstructure with both success and failure test cases in all test files
Files:
packages/arkenv/src/coerce.test.tspackages/arkenv/src/coercion.integration.test.ts
**/packages/**/*.{test,integration.test}.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Mock
process.envin tests to simulate different environment scenarios with both valid and invalid values
Files:
packages/arkenv/src/coerce.test.tspackages/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.envinbeforeEach/afterEachhooks to avoid test pollution
Files:
packages/arkenv/src/coerce.test.tspackages/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.tspackages/arkenv/src/coerce.tspackages/arkenv/src/coercion.integration.test.tspackages/arkenv/src/create-env.tspackages/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.tspackages/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.tssuffix to distinguish integration tests from unit testsIntegration tests should use
.integration.test.tssuffix, 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.mdpackages/arkenv/src/coerce.test.tspackages/arkenv/src/coerce.tspackages/arkenv/src/coercion.integration.test.tsopenspec/changes/add-coercion/specs/coercion/spec.mdapps/playgrounds/node/index.tsopenspec/changes/add-coercion/proposal.mdopenspec/changes/add-coercion/design.mdpackages/arkenv/src/create-env.tspackages/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.mdpackages/arkenv/src/coerce.test.tspackages/arkenv/src/coerce.tspackages/arkenv/src/coercion.integration.test.tsopenspec/changes/add-coercion/specs/coercion/spec.mdapps/playgrounds/node/index.tsopenspec/changes/add-coercion/proposal.mdopenspec/changes/add-coercion/design.mdpackages/arkenv/src/create-env.tspackages/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.mdopenspec/changes/add-coercion/tasks.mdpackages/arkenv/src/coerce.test.tspackages/arkenv/src/coerce.tspackages/arkenv/src/coercion.integration.test.tsopenspec/changes/add-coercion/proposal.mdopenspec/changes/add-coercion/design.mdpackages/arkenv/src/create-env.tspackages/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.mdpackages/arkenv/src/coerce.test.tspackages/arkenv/src/coerce.tspackages/arkenv/src/coercion.integration.test.tsopenspec/changes/add-coercion/proposal.mdopenspec/changes/add-coercion/design.mdpackages/arkenv/src/create-env.tspackages/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.mdpackages/arkenv/src/coerce.test.tspackages/arkenv/src/coerce.tspackages/arkenv/src/coercion.integration.test.tsopenspec/changes/add-coercion/proposal.mdopenspec/changes/add-coercion/design.mdpackages/arkenv/src/create-env.tspackages/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.mdpackages/arkenv/src/coerce.tsopenspec/changes/add-coercion/proposal.mdpackages/arkenv/src/create-env.tspackages/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.mdpackages/arkenv/src/coerce.test.tspackages/arkenv/src/coerce.tspackages/arkenv/src/coercion.integration.test.tsopenspec/changes/add-coercion/specs/coercion/spec.mdapps/playgrounds/node/index.tsopenspec/changes/add-coercion/proposal.mdopenspec/changes/add-coercion/design.mdpackages/arkenv/src/create-env.tspackages/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.mdpackages/arkenv/src/coerce.tsopenspec/changes/add-coercion/specs/coercion/spec.mdapps/playgrounds/node/index.tsopenspec/changes/add-coercion/proposal.mdopenspec/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.mdapps/playgrounds/node/index.tsopenspec/changes/add-coercion/proposal.mdopenspec/changes/add-coercion/design.mdpackages/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.mdopenspec/changes/add-coercion/tasks.mdpackages/arkenv/src/coerce.tspackages/arkenv/src/coercion.integration.test.tsopenspec/changes/add-coercion/specs/coercion/spec.mdapps/playgrounds/node/index.tsopenspec/changes/add-coercion/proposal.mdopenspec/changes/add-coercion/design.mdpackages/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.mdopenspec/changes/add-coercion/specs/coercion/spec.mdopenspec/changes/add-coercion/proposal.mdopenspec/changes/add-coercion/design.mdpackages/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.mdpackages/arkenv/src/coerce.test.tspackages/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.mdpackages/arkenv/src/coerce.test.tspackages/arkenv/src/coercion.integration.test.tsapps/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.mdpackages/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.mdpackages/arkenv/src/coerce.test.tspackages/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.mdpackages/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.tspackages/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.tspackages/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.tsapps/playgrounds/node/index.tspackages/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.tsopenspec/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.tspackages/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 solidThe
isCompiledTypeguard cleanly separates compiled ArkType inputs from raw schema objects and only appliescoerceto the latter, which matches the documented limitation around pre‑compiled types. PassingcoercedEnvintoschema(...)while preserving the existinginstanceof type.errors→ArkEnvErrorflow 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 goodThis 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 validationThese 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 thatcreateEnvandcoercework together as intended.
There was a problem hiding this comment.
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
porttype 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 increate-env.ts(lines 44-48). The added exampleMY_STRING_AS_NUMBERwith 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",
});
| ## 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 | ||
| }); | ||
| ``` |
There was a problem hiding this comment.
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.
| if (typeDef.startsWith("number")) { | ||
| const asNumber = Number(value); | ||
| if (!Number.isNaN(asNumber)) { | ||
| coerced[key] = asNumber; | ||
| } |
There was a problem hiding this comment.
Using Number(value) for coercion can produce unexpected results for edge cases:
- Empty strings:
Number("")returns0, which may not be the intended behavior - Whitespace:
Number(" ")returns0 - Scientific notation:
Number("1e3")returns1000(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.
| 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); | ||
| }); |
There was a problem hiding this comment.
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.
| 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; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
The coercion logic only handles simple string type definitions. It doesn't account for:
- Union types:
"number | string"- will try to coerce even though string is acceptable - Optional types:
"number?"- will coerce, but the?suffix might not be handled - Types with defaults:
"number = 3000"- will coerce, but the= 3000suffix needs testing
Consider adding logic to parse these modifiers or adding tests to verify current behavior with these patterns.
| 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); | ||
| }); |
There was a problem hiding this comment.
[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.
| ): Record<string, unknown> { | ||
| const coerced: Record<string, unknown> = { ...env }; |
There was a problem hiding this comment.
[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.
| ): Record<string, unknown> { | |
| const coerced: Record<string, unknown> = { ...env }; | |
| ): Record<string, string | number | boolean | undefined> { | |
| const coerced: Record<string, string | number | boolean | undefined> = { ...env }; |
| 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"); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
[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.
…/github.com/yamcodes/ark.env into 228-coercion-stringnumber-stringboolean-etc
📦 Bundle Size Report
✅ All size limits passed! |
…m Bun build config.
There was a problem hiding this comment.
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:examplesto update them before merging.#!/bin/bash # Run this command to sync the examples pnpm sync:examplesapps/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:examplesto 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
myStringdoesn't convey that the value has been transformed to a number. Consider usingmyNumberormyStringAsNumberfor clarity.- myString: env.MY_STRING_AS_NUMBER, + myNumber: env.MY_STRING_AS_NUMBER,
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 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}: Prefertypeoverinterfacefor type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverageconsttype 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 (noInferrableTypeserror)
Useas constwhere appropriate for immutable values (useAsConstAssertionerror)
Don't reassign function parameters (noParameterAssignerror)
Place default parameters last in function signatures (useDefaultParameterLasterror)
Always initialize enum values (useEnumInitializerserror)
Declare one variable per statement (useSingleVarDeclaratorerror)
Avoid unnecessary template literals (noUnusedTemplateLiteralerror)
PreferNumber.parseIntover globalparseInt(useNumberNamespaceerror)
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
UseArkEnvErrorfor environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type
**/*.{ts,tsx}: UsecreateEnv(schema)as the main function for validated environment objects, available as the default export
Use built-in validators (host, port, url, email) fromsrc/types.tswhen available instead of custom validation
UseArkEnvErrorfor 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.tspackages/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.tspackages/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.tspackages/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.tspackages/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 | numberand 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 schemasLearnt 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
There was a problem hiding this comment.
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 namedmyString. 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
⛔ Files ignored due to path filters (1)
examples/basic/package-lock.jsonis 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}: Prefertypeoverinterfacefor type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverageconsttype 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 (noInferrableTypeserror)
Useas constwhere appropriate for immutable values (useAsConstAssertionerror)
Don't reassign function parameters (noParameterAssignerror)
Place default parameters last in function signatures (useDefaultParameterLasterror)
Always initialize enum values (useEnumInitializerserror)
Declare one variable per statement (useSingleVarDeclaratorerror)
Avoid unnecessary template literals (noUnusedTemplateLiteralerror)
PreferNumber.parseIntover globalparseInt(useNumberNamespaceerror)
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
UseArkEnvErrorfor environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type
**/*.{ts,tsx}: UsecreateEnv(schema)as the main function for validated environment objects, available as the default export
Use built-in validators (host, port, url, email) fromsrc/types.tswhen available instead of custom validation
UseArkEnvErrorfor 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 theexamples/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)), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check the coerce utility implementation
find . -name "coerce.ts" -o -name "coerce.js" | head -20Repository: 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 -100Repository: 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 -B3Repository: 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 -B5Repository: 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 -B3Repository: yamcodes/arkenv
Length of output: 643
🏁 Script executed:
#!/bin/bash
# Read the coerce.ts file
cat packages/arkenv/src/coerce.tsRepository: 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 -B3Repository: 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 -A2Repository: 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.tsRepository: 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 -A5Repository: 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 -A2Repository: 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 -40Repository: 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 -A3Repository: 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.
| 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.
|
Deployment failed with the following error: Learn More: https://vercel.com/yamcodes?upgradeToPro=build-rate-limit |
|
Deployment failed with the following error: Learn More: https://vercel.com/yamcodes?upgradeToPro=build-rate-limit |
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
packages/arkenv/README.md (1)
62-75: Docs: clarify compiled-schema limitation + avoid potentially unsupportednumber.epochexample
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 usesnumber.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.epochis 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 defworks correctly in practice, but checking thatassertis 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
📒 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'stype()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 inscope.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 toArkEnvErrorfor 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}: Prefertypeoverinterfacefor type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverageconsttype 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 (noInferrableTypeserror)
Useas constwhere appropriate for immutable values (useAsConstAssertionerror)
Don't reassign function parameters (noParameterAssignerror)
Place default parameters last in function signatures (useDefaultParameterLasterror)
Always initialize enum values (useEnumInitializerserror)
Declare one variable per statement (useSingleVarDeclaratorerror)
Avoid unnecessary template literals (noUnusedTemplateLiteralerror)
PreferNumber.parseIntover globalparseInt(useNumberNamespaceerror)
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
UseArkEnvErrorfor environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type
**/*.{ts,tsx}: UsecreateEnv(schema)as the main function for validated environment objects, available as the default export
Use built-in validators (host, port, url, email) fromsrc/types.tswhen available instead of custom validation
UseArkEnvErrorfor 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 insrc/types.ts, error handling insrc/errors.ts, and utilities insrc/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.tspackages/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.tspackages/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.tspackages/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.tspackages/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.tspackages/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.tspackages/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.tspackages/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.tspackages/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.tspackages/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.tspackages/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)
|
Deployment failed with the following error: Learn More: https://vercel.com/yamcodes?upgradeToPro=build-rate-limit |
|
This implementation is unacceptable. With this implementation, coercion only works with raw schema objects (e.g., This is a big no-no. Coercion should work either through the 'type' function (supplied via Closing. |
Closes #228
Summary by CodeRabbit
New Features
✏️ Tip: You can customize this high-level summary in your review settings.