Skip to content

Commit 837656a

Browse files
committed
Retargeted to SolidJS 2.0 exclusively
1 parent 83b41e3 commit 837656a

12 files changed

Lines changed: 198 additions & 89 deletions

File tree

.github/workflows/ci.yml

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ concurrency:
1212

1313
jobs:
1414
main:
15-
name: build & test (solid-js@1.9)
15+
# Single job. There is no `solid-js@1.9` leg, gating or otherwise: a v1-target port lives in a
16+
# separate repo (`@react-querybuilder/solid1`), and a non-gating leg nobody acts on is exactly
17+
# the kind of inert check this project's standing rule exists to prevent.
18+
name: build & test (solid-js@2.0.0-beta.32)
1619
runs-on: ubuntu-latest
1720
steps:
1821
- uses: actions/checkout@v5
@@ -24,6 +27,13 @@ jobs:
2427
- name: Install
2528
run: bun install --frozen-lockfile
2629

30+
# First, and deliberately loud. The whole toolchain is on prereleases; an install that
31+
# silently drifts onto a newer beta -- or onto `@solidjs/web`'s `latest` tag, which is the
32+
# incompatible `2.0.0-experimental.0` line -- should report itself as a version drift rather
33+
# than as 200 broken assertions further down.
34+
- name: Assert resolved toolchain versions
35+
run: bun run check:versions
36+
2737
- name: Format check
2838
run: bun run fmt:check
2939

@@ -47,36 +57,3 @@ jobs:
4757

4858
- name: SSR smoke test
4959
run: bun run test:ssr
50-
51-
# SKIPPING FOR NOW
52-
# solid-next:
53-
# name: build & test (solid-js@2.0.0-beta.32, non-gating)
54-
# runs-on: ubuntu-latest
55-
# continue-on-error: true
56-
# steps:
57-
# - uses: actions/checkout@v5
58-
59-
# - uses: oven-sh/setup-bun@v2
60-
# with:
61-
# bun-version: latest
62-
63-
# - name: Install
64-
# run: bun install --frozen-lockfile
65-
66-
# - name: Bump solid-js to next
67-
# run: bun add -D solid-js@2.0.0-beta.32
68-
69-
# - name: Build
70-
# run: bun run build
71-
72-
# - name: Check
73-
# run: bun run check
74-
75-
# - name: Test
76-
# run: bun run test
77-
78-
# - name: Conformance
79-
# run: bun run conformance
80-
81-
# - name: SSR smoke test
82-
# run: bun run test:ssr

CHANGELOG.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,23 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- **Retargeted the port to Solid 2.0 exclusively.** `peerDependencies` is now
13+
`solid-js@^2.0.0-beta.32` **and `@solidjs/web@^2.0.0-beta.32`** — in Solid 2 the DOM runtime is
14+
its own package. The `^1.9` peer leg and the non-gating `solid-next` CI job are both gone; CI is
15+
a single gating job on the pinned beta, preceded by a `check:versions` step that asserts the
16+
resolved prerelease toolchain has not drifted. `jsxImportSource` is now `@solidjs/web`, and the
17+
SSR smoke test renders through Solid 2's synchronous `renderToString`. The `exports` map is
18+
unchanged. A v1-target port, should demand warrant one, will be a separate repo publishing as
19+
`@react-querybuilder/solid1`; this package will not carry `solid-js@1` compatibility shims.
20+
- `0.1.0` still publishes to the `latest` dist-tag. The prerelease peer is documented here and in
21+
`README.md` rather than encoded in the version.
22+
1023
### Added
1124

1225
- Repo bootstrap: Bun workspaces, root tooling config (`oxfmt`, `oxlint`, `.editorconfig`,
13-
`.npmrc`), root `vitest.config.ts` with `v8` coverage (80% lines), and CI (`main` gating job on
14-
`solid-js@1.9`, `solid-next` non-gating leg on `solid-js@2.0.0-beta`).
26+
`.npmrc`), root `vitest.config.ts` with `v8` coverage (80% lines), and CI.
1527
- `packages/solid-querybuilder` scaffold: the Solid triple `exports` map (`solid``types`
1628
`import`), build pipeline (`vite build` dom bundle, `tsc --jsx preserve` source bundle, types,
1729
css), `check:exports` specifier guard, and `scripts/ssr-smoke.ts` as a real gate from day one —

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ byte-identical DOM output.
1111
npm install solid-querybuilder
1212
```
1313

14-
`solid-js@^1.9 || ^2.0.0-0` is a peer dependency. `@react-querybuilder/core` is a regular
15-
dependency and is re-exported in full, so you never need to depend on it directly.
14+
`solid-js@^2.0.0-beta.32` and `@solidjs/web@^2.0.0-beta.32` are peer dependencies — this package
15+
targets **Solid 2 only**, where the DOM runtime ships as its own package. Install `@solidjs/web`
16+
from the `next` dist-tag; its `latest` tag is `2.0.0-experimental.0`, an incompatible line.
17+
`@react-querybuilder/core` is a regular dependency and is re-exported in full, so you never need
18+
to depend on it directly.
1619

1720
## Quick start
1821

bun.lock

Lines changed: 54 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"build": "bun run --filter solid-querybuilder build",
1212
"check": "bun run --filter solid-querybuilder check",
1313
"check:exports": "bun run --filter solid-querybuilder check:exports",
14-
"check:all": "bun run fmt:check && bun run build && bun run check && bun run check:exports && bun run lint && bun run test:coverage && bun run conformance && bun run test:ssr",
14+
"check:versions": "bun run --filter solid-querybuilder check:versions",
15+
"check:all": "bun run check:versions && bun run fmt:check && bun run build && bun run check && bun run check:exports && bun run lint && bun run test:coverage && bun run conformance && bun run test:ssr",
1516
"lint": "oxlint",
1617
"fmt": "oxfmt",
1718
"fmt:check": "oxfmt --check",
@@ -23,7 +24,8 @@
2324
},
2425
"devDependencies": {
2526
"@arethetypeswrong/cli": "^0.18.5",
26-
"@solidjs/testing-library": "^0.8.10",
27+
"@solidjs/testing-library": "1.0.0-beta.2",
28+
"@solidjs/web": "2.0.0-beta.32",
2729
"@testing-library/jest-dom": "^7.0.0",
2830
"@testing-library/user-event": "^14.6.3",
2931
"@types/bun": "^1.3.14",
@@ -33,10 +35,10 @@
3335
"oxfmt": "^0.62.0",
3436
"oxlint": "^1.77.0",
3537
"sass": "^1.102.0",
36-
"solid-js": "^1.9.14",
38+
"solid-js": "2.0.0-beta.32",
3739
"typescript": "^5.9.3",
3840
"vite": "^8.2.0",
39-
"vite-plugin-solid": "^2.11.14",
41+
"vite-plugin-solid": "3.0.0-next.23",
4042
"vitest": "^4.1.10",
4143
"vitest-axe": "^0.1.0"
4244
}

packages/solid-querybuilder/package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,24 @@
5757
"build:css": "mkdir -p dist/styles && cp ../../node_modules/@react-querybuilder/core/dist/*.scss dist && cp ../../node_modules/@react-querybuilder/core/dist/styles/*.scss dist/styles && cp -f src/styles/*.scss dist/styles 2>/dev/null || true; bun sass --style=compressed dist",
5858
"check": "tsc --noEmit -p tsconfig.json",
5959
"check:exports": "bun run ./scripts/check-dist-specifiers.ts && attw --pack . --profile esm-only",
60+
"check:versions": "bun run ./scripts/check-versions.ts",
6061
"test:ssr": "bun run ./scripts/ssr-smoke.ts",
6162
"conformance": "echo 'conformance harness lands at step 6' && exit 0"
6263
},
6364
"peerDependencies": {
64-
"solid-js": "^1.9 || ^2.0.0-0"
65+
"solid-js": "^2.0.0-beta.32",
66+
"@solidjs/web": "^2.0.0-beta.32"
6567
},
6668
"dependencies": {
6769
"@react-querybuilder/core": "^8.22.4"
6870
},
6971
"devDependencies": {
7072
"@arethetypeswrong/cli": "^0.18.5",
71-
"solid-js": "^1.9.14",
73+
"@solidjs/web": "2.0.0-beta.32",
74+
"solid-js": "2.0.0-beta.32",
7275
"typescript": "^5.9.3",
7376
"vite": "^8.2.0",
74-
"vite-plugin-solid": "^2.11.14"
77+
"vite-plugin-solid": "3.0.0-next.23"
7578
},
7679
"publishConfig": {
7780
"access": "public"
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/**
2+
* Resolved-version assertions for the pinned Solid 2 prerelease toolchain.
3+
*
4+
* The whole matrix sits on prereleases, and a `bun install` that silently drifts onto a newer
5+
* beta — or, worse, onto `@solidjs/web`'s `latest` tag, which is the incompatible
6+
* `2.0.0-experimental.0` line — is the single most likely cause of an inexplicable failure in
7+
* this repo. It should report itself as a version drift, not as 200 broken assertions.
8+
*
9+
* Runs before every other gate in CI.
10+
*/
11+
import { existsSync } from 'node:fs';
12+
import { dirname, resolve } from 'node:path';
13+
import { fileURLToPath } from 'node:url';
14+
15+
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../../..');
16+
17+
const failures: string[] = [];
18+
19+
const read = async (pkg: string): Promise<string | undefined> => {
20+
const manifest = resolve(repoRoot, 'node_modules', pkg, 'package.json');
21+
if (!existsSync(manifest)) return undefined;
22+
const json = await Bun.file(manifest).json();
23+
return json.version as string;
24+
};
25+
26+
// Exact pins. `solid-js` and `@solidjs/web` must move together, and only deliberately.
27+
const exact: Record<string, string> = {
28+
'solid-js': '2.0.0-beta.32',
29+
'@solidjs/web': '2.0.0-beta.32',
30+
'vite-plugin-solid': '3.0.0-next.23',
31+
'@solidjs/testing-library': '1.0.0-beta.2',
32+
};
33+
34+
for (const [pkg, want] of Object.entries(exact)) {
35+
const got = await read(pkg);
36+
if (got === undefined) {
37+
failures.push(`${pkg} is not installed`);
38+
} else if (got !== want) {
39+
failures.push(`${pkg} resolved to ${got}, expected exactly ${want}`);
40+
}
41+
}
42+
43+
// Line assertions. These catch the two drifts that produce confusing *compile* errors rather
44+
// than a resolution failure, and they stay correct if the exact pins above are bumped.
45+
const pluginVersion = await read('vite-plugin-solid');
46+
if (pluginVersion && !pluginVersion.startsWith('3.')) {
47+
failures.push(`vite-plugin-solid must be on the 3.x line, got ${pluginVersion}`);
48+
}
49+
50+
const webVersion = await read('@solidjs/web');
51+
if (webVersion?.includes('-experimental.')) {
52+
failures.push(
53+
`@solidjs/web resolved to the experimental line (${webVersion}). That is npm's \`latest\` ` +
54+
`tag and vite-plugin-solid@3 explicitly excludes it (<2.0.0-experimental.0). Install from ` +
55+
`the \`next\` tag.`
56+
);
57+
}
58+
59+
// The DOM runtime is compiled against the core package; a split between them is silent and fatal.
60+
const solidVersion = await read('solid-js');
61+
if (solidVersion && webVersion && solidVersion !== webVersion) {
62+
failures.push(
63+
`solid-js (${solidVersion}) and @solidjs/web (${webVersion}) must be the same version`
64+
);
65+
}
66+
67+
if (failures.length > 0) {
68+
console.error('check:versions FAILED — the Solid 2 toolchain drifted:');
69+
for (const f of failures) console.error(` - ${f}`);
70+
process.exit(1);
71+
}
72+
73+
console.log(
74+
`check:versions ok — solid-js ${solidVersion}, @solidjs/web ${webVersion}, ` +
75+
`vite-plugin-solid ${pluginVersion}`
76+
);

packages/solid-querybuilder/scripts/ssr-smoke-entry.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
* SSR smoke-test entry, loaded through Vite's SSR pipeline by `scripts/ssr-smoke.ts`.
33
*
44
* Both imports must be resolved *inside* Vite's module graph so the component and the renderer
5-
* share one instance of `solid-js` / `solid-js/web` — see the comment at the `ssrLoadModule`
5+
* share one instance of `solid-js` / `@solidjs/web` — see the comment at the `ssrLoadModule`
66
* call. The library is imported by BARE SPECIFIER on purpose: that exercises the `solid` export
77
* condition the same way a real SSR consumer does.
88
*
99
* Plain `.jsx`, not `.tsx`, so it stays out of the typecheck project — `bun run check` must not
1010
* depend on `dist/` existing.
1111
*/
12-
import { renderToStringAsync } from 'solid-js/web';
12+
import { renderToString } from '@solidjs/web';
1313
import { Placeholder } from 'solid-querybuilder';
1414

15-
export const render = () => renderToStringAsync(() => <Placeholder label="ssr-smoke" />);
15+
export const render = () => renderToString(() => <Placeholder label="ssr-smoke" />);

packages/solid-querybuilder/scripts/ssr-smoke.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
* silently dead, and a key-lookup check cannot see that.
1111
* 2. Compile-and-run a trivial consumer through Vite's SSR pipeline with
1212
* `vite-plugin-solid({ solid: { generate: 'ssr', hydratable: false } })`, rendering with
13-
* `renderToStringAsync` from `solid-js/web`, and assert the full markup.
13+
* `renderToString` from `@solidjs/web` (synchronous in Solid 2), and assert the full
14+
* markup.
1415
*
1516
* At step 1 the component under test is `Placeholder`; step 4 repoints this at `QueryBuilder`.
1617
* Step 8 adds a SolidStart SSR gate but keeps this script, because it is the only thing that
@@ -124,26 +125,31 @@ const vite = await createServer({
124125
configFile: false,
125126
logLevel: 'error',
126127
plugins: [solid({ solid: { generate: 'ssr', hydratable: false } })],
127-
// `solid` so the library resolves to its raw-JSX entry, `node` so `solid-js/web` resolves to
128-
// its SERVER build. Listing `solid` alone clobbers Vite's defaults and silently hands back
129-
// `solid-js/web`'s browser build, whose `renderToStringAsync` is a stub that throws. Never
130-
// add `browser` here.
128+
// NO hand-written `ssr.resolve.conditions`. `vite-plugin-solid@3` gives the ssr environment
129+
// `['solid', 'development', 'module', 'node', 'development|production']` on its own — measured,
130+
// not assumed — which resolves the library to its raw-JSX entry (`solid`) and `@solidjs/web` to
131+
// `dist/server.js` (`node`). The Solid 1 value `['solid', 'node', 'development']` was
132+
// compensating for the 2.x plugin and now only *removes* `module` and
133+
// `development|production` from that list.
134+
//
135+
// The failure this guards against is unchanged: `@solidjs/web`'s exports map lists `browser`
136+
// BEFORE `node`, so any condition set carrying `browser` hands back the browser build, whose
137+
// server renderer is a stub that throws. Never add `browser` here.
131138
ssr: {
132139
noExternal: true,
133-
resolve: { conditions: ['solid', 'node', 'development'] },
134140
},
135141
});
136142

137-
// The entry is loaded *through* Vite, and it imports both `solid-js/web` and the library itself.
143+
// The entry is loaded *through* Vite, and it imports both `@solidjs/web` and the library itself.
138144
// That is load-bearing: `ssr.noExternal` gives Vite's module graph its own copy of `solid-js`,
139-
// so a `renderToStringAsync` imported out here in the host process would be a DIFFERENT instance
145+
// so a `renderToString` imported out here in the host process would be a DIFFERENT instance
140146
// than the one the component was compiled against. Solid keeps owner/`sharedConfig` state at
141147
// module scope, so the two copies do not share it — a trivial component survives that, but
142148
// anything using `createContext`/`createStore`/`createEffect` (i.e. `QueryBuilder`, from step 4)
143149
// does not. Keep the render inside the graph.
144150
const entry = resolve(packageRoot, 'scripts/ssr-smoke-entry.jsx');
145151
const mod = await vite.ssrLoadModule(entry);
146-
const html: string = await mod.render();
152+
const html: string = mod.render();
147153

148154
await vite.close();
149155

packages/solid-querybuilder/src/types/translations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type {
44
BaseTranslationWithLabel,
55
BaseTranslationWithPlaceholders,
66
} from '@react-querybuilder/core';
7-
import type { JSX } from 'solid-js';
7+
import type { JSX } from '@solidjs/web';
88

99
/**
1010
* Anything that can be rendered as a label.

0 commit comments

Comments
 (0)