Skip to content

feat(schema): implement Phase 2 StringSchema and NumberSchema#13

Merged
viniciusdacal merged 2 commits intomainfrom
feat/schema-phase-2
Feb 6, 2026
Merged

feat(schema): implement Phase 2 StringSchema and NumberSchema#13
viniciusdacal merged 2 commits intomainfrom
feat/schema-phase-2

Conversation

@viniciusdacal
Copy link
Copy Markdown
Contributor

Summary

  • Implements StringSchema and NumberSchema for @vertz/schema via strict TDD (18 red-green-refactor cycles)
  • 43 tests across 9 test files — all passing
  • Covers: type validation, constraints, transforms, custom error messages, and JSON Schema output

StringSchema

  • Type validation (accepts string, rejects non-string)
  • Constraints: .min(), .max(), .length(), .regex(), .startsWith(), .endsWith(), .includes()
  • Validators: .uppercase(), .lowercase()
  • Transforms: .trim(), .toLowerCase(), .toUpperCase(), .normalize()
  • Per-rule custom error messages: .min(5, 'Too short')
  • .toJSONSchema(){ type, minLength, maxLength, pattern }

NumberSchema

  • Type validation (accepts number, rejects non-number including NaN)
  • Bounds: .gte()/.min(), .gt(), .lte()/.max(), .lt()
  • Validators: .int(), .positive(), .negative(), .nonnegative(), .nonpositive(), .finite()
  • .multipleOf()/.step()
  • Per-rule custom error messages
  • .toJSONSchema(){ type (number|integer), minimum, exclusiveMinimum, maximum, exclusiveMaximum, multipleOf }

Test plan

  • npx vitest run — 43 tests passing
  • All public API exports from index.ts updated
  • Strict TDD: every behavior test-driven with red-green-refactor

🤖 Generated with Claude Code

StringSchema: type validation, min/max/length, regex, startsWith/endsWith/includes,
uppercase/lowercase validation, trim/toLowerCase/toUpperCase/normalize transforms,
per-rule custom error messages, JSON Schema output.

NumberSchema: type validation (rejects NaN), gte/gt/lte/lt bounds, int, positive/
negative/nonnegative/nonpositive, multipleOf/step, finite, per-rule custom error
messages, JSON Schema output with integer type support.

18 TDD cycles, 43 tests passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor Author

@viniciusdacal viniciusdacal left a comment

Choose a reason for hiding this comment

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

Code Review — PR #13: Phase 2 StringSchema and NumberSchema

Strengths

  • Strict TDD followed — 18 red-green-refactor cycles, 43 tests
  • Immutable chaining pattern consistent with Phase 1 base class
  • Transforms (trim, toLowerCase, toUpperCase, normalize) correctly applied before validation
  • JSON Schema output correctly maps constraints (minLength, maxLength, pattern, minimum, exclusiveMinimum, etc.)
  • NumberSchema.int() correctly maps to { type: "integer" } in JSON Schema

Issues & Suggestions

1. _clone() boilerplate is growingstring.ts, number.ts

Both schemas have 15+ fields to copy in _clone(). This is correct and safe, but as more constraint methods are added it becomes a maintenance burden. Consider a shared helper or Object.assign pattern in a future refactor phase (e.g., Phase 4 when wrapper schemas introduce more cloning).

2. gt() and lt() don't support custom error messagesnumber.ts

.gte() and .lte() accept an optional message param, but .gt() and .lt() don't. This is inconsistent — consider adding the same optional message param for parity.

3. StringSchema.regex() error message is just "Invalid"string.ts:51

Other constraints have descriptive messages, but regex failure says "Invalid". Consider including the pattern: Invalid: must match ${pattern}.

4. Missing DateSchema.toISOString() transform from plan — noted for Phase 3 scope

The plan mentions .toISOString() as a transform on DateSchema. This wasn't included in Phase 2 (which is correct since DateSchema is Phase 3), but it's also missing from Phase 3. Worth tracking.

5. length() doesn't support custom error messagesstring.ts

.min() and .max() accept custom messages but .length() does not. Minor inconsistency.

Test Coverage

  • Good coverage of happy/unhappy paths for all constraints
  • Tests verify both parse() throwing and safeParse() returning errors
  • Custom error message tests included for min/max on both schemas
  • JSON Schema output tested with combined constraints

Summary

Clean, well-tested implementation. The main suggestions are minor consistency improvements (custom messages on all constraint methods, better regex error message). Nothing blocking.

…mprove regex message

Address PR #13 review feedback: consistent custom message support
across all constraint methods and descriptive regex failure messages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@viniciusdacal viniciusdacal merged commit 5318718 into main Feb 6, 2026
viniciusdacal added a commit that referenced this pull request Feb 22, 2026
* feat(schema): implement Phase 2 StringSchema and NumberSchema

StringSchema: type validation, min/max/length, regex, startsWith/endsWith/includes,
uppercase/lowercase validation, trim/toLowerCase/toUpperCase/normalize transforms,
per-rule custom error messages, JSON Schema output.

NumberSchema: type validation (rejects NaN), gte/gt/lte/lt bounds, int, positive/
negative/nonnegative/nonpositive, multipleOf/step, finite, per-rule custom error
messages, JSON Schema output with integer type support.

18 TDD cycles, 43 tests passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(schema): add custom error messages to gt(), lt(), length(), and improve regex message

Address PR #13 review feedback: consistent custom message support
across all constraint methods and descriptive regex failure messages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@viniciusdacal viniciusdacal deleted the feat/schema-phase-2 branch February 22, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant