Extend PUT /contacts/:id route to support updating phones, emails, and
addresses arrays with replacement semantics. Uses atomic transactions
to DELETE all existing multi-values then INSERT new ones. Validates
all multi-value fields before updating. Response includes full contact
with multi-value fields via loadMultiValueFields() helper.
Backward compatible: multi-value fields only replaced when present in
request body. Scalar fields (name, category, etc.) continue to work
independently.
Tests added:
- Update with multi-value fields (replacement semantics verified)
- Validation error on invalid phone data (400)
- Backward compatibility: update without multi-values preserves them
All 109 tests pass.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements Task 12: Extend POST /contacts to accept and persist phones,
emails, and addresses arrays. Uses atomic transactions to ensure all
related records are created together or rolled back on error.
- Validation: validatePhones/Emails/Addresses before insert
- Transaction: db.transaction() for atomic Contact + Multi-Values
- Backward compatible: Multi-value fields are optional
- Refactoring: Extracted loadMultiValueFields() helper (DRY)
- Response includes all multi-value fields with generated IDs
Tests: 3 new tests (create with multi-values, validation, backward compat)
TDD workflow: RED → GREEN → REFACTOR → Commit
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements Task 11: Extend GET /contacts/:id to include phones, emails,
and addresses arrays. Each multi-value field is queried from its respective
table (contact_phones, contact_emails, contact_addresses) and mapped to
camelCase response format with isPrimary boolean conversion.
Tests: 2 new tests (contact with multi-values, empty arrays)
TDD workflow: RED → GREEN → Commit
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
All 4 previously interdependent tests now use shared aliceContact from
before() hook. 54/54 tests passing with full isolation.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>