feat: release 4.6.0 (graduate dev → main) - #3455
Conversation
Avoid wiping cart items after Quick Order by omitting stale session `sc` on the initial orderForm GET and adopting the orderForm SC when the cart etag is stale. Also defer client validateCart until the first validateSession completes.
Align the unit test path with the commerce/index.ts source module.
Extract SC adoption glue to reduce cognitive complexity, flatten nested template literals in checkout.orderForm, and narrow the cartSalesChannel test without a type assertion.
Extract the session-wait helper so unit tests can exercise immediate, subscribe, race, and timeout paths under the Quality Gate threshold.
This reverts commit d5be27c.
Prevent permanent 404 caching when Search/stock gaps cause the first generation (often via prefetch) to miss a product that later becomes available.
## What's the purpose of this pull request? Restores the `account, path, port` positional argument order on the `faststore dev` command, matching `build` (`account, path`), `serve` (`account, path, port`) and the [FastStore Platform Spec](https://github.com/vtex/faststore-platform/blob/main/docs/specification.md). The inversion was an unintended side effect of the oclif migration in #3111: `static args` went from an array to an object, and since positional order now follows key order, `path` ended up ahead of `account` — on `dev` only. `build` and `serve` were migrated in the same commit and kept the original order (introduced deliberately in #2491 to comply with the spec). The impact is on the FastStore Platform CLI, which calls the module commands positionally: ```ts // vtex/faststore-platform packages/cli/src/commands/dev.ts return dev.run([account, path, port?.toString() ?? '']) ``` With the current v4 order, the account name lands in `args.path`, so `getBasePath()` resolves the base path to a directory named after the account. `build.run([account, path])` and `serve.run([account, path, port])` are unaffected because those commands kept the correct order. ## Is this a breaking change? No known consumer depends on the current v4 order: - **Stores:** a code search for `"faststore dev"` in `package.json` across GitHub returns 50+ stores, all using `"dev": "faststore dev"` with no positional arguments. Since all three args are optional, those are unaffected. - **Programmatic callers:** searching for `loadedCli` across the `vtex` org returns only `vtex/faststore-platform`, which already uses the spec order for `dev`, `build` and `serve`. - **This monorepo:** nothing invokes `faststore dev` with positional arguments. `@faststore/core`'s `dev` script is `next dev`, and the internal spawns inside `dev.ts` target `generate-types`, `cache-graphql` and `generate-i18n` with an explicit `basePath`. - **CI/CD:** pipelines run `build` and `serve`, never `dev`. Passing a path as the single positional (`faststore dev ./store`) never worked on v3 either, since `account` has always been the first argument there. `account` remains a noop — `run()` only reads `args.path` and `args.port` — so this changes nothing beyond the positional mapping. ## How to test it? Install the version generated by the codesandbox check in a monorepo store and run `fsp dev <account>`. The dev server should start at the module path declared in `faststore.json` instead of failing to resolve a directory named after the account. For a single store, `yarn dev` (i.e. `faststore dev` with no arguments) should behave exactly as before. ## References - Spec: https://github.com/vtex/faststore-platform/blob/main/docs/specification.md - Order introduced in #2491 - Order accidentally inverted in #3111 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated the `faststore dev` command documentation to list `ACCOUNT` before `PATH`. * Revised the command usage, heading, index, and argument descriptions. * **Bug Fixes** * Corrected positional argument ordering for the `faststore dev` command: `ACCOUNT`, `PATH`, then `PORT`. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Cursor <cursoragent@cursor.com>
Testing OTEL without `@vtex/diagnostics-nodejs` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added OpenTelemetry-based tracing for GraphQL with per-request root spans. * Enabled OTLP trace and log exporting, including automatic log capture from console. * Increased default trace sampling rate. * **Bug Fixes** * More consistent resolver span lifecycle and error reporting for both sync and async failures. * **Chores** * Updated analytics service naming and simplified telemetry enablement configuration. * **Tests** * Updated telemetry mocks and integration/unit tests. <!-- end of auto-generated comment: release notes by coderabbit.ai --> [SFS-3279](https://vtex-dev.atlassian.net/browse/SFS-3279) [SFS-3219](https://vtex-dev.atlassian.net/browse/SFS-3139) [SFS-3279]: https://vtex-dev.atlassian.net/browse/SFS-3279?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [SFS-3219]: https://vtex-dev.atlassian.net/browse/SFS-3219?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
…endations Move the VRN parsing, anonymous user id and recommendations query out of the RecommendationShelf section and into a headless SDK module, orchestrated by a new useRecommendationShelf() hook. The section becomes a presentation-only component that consumes the hook. No behavior change: the campaign rules, the CMS opt-in gate and the error handling are the same code, only relocated.
The previous wording claimed no personalization cookie is read when the opt-in is off. The cookie lookup is not gated (and was not before this refactor), so describe what actually happens: the campaign is never requested and the resolved user id goes unused.
Vitest 4.0.7 times out starting fork workers under CI load (5s limit), which made @faststore/core#test fail the CD run even though all assertions passed. 4.0.9+ raises the worker start timeout; align the catalog (and @faststore/api) on 4.0.18.
core#generate shells out to the CLI binary; without compiling @faststore/cli first the sync job fails and never opens the PR.
# Conflicts: # CHANGELOG.md # lerna.json # packages/api/CHANGELOG.md # packages/api/package.json # packages/cli/CHANGELOG.md # packages/cli/package.json # packages/components/CHANGELOG.md # packages/components/package.json # packages/core/CHANGELOG.md # packages/core/package.json # packages/diagnostics/CHANGELOG.md # packages/diagnostics/package.json # packages/lighthouse/CHANGELOG.md # packages/lighthouse/package.json # packages/sdk/CHANGELOG.md # packages/sdk/package.json # packages/storybook/CHANGELOG.md # packages/storybook/package.json # packages/ui/CHANGELOG.md # packages/ui/package.json
dev was already ahead of the 4.5.1 stable hotfix; do not downgrade the prerelease cycle when syncing main into dev.
Stop refetching Checkout with a lagging session SC on later validations, which wiped Quick Order items one request after the first preserve/adopt. Expose optional StoreOrder.salesChannel when SC was adopted from a stale cart.
Keep Checkout on the orderForm trade policy when session SC lags, return the adopted SC from validateCart, and silently align fs::session so later requests use the correct channel without revalidating the cart mid-flight.
Lower validateCart/validateSession cognitive complexity, guard non-object channel JSON before syncing adopted SC, and add coverage for the new paths.
Extract session helpers into a dedicated util and add unit tests so the validateSession refactor no longer tanks Coverage on New Code.
## What's the purpose of this pull request?
On Windows, custom GraphQL type definitions placed in
`src/graphql/**/typeDefs/*.graphql` are silently dropped when the CLI
merges the store's GraphQL schema. Any custom Query/Mutation extension
is missing from the merged schema, and codegen fails with:
```
Cannot query field "<customField>" on type "Query"
```
There is no warning that the typeDefs folder was skipped, which makes
this very hard to debug — the schema extension guide works on
macOS/Linux but fails on Windows with no indication why.
## How it works?
`getTypeDefsFromFolder` (`packages/cli/src/utils/generate-types.ts`)
builds the globby pattern with `path.join(...)`. On Windows this
produces backslash-separated paths, and globby/fast-glob treat `\` in
patterns as an escape character, not a path separator (documented globby
behavior — patterns must always use forward slashes). The pattern
therefore matches nothing and the custom typeDefs never reach
`mergeTypeDefs`.
The fix normalizes the joined path with globby's own
`convertPathToPattern` helper before calling `globbySync`. This is a
no-op on POSIX systems and also handles glob-special characters in the
path (e.g. parentheses in a user's directory name). The helper is now
exported so it can be unit-tested, and a unit test with a real on-disk
fixture is added — on Windows it fails without the fix (globby returns
`[]`) and passes with it.
## How to test it?
- On a Windows machine, scaffold a store with a custom schema extension,
e.g. `src/graphql/thirdParty/typeDefs/hello.graphql` (`extend type Query
{ hello: String! }`) with a matching resolver, add a query using the new
field, and run `faststore generate`.
- Before this change: codegen fails with `Cannot query field "hello" on
type "Query"`.
- After this change: the typeDefs are merged and codegen succeeds (same
as on macOS/Linux).
- Unit test: `packages/cli/src/utils/generate-types.test.ts` (`pnpm exec
vitest run src/utils/generate-types.test.ts` in `packages/cli`).
**How it was tested:**
- Windows 11 / Node 24:
- New unit test fails before the fix (globby returns an empty array) and
passes after it — verified in both directions.
- `pnpm turbo run build --filter "@faststore/cli..."` passes.
- Full CLI vitest suite: 101 passed; the 5 remaining failures are
pre-existing Windows-environment issues in unrelated test files
(temp-dir `EPERM` cleanup, symlink privileges, backslash comparisons in
`cp-schema` tests) and are untouched by this change.
- Real-world verification on Windows 11 in a production FastStore 4.4.0
storefront with custom typeDefs (`src/graphql/thirdParty`): with the
unpatched CLI, `faststore generate` fails with `Cannot query field
"storeBrands" on type "Query"`; with exactly this normalization applied
to the installed CLI bundle, `faststore generate` and `tsc --noEmit`
both pass.
- Linux/macOS: no behavior change expected (the normalization is a no-op
on POSIX); CI should confirm.
## References
- globby / fast-glob pattern syntax: backslash is an escape character in
patterns; Windows paths must be converted to forward slashes
(`convertPathToPattern` exists for exactly this purpose):
https://github.com/sindresorhus/globby#api /
https://github.com/mrmlnc/fast-glob#how-to-write-patterns-on-windows
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved GraphQL type definition discovery by generating
forward-slash-safe glob patterns (including Windows-compatible path
handling).
* Ensures type generation returns an empty result when the requested
custom folder contains no matching `.graphql` files.
* **Tests**
* Expanded test coverage with an additional fixture where the root path
includes glob-special characters.
* Added assertions confirming type definition parsing still returns the
expected single document and that the empty-folder scenario is handled
correctly.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Fanny Chien <fanny.chien@vtex.com>
Keep the successful PDP ISR window independent so a long revalidate does not freeze transient 404s.
…#3440) ## What's the purpose of this pull request? The generated `.faststore` package has no `node_modules` of its own (`node_modules` is in the generate step's `ignorePaths`, and nothing installs dependencies in there). The scripts we inject into `.faststore/package.json` do rely on binaries, though: ``` 'dev-only': 'next dev --webpack', predev: 'na run partytown', prebuild: 'na run partytown', ``` Those binaries only exist in the `node_modules/.bin` of an ancestor directory — the store root or, on hoisted monorepos, the workspace root. We spawn all three scripts with `cwd` pointing at `.faststore` and never add those directories to `PATH`: `runCommandSync` calls `execSync` with `cwd` only, and the `spawn`/`spawnSync` calls pass `env` without touching `PATH`. On native Windows with a monorepo this fails outright: ``` yarn.cmd predev 'na' is not recognized as an internal command yarn.cmd dev-only --port 3001 'next' is not recognized as an internal command ``` This PR adds a `withNodeModulesBins` helper that walks up from `.faststore` collecting every existing `node_modules/.bin` and prepends them to `PATH`, and wires it into the four places that run a script inside `.faststore`: `predev` and `dev-only` in `dev`, `run build` in `build`, and `run test:e2e` in `test`. Note that `build` is affected for the same reason (`prebuild: 'na run partytown'`), so fixing only `dev` would leave `faststore build` broken on the same setups. `test` runs the `test:e2e` script inherited from `@faststore/core` (`cypress open`), which has the same gap. ## Implementation notes - **Nearest ancestor wins.** A dependency installed at the store level takes precedence over the workspace root one. This mirrors what npm/yarn already do when running a script. - **Reordering, not just prepending.** Package managers already put some of these directories in `PATH` when they run a script, so the helper cannot simply prepend the missing ones: doing that would let a workspace-root binary that was absent from `PATH` jump ahead of the store-level one that was already there, inverting the precedence above. It removes every discovered bin directory from its current position and reinserts the whole set nearest-first, leaving unrelated `PATH` entries in their original order. Each call rebuilds from `process.env`, so nothing accumulates across runs. - **Windows `PATH` casing.** Environment variables are case-insensitive on Windows, where the key is usually `Path`. The helper reuses whichever key already exists instead of blindly writing `PATH`, otherwise the child process would receive both keys and could keep using the old value — i.e. the fix would silently not work on the only platform that needs it. Covered by a test. - **No-op when there is nothing to add.** If no ancestor `node_modules/.bin` exists, the helper returns a copy of the environment, which is indistinguishable from today's behavior. ## Is this a breaking change? No. The main thing to be careful about is that passing `env` to `execSync`/`spawn` replaces the environment instead of extending it — the helper always starts from a spread of `process.env`, so nothing is lost. The other `runCommandSync` call sites (`cp-schema`, `generate-graphql`, `dependencies`) don't pass `env`, so they get `undefined`, which Node treats as "use `process.env`": same behavior as before, and covered by a test. The one behavioral change is that project binaries now take precedence over the system `PATH` inside these child processes, which is the same precedence a package manager applies to its own scripts. Left out on purpose: - `generate-graphql.ts` also runs `${packageManager} run generate:schema` inside `.faststore` and has the same gap, but that command is orphaned on v4 — nothing invokes it (`dev` and `build` call `generate-types`, `cache-graphql` and `generate-i18n`) and the `generate:schema` / `generate:codegen` scripts no longer exist in `@faststore/core`'s `package.json`. - `start.ts` looks similar but is **not** affected: it spawns from the store root without `cwd: tmpDir`, so the package manager resolves the binary the usual way. ## How to test it? Unit tests: `packages/cli/src/utils/binPaths.test.ts` and `packages/cli/src/utils/runCommandSync.test.ts` (`pnpm vitest run src/utils` in `packages/cli`). They build a fixture that mimics a hoisted monorepo and assert ordering, ancestor skipping, deduplication, the no-op case, the `env` passthrough and the Windows `Path` casing. One of them goes further than asserting on the returned object: it writes an executable probe into the fixture's `node_modules/.bin` and spawns it by bare name from `.faststore`, against a `PATH` that cannot resolve it on its own. The assertion can only pass because of the directories the helper adds, so it covers the resolution mechanism end to end rather than the string we build. It is skipped on Windows, where the fixture would need a `.cmd` shim. What the unit tests cannot prove is the original symptom, which is native Windows. That needs a manual run with the CodeSandbox preview of this PR, in a monorepo store: `faststore dev` should complete `predev` and reach Next's `Ready`, and `faststore build` should get past `prebuild`, with `na` and `next` resolved without a global install or a manual `PATH` change. ## References Reported by a partner alongside the FastStore v4 migration, as item 1 (P0) of their handoff document. The other two items are #3439 (argument order, merged) and #3419 (Windows glob for GraphQL typeDefs). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Build, development, and test commands now automatically locate locally installed command-line tools across nested project directories. * Command execution preserves existing environment variables and avoids duplicate path entries. * **Bug Fixes** * Improved compatibility with platform-specific PATH casing and empty or missing PATH environments. * **Tests** * Added coverage for nested installations, missing directories, path ordering, deduplication, environment preservation, and custom command environments. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (11)
📒 Files selected for processing (92)
WalkthroughFastStore updates VTEX session and cart sales-channel synchronization, migrates diagnostics to OpenTelemetry, improves CLI child-process environments, centralizes recommendation logic, adds core request tracing and logging, and updates not-found ISR and Twitter SEO behavior. ChangesAPI session and cart synchronization
Diagnostics OpenTelemetry migration
CLI process and type generation
Recommendations SDK integration
Core session, server, SEO, and runtime updates
Shared package release updates
Estimated code review effort: 4 (Complex) | ~60 minutes ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. |
|

0 New Issues
0 Fixed Issues
0 Accepted Issues
No data about coverage (32.50% Estimated after merge)
What's the purpose of this pull request?
Graduation of the
devprerelease cycle (4.6.0-dev.6) into a stable4.6.0release onmain. Merging this PR triggers thereleaseCD workflow, which runslerna version --conventional-graduate --force-conventional-graduateand publishes all 8@faststore/*packages under thelatestdist-tag.The bump is decided by the Conventional Commits accumulated on
dev(feat: removing vtex/diagnostics-nodejs→ minor4.6.0).How it works?
No new product code in this PR itself — it is the merge of
devintomain. After merge, CD graduates4.6.0-dev.6→4.6.0.Highlights (features)
Fixes
devcommand (fix: restore account, path, port arg order on cli dev command #3439).faststore(fix: resolve node_modules bins when running scripts inside .faststore #3440)Packages published (latest)
@faststore/{api,cli,components,core,diagnostics,lighthouse,sdk,ui}→4.6.0How to test it?
releaseworkflow succeeds onmain4.6.0under thelatestdist-tag on npmmain→devto open the next dev cycleChecklist
PR Title and Commit Messages
PR Description
Dependencies
Made with Cursor
Summary by CodeRabbit
New Features
Bug Fixes
Documentation