@valbuild/cli 0.124.0 → 0.125.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,93 @@
1
1
  # @valbuild/cli
2
2
 
3
+ ## 0.125.0
4
+
5
+ ### Patch Changes
6
+
7
+ - [#638](https://github.com/valbuild/val/pull/638) [`c390397`](https://github.com/valbuild/val/commit/c390397cb5e203eb1bedae3a6fab15726e850b90) Thanks [@freekh](https://github.com/freekh)! - Val now runs on TanStack Start.
8
+
9
+ `@valbuild/tanstack` is a new package with everything `@valbuild/next` has: Val
10
+ Studio at `/val`, the on-page overlay and canvas, draft mode, the client hooks,
11
+ server-side content reads, images, and the MCP tools.
12
+
13
+ ```sh
14
+ npm install @valbuild/tanstack
15
+ ```
16
+
17
+ ```ts
18
+ // val.config.ts
19
+ import { initVal } from "@valbuild/tanstack";
20
+ const { s, c, config, tanstackRouter } = initVal({ project: "org/project" });
21
+ ```
22
+
23
+ **Routes are first class.** A Val module for a route is named after the route
24
+ file it sits beside — `src/routes/posts.$postId.tsx` is served content by
25
+ `src/routes/posts.$postId.val.ts` — and its keys are the URLs that route serves:
26
+
27
+ ```ts
28
+ export default c.define(
29
+ "/src/routes/posts.$postId.val.ts",
30
+ s.router(tanstackRouter, s.object({ title: s.string() })),
31
+ { "/posts/hello-world": { title: "Hello world" } },
32
+ );
33
+ ```
34
+
35
+ `.` and `/` both separate segments, `$param` is a parameter, `$` is a splat, and
36
+ `index`, `route`, `(groups)` and `_pathless` layouts add no URL segment — the
37
+ same rules TanStack Router uses for the route file itself. Val validates every
38
+ key against that pattern, and Val Studio shows these modules as a sitemap under
39
+ **Pages**, where an editor can add a page.
40
+
41
+ Point the route generator away from your content files, in `vite.config.ts` and
42
+ `tsr.config.json`:
43
+
44
+ ```ts
45
+ tanstackStart({ router: { routeFileIgnorePattern: "\\.val\\.[tj]sx?$" } });
46
+ ```
47
+
48
+ See the [README](https://github.com/valbuild/val/blob/main/packages/tanstack/README.md)
49
+ for the full wiring, and `examples/tanstack` for a working app.
50
+
51
+ **Also fixed, for everyone:** `Internal.VERSION.core` was `null` in any ESM
52
+ bundle — it was read with `require("../package.json")` inside a `try`, so the
53
+ failure was silent. That version goes into every remote file ref and proxy mode
54
+ refuses to start without it. Every package now reads its version through a
55
+ static JSON import, which is inlined at build time.
56
+
57
+ Two smaller fixes that came out of running the whole toolchain against a
58
+ TanStack project:
59
+
60
+ - `val versions` reports `@valbuild/tanstack`, and `val debug` writes a snapshot
61
+ that names whichever framework package the captured project actually has.
62
+ - `@valbuild/eslint-plugin` reads a `tsconfig.json` that has comments in it. A
63
+ tsconfig is JSONC, and `JSON.parse` is not — so on any project whose tsconfig
64
+ carries a comment (the TanStack starter's does) the
65
+ `module-in-val-modules` rule threw `Expected double-quoted property name in
66
+ JSON` on the first file and took the whole lint run with it.
67
+
68
+ Three fixes found by driving the Studio against a real TanStack app:
69
+
70
+ - **A draft image now loads on the page.** The source the Studio pushes to the
71
+ host page carries `patch_id` for any file whose bytes are still in a patch, so
72
+ the page asks `/api/val/files/...?patch_id=` rather than a `/public` path that
73
+ nothing has written yet. This was silent — the image just did not appear — and
74
+ it affects any page that reads media through the hooks rather than on the
75
+ server, `@valbuild/next` included.
76
+ - **A splat route no longer logs an error on every render.** TanStack returns
77
+ both `_splat` and `*` for the same parameter; Val reported the second as a
78
+ parameter it could not place in the path.
79
+ - The TanStack example and starter render a 404 page instead of throwing
80
+ `notFound()` from a component, which escaped to the error boundary and logged
81
+ `Error in renderToReadableStream` (and, with no not-found component
82
+ configured, aborted the response) on every miss.
83
+
84
+ - Updated dependencies [[`22f78b4`](https://github.com/valbuild/val/commit/22f78b471fd18e542f518f72b75bd472d7c3dc52), [`c390397`](https://github.com/valbuild/val/commit/c390397cb5e203eb1bedae3a6fab15726e850b90)]:
85
+ - @valbuild/language-server@0.125.0
86
+ - @valbuild/core@0.125.0
87
+ - @valbuild/shared@0.125.0
88
+ - @valbuild/eslint-plugin@0.125.0
89
+ - @valbuild/server@0.125.0
90
+
3
91
  ## 0.124.0
4
92
 
5
93
  ### Patch Changes
@@ -975,30 +975,33 @@ function isFileRef(value) {
975
975
  return !!value && typeof value === "object" && "path" in value && typeof value.path === "string";
976
976
  }
977
977
 
978
+ /**
979
+ * The versions of the Val packages this project has installed.
980
+ *
981
+ * Each is resolved from the project rather than declared, because the CLI is a
982
+ * dependency of the project and not the other way round — and a project has
983
+ * exactly one framework package, so the one that is absent is absent rather
984
+ * than broken. `undefined` is the honest answer for it.
985
+ */
978
986
  const getVersions = () => {
979
- const coreVersion = (() => {
980
- try {
981
- var _require;
982
- // eslint-disable-next-line @typescript-eslint/no-require-imports
983
- return (_require = require("@valbuild/core")) === null || _require === void 0 || (_require = _require.Internal) === null || _require === void 0 || (_require = _require.VERSION) === null || _require === void 0 ? void 0 : _require.core;
984
- } catch {
985
- return null;
986
- }
987
- })();
988
- const nextVersion = (() => {
989
- try {
990
- var _require2;
991
- // eslint-disable-next-line @typescript-eslint/no-require-imports
992
- return (_require2 = require("@valbuild/next")) === null || _require2 === void 0 || (_require2 = _require2.Internal) === null || _require2 === void 0 || (_require2 = _require2.VERSION) === null || _require2 === void 0 ? void 0 : _require2.next;
993
- } catch {
994
- return null;
995
- }
996
- })();
987
+ const coreVersion = requireVersion("@valbuild/core", "core");
988
+ const nextVersion = requireVersion("@valbuild/next", "next");
989
+ const tanstackVersion = requireVersion("@valbuild/tanstack", "tanstack");
997
990
  return {
998
991
  coreVersion: coreVersion || undefined,
999
- nextVersion: nextVersion || undefined
992
+ nextVersion: nextVersion || undefined,
993
+ tanstackVersion: tanstackVersion || undefined
1000
994
  };
1001
995
  };
996
+ function requireVersion(packageName, key) {
997
+ try {
998
+ var _require;
999
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
1000
+ return ((_require = require(packageName)) === null || _require === void 0 || (_require = _require.Internal) === null || _require === void 0 || (_require = _require.VERSION) === null || _require === void 0 ? void 0 : _require[key]) ?? null;
1001
+ } catch {
1002
+ return null;
1003
+ }
1004
+ }
1002
1005
 
1003
1006
  const host = process.env.VAL_BUILD_URL || "https://admin.val.build";
1004
1007
  async function connect(options) {
@@ -1597,6 +1600,7 @@ async function buildSnapshot(ctx, options = {}) {
1597
1600
  versions: {
1598
1601
  core: getVersions().coreVersion,
1599
1602
  next: getVersions().nextVersion,
1603
+ tanstack: getVersions().tanstackVersion,
1600
1604
  project: readProjectValVersions(ctx.projectRoot),
1601
1605
  node: process.version,
1602
1606
  platform: `${process.platform}-${process.arch}`
@@ -1692,9 +1696,18 @@ function generateValModules(moduleFilePaths) {
1692
1696
  const withoutExt = moduleFilePath.replace(/\.(ts|js|tsx|jsx)$/, "");
1693
1697
  return ` { def: () => import(".${withoutExt}") },`;
1694
1698
  }).join("\n");
1699
+ /*
1700
+ * The framework package the captured project actually has.
1701
+ *
1702
+ * A snapshot is replayed by loading this file, so naming the wrong one makes
1703
+ * it fail to resolve on a machine that has the other. `getVersions` answers
1704
+ * from what is installed; the fallback matters only for a project with
1705
+ * neither, which could not have produced a snapshot anyway.
1706
+ */
1707
+ const frameworkPackage = getVersions().tanstackVersion ? "@valbuild/tanstack" : "@valbuild/next";
1695
1708
  return `// GENERATED by \`val debug\`: trimmed to the modules this snapshot carries.
1696
1709
  // The project's original is kept as val.modules.original.ts.
1697
- import { modules } from "@valbuild/next";
1710
+ import { modules } from "${frameworkPackage}";
1698
1711
  import { config } from "./val.config";
1699
1712
 
1700
1713
  export default modules(config, [
@@ -1709,7 +1722,7 @@ Captured ${manifest.generatedAt} from project \`${manifest.project ?? "(fs mode)
1709
1722
  branch \`${manifest.branch ?? "?"}\`, commit \`${manifest.commit ?? "?"}\`.
1710
1723
 
1711
1724
  - @valbuild/core: \`${manifest.versions.core ?? "?"}\`
1712
- - @valbuild/next: \`${manifest.versions.next ?? "?"}\`
1725
+ - ${manifest.versions.tanstack ? `@valbuild/tanstack: \`${manifest.versions.tanstack}\`` : `@valbuild/next: \`${manifest.versions.next ?? "?"}\``}
1713
1726
  - ${manifest.patchCount} pending patches, ${manifest.unappliablePatchCount} of which could not be applied.
1714
1727
 
1715
1728
  ## Replaying it
@@ -2234,5 +2247,15 @@ void main().catch(err => {
2234
2247
  async function versions() {
2235
2248
  const foundVersions = getVersions();
2236
2249
  console.log(`${chalk__default["default"].cyan("@valbuild/core")}: ${foundVersions.coreVersion}`);
2237
- console.log(`${chalk__default["default"].cyan("@valbuild/next")}: ${foundVersions.nextVersion}`);
2250
+ // Only the framework package this project actually has. Printing the other
2251
+ // as `undefined` reads as something missing rather than something absent.
2252
+ if (foundVersions.nextVersion) {
2253
+ console.log(`${chalk__default["default"].cyan("@valbuild/next")}: ${foundVersions.nextVersion}`);
2254
+ }
2255
+ if (foundVersions.tanstackVersion) {
2256
+ console.log(`${chalk__default["default"].cyan("@valbuild/tanstack")}: ${foundVersions.tanstackVersion}`);
2257
+ }
2258
+ if (!foundVersions.nextVersion && !foundVersions.tanstackVersion) {
2259
+ console.log(`${chalk__default["default"].yellow("No framework package found")}: install @valbuild/next or @valbuild/tanstack`);
2260
+ }
2238
2261
  }
@@ -975,30 +975,33 @@ function isFileRef(value) {
975
975
  return !!value && typeof value === "object" && "path" in value && typeof value.path === "string";
976
976
  }
977
977
 
978
+ /**
979
+ * The versions of the Val packages this project has installed.
980
+ *
981
+ * Each is resolved from the project rather than declared, because the CLI is a
982
+ * dependency of the project and not the other way round — and a project has
983
+ * exactly one framework package, so the one that is absent is absent rather
984
+ * than broken. `undefined` is the honest answer for it.
985
+ */
978
986
  const getVersions = () => {
979
- const coreVersion = (() => {
980
- try {
981
- var _require;
982
- // eslint-disable-next-line @typescript-eslint/no-require-imports
983
- return (_require = require("@valbuild/core")) === null || _require === void 0 || (_require = _require.Internal) === null || _require === void 0 || (_require = _require.VERSION) === null || _require === void 0 ? void 0 : _require.core;
984
- } catch {
985
- return null;
986
- }
987
- })();
988
- const nextVersion = (() => {
989
- try {
990
- var _require2;
991
- // eslint-disable-next-line @typescript-eslint/no-require-imports
992
- return (_require2 = require("@valbuild/next")) === null || _require2 === void 0 || (_require2 = _require2.Internal) === null || _require2 === void 0 || (_require2 = _require2.VERSION) === null || _require2 === void 0 ? void 0 : _require2.next;
993
- } catch {
994
- return null;
995
- }
996
- })();
987
+ const coreVersion = requireVersion("@valbuild/core", "core");
988
+ const nextVersion = requireVersion("@valbuild/next", "next");
989
+ const tanstackVersion = requireVersion("@valbuild/tanstack", "tanstack");
997
990
  return {
998
991
  coreVersion: coreVersion || undefined,
999
- nextVersion: nextVersion || undefined
992
+ nextVersion: nextVersion || undefined,
993
+ tanstackVersion: tanstackVersion || undefined
1000
994
  };
1001
995
  };
996
+ function requireVersion(packageName, key) {
997
+ try {
998
+ var _require;
999
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
1000
+ return ((_require = require(packageName)) === null || _require === void 0 || (_require = _require.Internal) === null || _require === void 0 || (_require = _require.VERSION) === null || _require === void 0 ? void 0 : _require[key]) ?? null;
1001
+ } catch {
1002
+ return null;
1003
+ }
1004
+ }
1002
1005
 
1003
1006
  const host = process.env.VAL_BUILD_URL || "https://admin.val.build";
1004
1007
  async function connect(options) {
@@ -1597,6 +1600,7 @@ async function buildSnapshot(ctx, options = {}) {
1597
1600
  versions: {
1598
1601
  core: getVersions().coreVersion,
1599
1602
  next: getVersions().nextVersion,
1603
+ tanstack: getVersions().tanstackVersion,
1600
1604
  project: readProjectValVersions(ctx.projectRoot),
1601
1605
  node: process.version,
1602
1606
  platform: `${process.platform}-${process.arch}`
@@ -1692,9 +1696,18 @@ function generateValModules(moduleFilePaths) {
1692
1696
  const withoutExt = moduleFilePath.replace(/\.(ts|js|tsx|jsx)$/, "");
1693
1697
  return ` { def: () => import(".${withoutExt}") },`;
1694
1698
  }).join("\n");
1699
+ /*
1700
+ * The framework package the captured project actually has.
1701
+ *
1702
+ * A snapshot is replayed by loading this file, so naming the wrong one makes
1703
+ * it fail to resolve on a machine that has the other. `getVersions` answers
1704
+ * from what is installed; the fallback matters only for a project with
1705
+ * neither, which could not have produced a snapshot anyway.
1706
+ */
1707
+ const frameworkPackage = getVersions().tanstackVersion ? "@valbuild/tanstack" : "@valbuild/next";
1695
1708
  return `// GENERATED by \`val debug\`: trimmed to the modules this snapshot carries.
1696
1709
  // The project's original is kept as val.modules.original.ts.
1697
- import { modules } from "@valbuild/next";
1710
+ import { modules } from "${frameworkPackage}";
1698
1711
  import { config } from "./val.config";
1699
1712
 
1700
1713
  export default modules(config, [
@@ -1709,7 +1722,7 @@ Captured ${manifest.generatedAt} from project \`${manifest.project ?? "(fs mode)
1709
1722
  branch \`${manifest.branch ?? "?"}\`, commit \`${manifest.commit ?? "?"}\`.
1710
1723
 
1711
1724
  - @valbuild/core: \`${manifest.versions.core ?? "?"}\`
1712
- - @valbuild/next: \`${manifest.versions.next ?? "?"}\`
1725
+ - ${manifest.versions.tanstack ? `@valbuild/tanstack: \`${manifest.versions.tanstack}\`` : `@valbuild/next: \`${manifest.versions.next ?? "?"}\``}
1713
1726
  - ${manifest.patchCount} pending patches, ${manifest.unappliablePatchCount} of which could not be applied.
1714
1727
 
1715
1728
  ## Replaying it
@@ -2234,5 +2247,15 @@ void main().catch(err => {
2234
2247
  async function versions() {
2235
2248
  const foundVersions = getVersions();
2236
2249
  console.log(`${chalk__default["default"].cyan("@valbuild/core")}: ${foundVersions.coreVersion}`);
2237
- console.log(`${chalk__default["default"].cyan("@valbuild/next")}: ${foundVersions.nextVersion}`);
2250
+ // Only the framework package this project actually has. Printing the other
2251
+ // as `undefined` reads as something missing rather than something absent.
2252
+ if (foundVersions.nextVersion) {
2253
+ console.log(`${chalk__default["default"].cyan("@valbuild/next")}: ${foundVersions.nextVersion}`);
2254
+ }
2255
+ if (foundVersions.tanstackVersion) {
2256
+ console.log(`${chalk__default["default"].cyan("@valbuild/tanstack")}: ${foundVersions.tanstackVersion}`);
2257
+ }
2258
+ if (!foundVersions.nextVersion && !foundVersions.tanstackVersion) {
2259
+ console.log(`${chalk__default["default"].yellow("No framework package found")}: install @valbuild/next or @valbuild/tanstack`);
2260
+ }
2238
2261
  }
@@ -943,30 +943,33 @@ function isFileRef(value) {
943
943
  return !!value && typeof value === "object" && "path" in value && typeof value.path === "string";
944
944
  }
945
945
 
946
+ /**
947
+ * The versions of the Val packages this project has installed.
948
+ *
949
+ * Each is resolved from the project rather than declared, because the CLI is a
950
+ * dependency of the project and not the other way round — and a project has
951
+ * exactly one framework package, so the one that is absent is absent rather
952
+ * than broken. `undefined` is the honest answer for it.
953
+ */
946
954
  const getVersions = () => {
947
- const coreVersion = (() => {
948
- try {
949
- var _require;
950
- // eslint-disable-next-line @typescript-eslint/no-require-imports
951
- return (_require = require("@valbuild/core")) === null || _require === void 0 || (_require = _require.Internal) === null || _require === void 0 || (_require = _require.VERSION) === null || _require === void 0 ? void 0 : _require.core;
952
- } catch {
953
- return null;
954
- }
955
- })();
956
- const nextVersion = (() => {
957
- try {
958
- var _require2;
959
- // eslint-disable-next-line @typescript-eslint/no-require-imports
960
- return (_require2 = require("@valbuild/next")) === null || _require2 === void 0 || (_require2 = _require2.Internal) === null || _require2 === void 0 || (_require2 = _require2.VERSION) === null || _require2 === void 0 ? void 0 : _require2.next;
961
- } catch {
962
- return null;
963
- }
964
- })();
955
+ const coreVersion = requireVersion("@valbuild/core", "core");
956
+ const nextVersion = requireVersion("@valbuild/next", "next");
957
+ const tanstackVersion = requireVersion("@valbuild/tanstack", "tanstack");
965
958
  return {
966
959
  coreVersion: coreVersion || undefined,
967
- nextVersion: nextVersion || undefined
960
+ nextVersion: nextVersion || undefined,
961
+ tanstackVersion: tanstackVersion || undefined
968
962
  };
969
963
  };
964
+ function requireVersion(packageName, key) {
965
+ try {
966
+ var _require;
967
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
968
+ return ((_require = require(packageName)) === null || _require === void 0 || (_require = _require.Internal) === null || _require === void 0 || (_require = _require.VERSION) === null || _require === void 0 ? void 0 : _require[key]) ?? null;
969
+ } catch {
970
+ return null;
971
+ }
972
+ }
970
973
 
971
974
  const host = process.env.VAL_BUILD_URL || "https://admin.val.build";
972
975
  async function connect(options) {
@@ -1565,6 +1568,7 @@ async function buildSnapshot(ctx, options = {}) {
1565
1568
  versions: {
1566
1569
  core: getVersions().coreVersion,
1567
1570
  next: getVersions().nextVersion,
1571
+ tanstack: getVersions().tanstackVersion,
1568
1572
  project: readProjectValVersions(ctx.projectRoot),
1569
1573
  node: process.version,
1570
1574
  platform: `${process.platform}-${process.arch}`
@@ -1660,9 +1664,18 @@ function generateValModules(moduleFilePaths) {
1660
1664
  const withoutExt = moduleFilePath.replace(/\.(ts|js|tsx|jsx)$/, "");
1661
1665
  return ` { def: () => import(".${withoutExt}") },`;
1662
1666
  }).join("\n");
1667
+ /*
1668
+ * The framework package the captured project actually has.
1669
+ *
1670
+ * A snapshot is replayed by loading this file, so naming the wrong one makes
1671
+ * it fail to resolve on a machine that has the other. `getVersions` answers
1672
+ * from what is installed; the fallback matters only for a project with
1673
+ * neither, which could not have produced a snapshot anyway.
1674
+ */
1675
+ const frameworkPackage = getVersions().tanstackVersion ? "@valbuild/tanstack" : "@valbuild/next";
1663
1676
  return `// GENERATED by \`val debug\`: trimmed to the modules this snapshot carries.
1664
1677
  // The project's original is kept as val.modules.original.ts.
1665
- import { modules } from "@valbuild/next";
1678
+ import { modules } from "${frameworkPackage}";
1666
1679
  import { config } from "./val.config";
1667
1680
 
1668
1681
  export default modules(config, [
@@ -1677,7 +1690,7 @@ Captured ${manifest.generatedAt} from project \`${manifest.project ?? "(fs mode)
1677
1690
  branch \`${manifest.branch ?? "?"}\`, commit \`${manifest.commit ?? "?"}\`.
1678
1691
 
1679
1692
  - @valbuild/core: \`${manifest.versions.core ?? "?"}\`
1680
- - @valbuild/next: \`${manifest.versions.next ?? "?"}\`
1693
+ - ${manifest.versions.tanstack ? `@valbuild/tanstack: \`${manifest.versions.tanstack}\`` : `@valbuild/next: \`${manifest.versions.next ?? "?"}\``}
1681
1694
  - ${manifest.patchCount} pending patches, ${manifest.unappliablePatchCount} of which could not be applied.
1682
1695
 
1683
1696
  ## Replaying it
@@ -2202,5 +2215,15 @@ void main().catch(err => {
2202
2215
  async function versions() {
2203
2216
  const foundVersions = getVersions();
2204
2217
  console.log(`${chalk.cyan("@valbuild/core")}: ${foundVersions.coreVersion}`);
2205
- console.log(`${chalk.cyan("@valbuild/next")}: ${foundVersions.nextVersion}`);
2218
+ // Only the framework package this project actually has. Printing the other
2219
+ // as `undefined` reads as something missing rather than something absent.
2220
+ if (foundVersions.nextVersion) {
2221
+ console.log(`${chalk.cyan("@valbuild/next")}: ${foundVersions.nextVersion}`);
2222
+ }
2223
+ if (foundVersions.tanstackVersion) {
2224
+ console.log(`${chalk.cyan("@valbuild/tanstack")}: ${foundVersions.tanstackVersion}`);
2225
+ }
2226
+ if (!foundVersions.nextVersion && !foundVersions.tanstackVersion) {
2227
+ console.log(`${chalk.yellow("No framework package found")}: install @valbuild/next or @valbuild/tanstack`);
2228
+ }
2206
2229
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@valbuild/cli",
3
3
  "private": false,
4
- "version": "0.124.0",
4
+ "version": "0.125.0",
5
5
  "description": "Val CLI tools",
6
6
  "repository": {
7
7
  "type": "git",
@@ -24,11 +24,11 @@
24
24
  "jszip": "^3.10.1",
25
25
  "meow": "^9.0.0",
26
26
  "picocolors": "^1.1.1",
27
- "@valbuild/core": "0.124.0",
28
- "@valbuild/eslint-plugin": "0.108.0",
29
- "@valbuild/language-server": "0.124.0",
30
- "@valbuild/server": "0.124.0",
31
- "@valbuild/shared": "0.124.0"
27
+ "@valbuild/eslint-plugin": "0.125.0",
28
+ "@valbuild/core": "0.125.0",
29
+ "@valbuild/shared": "0.125.0",
30
+ "@valbuild/language-server": "0.125.0",
31
+ "@valbuild/server": "0.125.0"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "prettier": "*",
package/src/cli.ts CHANGED
@@ -228,5 +228,21 @@ void main().catch((err) => {
228
228
  async function versions() {
229
229
  const foundVersions = getVersions();
230
230
  console.log(`${chalk.cyan("@valbuild/core")}: ${foundVersions.coreVersion}`);
231
- console.log(`${chalk.cyan("@valbuild/next")}: ${foundVersions.nextVersion}`);
231
+ // Only the framework package this project actually has. Printing the other
232
+ // as `undefined` reads as something missing rather than something absent.
233
+ if (foundVersions.nextVersion) {
234
+ console.log(
235
+ `${chalk.cyan("@valbuild/next")}: ${foundVersions.nextVersion}`,
236
+ );
237
+ }
238
+ if (foundVersions.tanstackVersion) {
239
+ console.log(
240
+ `${chalk.cyan("@valbuild/tanstack")}: ${foundVersions.tanstackVersion}`,
241
+ );
242
+ }
243
+ if (!foundVersions.nextVersion && !foundVersions.tanstackVersion) {
244
+ console.log(
245
+ `${chalk.yellow("No framework package found")}: install @valbuild/next or @valbuild/tanstack`,
246
+ );
247
+ }
232
248
  }
@@ -39,6 +39,7 @@ export type SnapshotManifest = {
39
39
  /** Resolved at runtime by the cli that captured this. */
40
40
  core?: string;
41
41
  next?: string;
42
+ tanstack?: string;
42
43
  /**
43
44
  * The @valbuild/* versions the project declares. This is what to check out
44
45
  * in the val repo in order to replay on the code the customer was running.
@@ -253,6 +254,7 @@ export async function buildSnapshot(
253
254
  versions: {
254
255
  core: getVersions().coreVersion,
255
256
  next: getVersions().nextVersion,
257
+ tanstack: getVersions().tanstackVersion,
256
258
  project: readProjectValVersions(ctx.projectRoot),
257
259
  node: process.version,
258
260
  platform: `${process.platform}-${process.arch}`,
@@ -380,9 +382,20 @@ function generateValModules(moduleFilePaths: string[]): string {
380
382
  return ` { def: () => import(".${withoutExt}") },`;
381
383
  })
382
384
  .join("\n");
385
+ /*
386
+ * The framework package the captured project actually has.
387
+ *
388
+ * A snapshot is replayed by loading this file, so naming the wrong one makes
389
+ * it fail to resolve on a machine that has the other. `getVersions` answers
390
+ * from what is installed; the fallback matters only for a project with
391
+ * neither, which could not have produced a snapshot anyway.
392
+ */
393
+ const frameworkPackage = getVersions().tanstackVersion
394
+ ? "@valbuild/tanstack"
395
+ : "@valbuild/next";
383
396
  return `// GENERATED by \`val debug\`: trimmed to the modules this snapshot carries.
384
397
  // The project's original is kept as val.modules.original.ts.
385
- import { modules } from "@valbuild/next";
398
+ import { modules } from "${frameworkPackage}";
386
399
  import { config } from "./val.config";
387
400
 
388
401
  export default modules(config, [
@@ -398,7 +411,11 @@ Captured ${manifest.generatedAt} from project \`${manifest.project ?? "(fs mode)
398
411
  branch \`${manifest.branch ?? "?"}\`, commit \`${manifest.commit ?? "?"}\`.
399
412
 
400
413
  - @valbuild/core: \`${manifest.versions.core ?? "?"}\`
401
- - @valbuild/next: \`${manifest.versions.next ?? "?"}\`
414
+ - ${
415
+ manifest.versions.tanstack
416
+ ? `@valbuild/tanstack: \`${manifest.versions.tanstack}\``
417
+ : `@valbuild/next: \`${manifest.versions.next ?? "?"}\``
418
+ }
402
419
  - ${manifest.patchCount} pending patches, ${manifest.unappliablePatchCount} of which could not be applied.
403
420
 
404
421
  ## Replaying it
@@ -1,25 +1,31 @@
1
+ /**
2
+ * The versions of the Val packages this project has installed.
3
+ *
4
+ * Each is resolved from the project rather than declared, because the CLI is a
5
+ * dependency of the project and not the other way round — and a project has
6
+ * exactly one framework package, so the one that is absent is absent rather
7
+ * than broken. `undefined` is the honest answer for it.
8
+ */
1
9
  export const getVersions = (): {
2
10
  coreVersion?: string;
3
11
  nextVersion?: string;
12
+ tanstackVersion?: string;
4
13
  } => {
5
- const coreVersion = (() => {
6
- try {
7
- // eslint-disable-next-line @typescript-eslint/no-require-imports
8
- return require("@valbuild/core")?.Internal?.VERSION?.core;
9
- } catch {
10
- return null;
11
- }
12
- })();
13
- const nextVersion = (() => {
14
- try {
15
- // eslint-disable-next-line @typescript-eslint/no-require-imports
16
- return require("@valbuild/next")?.Internal?.VERSION?.next;
17
- } catch {
18
- return null;
19
- }
20
- })();
14
+ const coreVersion = requireVersion("@valbuild/core", "core");
15
+ const nextVersion = requireVersion("@valbuild/next", "next");
16
+ const tanstackVersion = requireVersion("@valbuild/tanstack", "tanstack");
21
17
  return {
22
18
  coreVersion: coreVersion || undefined,
23
19
  nextVersion: nextVersion || undefined,
20
+ tanstackVersion: tanstackVersion || undefined,
24
21
  };
25
22
  };
23
+
24
+ function requireVersion(packageName: string, key: string): string | null {
25
+ try {
26
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
27
+ return require(packageName)?.Internal?.VERSION?.[key] ?? null;
28
+ } catch {
29
+ return null;
30
+ }
31
+ }