Skip to content

Schema-Directed Coercion JSON Schema (100% Public API Coercion implementation)#578

Merged
yamcodes merged 63 commits intocoercionfrom
coercion-public-api-json-schema
Dec 22, 2025
Merged

Schema-Directed Coercion JSON Schema (100% Public API Coercion implementation)#578
yamcodes merged 63 commits intocoercionfrom
coercion-public-api-json-schema

Conversation

@yamcodes
Copy link
Owner

@yamcodes yamcodes commented Dec 22, 2025

Closes #577

Summary by CodeRabbit

  • Breaking Changes

    • Removed the root-level custom boolean keyword; boolean coercion is now centralized.
    • Removed strict parsed-number/boolean variants; numeric/boolean handling now uses the centralized approach and a stricter numeric behavior for port-like fields.
  • Improvements

    • Coercion refactored to a schema-driven, pipeline-based pre-processing step using public introspection.
    • Eliminated reliance on undocumented internals for more stable, reliable coercion and improved performance via one-time introspection.

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

yamcodes and others added 30 commits December 21, 2025 02:49
…chema definitions and refinements, and refine various type and regex functionalities.
…ort` to use `parsedNumber`, and integrate `port` into the ArkType scope.
…, and enhance `number` and `boolean` coercion in `arkenv`.
…ransformation, supporting numeric refinements.
…and boolean type coercion and add new playground debug files.
…oerce` utility and remove playground files.
…t coercion from their definitions and from the `type` export, relying on global coercion instead.
…bers, booleans, ranges, and optional properties.
…oolean nodes, improving internal handling and type inference
… boolean types, ensuring correct application order and type handling
…numeric and boolean types, adding warnings for reliance on undocumented ArkType APIs
…e type assertions in the `coerce` function.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/arkenv/src/utils/coerce.ts (2)

77-93: Consider deduplicating coercion targets for union types.

When processing anyOf, allOf, or oneOf branches, the same path is passed to all alternatives. For schemas like type("number | boolean"), this can produce duplicate targets with identical paths.

While functionally correct (the coercion logic handles both types), deduplicating targets before returning could improve performance for complex union schemas.

💡 Potential optimization

Add deduplication before returning:

	return results;
};

Replace with:

	// Deduplicate by path
	const seen = new Set<string>();
	return results.filter((t) => {
		const key = t.path.join(".");
		if (seen.has(key)) return false;
		seen.add(key);
		return true;
	});
};

118-125: Add comment explaining the empty path array traversal case.

The empty path handling appears defensive for edge cases that may not occur with current findCoercionPaths logic. A brief comment would clarify when this branch is expected to trigger and why it recursively walks array items with an empty path.

📝 Suggested comment
-		// Handle root-level array traversal where path is empty/exhausted but we have a collection
+		// Defensive: handle root-level or exhausted-path array traversal
+		// Currently, root arrays produce targets like [{ path: ["*"] }] so this is rarely reached,
+		// but guards against edge cases in schema introspection
 		if (targetPath.length === 0) {
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f4f2844 and 4eed10e.

📒 Files selected for processing (2)
  • openspec/changes/coercion-public-api/proposal.md
  • packages/arkenv/src/utils/coerce.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • openspec/changes/coercion-public-api/proposal.md
🧰 Additional context used
📓 Path-based instructions (4)
packages/arkenv/**/*.ts

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

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

Files:

  • packages/arkenv/src/utils/coerce.ts
**/*.{ts,tsx}

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

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

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

Files:

  • packages/arkenv/src/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 in src/types.ts, error handling in src/errors.ts, and utilities in src/utils.ts

Files:

  • packages/arkenv/src/utils/coerce.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/utils/coerce.ts
🧠 Learnings (10)
📓 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 : 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 : 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 : Use ArkType's `type()` function to define schemas in environment variable definitions
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
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: .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 : Leverage ArkType's type inference for TypeScript types instead of manual type 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 : 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/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
📚 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/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 built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas

Applied to files:

  • packages/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:

  • packages/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:

  • packages/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/scope.ts : Define custom types in `scope.ts` using ArkType's scoped type system for reusability across schemas

Applied to files:

  • packages/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:

  • packages/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:

  • packages/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 the scoped `$` type system for custom types defined in `scope.ts`

Applied to files:

  • packages/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 : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type

Applied to files:

  • packages/arkenv/src/utils/coerce.ts
🧬 Code graph analysis (1)
packages/arkenv/src/utils/coerce.ts (3)
packages/internal/keywords/src/index.ts (2)
  • maybeParsedNumber (12-17)
  • maybeParsedBoolean (28-32)
packages/internal/scope/src/index.ts (2)
  • $ (9-18)
  • $ (20-20)
packages/arkenv/src/type.ts (1)
  • type (3-3)
🔇 Additional comments (4)
packages/arkenv/src/utils/coerce.ts (4)

47-65: Excellent resolution of past review feedback!

The implementation now correctly handles:

  • Array items via ARRAY_ITEM_MARKER for lists (line 61) and numeric indices for tuples (line 53)
  • Array-valued properties at terminus (lines 151-160)
  • Root-level arrays with empty paths (lines 118-125)
  • Mid-path array traversal (lines 177-184)

The recursive walk logic properly distinguishes between descending into array containers versus coercing individual array elements.

Also applies to: 118-125, 131-144, 151-160, 177-184


128-172: Terminus coercion logic is comprehensive and defensive.

The terminus handling covers three cases:

  1. ARRAY_ITEM_MARKER (lines 131-144): Correctly iterates and coerces array elements
  2. Array-valued property (lines 151-160): Defensive handling for edge cases
  3. Scalar property (lines 161-169): Standard coercion path

While the array-valued property case (lines 151-160) may not be reached with current findCoercionPaths logic (which descends into arrays and adds the marker), this defensive code makes the function more robust to potential schema introspection variations.


200-217: Clean public API implementation with well-documented type workaround.

The function correctly:

  • Uses toJsonSchema() for introspection (public API only)
  • Returns early when no coercion is needed
  • Applies the pipeline pattern for non-destructive transformation

The type cast at line 216 is well-justified in the comment. Since applyCoercion doesn't modify the type structure (only coerces values), and the final pipe(schema) validates against the original schema with scope $, the cast is safe.


1-217: Strong implementation of schema-directed coercion using public APIs.

This refactor successfully achieves the PR objectives:

  • ✅ Uses only public ArkType APIs (toJsonSchema(), pipe())
  • ✅ Non-destructive: validation happens after coercion
  • ✅ Selective: only coerces paths identified as number/integer/boolean types
  • ✅ Handles complex structures: nested objects, arrays, tuples, unions

The implementation is well-structured with clear separation of concerns:

  • findCoercionPaths: Schema introspection and path discovery
  • applyCoercion: Runtime data mutation at identified paths
  • coerce: Public API wrapper with pipeline integration

Minor optional improvements suggested above (deduplication, comments) but nothing blocking. Based on learnings, the approach correctly leverages ArkType's type inference and public APIs.

@yamcodes
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@yamcodes
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@yamcodes yamcodes changed the title Selective Path Coercion JSON Schema (100% Public API Coercion implementation) Schema-Directed Coercion JSON Schema (100% Public API Coercion implementation) Dec 22, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
packages/arkenv/src/utils/coerce.ts (3)

14-16: Consider using type instead of interface.

Per coding guidelines, prefer type over interface for type definitions.

🔎 Proposed fix
-interface CoercionTarget {
-	path: string[];
-}
+type CoercionTarget = {
+	path: string[];
+};

99-106: Path deduplication may collide when property names contain dots.

Using path.join(".") for deduplication can cause false positives if property names contain literal dots. For example, paths ["a.b", "c"] and ["a", "b.c"] would both produce key "a.b.c".

Consider using a delimiter that's less likely to appear in property names, or use JSON.stringify(t.path) for a collision-free key.

🔎 Proposed fix
 	// Deduplicate by path
 	const seen = new Set<string>();
 	return results.filter((t) => {
-		const key = t.path.join(".");
+		const key = JSON.stringify(t.path);
 		if (seen.has(key)) return false;
 		seen.add(key);
 		return true;
 	});

210-212: Update JSDoc to reflect the new implementation.

The current JSDoc mentions "wraps numeric or boolean values in coercion morphs," but the implementation now uses a pre-processing pipeline with JSON Schema introspection. Consider updating to describe the actual behavior.

🔎 Proposed fix
 /**
- * Traverses an ArkType schema and wraps numeric or boolean values in coercion morphs.
+ * Creates a coercing wrapper around an ArkType schema using JSON Schema introspection.
+ * Pre-processes input data to coerce string values to numbers/booleans at identified paths
+ * before validation.
  */
 export function coerce<t, $ = {}>(schema: BaseType<t, $>): BaseType<t, $> {
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4eed10e and be19258.

📒 Files selected for processing (1)
  • packages/arkenv/src/utils/coerce.ts
🧰 Additional context used
📓 Path-based instructions (4)
packages/arkenv/**/*.ts

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

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

Files:

  • packages/arkenv/src/utils/coerce.ts
**/*.{ts,tsx}

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

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

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

Files:

  • packages/arkenv/src/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 in src/types.ts, error handling in src/errors.ts, and utilities in src/utils.ts

Files:

  • packages/arkenv/src/utils/coerce.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/utils/coerce.ts
🧠 Learnings (10)
📓 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 : 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 : 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 : Use ArkType's `type()` function to define schemas in environment variable definitions
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
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: .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 : Leverage ArkType's type inference for TypeScript types instead of manual type 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/scope.ts : Define custom types in `scope.ts` using ArkType's scoped type system for reusability across 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 : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type
📚 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/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 built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas

Applied to files:

  • packages/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:

  • packages/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:

  • packages/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:

  • packages/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/scope.ts : Define custom types in `scope.ts` using ArkType's scoped type system for reusability across schemas

Applied to files:

  • packages/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:

  • packages/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 the scoped `$` type system for custom types defined in `scope.ts`

Applied to files:

  • packages/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 : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type

Applied to files:

  • packages/arkenv/src/utils/coerce.ts
🧬 Code graph analysis (1)
packages/arkenv/src/utils/coerce.ts (3)
packages/internal/keywords/src/index.ts (2)
  • maybeParsedNumber (12-17)
  • maybeParsedBoolean (28-32)
packages/internal/scope/src/index.ts (2)
  • $ (9-18)
  • $ (20-20)
packages/arkenv/src/type.ts (1)
  • type (3-3)
🔇 Additional comments (3)
packages/arkenv/src/utils/coerce.ts (3)

4-8: LGTM!

The ARRAY_ITEM_MARKER constant is well-documented and follows naming conventions. Using "*" as a marker clearly distinguishes array item paths from regular property paths.


131-138: Defensive branch may not coerce primitives in edge cases.

When targetPath.length === 0 and current is an array of primitives, this branch iterates and recurses with an empty path. However, primitive items exit at line 126 without being coerced.

If this is intentionally defensive (as the comment suggests), consider adding a brief note that this branch is a no-op for primitive arrays, or extend it to handle that case if needed.


213-229: LGTM!

The pipeline-based approach is clean and effective:

  1. Accepts unknown input via type("unknown")
  2. Applies in-place coercion to the data
  3. Validates through the original schema

The type cast is well-justified by the accompanying comment about scope mismatch. The early return optimization for schemas with no coercion targets is a nice touch.

…g custom boolean and updating number.port for strict numeric refinement.
…riable type conversion via standard JSON Schema introspection and update release type to minor.
@yamcodes
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arkenv Changes to the `arkenv` npm package. docs Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant