refactor: apply nuclear-review findings (boundary validation, cart types, dedup) - #198
Merged
Conversation
…oundaries Add a shared parseApiResponse helper and use it to validate HubSpot, Mailchimp, and Shopify responses at the fetch boundary instead of casting (await res.json()) as T. Malformed responses now throw a descriptive error naming the bad paths rather than crashing later as a property access. - Mailchimp: replace error-string sniffing with a typed MailchimpErrorCode union; tag/note writes are now explicitly best-effort and no longer flip the result to failure; extract upsertMember to dedup the two subscribe paths. - HubSpot: drop the unused hubspotType field and its orphaned typeSetter. - Turnstile: collapse the duplicate dev-mode bypass so validateFormWithTurnstile delegates to validateTurnstile (production path unchanged).
Name the post-reshape line item (CartLineItem), derive CartLine from it, and make Cart.id required so the reshape layer is typed end-to-end. Removes the casts those missing types forced (cart-operations, reshape, actions, modal) and guards the addCartItem reducer against an undefined variant. removeItem/updateItemQuantity now take the lineId the client already holds, skipping the extra getCart round-trip per mutation (a getCart fallback is kept for optimistic lines whose server id is not yet confirmed). collections: give the synthetic 'All' collection a stable updatedAt so it does not bust caches.
- ast-transforms: create a single in-memory Project per applyOpsToText and thread it through every handler instead of instantiating up to six. - generate-manifest: reuse toPascalCase from generate-shared, drop the local duplicate. - setup-project / prepare-handoff: adopt the existing cancelGuard for clack prompts (removing manual isCancel checks and casts); rename the two divergent updatePackageJson functions to describe what each does.
animation.ts re-exported clamp/lerp/mapRange/modulo/truncate from sibling util modules, creating two import paths for the same functions. Keep only the animation-owned exports and repoint the one importer (marquee) to @/utils/math.
Reflects the dropped animation.ts re-exports and the new parseApiResponse helper. Fixes the manifest:check CI step.
arzafran
added a commit
that referenced
this pull request
Jun 8, 2026
- CHANGELOG [Unreleased]: log the boundary validation + cart-type work (#198), the effort:low fixes (#205), the WebGL cleanup (#199/#206), lenis-prevent (#207), the Sanity 'use cache' fix (#208), and react-scan as an Orchestra toggle (#209). - components/README: drop the deleted dropdown/ row (now Base UI Select). - lib/dev/README: add the 🧊 webgl and 🔬 react-scan toggles to the Orchestra table; note react-scan is opt-in and how it relates to Stats. - sanity/README: show the 'use cache' fetch pattern required under cacheComponents (bare sanityFetch throws cacheTag()).
arzafran
added a commit
that referenced
this pull request
Jun 9, 2026
- AGENTS.md: document the 'use cache' rule for cacheTag()-calling fetches (the #208 crash) and parseApiResponse boundary response-validation (#198) - shopify README: updateItemQuantity/removeItem now take client-held lineId; note GraphQL envelope validation - webgl README: flowmap/fluid sims are opt-in (#199, #206) - biome-custom-rules: flag the cited dropdown example as since-removed (#202)
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.
What this does
Applies the findings from a whole-codebase maintainability review (
/nuclear-review). It's all behaviour-preserving cleanup — no features change — but it removes a class of latent bugs: malformed responses from HubSpot, Mailchimp, and Shopify now fail with a clear error at the network boundary instead of crashing later as a confusing property-access error, and the Shopify cart stops making an extra API call on every quantity change.No user-facing behaviour changes. The success paths (form submits, cart add/remove/update, product fetch) work exactly as before.
Summary
Boundary validation (
refactor(integrations))parseApiResponse(schema, json, context)helper inlib/utils/validation.ts; HubSpot, Mailchimp, and the Shopify GraphQL envelope are now zod-validated at the fetch boundary instead of(await res.json()) as T.MailchimpErrorCodeunion replaces error-string sniffing; tag/note writes are explicitly best-effort (no longer flip the result to failure);upsertMemberdedups the two subscribe paths.hubspotTypefield and its orphanedtypeSetter.Shopify cart (
refactor(shopify)+perf(shopify))CartLineItem), derivedCartLinefrom it, madeCart.idrequired — removing 11ascasts the missing types forced, and guardingaddCartItemagainst an undefined variant.removeItem/updateItemQuantitytake thelineIdthe client already holds, dropping the redundantgetCartround-trip per mutation (a fallback is kept for optimistic lines without a confirmed id).updatedAtso it doesn't bust caches.Scripts & utils (
refactor(scripts)+refactor(utils))ast-transforms: one shared in-memory ts-morphProjectperapplyOpsToTextinstead of up to six.pascalCase, adopted the existingcancelGuardfor clack prompts (dropping manual casts), and renamed the two divergentupdatePackageJsonfunctions.animation.tsre-export barrel so each util has one canonical import path.Reviewed but intentionally not changed
setup-projectvsprepare-handoff): left separate. They diverge on purpose — setup preserves unknown custom vars (blocklist), handoff strips them (allowlist). Merging would break one guarantee.Follow-up (out of scope, not a regression)
fieldTypeinto<input type=...>, so aphonefield renders<input type="phone">(invalid → falls back to text). Pre-existing; fixing it is a HubSpot-type → HTML-input-type mapping decision worth its own change.Test Plan
bun run checkgreen — biome (0 errors),tsgo --noEmit, 414 tests pass