feat!: v0.2.0 — reshape ParseIssue and strengthen ParseResult types#59
Merged
feat!: v0.2.0 — reshape ParseIssue and strengthen ParseResult types#59
Conversation
BREAKING CHANGE: ParseIssue.path (always-empty array for external format
compatibility) is removed. It conveyed no information and implied false
Standard Schema compliance.
BREAKING CHANGE: ParseIssue.key type changes from optional `unknown` to
required `string`. FormData keys are always strings per spec; the previous
type was misleading.
ParseIssue is now: { code: IssueCode; key: string }
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reflect removal of path field and key type change (unknown → string) in AGENTS.md, README.md, and all boundary-validator skill references. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BREAKING CHANGE: ParseResult failure branch issues type changes from ParseIssue[] to [ParseIssue, ...ParseIssue[]], reflecting the invariant that at least one issue always exists when data is null. Uses destructuring at the return site to let TypeScript infer the non-empty tuple type without a type assertion. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Derived from ParseResult via Extract, providing named aliases for
each branch of the discriminated union without changing ParseResult itself.
SuccessResult = Extract<ParseResult, { data: Record<string, string | File> }>
FailureResult = Extract<ParseResult, { data: null }>
FailureResult.issues is [ParseIssue, ...ParseIssue[]], reflecting the
non-empty tuple introduced in the previous commit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous description claimed keys with characters outside [a-zA-Z0-9_-] were rejected, but the implementation only rejects empty strings and non-string keys. Keys are treated as opaque strings per design. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Object.create(null) returns any; using a type annotation instead of a cast (as) lets TypeScript verify assignability rather than silence it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add explicit `ParseIssue[]` type annotation to `issues` array (was inferred as `never[]`) - Add comment explaining destructuring pattern used to avoid type assertion - Fix JSDoc example: `if (result.data)` → `if (result.data !== null)` - Fix JSDoc description: "unsafe characters" → "empty or not a string" for invalid_key Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ParseResult type in api-contract - Add SuccessResult/FailureResult utility types to Public API section - Update ParseResult failure branch: ParseIssue[] → [ParseIssue, ...ParseIssue[]] - Update constraint description to mention "non-empty tuple" - Add checklist item for SuccessResult/FailureResult derivation rule - Update Last updated date Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Document breaking changes with before/after examples and migration steps:
- ParseIssue.path removal
- ParseIssue.key addition (required string)
- issues type narrowed to non-empty tuple [ParseIssue, ...ParseIssue[]]
Use [Unreleased] header to align with planned workflow automation
that will auto-rewrite it to [v{version}] at release time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #59 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 3 3
Lines 22 23 +1
Branches 6 5 -1
=========================================
+ Hits 22 23 +1 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Implements all breaking changes planned for v0.2.0, focused on making
ParseIssueandParseResultmore precise and honest.ParseIssue.path(was alwaysreadonly []— carried no information)ParseIssue.key: string(required, identifies the offending FormData key)ParseResultfailureissuesto a non-empty tuple[ParseIssue, ...ParseIssue[]]SuccessResultandFailureResultnamed utility typesType of Change
Boundary Checklist (Required for Implementation Changes)
[],., brackets, paths, etc.)📘 Boundary rules & non-goals:
https://github.com/roottool/safe-formdata/blob/main/AGENTS.md
Security & API Stability
Security Impact
API Contract
parsefunction signature, type definitions)CHANGELOG.mdBreaking changes:
ParseIssue.pathremoved — callers referencingissue.pathmust delete those referencesParseIssue.key: stringadded (required) — type definitions referencingParseIssuemust be updatedissues: [ParseIssue, ...ParseIssue[]]on failure — explicit type annotations may need updatingVersioning
CHANGELOG.md.Testing
Automated Checks
bun run check:type:source)bun run test)bun run build)Additional Verification
issue.key(removedissue.pathassertions)boundary-validatorskill run against all changes; findings resolvedAutomated Review (Optional)
boundary-validatorwas run as part of this PR. All findings were resolved:ParseIssue[]type annotation toissuesarray inparse.tsif (result.data)→if (result.data !== null)invalid_keydescription: "unsafe characters" → "empty or not a string"🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com