feat(wallet-sdk): contacts slice (step 7) - #1174
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d api, sdk wiring Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d seam The index shadow export hid the contract Contact; resolve-destination now takes the public projection with typeof narrowing (isContact deleted with its last consumer), and the API keeps ownerId riding along at runtime like the account entities. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| * @param value - The value to check | ||
| * @returns True if the value is a valid Contact, false otherwise | ||
| */ | ||
| export const isContact = (value: unknown): value is Contact => { |
There was a problem hiding this comment.
It lost its last consumer in this PR (deviation 3 in the plan doc). At master, isContact had two consumers: the dead temporary.ts re-export (the web never imported it; pruned in d3973e0) and resolveSendDestination.
This PR retypes that seam's input to the public Contact. The zod guard validates the domain schema, which requires ownerId — a public-shaped contact fails the guard, falls into the string branch, and breaks resolution. typeof input !== 'string' narrows string | Contact exactly. With zero consumers left, the guard was deleted.
After d78a3b5 (thread above), api contacts also lack ownerId at runtime, so the old guard would now reject every real contact.
Restores plan decision 4, reversed mid-slice when the send seam surfaced as an extra Contact consumer. The seam now takes the public projection and no code reads ownerId, so the api strips it in get/list/create and the runtime shape matches the Omit contract. Tests assert the exact public shape; the stale projection comment is removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Step 7 of the no-cache SDK extraction (spec:
docs/superpowers/specs/2026-06-24-wallet-sdk-no-cache-production-design.md). Wraps the already-moved contacts domain in thesdk.contactscontract namespace and flips the web contacts feature off@agicash/wallet-sdk/temporary.Plan + recorded execution deviations:
docs/superpowers/plans/2026-08-11-wallet-sdk-contacts-slice.md.SDK
domain/sdk/contacts.ts):CreateContactParams = { username }(ownerId implicit from the session);findContactCandidates(query): Promise<UserProfile[]>— deviation from the step-4 stub'sContact[]: candidates are user profiles, a contact id exists only aftercreate.createContactsApi(domain/contacts/contacts-api.ts): session-fenced per the accounts pattern (requireUserId+sessionSignalpre/post checks); repository constructed once (db + lud16 domain are process-stable; contacts rows are plaintext, no key material). 11 bun tests.ContactRepository.get→.maybeSingle()+nullon missing (contract:Contact | null) +abortSignaloption.sdk.ts:contactsgetter no longer throwsNotImplementedError; wired withconfig.lightningAddressDomain(its first real consumer).Contactprojection surfaced: dropped the shadowingexport type { Contact }fromindex.ts(per that file's slice-deletes-its-names mechanism). The api stripsownerIdbefore it returns contacts, so the runtime shape matches theOmitprojection (review fix d78a3b5; the first pass let it ride along at runtime).resolve-destination.tstakes the publicContactand narrows withtypeof input !== 'string'— a host-built public-shaped contact must not fall through to string parsing. The zodisContactguard lost its last consumer and is deleted.Web
contact-hooks.ts:useContacts/useCreateContact/useDeleteContact/useFindContactCandidatesnow callsdk.contacts.*; query keys and cache semantics unchanged.ContactsCacheanduseContactChangeHandlersstay as-is — the realtime invalidation layer flips in step 18 (accounts precedent), so the handlers keep their two/temporaryimports.contact-repository-hooks.tsdeleted (last consumer gone); unusedisContactre-export pruned fromtemporary.ts.Verification
bun run fix:all,bun run typecheck(all packages),bun run test— all exit 0 (SDK 143 tests incl. 11 new; web 38).CONTACT_CREATEDecho — the sole cache-add path), detail page, delete. Zero console errors.🤖 Generated with Claude Code