Skip to content

Conversation

@mrbbot
Copy link
Contributor

@mrbbot mrbbot commented Mar 7, 2024

What this PR solves / how to test

Fixes #5018.

Previously, if your Worker returned a redirect response, calling dispatchFetch(url) would send another request to the original url rather than the redirect. This happened because...

  1. We always used this.#runtimeDispatcher for fetch()ing, which only sends request to the runtime. This meant if a Worker returned a redirect to a different origin, that origin would be ignored and the request would still go to the runtime.
  2. The MF-Original-URL header was not cleared/modified during redirects. This meant if a Worker returned a relative/absolute redirect to the same runtime origin, the path would not be updated in the request received by the user.

This change ensures redirects are followed correctly.

  • If your Worker returns a relative redirect or an absolute redirect with the same origin as the original url, the request will be sent to the Worker.
  • If your Worker instead returns an absolute redirect with a different origin, the request will be sent to the Internet.
  • If a redirected request to a different origin returns an absolute redirect with the same origin as the original url, the request will also be sent to the Worker.

Tests have been added to cover the different types of redirect. 👍

Author has addressed the following

  • Tests
    • TODO (before merge)
    • Included
    • Not necessary because:
  • Changeset (Changeset guidelines)
    • TODO (before merge)
    • Included
    • Not necessary because:
  • Public documentation
    • TODO (before merge)
    • Cloudflare docs PR(s):
    • Not necessary because: redirects working is expected behaviour 😅

@mrbbot mrbbot requested a review from a team as a code owner March 7, 2024 10:57
@changeset-bot
Copy link

changeset-bot bot commented Mar 7, 2024

🦋 Changeset detected

Latest commit: da7ad8f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
miniflare Patch
@cloudflare/pages-shared Patch
@cloudflare/vitest-pool-workers Patch
wrangler Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Mar 7, 2024

A wrangler prerelease is available for testing. You can install this latest build in your project with:

npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/8186988941/npm-package-wrangler-5191

You can reference the automatically updated head of this PR with:

npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/prs/5191/npm-package-wrangler-5191

Or you can use npx with this latest build directly:

npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/8186988941/npm-package-wrangler-5191 dev path/to/script.js
Additional artifacts:
npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/8186988941/npm-package-create-cloudflare-5191 --no-auto-update
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/8186988941/npm-package-cloudflare-kv-asset-handler-5191
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/8186988941/npm-package-miniflare-5191
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/8186988941/npm-package-cloudflare-pages-shared-5191
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/8186988941/npm-package-cloudflare-vitest-pool-workers-5191

Note that these links will no longer work once the GitHub Actions artifact expires.


wrangler@3.31.0 includes the following runtime dependencies:

Package Constraint Resolved
miniflare workspace:* 3.20240223.1
workerd 1.20240304.0 1.20240304.0
workerd --version 1.20240304.0 2024-03-04

Please ensure constraints are pinned, and miniflare/workerd minor versions match.

@codecov
Copy link

codecov bot commented Mar 7, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 70.37%. Comparing base (84eeee5) to head (da7ad8f).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #5191      +/-   ##
==========================================
+ Coverage   70.35%   70.37%   +0.02%     
==========================================
  Files         298      298              
  Lines       15567    15567              
  Branches     4007     4007              
==========================================
+ Hits        10952    10956       +4     
+ Misses       4615     4611       -4     

see 5 files with indirect coverage changes

@mrbbot mrbbot merged commit 27fb22b into main Mar 8, 2024
@mrbbot mrbbot deleted the bcoll/fix-dispatch-fetch-redirects branch March 8, 2024 14:03
@workers-devprod workers-devprod mentioned this pull request Mar 8, 2024
juanpprieto added a commit to Shopify/hydrogen that referenced this pull request Aug 26, 2025
…l redirects

The Miniflare v4 update introduced a breaking change where dispatchFetch automatically
follows redirects internally, preventing external OAuth redirects from working properly.
React Router's redirectDocument() expects the browser to handle external redirects,
but Miniflare was intercepting and following them within the worker runtime.

This fix adds {redirect: 'manual'} to all dispatchFetch calls in MiniOxygen, which
prevents Miniflare from following redirects automatically. This ensures that:
- External redirects (like OAuth flows to Shopify's Customer Account API) are passed
  to the browser as intended
- React Router's redirectDocument() works correctly for cross-origin navigation
- The X-Remix-Reload-Document header is respected for full document reloads

The implementation uses Function.prototype.call to pass both arguments to dispatchFetch
while maintaining TypeScript compatibility, as the property accessor doesn't properly
expose the second parameter in TypeScript definitions.

Also adds .tryhydrogen.dev to Vite's allowedHosts for development testing.

References:
- cloudflare/workers-sdk#5018
- cloudflare/workers-sdk#5191
kdaviduik pushed a commit to Shopify/hydrogen that referenced this pull request Aug 28, 2025
…ustomer-account-push flag (#3123)

* Fix MiniOxygen to support React Router's redirectDocument for external redirects

The Miniflare v4 update introduced a breaking change where dispatchFetch automatically
follows redirects internally, preventing external OAuth redirects from working properly.
React Router's redirectDocument() expects the browser to handle external redirects,
but Miniflare was intercepting and following them within the worker runtime.

This fix adds {redirect: 'manual'} to all dispatchFetch calls in MiniOxygen, which
prevents Miniflare from following redirects automatically. This ensures that:
- External redirects (like OAuth flows to Shopify's Customer Account API) are passed
  to the browser as intended
- React Router's redirectDocument() works correctly for cross-origin navigation
- The X-Remix-Reload-Document header is respected for full document reloads

The implementation uses Function.prototype.call to pass both arguments to dispatchFetch
while maintaining TypeScript compatibility, as the property accessor doesn't properly
expose the second parameter in TypeScript definitions.

Also adds .tryhydrogen.dev to Vite's allowedHosts for development testing.

References:
- cloudflare/workers-sdk#5018
- cloudflare/workers-sdk#5191

* Stabilize customer-account-push flag

- Changed from customer-account-push__unstable to customer-account-push
- Removed hidden: true to make flag visible in help
- Fixed typo: Oauth → OAuth in description
- Flag now works via CLI argument or SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH env var

* Fix MiniOxygen redirect handling for OAuth flows

Apply {redirect: 'manual'} to Miniflare's dispatchFetch calls to prevent automatic redirect following. This ensures external redirects (like OAuth) are passed to the browser instead of being followed internally.

Changes:
- Add redirect: 'manual' parameter to dispatchFetch in both worker and node environments
- Fix Headers.getSetCookie() usage for proper Set-Cookie header handling
- Add comprehensive tests for redirect behavior in both environments
- Stabilize customer-account-push CLI flag (remove __unstable prefix)

This fixes OAuth/PKCE authentication flows in React Router 7 where redirectDocument() and external redirects need to be handled by the browser, not the server.

* Add changeset for OAuth redirect fixes and stabilized CLI flag

* Fix intermittent CI test failures in MiniOxygen tests

- Use dynamic port allocation (port: 0) for all test servers to prevent EADDRINUSE errors
- Properly handle OS-assigned ports when using port 0
- Add server tracking and cleanup to ensure all servers are properly closed
- Fix proxy server test to use dynamic port allocation

This resolves race conditions and port conflicts that occur when tests run in parallel in CI environments.

* Fix TypeScript errors in MiniOxygen tests

- Change MiniOxygenOptions to MiniOxygenPreviewOptions in test files
- Add proper type imports for Request, Response, and DispatchFetch
- Add explicit types for onRequest callback parameters

This resolves TypeScript compilation errors that were failing CI.
kdaviduik pushed a commit to Shopify/hydrogen that referenced this pull request Sep 11, 2025
…ustomer-account-push flag (#3123)

* Fix MiniOxygen to support React Router's redirectDocument for external redirects

The Miniflare v4 update introduced a breaking change where dispatchFetch automatically
follows redirects internally, preventing external OAuth redirects from working properly.
React Router's redirectDocument() expects the browser to handle external redirects,
but Miniflare was intercepting and following them within the worker runtime.

This fix adds {redirect: 'manual'} to all dispatchFetch calls in MiniOxygen, which
prevents Miniflare from following redirects automatically. This ensures that:
- External redirects (like OAuth flows to Shopify's Customer Account API) are passed
  to the browser as intended
- React Router's redirectDocument() works correctly for cross-origin navigation
- The X-Remix-Reload-Document header is respected for full document reloads

The implementation uses Function.prototype.call to pass both arguments to dispatchFetch
while maintaining TypeScript compatibility, as the property accessor doesn't properly
expose the second parameter in TypeScript definitions.

Also adds .tryhydrogen.dev to Vite's allowedHosts for development testing.

References:
- cloudflare/workers-sdk#5018
- cloudflare/workers-sdk#5191

* Stabilize customer-account-push flag

- Changed from customer-account-push__unstable to customer-account-push
- Removed hidden: true to make flag visible in help
- Fixed typo: Oauth → OAuth in description
- Flag now works via CLI argument or SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH env var

* Fix MiniOxygen redirect handling for OAuth flows

Apply {redirect: 'manual'} to Miniflare's dispatchFetch calls to prevent automatic redirect following. This ensures external redirects (like OAuth) are passed to the browser instead of being followed internally.

Changes:
- Add redirect: 'manual' parameter to dispatchFetch in both worker and node environments
- Fix Headers.getSetCookie() usage for proper Set-Cookie header handling
- Add comprehensive tests for redirect behavior in both environments
- Stabilize customer-account-push CLI flag (remove __unstable prefix)

This fixes OAuth/PKCE authentication flows in React Router 7 where redirectDocument() and external redirects need to be handled by the browser, not the server.

* Add changeset for OAuth redirect fixes and stabilized CLI flag

* Fix intermittent CI test failures in MiniOxygen tests

- Use dynamic port allocation (port: 0) for all test servers to prevent EADDRINUSE errors
- Properly handle OS-assigned ports when using port 0
- Add server tracking and cleanup to ensure all servers are properly closed
- Fix proxy server test to use dynamic port allocation

This resolves race conditions and port conflicts that occur when tests run in parallel in CI environments.

* Fix TypeScript errors in MiniOxygen tests

- Change MiniOxygenOptions to MiniOxygenPreviewOptions in test files
- Add proper type imports for Request, Response, and DispatchFetch
- Add explicit types for onRequest callback parameters

This resolves TypeScript compilation errors that were failing CI.
kdaviduik added a commit to Shopify/hydrogen that referenced this pull request Sep 11, 2025
* [2025-07] Update Storefront API and Customer Account API

## Summary
Updated both Storefront API and Customer Account API from version 2025-04 to 2025-07

## Changes
- Updated version constants in hydrogen-react and hydrogen packages
- Regenerated GraphQL types and schemas for both APIs
- Updated all hardcoded version references in documentation and tests
- Regenerated skeleton template types
- Created 6 GitHub issues for tracking API changes implementation

## API Changes Tracked
- #3076: Subscription discount data in Customer Account API
- #3077: Cart warnings for non-applicable discount codes
- #3078: BUYER_CANNOT_PURCHASE_FOR_COMPANY_LOCATION cart error
- #3079: New order filter options in Customer Account API
- #3080: Imperial units in UnitPriceMeasurement
- #3081: Selling plan error handling in Cart mutations

## Validation
- TypeScript: ✅ No errors
- Tests: ✅ All passing
- Lint: ⚠️ 2 warnings (non-blocking import duplicates)
- Build: ✅ Successful

* Update skeleton @shopify/cli dependency to latest version

- Update from ~3.80.4 to ~3.83.3
- Include in changeset documentation

* Update package-lock.json for @shopify/cli dependency update

* [2025-07] Fix Monorepo RR7 CI build failures and improve reliability (#3091)

* fix: Complete React Router 7 migration for Express example

The Express example was partially migrated to React Router 7 but missing critical
configuration and dependencies, causing CI failures.

Changes:
- Add react-router.config.ts with proper preset and app directory configuration
- Fix vite.config.ts to call reactRouter() without arguments (RR7 API change)
- Add @react-router/dev as devDependency for TypeScript types
- Update entry.server.tsx to remove unnecessary @remix-run/web-fetch import
  (Node 20+ provides native Response globally)
- Fix environment variable loading using getEnv() helper
- Add .gitignore for React Router generated type files
- Update tsconfig.json to exclude generated directories

The example now builds successfully with React Router 7's framework mode.

* fix: Fix CLI build checks and TypeScript configuration

Multiple CLI-specific issues were causing CI failures after recent refactoring.

Changes:
- Fix build-check.mjs to expect .jsx extensions (tsup outputs .tsx→.jsx)
- Exclude assets/routes from TypeScript checking (template files for user projects)
- Align ast-grep to version 0.33.0 to match @shopify/cli's bundled version
- Fix isHydrogenMonorepo() detection to work in both dev and npm package contexts
- Add 'as const' assertions for ast-grep 0.33.0 API compatibility

Background:
- Template files were moved to assets/routes in May 2024 and inadvertently
  included in TypeScript scope
- ast-grep 0.34.1 conflicted with @shopify/cli's bundled 0.33.0

* fix: Fix CI workflow and monorepo build orchestration

The CI workflow and Turbo configuration had multiple issues causing intermittent
build failures, particularly the "No lockfile found" error.

Changes:
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK=false to typecheck step in CI
  (was only on build:all, but typecheck also triggers builds via Turbo)
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK to turbo.json globalEnv
- Add explicit build dependencies for all examples in turbo.json
- Remove docs-preview from workspaces to prevent React Router version conflicts
- Regenerate package-lock.json for dependency resolution

The root cause was that the typecheck step depends on build tasks (per turbo.json)
but wasn't receiving the lockfile check flag, causing skeleton builds to fail.
This has been a source of CI instability since the monorepo migration.

* [2025-07] Fix Money component compatibility with Customer Account API USDC currency (#3090)

* Fix Money component compatibility with Customer Account API USDC currency

The 2025-07 API update introduced USDC currency code to Customer Account API but not Storefront API, causing TypeScript errors and runtime failures.

Changes:
- Update Money component to accept MoneyV2 from both Storefront and Customer Account APIs via union types
- Enhance useMoney hook to detect unsupported currency codes (like USDC) and gracefully fall back to decimal formatting
- Add currency code suffix for unsupported currencies (e.g., "100.00 USDC") to maintain clarity
- Default to 2 decimal places for USDC to reinforce its 1:1 USD peg based on industry standards

Technical details:
- Handle Intl.NumberFormat RangeError for cryptocurrency codes not in ISO 4217
- Add comprehensive test coverage for both API types and USDC formatting
- Update TypeScript types to support both CurrencyCode enums

Fixes #3089

* Add changeset for Money component USDC compatibility fix

* Add build script to copy customer-account-api-types to dist

Since our Money component now imports from customer-account-api-types, we need to ensure this file is copied to the dist folder during the build process. Previously, only storefront-api-types was being copied.

- Replace copy-storefront-types with copy-api-types script that copies both API type files
- Update build and dev:demo scripts to use the new copy-api-types script
- This fixes the CI build failure where customer-account-api-types.d.ts was not found in dist

* Trigger CI rebuild

* chore: ignore tsup bundled config build artifacts

During the build process, tsup creates temporary bundled configuration files
(tsup.config.bundled_*.mjs) in each package directory. These are generated
artifacts that should not be tracked in version control.

These files:
- Are created when running 'npm run build:all' or similar build commands
- Contain bundled versions of tsup.config.ts files for build execution
- Have random hash suffixes (e.g., tsup.config.bundled_jt705ss6fz.mjs)
- Should be cleaned up automatically but sometimes persist

Adding the pattern '**/tsup.config.bundled_*.mjs' to gitignore prevents
these temporary build artifacts from cluttering git status and being
accidentally committed.

* fix: add missing TypeScript type definitions for cookbook dependencies

Added @types/inquirer and @types/yargs to cookbook devDependencies to resolve
TypeScript compilation errors when running cookbook commands.

This fixes the TS7016 error: 'Could not find a declaration file for module inquirer'
that occurs when running cookbook commands like 'npm run cookbook -- regenerate'
on fresh branches or after clean installs.

* chore: regenerate cookbook recipes with updated patch hashes

Regenerated all cookbook recipes to update patch file hashes after recent
changes to the skeleton template. This ensures the cookbook validation
passes in CI by keeping the patches in sync with the current state of
the skeleton template.

The regeneration updates:
- All patch files with new content hashes
- Recipe YAML files with updated patch references
- README and prompt files with current examples

This fixes the 'Validate Recipes' CI job failure.

* fix: Add lockfile check bypass to cookbook validation in CI

The cookbook validation was failing because the skeleton template
intentionally doesn't include a lockfile (templates shouldn't have
lockfiles), but the hydrogen build command validates lockfile presence
by default.

This fix adds SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK=false to the
cookbook validation step, consistent with how other CI build tasks
handle this requirement.

* fix: Remove unnecessary cli-hydrogen dependency from root package.json

The @shopify/cli-hydrogen dependency in the root package.json was causing
npm to incorrectly attempt to run scripts in all workspace packages when
executing root-level scripts like 'npm run build:pkg'. This resulted in
confusing error messages when npm tried to run 'build:pkg' in packages
that don't have that script defined (e.g., hydrogen-react).

This dependency was likely added accidentally during the v3_routeConfig
changes in March 2025 (commit 74ef1ba) but serves no actual purpose:

- The root package doesn't use cli-hydrogen directly
- Turbo.json already manages build dependencies correctly
- Workspace packages are linked automatically by npm workspaces
- The skeleton template correctly uses @shopify/cli (which bundles
  cli-hydrogen internally)

Removing this dependency:
- Eliminates the 'Missing script: build:pkg' error messages
- Prevents npm from unnecessarily propagating script execution
- Maintains all existing functionality (builds still work correctly)
- Simplifies the dependency tree

The actual build process through Turbo remains unchanged and continues
to work as expected.

* Suggested money changes for PR #3090 (#3097)

* Support imperial units in UnitPriceMeasurement (#3107)

* Support imperial units in UnitPriceMeasurement

* remove unnecessary changeset

* Use count instead of dimension, which doesn't exist

* Don't commit claude settings in this PR to avoid cluttering the branch

* [2025-07] Fix React Context error during client-side hydration (#3101)

* Fix React Context errors in Vite dev server

This fixes "Cannot read properties of null (reading 'useContext')" errors that occur when React Context hooks are used in development mode.

Root Cause:
Vite's module federation can cause multiple React instances to be loaded when @shopify/hydrogen is served as an external module. React Context requires a single React instance to function properly - when multiple instances exist, Context providers from one instance cannot be consumed by hooks from another instance, resulting in null context values.

Solution:
1. Added resolve.dedupe for react, react-dom, and @shopify/hydrogen to ensure Vite uses a single instance of these packages
2. Modified optimizeDeps.include to conditionally optimize @shopify/hydrogen:
   - In production/regular projects: Optimize @shopify/hydrogen to prevent context errors
   - In monorepo development: Skip optimization to allow live reload of source changes

This maintains development workflow in the monorepo while fixing the production build issue.

* Fix React Context error during client-side hydration

Resolves 'Cannot read properties of null (reading useContext)' error
that occurred on first page load when using CSP with nonces.

The issue was caused by NonceProvider being present during SSR but
missing during client hydration, creating a React Context mismatch.

Changes:
- Export NonceProvider from @shopify/hydrogen for client-side usage
- Add NonceProvider wrapper to skeleton's entry.client.tsx
- Simplify Vite config to improve React Context stability

* [2025-07] Display new Cart warnings in skeleton template (#3084)

* [2025-07] Display all cart warnings with user-friendly messages (fixes #3077, #3085)

* Remove CartWarning fragment from cart query - only available in mutations

* Add support for all cart user error types in skeleton template (#3121)

The Hydrogen cart handler's return type includes a union of three possible
user error types: CartUserError, MetafieldsSetUserError, and
MetafieldDeleteUserError. While the skeleton template currently only handles
non-metafield operations, the TypeScript types from the cart handler don't
narrow based on the specific operation performed.

This change updates the CartUserErrors, CartMain, and CartSummary components
to accept all three error types, resolving TypeScript errors and ensuring
the components are compatible with any cart operation that might be added
in the future.

* Update Vitest from v1.0.4 to v3.2.4 across all packages (#3126)

* Update Vitest from v1.0.4 to v3.2.4 across all packages

- Upgrade vitest to ^3.2.4 in all 5 packages that use it
- Upgrade @vitest/coverage-v8 to ^3.2.4 to match vitest version
- Add vitest as devDependency to create-hydrogen package (was missing)
- Add explicit coverage provider configuration (required in v3+)
  - Set provider: 'v8' in cli and hydrogen-react vitest configs

Breaking change: Vitest v2+ requires explicit coverage provider config

* Fix Vitest v3 Mock type breaking changes

In Vitest v3, vi.fn() returns Mock<() => unknown> instead of Mock<any[], any>,
requiring explicit type assertions or type parameters for mocks with specific
return types.

Changes:
- Add type assertion for fetchWithServerCache mock in storefront.test.ts
- Simplify Promise creation in session mocks (Promise.resolve instead of new Promise)
- Fix Mock type usage in Image.test.tsx for console.warn assertions
- Add vitest/globals to tsconfig for packages using global test functions
- Keep jest types alongside vitest types for @testing-library/jest-dom compatibility

The stricter typing in v3 catches more potential issues at compile time but
requires updating existing mocks that relied on v1's permissive typing.

* Fix formatting

* Add CODEOWNERS file to automatically request team's review on non-draft PRs (#3133)

* [2025-06] Fix MiniOxygen/Miniflare v4 redirects handling + Stable --customer-account-push  flag (#3123)

* Fix MiniOxygen to support React Router's redirectDocument for external redirects

The Miniflare v4 update introduced a breaking change where dispatchFetch automatically
follows redirects internally, preventing external OAuth redirects from working properly.
React Router's redirectDocument() expects the browser to handle external redirects,
but Miniflare was intercepting and following them within the worker runtime.

This fix adds {redirect: 'manual'} to all dispatchFetch calls in MiniOxygen, which
prevents Miniflare from following redirects automatically. This ensures that:
- External redirects (like OAuth flows to Shopify's Customer Account API) are passed
  to the browser as intended
- React Router's redirectDocument() works correctly for cross-origin navigation
- The X-Remix-Reload-Document header is respected for full document reloads

The implementation uses Function.prototype.call to pass both arguments to dispatchFetch
while maintaining TypeScript compatibility, as the property accessor doesn't properly
expose the second parameter in TypeScript definitions.

Also adds .tryhydrogen.dev to Vite's allowedHosts for development testing.

References:
- cloudflare/workers-sdk#5018
- cloudflare/workers-sdk#5191

* Stabilize customer-account-push flag

- Changed from customer-account-push__unstable to customer-account-push
- Removed hidden: true to make flag visible in help
- Fixed typo: Oauth → OAuth in description
- Flag now works via CLI argument or SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH env var

* Fix MiniOxygen redirect handling for OAuth flows

Apply {redirect: 'manual'} to Miniflare's dispatchFetch calls to prevent automatic redirect following. This ensures external redirects (like OAuth) are passed to the browser instead of being followed internally.

Changes:
- Add redirect: 'manual' parameter to dispatchFetch in both worker and node environments
- Fix Headers.getSetCookie() usage for proper Set-Cookie header handling
- Add comprehensive tests for redirect behavior in both environments
- Stabilize customer-account-push CLI flag (remove __unstable prefix)

This fixes OAuth/PKCE authentication flows in React Router 7 where redirectDocument() and external redirects need to be handled by the browser, not the server.

* Add changeset for OAuth redirect fixes and stabilized CLI flag

* Fix intermittent CI test failures in MiniOxygen tests

- Use dynamic port allocation (port: 0) for all test servers to prevent EADDRINUSE errors
- Properly handle OS-assigned ports when using port 0
- Add server tracking and cleanup to ensure all servers are properly closed
- Fix proxy server test to use dynamic port allocation

This resolves race conditions and port conflicts that occur when tests run in parallel in CI environments.

* Fix TypeScript errors in MiniOxygen tests

- Change MiniOxygenOptions to MiniOxygenPreviewOptions in test files
- Add proper type imports for Request, Response, and DispatchFetch
- Add explicit types for onRequest callback parameters

This resolves TypeScript compilation errors that were failing CI.

* Update subscriptions recipe with account/subscriptions (#3124)

* Delete unused variable

---------

Co-authored-by: Kara Daviduik <105449131+kdaviduik@users.noreply.github.com>
Co-authored-by: Kara Daviduik <kara.daviduik@shopify.com>
rbshop pushed a commit to Shopify/hydrogen that referenced this pull request Sep 16, 2025
…ustomer-account-push flag (#3123)

* Fix MiniOxygen to support React Router's redirectDocument for external redirects

The Miniflare v4 update introduced a breaking change where dispatchFetch automatically
follows redirects internally, preventing external OAuth redirects from working properly.
React Router's redirectDocument() expects the browser to handle external redirects,
but Miniflare was intercepting and following them within the worker runtime.

This fix adds {redirect: 'manual'} to all dispatchFetch calls in MiniOxygen, which
prevents Miniflare from following redirects automatically. This ensures that:
- External redirects (like OAuth flows to Shopify's Customer Account API) are passed
  to the browser as intended
- React Router's redirectDocument() works correctly for cross-origin navigation
- The X-Remix-Reload-Document header is respected for full document reloads

The implementation uses Function.prototype.call to pass both arguments to dispatchFetch
while maintaining TypeScript compatibility, as the property accessor doesn't properly
expose the second parameter in TypeScript definitions.

Also adds .tryhydrogen.dev to Vite's allowedHosts for development testing.

References:
- cloudflare/workers-sdk#5018
- cloudflare/workers-sdk#5191

* Stabilize customer-account-push flag

- Changed from customer-account-push__unstable to customer-account-push
- Removed hidden: true to make flag visible in help
- Fixed typo: Oauth → OAuth in description
- Flag now works via CLI argument or SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH env var

* Fix MiniOxygen redirect handling for OAuth flows

Apply {redirect: 'manual'} to Miniflare's dispatchFetch calls to prevent automatic redirect following. This ensures external redirects (like OAuth) are passed to the browser instead of being followed internally.

Changes:
- Add redirect: 'manual' parameter to dispatchFetch in both worker and node environments
- Fix Headers.getSetCookie() usage for proper Set-Cookie header handling
- Add comprehensive tests for redirect behavior in both environments
- Stabilize customer-account-push CLI flag (remove __unstable prefix)

This fixes OAuth/PKCE authentication flows in React Router 7 where redirectDocument() and external redirects need to be handled by the browser, not the server.

* Add changeset for OAuth redirect fixes and stabilized CLI flag

* Fix intermittent CI test failures in MiniOxygen tests

- Use dynamic port allocation (port: 0) for all test servers to prevent EADDRINUSE errors
- Properly handle OS-assigned ports when using port 0
- Add server tracking and cleanup to ensure all servers are properly closed
- Fix proxy server test to use dynamic port allocation

This resolves race conditions and port conflicts that occur when tests run in parallel in CI environments.

* Fix TypeScript errors in MiniOxygen tests

- Change MiniOxygenOptions to MiniOxygenPreviewOptions in test files
- Add proper type imports for Request, Response, and DispatchFetch
- Add explicit types for onRequest callback parameters

This resolves TypeScript compilation errors that were failing CI.
rbshop pushed a commit to Shopify/hydrogen that referenced this pull request Sep 16, 2025
…ustomer-account-push flag (#3123)

* Fix MiniOxygen to support React Router's redirectDocument for external redirects

The Miniflare v4 update introduced a breaking change where dispatchFetch automatically
follows redirects internally, preventing external OAuth redirects from working properly.
React Router's redirectDocument() expects the browser to handle external redirects,
but Miniflare was intercepting and following them within the worker runtime.

This fix adds {redirect: 'manual'} to all dispatchFetch calls in MiniOxygen, which
prevents Miniflare from following redirects automatically. This ensures that:
- External redirects (like OAuth flows to Shopify's Customer Account API) are passed
  to the browser as intended
- React Router's redirectDocument() works correctly for cross-origin navigation
- The X-Remix-Reload-Document header is respected for full document reloads

The implementation uses Function.prototype.call to pass both arguments to dispatchFetch
while maintaining TypeScript compatibility, as the property accessor doesn't properly
expose the second parameter in TypeScript definitions.

Also adds .tryhydrogen.dev to Vite's allowedHosts for development testing.

References:
- cloudflare/workers-sdk#5018
- cloudflare/workers-sdk#5191

* Stabilize customer-account-push flag

- Changed from customer-account-push__unstable to customer-account-push
- Removed hidden: true to make flag visible in help
- Fixed typo: Oauth → OAuth in description
- Flag now works via CLI argument or SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH env var

* Fix MiniOxygen redirect handling for OAuth flows

Apply {redirect: 'manual'} to Miniflare's dispatchFetch calls to prevent automatic redirect following. This ensures external redirects (like OAuth) are passed to the browser instead of being followed internally.

Changes:
- Add redirect: 'manual' parameter to dispatchFetch in both worker and node environments
- Fix Headers.getSetCookie() usage for proper Set-Cookie header handling
- Add comprehensive tests for redirect behavior in both environments
- Stabilize customer-account-push CLI flag (remove __unstable prefix)

This fixes OAuth/PKCE authentication flows in React Router 7 where redirectDocument() and external redirects need to be handled by the browser, not the server.

* Add changeset for OAuth redirect fixes and stabilized CLI flag

* Fix intermittent CI test failures in MiniOxygen tests

- Use dynamic port allocation (port: 0) for all test servers to prevent EADDRINUSE errors
- Properly handle OS-assigned ports when using port 0
- Add server tracking and cleanup to ensure all servers are properly closed
- Fix proxy server test to use dynamic port allocation

This resolves race conditions and port conflicts that occur when tests run in parallel in CI environments.

* Fix TypeScript errors in MiniOxygen tests

- Change MiniOxygenOptions to MiniOxygenPreviewOptions in test files
- Add proper type imports for Request, Response, and DispatchFetch
- Add explicit types for onRequest callback parameters

This resolves TypeScript compilation errors that were failing CI.
juanpprieto added a commit to Shopify/hydrogen that referenced this pull request Sep 16, 2025
* Update package-lock.json for @shopify/cli dependency update

* [2025-07] Fix Monorepo RR7 CI build failures and improve reliability (#3091)

* fix: Complete React Router 7 migration for Express example

The Express example was partially migrated to React Router 7 but missing critical
configuration and dependencies, causing CI failures.

Changes:
- Add react-router.config.ts with proper preset and app directory configuration
- Fix vite.config.ts to call reactRouter() without arguments (RR7 API change)
- Add @react-router/dev as devDependency for TypeScript types
- Update entry.server.tsx to remove unnecessary @remix-run/web-fetch import
  (Node 20+ provides native Response globally)
- Fix environment variable loading using getEnv() helper
- Add .gitignore for React Router generated type files
- Update tsconfig.json to exclude generated directories

The example now builds successfully with React Router 7's framework mode.

* fix: Fix CLI build checks and TypeScript configuration

Multiple CLI-specific issues were causing CI failures after recent refactoring.

Changes:
- Fix build-check.mjs to expect .jsx extensions (tsup outputs .tsx→.jsx)
- Exclude assets/routes from TypeScript checking (template files for user projects)
- Align ast-grep to version 0.33.0 to match @shopify/cli's bundled version
- Fix isHydrogenMonorepo() detection to work in both dev and npm package contexts
- Add 'as const' assertions for ast-grep 0.33.0 API compatibility

Background:
- Template files were moved to assets/routes in May 2024 and inadvertently
  included in TypeScript scope
- ast-grep 0.34.1 conflicted with @shopify/cli's bundled 0.33.0

* fix: Fix CI workflow and monorepo build orchestration

The CI workflow and Turbo configuration had multiple issues causing intermittent
build failures, particularly the "No lockfile found" error.

Changes:
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK=false to typecheck step in CI
  (was only on build:all, but typecheck also triggers builds via Turbo)
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK to turbo.json globalEnv
- Add explicit build dependencies for all examples in turbo.json
- Remove docs-preview from workspaces to prevent React Router version conflicts
- Regenerate package-lock.json for dependency resolution

The root cause was that the typecheck step depends on build tasks (per turbo.json)
but wasn't receiving the lockfile check flag, causing skeleton builds to fail.
This has been a source of CI instability since the monorepo migration.

* chore: regenerate cookbook recipes with updated patch hashes

Regenerated all cookbook recipes to update patch file hashes after recent
changes to the skeleton template. This ensures the cookbook validation
passes in CI by keeping the patches in sync with the current state of
the skeleton template.

The regeneration updates:
- All patch files with new content hashes
- Recipe YAML files with updated patch references
- README and prompt files with current examples

This fixes the 'Validate Recipes' CI job failure.

* [2025-07] Fix React Context error during client-side hydration (#3101)

* Fix React Context errors in Vite dev server

This fixes "Cannot read properties of null (reading 'useContext')" errors that occur when React Context hooks are used in development mode.

Root Cause:
Vite's module federation can cause multiple React instances to be loaded when @shopify/hydrogen is served as an external module. React Context requires a single React instance to function properly - when multiple instances exist, Context providers from one instance cannot be consumed by hooks from another instance, resulting in null context values.

Solution:
1. Added resolve.dedupe for react, react-dom, and @shopify/hydrogen to ensure Vite uses a single instance of these packages
2. Modified optimizeDeps.include to conditionally optimize @shopify/hydrogen:
   - In production/regular projects: Optimize @shopify/hydrogen to prevent context errors
   - In monorepo development: Skip optimization to allow live reload of source changes

This maintains development workflow in the monorepo while fixing the production build issue.

* Fix React Context error during client-side hydration

Resolves 'Cannot read properties of null (reading useContext)' error
that occurred on first page load when using CSP with nonces.

The issue was caused by NonceProvider being present during SSR but
missing during client hydration, creating a React Context mismatch.

Changes:
- Export NonceProvider from @shopify/hydrogen for client-side usage
- Add NonceProvider wrapper to skeleton's entry.client.tsx
- Simplify Vite config to improve React Context stability

* Update Vitest from v1.0.4 to v3.2.4 across all packages (#3126)

* Update Vitest from v1.0.4 to v3.2.4 across all packages

- Upgrade vitest to ^3.2.4 in all 5 packages that use it
- Upgrade @vitest/coverage-v8 to ^3.2.4 to match vitest version
- Add vitest as devDependency to create-hydrogen package (was missing)
- Add explicit coverage provider configuration (required in v3+)
  - Set provider: 'v8' in cli and hydrogen-react vitest configs

Breaking change: Vitest v2+ requires explicit coverage provider config

* Fix Vitest v3 Mock type breaking changes

In Vitest v3, vi.fn() returns Mock<() => unknown> instead of Mock<any[], any>,
requiring explicit type assertions or type parameters for mocks with specific
return types.

Changes:
- Add type assertion for fetchWithServerCache mock in storefront.test.ts
- Simplify Promise creation in session mocks (Promise.resolve instead of new Promise)
- Fix Mock type usage in Image.test.tsx for console.warn assertions
- Add vitest/globals to tsconfig for packages using global test functions
- Keep jest types alongside vitest types for @testing-library/jest-dom compatibility

The stricter typing in v3 catches more potential issues at compile time but
requires updating existing mocks that relied on v1's permissive typing.

* Fix formatting

* [2025-06] Fix MiniOxygen/Miniflare v4 redirects handling + Stable --customer-account-push  flag (#3123)

* Fix MiniOxygen to support React Router's redirectDocument for external redirects

The Miniflare v4 update introduced a breaking change where dispatchFetch automatically
follows redirects internally, preventing external OAuth redirects from working properly.
React Router's redirectDocument() expects the browser to handle external redirects,
but Miniflare was intercepting and following them within the worker runtime.

This fix adds {redirect: 'manual'} to all dispatchFetch calls in MiniOxygen, which
prevents Miniflare from following redirects automatically. This ensures that:
- External redirects (like OAuth flows to Shopify's Customer Account API) are passed
  to the browser as intended
- React Router's redirectDocument() works correctly for cross-origin navigation
- The X-Remix-Reload-Document header is respected for full document reloads

The implementation uses Function.prototype.call to pass both arguments to dispatchFetch
while maintaining TypeScript compatibility, as the property accessor doesn't properly
expose the second parameter in TypeScript definitions.

Also adds .tryhydrogen.dev to Vite's allowedHosts for development testing.

References:
- cloudflare/workers-sdk#5018
- cloudflare/workers-sdk#5191

* Stabilize customer-account-push flag

- Changed from customer-account-push__unstable to customer-account-push
- Removed hidden: true to make flag visible in help
- Fixed typo: Oauth → OAuth in description
- Flag now works via CLI argument or SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH env var

* Fix MiniOxygen redirect handling for OAuth flows

Apply {redirect: 'manual'} to Miniflare's dispatchFetch calls to prevent automatic redirect following. This ensures external redirects (like OAuth) are passed to the browser instead of being followed internally.

Changes:
- Add redirect: 'manual' parameter to dispatchFetch in both worker and node environments
- Fix Headers.getSetCookie() usage for proper Set-Cookie header handling
- Add comprehensive tests for redirect behavior in both environments
- Stabilize customer-account-push CLI flag (remove __unstable prefix)

This fixes OAuth/PKCE authentication flows in React Router 7 where redirectDocument() and external redirects need to be handled by the browser, not the server.

* Add changeset for OAuth redirect fixes and stabilized CLI flag

* Fix intermittent CI test failures in MiniOxygen tests

- Use dynamic port allocation (port: 0) for all test servers to prevent EADDRINUSE errors
- Properly handle OS-assigned ports when using port 0
- Add server tracking and cleanup to ensure all servers are properly closed
- Fix proxy server test to use dynamic port allocation

This resolves race conditions and port conflicts that occur when tests run in parallel in CI environments.

* Fix TypeScript errors in MiniOxygen tests

- Change MiniOxygenOptions to MiniOxygenPreviewOptions in test files
- Add proper type imports for Request, Response, and DispatchFetch
- Add explicit types for onRequest callback parameters

This resolves TypeScript compilation errors that were failing CI.

* Update subscriptions recipe with account/subscriptions (#3124)

* Delete unused variable

* 2025-07 generated types

* Add cartGiftCardCodesRemove mutation support

- Add new cartGiftCardCodesRemove mutation handler for removing specific gift cards by ID
- Integrate removeGiftCardCodes method into cart handler
- Add GiftCardCodesRemove action to CartForm
- Update cart fragments to include appliedGiftCards.id field
- Implement gift card removal UI in skeleton template
- Maintain existing additive behavior for adding/updating gift cards
- Add tests for new mutation handler

* Fix linting issues: sort exports and remove duplicate imports

* Fix tests for cartGiftCardCodesRemove mutation support

* Add missing appliedGiftCards id field

* fixing up after rebase

* Undoing an accidental non-change from the rebase

* Merge branch 'main' into feat-cartGiftCardCodesRemove

Resolved conflicts:
- Deleted examples/{b2b,custom-cart-method,subscriptions}/app/lib/fragments.ts
  (examples moved to cookbook in main)
- Regenerated GraphQL schemas for hydrogen-react package

The id field for appliedGiftCards is preserved in skeleton template

* Update lock

* Update multipass recipe

* fix multipass

* Fix multipass recipe for gift card removal feature and enhance patch conflict detection

- Fix TypeScript import errors in account_.login.multipass.tsx by using standard React Router types instead of generated route types
- Regenerate all multipass recipe patches to work with the gift card removal feature added to cart.tsx
- Add comprehensive patch conflict detection to apply.ts and validate.ts that:
  - Detects .orig and .rej files created during patching
  - Shows rejected patch content for easier debugging
  - Provides clear instructions for resolving conflicts
  - Throws errors early to prevent confusing TypeScript errors
- Update enhanced error logging in validate.ts to properly decode Buffer outputs

This ensures the multipass recipe validates successfully in CI with the new cartGiftCardCodesRemove feature.

* fix: resolve cookbook recipe validation failures for custom-cart-method and metaobjects

- Regenerated all patches for both recipes to work with gift card removal feature
- Fixed incorrect shared patch file issue (both recipes had same hash but different content)
- Added human-readable descriptions to all recipe.yaml patch entries
- Both recipes now validate successfully in CI

The root cause was that the git card removal feature (cartGiftCardCodesRemove) changed
the cart.tsx structure, causing patch conflicts in fragments.ts for both recipes.

---------

Co-authored-by: Kara Daviduik <105449131+kdaviduik@users.noreply.github.com>
Co-authored-by: Kara Daviduik <kara.daviduik@shopify.com>
Co-authored-by: rbshop <rheese.burgess@shopify.com>
juanpprieto added a commit to Shopify/hydrogen that referenced this pull request Sep 17, 2025
* [2025-07] Update Storefront API and Customer Account API

## Summary
Updated both Storefront API and Customer Account API from version 2025-04 to 2025-07

## Changes
- Updated version constants in hydrogen-react and hydrogen packages
- Regenerated GraphQL types and schemas for both APIs
- Updated all hardcoded version references in documentation and tests
- Regenerated skeleton template types
- Created 6 GitHub issues for tracking API changes implementation

## API Changes Tracked
- #3076: Subscription discount data in Customer Account API
- #3077: Cart warnings for non-applicable discount codes
- #3078: BUYER_CANNOT_PURCHASE_FOR_COMPANY_LOCATION cart error
- #3079: New order filter options in Customer Account API
- #3080: Imperial units in UnitPriceMeasurement
- #3081: Selling plan error handling in Cart mutations

## Validation
- TypeScript: ✅ No errors
- Tests: ✅ All passing
- Lint: ⚠️ 2 warnings (non-blocking import duplicates)
- Build: ✅ Successful

* Update skeleton @shopify/cli dependency to latest version

- Update from ~3.80.4 to ~3.83.3
- Include in changeset documentation

* Update package-lock.json for @shopify/cli dependency update

* [2025-07] Fix Monorepo RR7 CI build failures and improve reliability (#3091)

* fix: Complete React Router 7 migration for Express example

The Express example was partially migrated to React Router 7 but missing critical
configuration and dependencies, causing CI failures.

Changes:
- Add react-router.config.ts with proper preset and app directory configuration
- Fix vite.config.ts to call reactRouter() without arguments (RR7 API change)
- Add @react-router/dev as devDependency for TypeScript types
- Update entry.server.tsx to remove unnecessary @remix-run/web-fetch import
  (Node 20+ provides native Response globally)
- Fix environment variable loading using getEnv() helper
- Add .gitignore for React Router generated type files
- Update tsconfig.json to exclude generated directories

The example now builds successfully with React Router 7's framework mode.

* fix: Fix CLI build checks and TypeScript configuration

Multiple CLI-specific issues were causing CI failures after recent refactoring.

Changes:
- Fix build-check.mjs to expect .jsx extensions (tsup outputs .tsx→.jsx)
- Exclude assets/routes from TypeScript checking (template files for user projects)
- Align ast-grep to version 0.33.0 to match @shopify/cli's bundled version
- Fix isHydrogenMonorepo() detection to work in both dev and npm package contexts
- Add 'as const' assertions for ast-grep 0.33.0 API compatibility

Background:
- Template files were moved to assets/routes in May 2024 and inadvertently
  included in TypeScript scope
- ast-grep 0.34.1 conflicted with @shopify/cli's bundled 0.33.0

* fix: Fix CI workflow and monorepo build orchestration

The CI workflow and Turbo configuration had multiple issues causing intermittent
build failures, particularly the "No lockfile found" error.

Changes:
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK=false to typecheck step in CI
  (was only on build:all, but typecheck also triggers builds via Turbo)
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK to turbo.json globalEnv
- Add explicit build dependencies for all examples in turbo.json
- Remove docs-preview from workspaces to prevent React Router version conflicts
- Regenerate package-lock.json for dependency resolution

The root cause was that the typecheck step depends on build tasks (per turbo.json)
but wasn't receiving the lockfile check flag, causing skeleton builds to fail.
This has been a source of CI instability since the monorepo migration.

* [2025-07] Fix Money component compatibility with Customer Account API USDC currency (#3090)

* Fix Money component compatibility with Customer Account API USDC currency

The 2025-07 API update introduced USDC currency code to Customer Account API but not Storefront API, causing TypeScript errors and runtime failures.

Changes:
- Update Money component to accept MoneyV2 from both Storefront and Customer Account APIs via union types
- Enhance useMoney hook to detect unsupported currency codes (like USDC) and gracefully fall back to decimal formatting
- Add currency code suffix for unsupported currencies (e.g., "100.00 USDC") to maintain clarity
- Default to 2 decimal places for USDC to reinforce its 1:1 USD peg based on industry standards

Technical details:
- Handle Intl.NumberFormat RangeError for cryptocurrency codes not in ISO 4217
- Add comprehensive test coverage for both API types and USDC formatting
- Update TypeScript types to support both CurrencyCode enums

Fixes #3089

* Add changeset for Money component USDC compatibility fix

* Add build script to copy customer-account-api-types to dist

Since our Money component now imports from customer-account-api-types, we need to ensure this file is copied to the dist folder during the build process. Previously, only storefront-api-types was being copied.

- Replace copy-storefront-types with copy-api-types script that copies both API type files
- Update build and dev:demo scripts to use the new copy-api-types script
- This fixes the CI build failure where customer-account-api-types.d.ts was not found in dist

* Trigger CI rebuild

* chore: ignore tsup bundled config build artifacts

During the build process, tsup creates temporary bundled configuration files
(tsup.config.bundled_*.mjs) in each package directory. These are generated
artifacts that should not be tracked in version control.

These files:
- Are created when running 'npm run build:all' or similar build commands
- Contain bundled versions of tsup.config.ts files for build execution
- Have random hash suffixes (e.g., tsup.config.bundled_jt705ss6fz.mjs)
- Should be cleaned up automatically but sometimes persist

Adding the pattern '**/tsup.config.bundled_*.mjs' to gitignore prevents
these temporary build artifacts from cluttering git status and being
accidentally committed.

* fix: add missing TypeScript type definitions for cookbook dependencies

Added @types/inquirer and @types/yargs to cookbook devDependencies to resolve
TypeScript compilation errors when running cookbook commands.

This fixes the TS7016 error: 'Could not find a declaration file for module inquirer'
that occurs when running cookbook commands like 'npm run cookbook -- regenerate'
on fresh branches or after clean installs.

* chore: regenerate cookbook recipes with updated patch hashes

Regenerated all cookbook recipes to update patch file hashes after recent
changes to the skeleton template. This ensures the cookbook validation
passes in CI by keeping the patches in sync with the current state of
the skeleton template.

The regeneration updates:
- All patch files with new content hashes
- Recipe YAML files with updated patch references
- README and prompt files with current examples

This fixes the 'Validate Recipes' CI job failure.

* fix: Add lockfile check bypass to cookbook validation in CI

The cookbook validation was failing because the skeleton template
intentionally doesn't include a lockfile (templates shouldn't have
lockfiles), but the hydrogen build command validates lockfile presence
by default.

This fix adds SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK=false to the
cookbook validation step, consistent with how other CI build tasks
handle this requirement.

* fix: Remove unnecessary cli-hydrogen dependency from root package.json

The @shopify/cli-hydrogen dependency in the root package.json was causing
npm to incorrectly attempt to run scripts in all workspace packages when
executing root-level scripts like 'npm run build:pkg'. This resulted in
confusing error messages when npm tried to run 'build:pkg' in packages
that don't have that script defined (e.g., hydrogen-react).

This dependency was likely added accidentally during the v3_routeConfig
changes in March 2025 (commit 74ef1ba) but serves no actual purpose:

- The root package doesn't use cli-hydrogen directly
- Turbo.json already manages build dependencies correctly
- Workspace packages are linked automatically by npm workspaces
- The skeleton template correctly uses @shopify/cli (which bundles
  cli-hydrogen internally)

Removing this dependency:
- Eliminates the 'Missing script: build:pkg' error messages
- Prevents npm from unnecessarily propagating script execution
- Maintains all existing functionality (builds still work correctly)
- Simplifies the dependency tree

The actual build process through Turbo remains unchanged and continues
to work as expected.

* Suggested money changes for PR #3090 (#3097)

* Support imperial units in UnitPriceMeasurement (#3107)

* Support imperial units in UnitPriceMeasurement

* remove unnecessary changeset

* Use count instead of dimension, which doesn't exist

* Don't commit claude settings in this PR to avoid cluttering the branch

* [2025-07] Fix React Context error during client-side hydration (#3101)

* Fix React Context errors in Vite dev server

This fixes "Cannot read properties of null (reading 'useContext')" errors that occur when React Context hooks are used in development mode.

Root Cause:
Vite's module federation can cause multiple React instances to be loaded when @shopify/hydrogen is served as an external module. React Context requires a single React instance to function properly - when multiple instances exist, Context providers from one instance cannot be consumed by hooks from another instance, resulting in null context values.

Solution:
1. Added resolve.dedupe for react, react-dom, and @shopify/hydrogen to ensure Vite uses a single instance of these packages
2. Modified optimizeDeps.include to conditionally optimize @shopify/hydrogen:
   - In production/regular projects: Optimize @shopify/hydrogen to prevent context errors
   - In monorepo development: Skip optimization to allow live reload of source changes

This maintains development workflow in the monorepo while fixing the production build issue.

* Fix React Context error during client-side hydration

Resolves 'Cannot read properties of null (reading useContext)' error
that occurred on first page load when using CSP with nonces.

The issue was caused by NonceProvider being present during SSR but
missing during client hydration, creating a React Context mismatch.

Changes:
- Export NonceProvider from @shopify/hydrogen for client-side usage
- Add NonceProvider wrapper to skeleton's entry.client.tsx
- Simplify Vite config to improve React Context stability

* [2025-07] Display new Cart warnings in skeleton template (#3084)

* [2025-07] Display all cart warnings with user-friendly messages (fixes #3077, #3085)

* Remove CartWarning fragment from cart query - only available in mutations

* Add support for all cart user error types in skeleton template (#3121)

The Hydrogen cart handler's return type includes a union of three possible
user error types: CartUserError, MetafieldsSetUserError, and
MetafieldDeleteUserError. While the skeleton template currently only handles
non-metafield operations, the TypeScript types from the cart handler don't
narrow based on the specific operation performed.

This change updates the CartUserErrors, CartMain, and CartSummary components
to accept all three error types, resolving TypeScript errors and ensuring
the components are compatible with any cart operation that might be added
in the future.

* Update Vitest from v1.0.4 to v3.2.4 across all packages (#3126)

* Update Vitest from v1.0.4 to v3.2.4 across all packages

- Upgrade vitest to ^3.2.4 in all 5 packages that use it
- Upgrade @vitest/coverage-v8 to ^3.2.4 to match vitest version
- Add vitest as devDependency to create-hydrogen package (was missing)
- Add explicit coverage provider configuration (required in v3+)
  - Set provider: 'v8' in cli and hydrogen-react vitest configs

Breaking change: Vitest v2+ requires explicit coverage provider config

* Fix Vitest v3 Mock type breaking changes

In Vitest v3, vi.fn() returns Mock<() => unknown> instead of Mock<any[], any>,
requiring explicit type assertions or type parameters for mocks with specific
return types.

Changes:
- Add type assertion for fetchWithServerCache mock in storefront.test.ts
- Simplify Promise creation in session mocks (Promise.resolve instead of new Promise)
- Fix Mock type usage in Image.test.tsx for console.warn assertions
- Add vitest/globals to tsconfig for packages using global test functions
- Keep jest types alongside vitest types for @testing-library/jest-dom compatibility

The stricter typing in v3 catches more potential issues at compile time but
requires updating existing mocks that relied on v1's permissive typing.

* Fix formatting

* Add CODEOWNERS file to automatically request team's review on non-draft PRs (#3133)

* [2025-06] Fix MiniOxygen/Miniflare v4 redirects handling + Stable --customer-account-push  flag (#3123)

* Fix MiniOxygen to support React Router's redirectDocument for external redirects

The Miniflare v4 update introduced a breaking change where dispatchFetch automatically
follows redirects internally, preventing external OAuth redirects from working properly.
React Router's redirectDocument() expects the browser to handle external redirects,
but Miniflare was intercepting and following them within the worker runtime.

This fix adds {redirect: 'manual'} to all dispatchFetch calls in MiniOxygen, which
prevents Miniflare from following redirects automatically. This ensures that:
- External redirects (like OAuth flows to Shopify's Customer Account API) are passed
  to the browser as intended
- React Router's redirectDocument() works correctly for cross-origin navigation
- The X-Remix-Reload-Document header is respected for full document reloads

The implementation uses Function.prototype.call to pass both arguments to dispatchFetch
while maintaining TypeScript compatibility, as the property accessor doesn't properly
expose the second parameter in TypeScript definitions.

Also adds .tryhydrogen.dev to Vite's allowedHosts for development testing.

References:
- cloudflare/workers-sdk#5018
- cloudflare/workers-sdk#5191

* Stabilize customer-account-push flag

- Changed from customer-account-push__unstable to customer-account-push
- Removed hidden: true to make flag visible in help
- Fixed typo: Oauth → OAuth in description
- Flag now works via CLI argument or SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH env var

* Fix MiniOxygen redirect handling for OAuth flows

Apply {redirect: 'manual'} to Miniflare's dispatchFetch calls to prevent automatic redirect following. This ensures external redirects (like OAuth) are passed to the browser instead of being followed internally.

Changes:
- Add redirect: 'manual' parameter to dispatchFetch in both worker and node environments
- Fix Headers.getSetCookie() usage for proper Set-Cookie header handling
- Add comprehensive tests for redirect behavior in both environments
- Stabilize customer-account-push CLI flag (remove __unstable prefix)

This fixes OAuth/PKCE authentication flows in React Router 7 where redirectDocument() and external redirects need to be handled by the browser, not the server.

* Add changeset for OAuth redirect fixes and stabilized CLI flag

* Fix intermittent CI test failures in MiniOxygen tests

- Use dynamic port allocation (port: 0) for all test servers to prevent EADDRINUSE errors
- Properly handle OS-assigned ports when using port 0
- Add server tracking and cleanup to ensure all servers are properly closed
- Fix proxy server test to use dynamic port allocation

This resolves race conditions and port conflicts that occur when tests run in parallel in CI environments.

* Fix TypeScript errors in MiniOxygen tests

- Change MiniOxygenOptions to MiniOxygenPreviewOptions in test files
- Add proper type imports for Request, Response, and DispatchFetch
- Add explicit types for onRequest callback parameters

This resolves TypeScript compilation errors that were failing CI.

* Update subscriptions recipe with account/subscriptions (#3124)

* Delete unused variable

---------

Co-authored-by: Kara Daviduik <105449131+kdaviduik@users.noreply.github.com>
Co-authored-by: Kara Daviduik <kara.daviduik@shopify.com>
juanpprieto added a commit to Shopify/hydrogen that referenced this pull request Sep 17, 2025
* Update package-lock.json for @shopify/cli dependency update

* [2025-07] Fix Monorepo RR7 CI build failures and improve reliability (#3091)

* fix: Complete React Router 7 migration for Express example

The Express example was partially migrated to React Router 7 but missing critical
configuration and dependencies, causing CI failures.

Changes:
- Add react-router.config.ts with proper preset and app directory configuration
- Fix vite.config.ts to call reactRouter() without arguments (RR7 API change)
- Add @react-router/dev as devDependency for TypeScript types
- Update entry.server.tsx to remove unnecessary @remix-run/web-fetch import
  (Node 20+ provides native Response globally)
- Fix environment variable loading using getEnv() helper
- Add .gitignore for React Router generated type files
- Update tsconfig.json to exclude generated directories

The example now builds successfully with React Router 7's framework mode.

* fix: Fix CLI build checks and TypeScript configuration

Multiple CLI-specific issues were causing CI failures after recent refactoring.

Changes:
- Fix build-check.mjs to expect .jsx extensions (tsup outputs .tsx→.jsx)
- Exclude assets/routes from TypeScript checking (template files for user projects)
- Align ast-grep to version 0.33.0 to match @shopify/cli's bundled version
- Fix isHydrogenMonorepo() detection to work in both dev and npm package contexts
- Add 'as const' assertions for ast-grep 0.33.0 API compatibility

Background:
- Template files were moved to assets/routes in May 2024 and inadvertently
  included in TypeScript scope
- ast-grep 0.34.1 conflicted with @shopify/cli's bundled 0.33.0

* fix: Fix CI workflow and monorepo build orchestration

The CI workflow and Turbo configuration had multiple issues causing intermittent
build failures, particularly the "No lockfile found" error.

Changes:
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK=false to typecheck step in CI
  (was only on build:all, but typecheck also triggers builds via Turbo)
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK to turbo.json globalEnv
- Add explicit build dependencies for all examples in turbo.json
- Remove docs-preview from workspaces to prevent React Router version conflicts
- Regenerate package-lock.json for dependency resolution

The root cause was that the typecheck step depends on build tasks (per turbo.json)
but wasn't receiving the lockfile check flag, causing skeleton builds to fail.
This has been a source of CI instability since the monorepo migration.

* chore: regenerate cookbook recipes with updated patch hashes

Regenerated all cookbook recipes to update patch file hashes after recent
changes to the skeleton template. This ensures the cookbook validation
passes in CI by keeping the patches in sync with the current state of
the skeleton template.

The regeneration updates:
- All patch files with new content hashes
- Recipe YAML files with updated patch references
- README and prompt files with current examples

This fixes the 'Validate Recipes' CI job failure.

* [2025-07] Fix React Context error during client-side hydration (#3101)

* Fix React Context errors in Vite dev server

This fixes "Cannot read properties of null (reading 'useContext')" errors that occur when React Context hooks are used in development mode.

Root Cause:
Vite's module federation can cause multiple React instances to be loaded when @shopify/hydrogen is served as an external module. React Context requires a single React instance to function properly - when multiple instances exist, Context providers from one instance cannot be consumed by hooks from another instance, resulting in null context values.

Solution:
1. Added resolve.dedupe for react, react-dom, and @shopify/hydrogen to ensure Vite uses a single instance of these packages
2. Modified optimizeDeps.include to conditionally optimize @shopify/hydrogen:
   - In production/regular projects: Optimize @shopify/hydrogen to prevent context errors
   - In monorepo development: Skip optimization to allow live reload of source changes

This maintains development workflow in the monorepo while fixing the production build issue.

* Fix React Context error during client-side hydration

Resolves 'Cannot read properties of null (reading useContext)' error
that occurred on first page load when using CSP with nonces.

The issue was caused by NonceProvider being present during SSR but
missing during client hydration, creating a React Context mismatch.

Changes:
- Export NonceProvider from @shopify/hydrogen for client-side usage
- Add NonceProvider wrapper to skeleton's entry.client.tsx
- Simplify Vite config to improve React Context stability

* Update Vitest from v1.0.4 to v3.2.4 across all packages (#3126)

* Update Vitest from v1.0.4 to v3.2.4 across all packages

- Upgrade vitest to ^3.2.4 in all 5 packages that use it
- Upgrade @vitest/coverage-v8 to ^3.2.4 to match vitest version
- Add vitest as devDependency to create-hydrogen package (was missing)
- Add explicit coverage provider configuration (required in v3+)
  - Set provider: 'v8' in cli and hydrogen-react vitest configs

Breaking change: Vitest v2+ requires explicit coverage provider config

* Fix Vitest v3 Mock type breaking changes

In Vitest v3, vi.fn() returns Mock<() => unknown> instead of Mock<any[], any>,
requiring explicit type assertions or type parameters for mocks with specific
return types.

Changes:
- Add type assertion for fetchWithServerCache mock in storefront.test.ts
- Simplify Promise creation in session mocks (Promise.resolve instead of new Promise)
- Fix Mock type usage in Image.test.tsx for console.warn assertions
- Add vitest/globals to tsconfig for packages using global test functions
- Keep jest types alongside vitest types for @testing-library/jest-dom compatibility

The stricter typing in v3 catches more potential issues at compile time but
requires updating existing mocks that relied on v1's permissive typing.

* Fix formatting

* [2025-06] Fix MiniOxygen/Miniflare v4 redirects handling + Stable --customer-account-push  flag (#3123)

* Fix MiniOxygen to support React Router's redirectDocument for external redirects

The Miniflare v4 update introduced a breaking change where dispatchFetch automatically
follows redirects internally, preventing external OAuth redirects from working properly.
React Router's redirectDocument() expects the browser to handle external redirects,
but Miniflare was intercepting and following them within the worker runtime.

This fix adds {redirect: 'manual'} to all dispatchFetch calls in MiniOxygen, which
prevents Miniflare from following redirects automatically. This ensures that:
- External redirects (like OAuth flows to Shopify's Customer Account API) are passed
  to the browser as intended
- React Router's redirectDocument() works correctly for cross-origin navigation
- The X-Remix-Reload-Document header is respected for full document reloads

The implementation uses Function.prototype.call to pass both arguments to dispatchFetch
while maintaining TypeScript compatibility, as the property accessor doesn't properly
expose the second parameter in TypeScript definitions.

Also adds .tryhydrogen.dev to Vite's allowedHosts for development testing.

References:
- cloudflare/workers-sdk#5018
- cloudflare/workers-sdk#5191

* Stabilize customer-account-push flag

- Changed from customer-account-push__unstable to customer-account-push
- Removed hidden: true to make flag visible in help
- Fixed typo: Oauth → OAuth in description
- Flag now works via CLI argument or SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH env var

* Fix MiniOxygen redirect handling for OAuth flows

Apply {redirect: 'manual'} to Miniflare's dispatchFetch calls to prevent automatic redirect following. This ensures external redirects (like OAuth) are passed to the browser instead of being followed internally.

Changes:
- Add redirect: 'manual' parameter to dispatchFetch in both worker and node environments
- Fix Headers.getSetCookie() usage for proper Set-Cookie header handling
- Add comprehensive tests for redirect behavior in both environments
- Stabilize customer-account-push CLI flag (remove __unstable prefix)

This fixes OAuth/PKCE authentication flows in React Router 7 where redirectDocument() and external redirects need to be handled by the browser, not the server.

* Add changeset for OAuth redirect fixes and stabilized CLI flag

* Fix intermittent CI test failures in MiniOxygen tests

- Use dynamic port allocation (port: 0) for all test servers to prevent EADDRINUSE errors
- Properly handle OS-assigned ports when using port 0
- Add server tracking and cleanup to ensure all servers are properly closed
- Fix proxy server test to use dynamic port allocation

This resolves race conditions and port conflicts that occur when tests run in parallel in CI environments.

* Fix TypeScript errors in MiniOxygen tests

- Change MiniOxygenOptions to MiniOxygenPreviewOptions in test files
- Add proper type imports for Request, Response, and DispatchFetch
- Add explicit types for onRequest callback parameters

This resolves TypeScript compilation errors that were failing CI.

* Update subscriptions recipe with account/subscriptions (#3124)

* Delete unused variable

* 2025-07 generated types

* Add cartGiftCardCodesRemove mutation support

- Add new cartGiftCardCodesRemove mutation handler for removing specific gift cards by ID
- Integrate removeGiftCardCodes method into cart handler
- Add GiftCardCodesRemove action to CartForm
- Update cart fragments to include appliedGiftCards.id field
- Implement gift card removal UI in skeleton template
- Maintain existing additive behavior for adding/updating gift cards
- Add tests for new mutation handler

* Fix linting issues: sort exports and remove duplicate imports

* Fix tests for cartGiftCardCodesRemove mutation support

* Add missing appliedGiftCards id field

* fixing up after rebase

* Undoing an accidental non-change from the rebase

* Merge branch 'main' into feat-cartGiftCardCodesRemove

Resolved conflicts:
- Deleted examples/{b2b,custom-cart-method,subscriptions}/app/lib/fragments.ts
  (examples moved to cookbook in main)
- Regenerated GraphQL schemas for hydrogen-react package

The id field for appliedGiftCards is preserved in skeleton template

* Update lock

* Update multipass recipe

* fix multipass

* Fix multipass recipe for gift card removal feature and enhance patch conflict detection

- Fix TypeScript import errors in account_.login.multipass.tsx by using standard React Router types instead of generated route types
- Regenerate all multipass recipe patches to work with the gift card removal feature added to cart.tsx
- Add comprehensive patch conflict detection to apply.ts and validate.ts that:
  - Detects .orig and .rej files created during patching
  - Shows rejected patch content for easier debugging
  - Provides clear instructions for resolving conflicts
  - Throws errors early to prevent confusing TypeScript errors
- Update enhanced error logging in validate.ts to properly decode Buffer outputs

This ensures the multipass recipe validates successfully in CI with the new cartGiftCardCodesRemove feature.

* fix: resolve cookbook recipe validation failures for custom-cart-method and metaobjects

- Regenerated all patches for both recipes to work with gift card removal feature
- Fixed incorrect shared patch file issue (both recipes had same hash but different content)
- Added human-readable descriptions to all recipe.yaml patch entries
- Both recipes now validate successfully in CI

The root cause was that the git card removal feature (cartGiftCardCodesRemove) changed
the cart.tsx structure, causing patch conflicts in fragments.ts for both recipes.

---------

Co-authored-by: Kara Daviduik <105449131+kdaviduik@users.noreply.github.com>
Co-authored-by: Kara Daviduik <kara.daviduik@shopify.com>
Co-authored-by: rbshop <rheese.burgess@shopify.com>
albertopasqualetto pushed a commit to albertopasqualetto/hydrogen-react-native that referenced this pull request Sep 18, 2025
* [2025-07] Update Storefront API and Customer Account API

## Summary
Updated both Storefront API and Customer Account API from version 2025-04 to 2025-07

## Changes
- Updated version constants in hydrogen-react and hydrogen packages
- Regenerated GraphQL types and schemas for both APIs
- Updated all hardcoded version references in documentation and tests
- Regenerated skeleton template types
- Created 6 GitHub issues for tracking API changes implementation

## API Changes Tracked
- #3076: Subscription discount data in Customer Account API
- #3077: Cart warnings for non-applicable discount codes
- #3078: BUYER_CANNOT_PURCHASE_FOR_COMPANY_LOCATION cart error
- #3079: New order filter options in Customer Account API
- #3080: Imperial units in UnitPriceMeasurement
- #3081: Selling plan error handling in Cart mutations

## Validation
- TypeScript: ✅ No errors
- Tests: ✅ All passing
- Lint: ⚠️ 2 warnings (non-blocking import duplicates)
- Build: ✅ Successful

* Update skeleton @shopify/cli dependency to latest version

- Update from ~3.80.4 to ~3.83.3
- Include in changeset documentation

* Update package-lock.json for @shopify/cli dependency update

* [2025-07] Fix Monorepo RR7 CI build failures and improve reliability (#3091)

* fix: Complete React Router 7 migration for Express example

The Express example was partially migrated to React Router 7 but missing critical
configuration and dependencies, causing CI failures.

Changes:
- Add react-router.config.ts with proper preset and app directory configuration
- Fix vite.config.ts to call reactRouter() without arguments (RR7 API change)
- Add @react-router/dev as devDependency for TypeScript types
- Update entry.server.tsx to remove unnecessary @remix-run/web-fetch import
  (Node 20+ provides native Response globally)
- Fix environment variable loading using getEnv() helper
- Add .gitignore for React Router generated type files
- Update tsconfig.json to exclude generated directories

The example now builds successfully with React Router 7's framework mode.

* fix: Fix CLI build checks and TypeScript configuration

Multiple CLI-specific issues were causing CI failures after recent refactoring.

Changes:
- Fix build-check.mjs to expect .jsx extensions (tsup outputs .tsx→.jsx)
- Exclude assets/routes from TypeScript checking (template files for user projects)
- Align ast-grep to version 0.33.0 to match @shopify/cli's bundled version
- Fix isHydrogenMonorepo() detection to work in both dev and npm package contexts
- Add 'as const' assertions for ast-grep 0.33.0 API compatibility

Background:
- Template files were moved to assets/routes in May 2024 and inadvertently
  included in TypeScript scope
- ast-grep 0.34.1 conflicted with @shopify/cli's bundled 0.33.0

* fix: Fix CI workflow and monorepo build orchestration

The CI workflow and Turbo configuration had multiple issues causing intermittent
build failures, particularly the "No lockfile found" error.

Changes:
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK=false to typecheck step in CI
  (was only on build:all, but typecheck also triggers builds via Turbo)
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK to turbo.json globalEnv
- Add explicit build dependencies for all examples in turbo.json
- Remove docs-preview from workspaces to prevent React Router version conflicts
- Regenerate package-lock.json for dependency resolution

The root cause was that the typecheck step depends on build tasks (per turbo.json)
but wasn't receiving the lockfile check flag, causing skeleton builds to fail.
This has been a source of CI instability since the monorepo migration.

* [2025-07] Fix Money component compatibility with Customer Account API USDC currency (#3090)

* Fix Money component compatibility with Customer Account API USDC currency

The 2025-07 API update introduced USDC currency code to Customer Account API but not Storefront API, causing TypeScript errors and runtime failures.

Changes:
- Update Money component to accept MoneyV2 from both Storefront and Customer Account APIs via union types
- Enhance useMoney hook to detect unsupported currency codes (like USDC) and gracefully fall back to decimal formatting
- Add currency code suffix for unsupported currencies (e.g., "100.00 USDC") to maintain clarity
- Default to 2 decimal places for USDC to reinforce its 1:1 USD peg based on industry standards

Technical details:
- Handle Intl.NumberFormat RangeError for cryptocurrency codes not in ISO 4217
- Add comprehensive test coverage for both API types and USDC formatting
- Update TypeScript types to support both CurrencyCode enums

Fixes #3089

* Add changeset for Money component USDC compatibility fix

* Add build script to copy customer-account-api-types to dist

Since our Money component now imports from customer-account-api-types, we need to ensure this file is copied to the dist folder during the build process. Previously, only storefront-api-types was being copied.

- Replace copy-storefront-types with copy-api-types script that copies both API type files
- Update build and dev:demo scripts to use the new copy-api-types script
- This fixes the CI build failure where customer-account-api-types.d.ts was not found in dist

* Trigger CI rebuild

* chore: ignore tsup bundled config build artifacts

During the build process, tsup creates temporary bundled configuration files
(tsup.config.bundled_*.mjs) in each package directory. These are generated
artifacts that should not be tracked in version control.

These files:
- Are created when running 'npm run build:all' or similar build commands
- Contain bundled versions of tsup.config.ts files for build execution
- Have random hash suffixes (e.g., tsup.config.bundled_jt705ss6fz.mjs)
- Should be cleaned up automatically but sometimes persist

Adding the pattern '**/tsup.config.bundled_*.mjs' to gitignore prevents
these temporary build artifacts from cluttering git status and being
accidentally committed.

* fix: add missing TypeScript type definitions for cookbook dependencies

Added @types/inquirer and @types/yargs to cookbook devDependencies to resolve
TypeScript compilation errors when running cookbook commands.

This fixes the TS7016 error: 'Could not find a declaration file for module inquirer'
that occurs when running cookbook commands like 'npm run cookbook -- regenerate'
on fresh branches or after clean installs.

* chore: regenerate cookbook recipes with updated patch hashes

Regenerated all cookbook recipes to update patch file hashes after recent
changes to the skeleton template. This ensures the cookbook validation
passes in CI by keeping the patches in sync with the current state of
the skeleton template.

The regeneration updates:
- All patch files with new content hashes
- Recipe YAML files with updated patch references
- README and prompt files with current examples

This fixes the 'Validate Recipes' CI job failure.

* fix: Add lockfile check bypass to cookbook validation in CI

The cookbook validation was failing because the skeleton template
intentionally doesn't include a lockfile (templates shouldn't have
lockfiles), but the hydrogen build command validates lockfile presence
by default.

This fix adds SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK=false to the
cookbook validation step, consistent with how other CI build tasks
handle this requirement.

* fix: Remove unnecessary cli-hydrogen dependency from root package.json

The @shopify/cli-hydrogen dependency in the root package.json was causing
npm to incorrectly attempt to run scripts in all workspace packages when
executing root-level scripts like 'npm run build:pkg'. This resulted in
confusing error messages when npm tried to run 'build:pkg' in packages
that don't have that script defined (e.g., hydrogen-react).

This dependency was likely added accidentally during the v3_routeConfig
changes in March 2025 (commit 74ef1ba7d4) but serves no actual purpose:

- The root package doesn't use cli-hydrogen directly
- Turbo.json already manages build dependencies correctly
- Workspace packages are linked automatically by npm workspaces
- The skeleton template correctly uses @shopify/cli (which bundles
  cli-hydrogen internally)

Removing this dependency:
- Eliminates the 'Missing script: build:pkg' error messages
- Prevents npm from unnecessarily propagating script execution
- Maintains all existing functionality (builds still work correctly)
- Simplifies the dependency tree

The actual build process through Turbo remains unchanged and continues
to work as expected.

* Suggested money changes for PR #3090 (#3097)

* Support imperial units in UnitPriceMeasurement (#3107)

* Support imperial units in UnitPriceMeasurement

* remove unnecessary changeset

* Use count instead of dimension, which doesn't exist

* Don't commit claude settings in this PR to avoid cluttering the branch

* [2025-07] Fix React Context error during client-side hydration (#3101)

* Fix React Context errors in Vite dev server

This fixes "Cannot read properties of null (reading 'useContext')" errors that occur when React Context hooks are used in development mode.

Root Cause:
Vite's module federation can cause multiple React instances to be loaded when @shopify/hydrogen is served as an external module. React Context requires a single React instance to function properly - when multiple instances exist, Context providers from one instance cannot be consumed by hooks from another instance, resulting in null context values.

Solution:
1. Added resolve.dedupe for react, react-dom, and @shopify/hydrogen to ensure Vite uses a single instance of these packages
2. Modified optimizeDeps.include to conditionally optimize @shopify/hydrogen:
   - In production/regular projects: Optimize @shopify/hydrogen to prevent context errors
   - In monorepo development: Skip optimization to allow live reload of source changes

This maintains development workflow in the monorepo while fixing the production build issue.

* Fix React Context error during client-side hydration

Resolves 'Cannot read properties of null (reading useContext)' error
that occurred on first page load when using CSP with nonces.

The issue was caused by NonceProvider being present during SSR but
missing during client hydration, creating a React Context mismatch.

Changes:
- Export NonceProvider from @shopify/hydrogen for client-side usage
- Add NonceProvider wrapper to skeleton's entry.client.tsx
- Simplify Vite config to improve React Context stability

* [2025-07] Display new Cart warnings in skeleton template (#3084)

* [2025-07] Display all cart warnings with user-friendly messages (fixes #3077, #3085)

* Remove CartWarning fragment from cart query - only available in mutations

* Add support for all cart user error types in skeleton template (#3121)

The Hydrogen cart handler's return type includes a union of three possible
user error types: CartUserError, MetafieldsSetUserError, and
MetafieldDeleteUserError. While the skeleton template currently only handles
non-metafield operations, the TypeScript types from the cart handler don't
narrow based on the specific operation performed.

This change updates the CartUserErrors, CartMain, and CartSummary components
to accept all three error types, resolving TypeScript errors and ensuring
the components are compatible with any cart operation that might be added
in the future.

* Update Vitest from v1.0.4 to v3.2.4 across all packages (#3126)

* Update Vitest from v1.0.4 to v3.2.4 across all packages

- Upgrade vitest to ^3.2.4 in all 5 packages that use it
- Upgrade @vitest/coverage-v8 to ^3.2.4 to match vitest version
- Add vitest as devDependency to create-hydrogen package (was missing)
- Add explicit coverage provider configuration (required in v3+)
  - Set provider: 'v8' in cli and hydrogen-react vitest configs

Breaking change: Vitest v2+ requires explicit coverage provider config

* Fix Vitest v3 Mock type breaking changes

In Vitest v3, vi.fn() returns Mock<() => unknown> instead of Mock<any[], any>,
requiring explicit type assertions or type parameters for mocks with specific
return types.

Changes:
- Add type assertion for fetchWithServerCache mock in storefront.test.ts
- Simplify Promise creation in session mocks (Promise.resolve instead of new Promise)
- Fix Mock type usage in Image.test.tsx for console.warn assertions
- Add vitest/globals to tsconfig for packages using global test functions
- Keep jest types alongside vitest types for @testing-library/jest-dom compatibility

The stricter typing in v3 catches more potential issues at compile time but
requires updating existing mocks that relied on v1's permissive typing.

* Fix formatting

* Add CODEOWNERS file to automatically request team's review on non-draft PRs (#3133)

* [2025-06] Fix MiniOxygen/Miniflare v4 redirects handling + Stable --customer-account-push  flag (#3123)

* Fix MiniOxygen to support React Router's redirectDocument for external redirects

The Miniflare v4 update introduced a breaking change where dispatchFetch automatically
follows redirects internally, preventing external OAuth redirects from working properly.
React Router's redirectDocument() expects the browser to handle external redirects,
but Miniflare was intercepting and following them within the worker runtime.

This fix adds {redirect: 'manual'} to all dispatchFetch calls in MiniOxygen, which
prevents Miniflare from following redirects automatically. This ensures that:
- External redirects (like OAuth flows to Shopify's Customer Account API) are passed
  to the browser as intended
- React Router's redirectDocument() works correctly for cross-origin navigation
- The X-Remix-Reload-Document header is respected for full document reloads

The implementation uses Function.prototype.call to pass both arguments to dispatchFetch
while maintaining TypeScript compatibility, as the property accessor doesn't properly
expose the second parameter in TypeScript definitions.

Also adds .tryhydrogen.dev to Vite's allowedHosts for development testing.

References:
- cloudflare/workers-sdk#5018
- cloudflare/workers-sdk#5191

* Stabilize customer-account-push flag

- Changed from customer-account-push__unstable to customer-account-push
- Removed hidden: true to make flag visible in help
- Fixed typo: Oauth → OAuth in description
- Flag now works via CLI argument or SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH env var

* Fix MiniOxygen redirect handling for OAuth flows

Apply {redirect: 'manual'} to Miniflare's dispatchFetch calls to prevent automatic redirect following. This ensures external redirects (like OAuth) are passed to the browser instead of being followed internally.

Changes:
- Add redirect: 'manual' parameter to dispatchFetch in both worker and node environments
- Fix Headers.getSetCookie() usage for proper Set-Cookie header handling
- Add comprehensive tests for redirect behavior in both environments
- Stabilize customer-account-push CLI flag (remove __unstable prefix)

This fixes OAuth/PKCE authentication flows in React Router 7 where redirectDocument() and external redirects need to be handled by the browser, not the server.

* Add changeset for OAuth redirect fixes and stabilized CLI flag

* Fix intermittent CI test failures in MiniOxygen tests

- Use dynamic port allocation (port: 0) for all test servers to prevent EADDRINUSE errors
- Properly handle OS-assigned ports when using port 0
- Add server tracking and cleanup to ensure all servers are properly closed
- Fix proxy server test to use dynamic port allocation

This resolves race conditions and port conflicts that occur when tests run in parallel in CI environments.

* Fix TypeScript errors in MiniOxygen tests

- Change MiniOxygenOptions to MiniOxygenPreviewOptions in test files
- Add proper type imports for Request, Response, and DispatchFetch
- Add explicit types for onRequest callback parameters

This resolves TypeScript compilation errors that were failing CI.

* Update subscriptions recipe with account/subscriptions (#3124)

* Delete unused variable

---------

Co-authored-by: Kara Daviduik <105449131+kdaviduik@users.noreply.github.com>
Co-authored-by: Kara Daviduik <kara.daviduik@shopify.com>
albertopasqualetto pushed a commit to albertopasqualetto/hydrogen-react-native that referenced this pull request Sep 18, 2025
* Update package-lock.json for @shopify/cli dependency update

* [2025-07] Fix Monorepo RR7 CI build failures and improve reliability (#3091)

* fix: Complete React Router 7 migration for Express example

The Express example was partially migrated to React Router 7 but missing critical
configuration and dependencies, causing CI failures.

Changes:
- Add react-router.config.ts with proper preset and app directory configuration
- Fix vite.config.ts to call reactRouter() without arguments (RR7 API change)
- Add @react-router/dev as devDependency for TypeScript types
- Update entry.server.tsx to remove unnecessary @remix-run/web-fetch import
  (Node 20+ provides native Response globally)
- Fix environment variable loading using getEnv() helper
- Add .gitignore for React Router generated type files
- Update tsconfig.json to exclude generated directories

The example now builds successfully with React Router 7's framework mode.

* fix: Fix CLI build checks and TypeScript configuration

Multiple CLI-specific issues were causing CI failures after recent refactoring.

Changes:
- Fix build-check.mjs to expect .jsx extensions (tsup outputs .tsx→.jsx)
- Exclude assets/routes from TypeScript checking (template files for user projects)
- Align ast-grep to version 0.33.0 to match @shopify/cli's bundled version
- Fix isHydrogenMonorepo() detection to work in both dev and npm package contexts
- Add 'as const' assertions for ast-grep 0.33.0 API compatibility

Background:
- Template files were moved to assets/routes in May 2024 and inadvertently
  included in TypeScript scope
- ast-grep 0.34.1 conflicted with @shopify/cli's bundled 0.33.0

* fix: Fix CI workflow and monorepo build orchestration

The CI workflow and Turbo configuration had multiple issues causing intermittent
build failures, particularly the "No lockfile found" error.

Changes:
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK=false to typecheck step in CI
  (was only on build:all, but typecheck also triggers builds via Turbo)
- Add SHOPIFY_HYDROGEN_FLAG_LOCKFILE_CHECK to turbo.json globalEnv
- Add explicit build dependencies for all examples in turbo.json
- Remove docs-preview from workspaces to prevent React Router version conflicts
- Regenerate package-lock.json for dependency resolution

The root cause was that the typecheck step depends on build tasks (per turbo.json)
but wasn't receiving the lockfile check flag, causing skeleton builds to fail.
This has been a source of CI instability since the monorepo migration.

* chore: regenerate cookbook recipes with updated patch hashes

Regenerated all cookbook recipes to update patch file hashes after recent
changes to the skeleton template. This ensures the cookbook validation
passes in CI by keeping the patches in sync with the current state of
the skeleton template.

The regeneration updates:
- All patch files with new content hashes
- Recipe YAML files with updated patch references
- README and prompt files with current examples

This fixes the 'Validate Recipes' CI job failure.

* [2025-07] Fix React Context error during client-side hydration (#3101)

* Fix React Context errors in Vite dev server

This fixes "Cannot read properties of null (reading 'useContext')" errors that occur when React Context hooks are used in development mode.

Root Cause:
Vite's module federation can cause multiple React instances to be loaded when @shopify/hydrogen is served as an external module. React Context requires a single React instance to function properly - when multiple instances exist, Context providers from one instance cannot be consumed by hooks from another instance, resulting in null context values.

Solution:
1. Added resolve.dedupe for react, react-dom, and @shopify/hydrogen to ensure Vite uses a single instance of these packages
2. Modified optimizeDeps.include to conditionally optimize @shopify/hydrogen:
   - In production/regular projects: Optimize @shopify/hydrogen to prevent context errors
   - In monorepo development: Skip optimization to allow live reload of source changes

This maintains development workflow in the monorepo while fixing the production build issue.

* Fix React Context error during client-side hydration

Resolves 'Cannot read properties of null (reading useContext)' error
that occurred on first page load when using CSP with nonces.

The issue was caused by NonceProvider being present during SSR but
missing during client hydration, creating a React Context mismatch.

Changes:
- Export NonceProvider from @shopify/hydrogen for client-side usage
- Add NonceProvider wrapper to skeleton's entry.client.tsx
- Simplify Vite config to improve React Context stability

* Update Vitest from v1.0.4 to v3.2.4 across all packages (#3126)

* Update Vitest from v1.0.4 to v3.2.4 across all packages

- Upgrade vitest to ^3.2.4 in all 5 packages that use it
- Upgrade @vitest/coverage-v8 to ^3.2.4 to match vitest version
- Add vitest as devDependency to create-hydrogen package (was missing)
- Add explicit coverage provider configuration (required in v3+)
  - Set provider: 'v8' in cli and hydrogen-react vitest configs

Breaking change: Vitest v2+ requires explicit coverage provider config

* Fix Vitest v3 Mock type breaking changes

In Vitest v3, vi.fn() returns Mock<() => unknown> instead of Mock<any[], any>,
requiring explicit type assertions or type parameters for mocks with specific
return types.

Changes:
- Add type assertion for fetchWithServerCache mock in storefront.test.ts
- Simplify Promise creation in session mocks (Promise.resolve instead of new Promise)
- Fix Mock type usage in Image.test.tsx for console.warn assertions
- Add vitest/globals to tsconfig for packages using global test functions
- Keep jest types alongside vitest types for @testing-library/jest-dom compatibility

The stricter typing in v3 catches more potential issues at compile time but
requires updating existing mocks that relied on v1's permissive typing.

* Fix formatting

* [2025-06] Fix MiniOxygen/Miniflare v4 redirects handling + Stable --customer-account-push  flag (#3123)

* Fix MiniOxygen to support React Router's redirectDocument for external redirects

The Miniflare v4 update introduced a breaking change where dispatchFetch automatically
follows redirects internally, preventing external OAuth redirects from working properly.
React Router's redirectDocument() expects the browser to handle external redirects,
but Miniflare was intercepting and following them within the worker runtime.

This fix adds {redirect: 'manual'} to all dispatchFetch calls in MiniOxygen, which
prevents Miniflare from following redirects automatically. This ensures that:
- External redirects (like OAuth flows to Shopify's Customer Account API) are passed
  to the browser as intended
- React Router's redirectDocument() works correctly for cross-origin navigation
- The X-Remix-Reload-Document header is respected for full document reloads

The implementation uses Function.prototype.call to pass both arguments to dispatchFetch
while maintaining TypeScript compatibility, as the property accessor doesn't properly
expose the second parameter in TypeScript definitions.

Also adds .tryhydrogen.dev to Vite's allowedHosts for development testing.

References:
- cloudflare/workers-sdk#5018
- cloudflare/workers-sdk#5191

* Stabilize customer-account-push flag

- Changed from customer-account-push__unstable to customer-account-push
- Removed hidden: true to make flag visible in help
- Fixed typo: Oauth → OAuth in description
- Flag now works via CLI argument or SHOPIFY_HYDROGEN_FLAG_CUSTOMER_ACCOUNT_PUSH env var

* Fix MiniOxygen redirect handling for OAuth flows

Apply {redirect: 'manual'} to Miniflare's dispatchFetch calls to prevent automatic redirect following. This ensures external redirects (like OAuth) are passed to the browser instead of being followed internally.

Changes:
- Add redirect: 'manual' parameter to dispatchFetch in both worker and node environments
- Fix Headers.getSetCookie() usage for proper Set-Cookie header handling
- Add comprehensive tests for redirect behavior in both environments
- Stabilize customer-account-push CLI flag (remove __unstable prefix)

This fixes OAuth/PKCE authentication flows in React Router 7 where redirectDocument() and external redirects need to be handled by the browser, not the server.

* Add changeset for OAuth redirect fixes and stabilized CLI flag

* Fix intermittent CI test failures in MiniOxygen tests

- Use dynamic port allocation (port: 0) for all test servers to prevent EADDRINUSE errors
- Properly handle OS-assigned ports when using port 0
- Add server tracking and cleanup to ensure all servers are properly closed
- Fix proxy server test to use dynamic port allocation

This resolves race conditions and port conflicts that occur when tests run in parallel in CI environments.

* Fix TypeScript errors in MiniOxygen tests

- Change MiniOxygenOptions to MiniOxygenPreviewOptions in test files
- Add proper type imports for Request, Response, and DispatchFetch
- Add explicit types for onRequest callback parameters

This resolves TypeScript compilation errors that were failing CI.

* Update subscriptions recipe with account/subscriptions (#3124)

* Delete unused variable

* 2025-07 generated types

* Add cartGiftCardCodesRemove mutation support

- Add new cartGiftCardCodesRemove mutation handler for removing specific gift cards by ID
- Integrate removeGiftCardCodes method into cart handler
- Add GiftCardCodesRemove action to CartForm
- Update cart fragments to include appliedGiftCards.id field
- Implement gift card removal UI in skeleton template
- Maintain existing additive behavior for adding/updating gift cards
- Add tests for new mutation handler

* Fix linting issues: sort exports and remove duplicate imports

* Fix tests for cartGiftCardCodesRemove mutation support

* Add missing appliedGiftCards id field

* fixing up after rebase

* Undoing an accidental non-change from the rebase

* Merge branch 'main' into feat-cartGiftCardCodesRemove

Resolved conflicts:
- Deleted examples/{b2b,custom-cart-method,subscriptions}/app/lib/fragments.ts
  (examples moved to cookbook in main)
- Regenerated GraphQL schemas for hydrogen-react package

The id field for appliedGiftCards is preserved in skeleton template

* Update lock

* Update multipass recipe

* fix multipass

* Fix multipass recipe for gift card removal feature and enhance patch conflict detection

- Fix TypeScript import errors in account_.login.multipass.tsx by using standard React Router types instead of generated route types
- Regenerate all multipass recipe patches to work with the gift card removal feature added to cart.tsx
- Add comprehensive patch conflict detection to apply.ts and validate.ts that:
  - Detects .orig and .rej files created during patching
  - Shows rejected patch content for easier debugging
  - Provides clear instructions for resolving conflicts
  - Throws errors early to prevent confusing TypeScript errors
- Update enhanced error logging in validate.ts to properly decode Buffer outputs

This ensures the multipass recipe validates successfully in CI with the new cartGiftCardCodesRemove feature.

* fix: resolve cookbook recipe validation failures for custom-cart-method and metaobjects

- Regenerated all patches for both recipes to work with gift card removal feature
- Fixed incorrect shared patch file issue (both recipes had same hash but different content)
- Added human-readable descriptions to all recipe.yaml patch entries
- Both recipes now validate successfully in CI

The root cause was that the git card removal feature (cartGiftCardCodesRemove) changed
the cart.tsx structure, causing patch conflicts in fragments.ts for both recipes.

---------

Co-authored-by: Kara Daviduik <105449131+kdaviduik@users.noreply.github.com>
Co-authored-by: Kara Daviduik <kara.daviduik@shopify.com>
Co-authored-by: rbshop <rheese.burgess@shopify.com>
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.

🐛 BUG: does Miniflare.dispatchFetch handle redirect Response from worker script?

2 participants