Repository navigation
fix(devtools): rename Solid use* primitives to create* for React Compiler compat - #477
Conversation
…iler compat The devtools packages are Solid but used React-style naming (useStyles, useTheme, useDevtoolsState, ...) for their custom primitives. When an app enables React Compiler, it matches the use* convention and transforms this Solid code as if it were React, breaking the panel. Rename every custom Solid primitive in @tanstack/devtools, devtools-ui, and devtools-a11y from use* to create*, and import Solid's useContext and @solid-primitives' useKeyDownList under non-use aliases (getContext, getKeyDownList). BREAKING(@tanstack/devtools-ui): exported useTheme is renamed to createTheme.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughSolid theme, context, styles, and helper APIs are renamed from ChangesSolid use* → create* Primitive Rename
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
View your CI Pipeline Execution ↗ for commit 0022e02
☁️ Nx Cloud last updated this comment at |
|
View your CI Pipeline Execution ↗ for commit 0022e02
☁️ Nx Cloud last updated this comment at |
More templates
@tanstack/angular-devtools
@tanstack/devtools
@tanstack/devtools-a11y
@tanstack/devtools-client
@tanstack/devtools-ui
@tanstack/devtools-utils
@tanstack/devtools-vite
@tanstack/devtools-event-bus
@tanstack/devtools-event-client
@tanstack/preact-devtools
@tanstack/react-devtools
@tanstack/solid-devtools
@tanstack/svelte-devtools
@tanstack/vue-devtools
commit: |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/devtools-a11y/src/core/components/Shell.tsx (1)
22-29: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winInvert the
handleExportguard.Line 23 returns when
allyResult.auditexists, so both export buttons become no-ops in the only state where they are shown. It also leaves Line 28 dereferencingallyResult.audit!on the no-audit path.Suggested fix
const handleExport = (format: 'json' | 'csv') => { - if (allyResult.audit) return + if (!allyResult.audit) return // Keep export logic in runtime via event -> overlay? export is still a direct helper. // We keep this import local to avoid pulling export code into the runtime module. void import('../utils/export-audit.uitls').then((m) => m.exportAuditResults(allyResult.audit!, { format }), ) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/devtools-a11y/src/core/components/Shell.tsx` around lines 22 - 29, The handleExport guard in Shell.tsx is inverted, causing exports to exit when allyResult.audit exists and leaving exportAuditResults to dereference allyResult.audit! when it is absent. Update handleExport so it only returns early when there is no audit result, then pass the existing audit value into exportAuditResults after the local import resolves, keeping the behavior aligned with the export buttons.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/devtools/src/components/tabs.tsx`:
- Around line 18-21: The PiP feature string built in handleDetachment is
malformed because the left value includes an extra closing brace, which can
cause the window position to be ignored. Update the requestPipWindow argument in
tabs.tsx to remove the stray character and ensure the width, height, top, and
left entries are formatted consistently.
In `@packages/devtools/src/context/use-devtools-context.ts`:
- Around line 8-16: Update the JSDoc on createDevtoolsContext so it accurately
describes DevtoolsContext and its store/setStore API instead of ShellContext
state/setState, and change the missing-provider error message to reference the
correct DevtoolsContextProvider rather than ShellContextProvider. Keep the
wording aligned with the actual symbols in use (createDevtoolsContext,
DevtoolsContext, store, setStore) so the generated docs and runtime hint match
the implementation.
---
Outside diff comments:
In `@packages/devtools-a11y/src/core/components/Shell.tsx`:
- Around line 22-29: The handleExport guard in Shell.tsx is inverted, causing
exports to exit when allyResult.audit exists and leaving exportAuditResults to
dereference allyResult.audit! when it is absent. Update handleExport so it only
returns early when there is no audit result, then pass the existing audit value
into exportAuditResults after the local import resolves, keeping the behavior
aligned with the export buttons.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0c7e946c-c2b4-4128-9a8a-5a2a51a3b541
📒 Files selected for processing (45)
.changeset/solid-hook-naming-react-compiler.mdpackages/devtools-a11y/src/core/components/IssueCard.tsxpackages/devtools-a11y/src/core/components/IssueList.tsxpackages/devtools-a11y/src/core/components/Settings.tsxpackages/devtools-a11y/src/core/components/Shell.tsxpackages/devtools-a11y/src/core/contexts/allyContext.tsxpackages/devtools-a11y/src/core/styles/styles.tspackages/devtools-ui/src/components/button.tsxpackages/devtools-ui/src/components/checkbox.tsxpackages/devtools-ui/src/components/header.tsxpackages/devtools-ui/src/components/input.tsxpackages/devtools-ui/src/components/logo.tsxpackages/devtools-ui/src/components/main-panel.tsxpackages/devtools-ui/src/components/section.tsxpackages/devtools-ui/src/components/select.tsxpackages/devtools-ui/src/components/tag.tsxpackages/devtools-ui/src/components/theme.tsxpackages/devtools-ui/src/components/tree.tsxpackages/devtools-ui/src/index.tspackages/devtools-ui/src/styles/use-styles.tspackages/devtools/src/components/content-panel.tsxpackages/devtools/src/components/main-panel.tsxpackages/devtools/src/components/source-inspector.tsxpackages/devtools/src/components/tab-content.tsxpackages/devtools/src/components/tabs.tsxpackages/devtools/src/components/trigger.tsxpackages/devtools/src/context/draw-context.tsxpackages/devtools/src/context/pip-context.tsxpackages/devtools/src/context/use-devtools-context.tspackages/devtools/src/devtools.tsxpackages/devtools/src/hooks/use-disable-tabbing.tspackages/devtools/src/hooks/use-head-changes.tspackages/devtools/src/styles/use-styles.tspackages/devtools/src/tabs/hotkey-config.tsxpackages/devtools/src/tabs/marketplace/marketplace-header.tsxpackages/devtools/src/tabs/marketplace/plugin-card.tsxpackages/devtools/src/tabs/marketplace/plugin-section.tsxpackages/devtools/src/tabs/marketplace/settings-panel.tsxpackages/devtools/src/tabs/marketplace/tag-filters.tsxpackages/devtools/src/tabs/plugin-marketplace.tsxpackages/devtools/src/tabs/plugins-tab.tsxpackages/devtools/src/tabs/seo-tab/index.tsxpackages/devtools/src/tabs/seo-tab/serp-preview.tsxpackages/devtools/src/tabs/seo-tab/social-previews.tsxpackages/devtools/src/tabs/settings-tab.tsx
| const handleDetachment = () => { | ||
| pipWindow().requestPipWindow( | ||
| `width=${window.innerWidth},height=${state().height},top=${window.screen.height},left=${window.screenLeft}}`, | ||
| ) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Remove the stray } from the PiP feature string.
Line 20 builds left=${window.screenLeft}}, which makes the features string malformed. That can cause the left position to be ignored when the detached window opens.
Suggested fix
const handleDetachment = () => {
pipWindow().requestPipWindow(
- `width=${window.innerWidth},height=${state().height},top=${window.screen.height},left=${window.screenLeft}}`,
+ `width=${window.innerWidth},height=${state().height},top=${window.screen.height},left=${window.screenLeft}`,
)
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const handleDetachment = () => { | |
| pipWindow().requestPipWindow( | |
| `width=${window.innerWidth},height=${state().height},top=${window.screen.height},left=${window.screenLeft}}`, | |
| ) | |
| const handleDetachment = () => { | |
| pipWindow().requestPipWindow( | |
| `width=${window.innerWidth},height=${state().height},top=${window.screen.height},left=${window.screenLeft}`, | |
| ) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/devtools/src/components/tabs.tsx` around lines 18 - 21, The PiP
feature string built in handleDetachment is malformed because the left value
includes an extra closing brace, which can cause the window position to be
ignored. Update the requestPipWindow argument in tabs.tsx to remove the stray
character and ensure the width, height, top, and left entries are formatted
consistently.
| /** | ||
| * Returns an object containing the current state and setState function of the ShellContext. | ||
| * Throws an error if used outside of a ShellContextProvider. | ||
| */ | ||
| const useDevtoolsContext = () => { | ||
| const context = useContext(DevtoolsContext) | ||
| const createDevtoolsContext = () => { | ||
| const context = getContext(DevtoolsContext) | ||
| if (context === undefined) { | ||
| throw new Error( | ||
| 'useDevtoolsShellContext must be used within a ShellContextProvider', | ||
| 'createDevtoolsContext must be used within a ShellContextProvider', |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the stale context docs and provider hint.
This helper reads DevtoolsContext, which exposes store/setStore, but the JSDoc still documents state/setState from ShellContext, and Line 16 still tells callers to use ShellContextProvider. That will publish incorrect docs and mislead anyone debugging a missing-provider failure.
As per coding guidelines, JSDoc should read like documentation as it gets converted to markdown docs for the website.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/devtools/src/context/use-devtools-context.ts` around lines 8 - 16,
Update the JSDoc on createDevtoolsContext so it accurately describes
DevtoolsContext and its store/setStore API instead of ShellContext
state/setState, and change the missing-provider error message to reference the
correct DevtoolsContextProvider rather than ShellContextProvider. Keep the
wording aligned with the actual symbols in use (createDevtoolsContext,
DevtoolsContext, store, setStore) so the generated docs and runtime hint match
the implementation.
Source: Coding guidelines
#472 added component tests (tabs.test.tsx, settings-tab.test.tsx) using the old useDevtoolsState/useDevtoolsSettings names, and the devtools-plugin-panel skill docs referenced the renamed devtools-ui export useTheme. Update them to the create* names.
nx.json sets `parallel: 5`, which is fine for local dev machines but oversubscribes GitHub-hosted runners: each affected `test:lib` (vitest) and `test:types` (tsc) task spawns its own worker pool, so 5 heavy tasks at once exhaust CPU/RAM and intermittently stall or OOM-kill deterministic tasks. That produced flaky failures across unrelated PRs (#471, #477, #478) that pass on a plain re-run. The team already pins `test:e2e` to `--parallel=1` for the same reason; cap the Test job's nx parallelism via NX_PARALLEL=3 (CI-only, leaves local dev at 5). Combined with the raised vitest timeouts, this keeps tasks within the runner's budget.
…uts) (#478) * test(devtools): raise vitest timeouts to stop flaky component test:lib in CI The component tests added in #472 render the full Solid + goober tree and take 1-4s locally. Shared CI runners are ~4x slower (the suite runs in ~8s locally but ~31s in CI), which pushes individual tests past vitest's default 5s testTimeout and causes intermittent `@tanstack/devtools:test:lib` failures across unrelated PRs (e.g. #471, #477). Raise testTimeout and hookTimeout to 30s for the devtools package so slow CI runs have headroom. Fast unit tests are unaffected; a real hang still fails (just after 30s instead of 5s). * ci: cap nx parallelism to 3 to fix flaky Test job nx.json sets `parallel: 5`, which is fine for local dev machines but oversubscribes GitHub-hosted runners: each affected `test:lib` (vitest) and `test:types` (tsc) task spawns its own worker pool, so 5 heavy tasks at once exhaust CPU/RAM and intermittently stall or OOM-kill deterministic tasks. That produced flaky failures across unrelated PRs (#471, #477, #478) that pass on a plain re-run. The team already pins `test:e2e` to `--parallel=1` for the same reason; cap the Test job's nx parallelism via NX_PARALLEL=3 (CI-only, leaves local dev at 5). Combined with the raised vitest timeouts, this keeps tasks within the runner's budget.
## Summary
Updates the TanStack data + devtools packages in `frontend` to their
latest versions:
| Package | From | To | Kind |
| --- | --- | --- | --- |
| `@tanstack/solid-db` | 0.2.22 | **0.3.12** | dep |
| `@tanstack/query-db-collection` | 1.0.40 | **1.4.8** | dep |
| `@tanstack/solid-query` | 5.101.0 | **5.104.5** | dep |
| `@tanstack/solid-devtools` | 0.8.5 | **0.8.13** | devDep |
| `@tanstack/solid-query-devtools` | 5.101.0 | **5.104.5** | devDep |
```
frontend/src/ts/
├── collections/ # 8 query-backed collections: writes → await/void, isPersisted → when("settled"), id workaround removed
│ ├── results.ts # + last-10 average live-query: empty single-result state ([] → undefined)
│ ├── tags.ts presets.ts connections.ts inbox.ts
│ ├── ape-keys.ts custom-themes.ts result-filter-presets.ts
│ └── utils/misc.ts # applyIdWorkaround deleted (TanStack/db#1524 fixed upstream)
├── ape/server-configuration.ts # fetchQuery → queryClient.query()
├── router/routes.ts # 9× prefetchQuery → query().catch(noop), ensureQueryData → query() + staleTime "static"
└── components/pages/
├── leaderboard/LeaderboardPage.tsx # next-page prefetchQuery → query().catch(noop)
└── profile/ProfileSearchPage.tsx # fetchQuery → queryClient.query()
```
### Breaking changes found and how they were handled
<details>
<summary><b>1. <code>@tanstack/db</code> 0.15.0 — <code>setWindow</code>
on <code>findOne</code> queries (no code change, verified
unused)</b></summary>
Breaking: a `findOne` keeps its compiled limit (1). An ordered
`findOne`'s `setWindow` can move the offset but now **throws
`SetWindowFindOneLimitError`** for any other limit (before it silently
made the `findOne` return N rows); an unordered `findOne` with a nonzero
offset **throws `SetWindowRequiresOrderByError`**.
- Docs: [TanStack DB — Query
windowing](https://tanstack.com/db/latest/docs/queries/windowing)
- Changelog: [`@tanstack/db`
0.15.0](https://github.com/TanStack/db/blob/main/packages/db/CHANGELOG.md)
Our three `findOne()` usages (`results.ts` averages/daily-best) are
aggregate projections and never call `setWindow`/`getWindow` —
**verified unused, no fix needed**.
</details>
<details>
<summary><b>2. <code>@tanstack/db</code> 0.12.0 — removal of
<code>begin({ immediate })</code> (no code change, verified
unused)</b></summary>
Breaking: the `immediate` option of the sync `begin()` API was removed;
writes made while a mutation persists now queue behind it instead of
applying at once.
- Docs: [TanStack DB —
Transactions](https://tanstack.com/db/latest/docs/collections/transactions)
- Changelog: [`@tanstack/db`
0.12.0](https://github.com/TanStack/db/blob/main/packages/db/CHANGELOG.md)
The app never calls `begin({ immediate })` — **verified unused, no fix
needed**.
</details>
<details open>
<summary><b>3. <code>@tanstack/query-db-collection</code> 1.4.0 —
collection writes now reject promises instead of throwing synchronously
(code change)</b></summary>
Breaking: validation errors from `writeInsert`, `writeUpdate`,
`writeDelete`, `writeUpsert` and `writeBatch` now **reject the returned
promise**; before they threw synchronously. The changelog's migration
guidance: *"Await the promise and catch the error."*
- Docs: [TanStack DB — Query collections: direct
writes](https://tanstack.com/db/latest/docs/collections/query-collection)
- Changelog: [`@tanstack/query-db-collection` 1.4.0, PR
#2044](TanStack/db#2044)
Until 1.3.2 these writes returned a sync receipt, so all 31 call sites
in the 8 collections were bare expressions. Since writes now return
`Promise<void>`, they had to be handled or the repo's
`no-floating-promises` lint rule (error severity) fails:
- **24 calls inside async `mutationFn`s → `await`** (e.g.
`collections/tags.ts`, `results.ts`, `presets.ts`, `connections.ts`,
`ape-keys.ts`, `custom-themes.ts`, `result-filter-presets.ts`). This
preserves the old semantics exactly: a write validation failure rejects
the mutation (previously the sync throw already did, inside the async
function) instead of becoming an unhandled rejection.
- **7 calls inside sync `onMutate` / `writeBatch` callbacks → `void`**
(tags `toggleTagActive`/`setTagActive`/`clearActiveTags`, `inbox.ts`
batch delete/read) — sync callbacks can't await; these are
fire-and-forget, as before.
</details>
<details open>
<summary><b>4. <code>@tanstack/db</code> 0.15.x /
<code>query-db-collection</code> 1.3.5 — transaction settlement rework,
<code>isPersisted</code> deprecated (code change)</b></summary>
The sync transaction API gained two moments (accepted vs. visible):
`commit()` receipts and subset loads resolve at *visibility*, while
handler-facing writes resolve at *acceptance*. As part of this,
**`Transaction.isPersisted` is deprecated — "Use `when('settled')`
instead. This alias will be removed in the 1.0 RC."** (`when('settled')`
has the same resolve/reject semantics: resolves with the transaction on
success, rejects with the original error on failure.)
- Docs: [TanStack DB — Transactions:
`when()`](https://tanstack.com/db/latest/docs/collections/transactions)
- Changelog: [`@tanstack/db` 0.12.0 / 1.3.5
entry](https://github.com/TanStack/db/blob/main/packages/query-db-collection/CHANGELOG.md)
All **26** `await transaction.isPersisted.promise` occurrences (public
action wrappers in the 8 collections, e.g. `addCustomTheme`,
`insertApeKey`, `acceptConnection`, `updateResultTags`) → `await
transaction.when("settled")`.
</details>
<details open>
<summary><b>5. <code>@tanstack/solid-db</code> 0.2.46 — live-query
result types include the empty single-result representation (code
change)</b></summary>
Type-level breaking: conditional live-query result types were aligned
with the disabled/empty reactive bindings, so a `findOne()` inside
`useLiveQuery` now types its empty state as `[]` (empty array) in the
union: `{ ...; wpm: number; acc: number } | []`. Property access on the
union (`last10()?.wpm` in `AverageNotice.tsx`) no longer type-checks
(TS2339).
- Docs: [TanStack DB — Solid: live
queries](https://tanstack.com/db/latest/docs/frameworks/solid)
- Changelog: [`@tanstack/solid-db`
0.2.46](https://github.com/TanStack/db/blob/main/packages/solid-db/CHANGELOG.md)
`useUserAverage10LiveQuery` (`results.ts`) now normalizes through a
`createMemo`: `[]` (and `undefined`) → `undefined`, keeping the existing
"no average" rendering path. This is the only consumer of a
single-result live query.
</details>
<details open>
<summary><b>6. <code>@tanstack/query-core</code> 5.102.0 — imperative
<code>QueryClient</code> methods deprecated (code change)</b></summary>
Minor in 5.x (non-breaking: methods still work, removal is "next major
version"), but the repo lints deprecations as errors, so these had to be
migrated to the new API:
- `prefetchQuery` → **`queryClient.query(options)`** — new
`query()`/`infiniteQuery()` methods added in
[#10658](TanStack/query#10658). Unlike
`prefetchQuery` (which never rejected), `query()` rejects on error, so
fire-and-forget prefetches in `router/routes.ts` (9) and
`LeaderboardPage.tsx` (1) now end in `.catch(noop)` to keep the old
swallow-errors behavior.
- `fetchQuery` → **`queryClient.query(options)`** (1:1, both reject on
error): `ape/server-configuration.ts` sync, `ProfileSearchPage.tsx`
username validation.
- `ensureQueryData` → **`queryClient.query({ ...options, staleTime:
"static" })`** — the mapping recommended in the deprecation tag;
`staleTime: "static"` ("never stale") is new in 5.102. Used in the
friends route loader.
- Docs: [TanStack Query —
`QueryClient`](https://tanstack.com/query/latest/docs/framework/solid/api/queryclient#queryclientquery)
</details>
<details>
<summary><b>7. <code>@tanstack/solid-devtools</code> 0.8.5 → 0.8.13 /
core <code>@tanstack/devtools</code> 0.12.2 → 0.15.0 (no code
change)</b></summary>
The adapter is patch-only (0.8.x); the movement is in the core
`@tanstack/devtools` package it wraps. Relevant entries, checked against
our usage in `components/dev/TanstackDevtools.tsx` (`<TsDevTools
plugins={[inline query plugin, hotkeysDevtoolsPlugin(),
SignalsDevtoolsPlugin()]} config={{ defaultOpen: false }} />`):
- **Plugin pane workspace**
([#492](TanStack/devtools#492)): panes can now
be split/stacked/resized, up to 18 open (was 3). User-visible change;
also, `state.activePlugins` in the devtools `localStorage` state is
superseded by `state.layout` — **existing state is migrated
automatically on first read** (unusable entries repaired, unknown ids
dropped), so no app-side action needed.
- **Plugin lifecycle guarantees** (same PR): a pane's mount node is
never removed while the plugin is open (iframes/canvas keep living) and
`destroy` fires exactly once on close — a fix for plugin authors, no API
change.
- **`use*` → `create*` rename**
([#477](TanStack/devtools#477)): the only
breaking tag in the range is `@tanstack/devtools-ui`'s exported
`useTheme` → `createTheme` (prevents React Compiler from transforming
the Solid panel code). We don't import `@tanstack/devtools-ui` directly
— **no impact**.
- Docs: [TanStack Devtools](https://tanstack.com/devtools)
Our plugin objects (`{ id, name, render, defaultOpen }`) satisfy the
unchanged plugin interface — typecheck clean.
`@tanstack/solid-hotkeys-devtools@0.7.0` (unchanged) peers only on
`solid-js`, so no coupling with the new core.
</details>
<details>
<summary><b>8. <code>@tanstack/solid-query-devtools</code> 5.101.0 →
5.104.5 (no code change)</b></summary>
Patch-only range — every release is a version alignment with
`@tanstack/query-devtools`/`@tanstack/solid-query` (5.x stable, no API
changes). `SolidQueryDevtoolsPanel`'s `client` prop is unchanged. Docs:
[TanStack Query
devtools](https://tanstack.com/query/latest/docs/framework/solid/overview)
</details>
<details open>
<summary><b>9. <code>applyIdWorkaround</code> workaround removed (code
change)</b></summary>
`collections/utils/misc.ts` carried `applyIdWorkaround` — a temp
workaround for
[TanStack/db#1524](TanStack/db#1524) (Solid
rendering showed one item for all rows in a `getKey: (it) => it._id`
collection with ordered live queries, fixed by copying `_id` onto an
`id` property of every fetched row). That issue is closed and its fixes
— [solid-db#1598](TanStack/db#1598) (reconcile
key), [solid-db#1604](TanStack/db#1604) (row
cloning in `syncDataFromCollection`),
[solid-db#1825](TanStack/db#1825) (preserve live
result identity for custom-key rows, shipped in `@tanstack/solid-db`
0.2.46, see [Solid live-query
docs](https://tanstack.com/db/latest/docs/frameworks/solid)) — are all
part of the updated 0.3.12.
Removed the helper and all 7 usages (the `queryFn` row-mapping in the
`custom-themes`, `connections`, `ape-keys`, `presets`, `results`,
`result-filter-presets` and `tags` collections). All consumers type rows
via the zod schemas, which never declared `id`, so no code could depend
on the injected property — typecheck confirms.
</details>
### Entries checked and deliberately not actioned
- **`query-db-collection` 1.2.0**: QueryClient-default `placeholderData`
no longer materializes as collection rows, QueryClient-default
`initialData` no longer seeds on-demand subset observers. Our
`QueryClient` (`queries/index.ts`) sets neither globally — no impact.
- **`query-db-collection` 1.3.0**: mutation-handler auto-refetch
deprecated (`warnOnce` when a handler doesn't return `{ refetch: false
}`). Our collections register **no** `onInsert`/`onUpdate`/`onDelete`
handlers (mutations run through `createOptimisticAction` + explicit
`write*`), so the warning never fires. When handlers are ever added, the
library wants an explicit `{ refetch: false }` or manual `await
collection.utils.refetch()`.
- **`@tanstack/solid-db` 0.3.0 (minor)**: opt-in network-first initial
rendering for *persisted* (SQLite) collections (`initialRender: {
strategy: "network-first" }`, new `persistedStatus`/`isPersistedReady`
flags). We use pure Query-backed collections with no persistence adapter
— no impact.
- **`@tanstack/solid-query` 5.104.4**: type-only re-exports switched to
`export type *` — our named imports (incl. `UseQueryResult`) unaffected,
typecheck clean. (Same `export type *` change landed in
`solid-query-devtools`'s `query-devtools` dep — devtools-only, no app
code touched.)
## Evidence
- **Before:** draft — signed-in browser smoke test still owed, no
runtime evidence for the write/settlement rework.
**After:** smoke run on the dev server (3000/5005) as a signed-in test
account:
- **Average notice** (`useUserAverage10LiveQuery`): with ≥10 results it
shows the real average (84 wpm 87% acc); switching the test language so
the settings filter matches zero results, the empty single-result state
(`[]`) renders "no average" via the new `createMemo` normalization, and
switches back when the language returns — the only consumer of a
single-result live query.
- **Tags, presets, custom themes, ape keys**: create → rename → delete
through the real UI for each. Every mutation settled with no error
notification and no optimistic rollback; every `_id`-keyed list rendered
each row with its own data. Renaming a custom theme re-sorted it to the
top with both rows keeping their own name/colors — the
one-item-for-all-rows regression behind the removed `applyIdWorkaround`
(TanStack/db#1524) is not present.
- **Inbox/connections**: friends page renders with the (empty)
connections list; the account has no pending requests, so the
`writeBatch` read/delete path went unexercised.
- **`queryClient.query()`**: profile search rejects an unknown username
("Unknown user", submit disabled) and accepts an existing one (submit
enabled); the about page rendered all four prefetched sections; the
leaderboard rendered its table.
- **Devtools panel**: skipped — core package is patch-only alignment, no
app code touched.
Observed while smoke-testing (filed as bugs, not blockers): rename
modals (custom theme, ape key) apply the change but the modal takes
several seconds to close — `when("settled")` settles later than
`isPersisted` did for query-backed collections; and a SimpleModal whose
boolean input is never touched reports invalid until the checkbox is
toggled once (form layer, untouched by this PR).
- **Automated:**
- `pnpm oxlint --type-aware --type-check` — exit 0, 0 errors
- `pnpm vitest run` — 84 files, **1622/1622 tests pass**
- `pnpm vite build` — success (catches bundler-level issues from the
`export type *` change and the new `db-ivm` dep)
> The original draft note — a signed-in browser smoke test is still
owed: tag/preset/custom-theme create-edit-delete, inbox read/delete, the
average notice on the test page (the transaction-acceptance and
write-validation rework in 1.3.x/1.4.x is runtime behavior the test
suite doesn't exercise), reordering a `_id`-keyed list — e.g. rename a
custom theme so it sorts to the top and check every row shows its own
data (the regression behind the removed #1524 workaround) — and a look
at the redesigned devtools plugins panel (pane workspace layout, plus
the `localStorage` state migration for anyone who has customized open
panes) — is now resolved by the smoke run above; the observed issues
remain as filed bugs, not blockers.
## Merge Danger
**Door:** two-way
Dependency bump plus mechanical API migration; reverting the PR restores
the prior versions and behavior. No schema, storage, or API contract
changes — a rollback costs one revert.
**Blast Radius:** app-wide
Every signed-in data flow runs through the changed code: the 8
query-backed collections (tags, results, presets, connections, inbox,
ape keys, custom themes, result-filter-presets) with their new
write/settlement semantics, and every route's background data fetch on
the new `queryClient.query()` API. A divergence in write timing or
live-query reconciliation would surface as slow-closing modals,
rolled-back mutations, or duplicated list rows across the whole
signed-in experience.
---------
Co-authored-by: Jack <jack@monkeytype.com>
Problem
The devtools packages are written in Solid, but their custom primitives used React-style
use*naming (useStyles,useTheme,useDevtoolsState, …). When a consuming app enables React Compiler, the compiler matches theuse*naming convention and transforms/optimizes this Solid code as if it were React hooks — which breaks the panel, because it's Solid JSX, not React.Change
Rename every custom Solid primitive across the three Solid packages from
use*→create*, and import the frameworkuse*primitives under non-usealiases so the compiler no longer flags them:useStyles→createStyles,useTheme→createTheme,useDevtoolsContext/useDevtoolsState/useDevtoolsSettings/usePlugins/usePersistOpen/useHeight,useDraw/useDrawContext,usePiPWindow,useHeadChanges,useDisableTabbing,useAllyValue/useAllyContext.useContext→ imported asgetContext(couldn't reusecreateContext— it's a separate Solid export already imported in the same files).@solid-primitives/keyboard'suseKeyDownList→ imported asgetKeyDownList(same compiler risk).Breaking change
@tanstack/devtools-ui(minor): the exporteduseThemeis renamed tocreateTheme. All other renames are internal (not part of any package's public entry).Verification
nx build✅ all 7 affected packages (build emits.d.tsvia tsc, so types are clean)nx test:lib✅ all three packagesnx test:eslint✅ all three packagesChangeset included.
Summary by CodeRabbit
New Features
create*APIs for theming, styles, context, settings, state, and hotkeys across the devtools and UI packages.Bug Fixes
Breaking Changes
useTheme→createTheme.use*→create*(includinguseStyles,usePlugins,useDevtoolsState,useDevtoolsSettings,usePersistOpen,useHeight,useDrawContext,usePiPWindow, anduseHeadChanges).