feat(arkenv): Fix coercion crashes for predicates#595
Conversation
- Use `toJsonSchema` fallback - Handle unjsonifiable types - Preserve base schema structure - Use public API for introspection
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThe changes introduce a fallback mechanism to Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10-15 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
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 |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
openspec/changes/coercion-public-api/design.mdopenspec/changes/coercion-public-api/proposal.mdpackages/arkenv/src/utils/coerce.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,json,md}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use Biome for linting and formatting instead of ESLint and Prettier
Files:
openspec/changes/coercion-public-api/design.mdopenspec/changes/coercion-public-api/proposal.mdpackages/arkenv/src/utils/coerce.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/coercion-public-api/proposal.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/utils/coerce.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/utils/coerce.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/utils/coerce.ts
🧠 Learnings (10)
📚 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:
openspec/changes/coercion-public-api/design.mdopenspec/changes/coercion-public-api/proposal.mdpackages/arkenv/src/utils/coerce.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:
openspec/changes/coercion-public-api/design.mdopenspec/changes/coercion-public-api/proposal.mdpackages/arkenv/src/utils/coerce.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:
openspec/changes/coercion-public-api/proposal.mdpackages/arkenv/src/utils/coerce.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:
openspec/changes/coercion-public-api/proposal.mdpackages/arkenv/src/utils/coerce.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:
openspec/changes/coercion-public-api/proposal.mdpackages/arkenv/src/utils/coerce.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:
openspec/changes/coercion-public-api/proposal.mdpackages/arkenv/src/utils/coerce.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:
openspec/changes/coercion-public-api/proposal.md
📚 Learning: 2025-12-05T20:33:10.676Z
Learnt from: yamcodes
Repo: yamcodes/arkenv PR: 498
File: apps/playgrounds/node/index.ts:2-2
Timestamp: 2025-12-05T20:33:10.676Z
Learning: ArkType 2.1.28+ supports Standard Schema specification, allowing interoperability with other Standard Schema-compliant validation libraries (e.g., Zod, Valibot) within the same schema definition
Applied to files:
openspec/changes/coercion-public-api/proposal.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:
openspec/changes/coercion-public-api/proposal.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:
openspec/changes/coercion-public-api/proposal.mdpackages/arkenv/src/utils/coerce.ts
🪛 LanguageTool
openspec/changes/coercion-public-api/design.md
[grammar] ~9-~9: Ensure spelling is correct
Context: ...hs*. To ensure 100% stability even when encountereing types that are not representable in JSO...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🔇 Additional comments (3)
openspec/changes/coercion-public-api/proposal.md (1)
12-12: LGTM! Clear technical description.The explanation accurately describes the fallback mechanism and its role in handling unjsonifiable types while preserving base schema information.
openspec/changes/coercion-public-api/design.md (1)
11-26: Excellent technical explanation.The code snippet and rationale clearly demonstrate how the fallback mechanism provides resilience while maintaining standards compliance. The identification rules effectively map to JSON Schema concepts.
packages/arkenv/src/utils/coerce.ts (1)
216-222: The implementation correctly uses ArkType's documentedfallbackAPI.ArkType's
toJsonSchema()method supports thefallbackoption wherectx.baserepresents the schema being generated and can be used to effectively ignore incompatible constraints. The code properly handles schema parts that cannot be fully represented in JSON Schema by preserving the base schema through the fallback mechanism.
| ### 1. Introspection via `schema.in.toJsonSchema()` with Fallback | ||
|
|
||
| We use `schema.in` to get a representation of the schema's input *without morphs* and then call `.toJsonSchema()` to get a standard JSON Schema representation for traversal. This ensures compatibility with schemas that use `.pipe()` or other morphs, which would otherwise cause `toJsonSchema()` to throw. | ||
| We use `schema.in` to get a representation of the schema's input *without morphs*. To ensure 100% stability even when encountereing types that are not representable in JSON Schema (like those with customized predicates or narrows), we call `.toJsonSchema()` with a base-preserving fallback: |
There was a problem hiding this comment.
Fix typo in documentation.
The word "encountereing" should be "encountering".
🔎 Proposed fix
-We use `schema.in` to get a representation of the schema's input *without morphs*. To ensure 100% stability even when encountereing types that are not representable in JSON Schema (like those with customized predicates or narrows), we call `.toJsonSchema()` with a base-preserving fallback:
+We use `schema.in` to get a representation of the schema's input *without morphs*. To ensure 100% stability even when encountering types that are not representable in JSON Schema (like those with customized predicates or narrows), we call `.toJsonSchema()` with a base-preserving fallback:📝 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.
| We use `schema.in` to get a representation of the schema's input *without morphs*. To ensure 100% stability even when encountereing types that are not representable in JSON Schema (like those with customized predicates or narrows), we call `.toJsonSchema()` with a base-preserving fallback: | |
| We use `schema.in` to get a representation of the schema's input *without morphs*. To ensure 100% stability even when encountering types that are not representable in JSON Schema (like those with customized predicates or narrows), we call `.toJsonSchema()` with a base-preserving fallback: |
🧰 Tools
🪛 LanguageTool
[grammar] ~9-~9: Ensure spelling is correct
Context: ...hs*. To ensure 100% stability even when encountereing types that are not representable in JSO...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🤖 Prompt for AI Agents
In openspec/changes/coercion-public-api/design.md around line 9, fix the typo
"encountereing" to "encountering" in the sentence describing calling
`.toJsonSchema()` with a base-preserving fallback so the documentation reads
correctly.
- Corrected "encountereing" to "encountering"
toJsonSchemafallbackCloses #594
Summary by CodeRabbit
Improvements
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.