@valbuild/cli 0.149.1 → 0.149.3

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,21 @@
1
1
  # @valbuild/cli
2
2
 
3
+ ## 0.149.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies []:
8
+ - @valbuild/server@0.149.3
9
+ - @valbuild/language-server@0.149.3
10
+
11
+ ## 0.149.2
12
+
13
+ ### Patch Changes
14
+
15
+ - [#917](https://github.com/valbuild/val/pull/917) [`48ca810`](https://github.com/valbuild/val/commit/48ca810a985af2a0af845c779d39c3da7f7fb0fc) Thanks [@freekh](https://github.com/freekh)! - `val publish` now declares `@valbuild/ui` at the version your project actually runs. A project that does not declare `@valbuild/ui` gets it added when it is wired for the platform, because the Studio's bundle lives there. It used to be added at `@valbuild/core`'s version, which can be an older release than the `@valbuild/ui` your `@valbuild/tanstack` uses. The two are no longer always released together, and the mismatch could install a second, older Studio. It now takes the version installed beside `@valbuild/tanstack`, and if no installed copy can be found it says so in a warning. A project that declares `@valbuild/ui` itself is left unchanged.
16
+ - Updated dependencies [[`48ca810`](https://github.com/valbuild/val/commit/48ca810a985af2a0af845c779d39c3da7f7fb0fc)]:
17
+ - @valbuild/tanstack-build@0.149.2
18
+
3
19
  ## 0.149.1
4
20
 
5
21
  ### Patch Changes
@@ -2517,6 +2517,45 @@ async function loadBuilder() {
2517
2517
  }
2518
2518
  }
2519
2519
 
2520
+ /**
2521
+ * The `@valbuild/ui` this checkout runs: the one its `@valbuild/tanstack`
2522
+ * resolves, which is a transitive dependency pnpm does not hoist -- so it is
2523
+ * looked for FROM that package, and only then from the project itself. `null`
2524
+ * when neither has one installed.
2525
+ *
2526
+ * Handed to `wireUp`, which declares `@valbuild/ui` for a project that does
2527
+ * not and can only see source files.
2528
+ */
2529
+ function installedStudioVersion(root) {
2530
+ const tanstack = installedPackageDir(root, "@valbuild/tanstack");
2531
+ const ui = (tanstack ? installedPackageDir(tanstack, "@valbuild/ui") : null) ?? installedPackageDir(root, "@valbuild/ui");
2532
+ if (ui === null) return null;
2533
+ try {
2534
+ const manifest = JSON.parse(fs__default$1["default"].readFileSync(path__default["default"].join(ui, "package.json"), "utf8"));
2535
+ return typeof manifest === "object" && manifest !== null && "version" in manifest && typeof manifest.version === "string" ? manifest.version : null;
2536
+ } catch {
2537
+ return null;
2538
+ }
2539
+ }
2540
+
2541
+ /**
2542
+ * Where `name` is installed as Node would find it from `from`: in the nearest
2543
+ * `node_modules` upward, through pnpm's symlinks. Walked by hand rather than
2544
+ * with `require.resolve`, which a test runner replaces with its own resolver.
2545
+ */
2546
+ function installedPackageDir(from, name) {
2547
+ let dir = path__default["default"].resolve(from);
2548
+ for (;;) {
2549
+ const candidate = path__default["default"].join(dir, "node_modules", name);
2550
+ if (fs__default$1["default"].existsSync(path__default["default"].join(candidate, "package.json"))) {
2551
+ return fs__default$1["default"].realpathSync(candidate);
2552
+ }
2553
+ const parent = path__default["default"].dirname(dir);
2554
+ if (parent === dir) return null;
2555
+ dir = parent;
2556
+ }
2557
+ }
2558
+
2520
2559
  /**
2521
2560
  * Never the project's own files, at any depth: installed packages. Dot
2522
2561
  * directories (`.git`, `.tanstack`, `.val`, `.output`) are tooling too.
@@ -2686,11 +2725,15 @@ async function buildArtifacts(options) {
2686
2725
  sources: onDisk,
2687
2726
  assets
2688
2727
  } = readProjectFiles(root, builder.isAsset);
2728
+ const studioVersion = installedStudioVersion(root);
2689
2729
  const wiring = builder.isValProject(onDisk) && !builder.isWired(onDisk) ? builder.wireUp(onDisk, {
2690
2730
  project: options.project,
2691
2731
  loader: options.contentHost,
2692
2732
  ...(options.git ? {
2693
2733
  git: options.git
2734
+ } : {}),
2735
+ ...(studioVersion ? {
2736
+ studioVersion
2694
2737
  } : {})
2695
2738
  }) : null;
2696
2739
  // Less the one about the layer, which is the thing this goes on to build.
@@ -2517,6 +2517,45 @@ async function loadBuilder() {
2517
2517
  }
2518
2518
  }
2519
2519
 
2520
+ /**
2521
+ * The `@valbuild/ui` this checkout runs: the one its `@valbuild/tanstack`
2522
+ * resolves, which is a transitive dependency pnpm does not hoist -- so it is
2523
+ * looked for FROM that package, and only then from the project itself. `null`
2524
+ * when neither has one installed.
2525
+ *
2526
+ * Handed to `wireUp`, which declares `@valbuild/ui` for a project that does
2527
+ * not and can only see source files.
2528
+ */
2529
+ function installedStudioVersion(root) {
2530
+ const tanstack = installedPackageDir(root, "@valbuild/tanstack");
2531
+ const ui = (tanstack ? installedPackageDir(tanstack, "@valbuild/ui") : null) ?? installedPackageDir(root, "@valbuild/ui");
2532
+ if (ui === null) return null;
2533
+ try {
2534
+ const manifest = JSON.parse(fs__default$1["default"].readFileSync(path__default["default"].join(ui, "package.json"), "utf8"));
2535
+ return typeof manifest === "object" && manifest !== null && "version" in manifest && typeof manifest.version === "string" ? manifest.version : null;
2536
+ } catch {
2537
+ return null;
2538
+ }
2539
+ }
2540
+
2541
+ /**
2542
+ * Where `name` is installed as Node would find it from `from`: in the nearest
2543
+ * `node_modules` upward, through pnpm's symlinks. Walked by hand rather than
2544
+ * with `require.resolve`, which a test runner replaces with its own resolver.
2545
+ */
2546
+ function installedPackageDir(from, name) {
2547
+ let dir = path__default["default"].resolve(from);
2548
+ for (;;) {
2549
+ const candidate = path__default["default"].join(dir, "node_modules", name);
2550
+ if (fs__default$1["default"].existsSync(path__default["default"].join(candidate, "package.json"))) {
2551
+ return fs__default$1["default"].realpathSync(candidate);
2552
+ }
2553
+ const parent = path__default["default"].dirname(dir);
2554
+ if (parent === dir) return null;
2555
+ dir = parent;
2556
+ }
2557
+ }
2558
+
2520
2559
  /**
2521
2560
  * Never the project's own files, at any depth: installed packages. Dot
2522
2561
  * directories (`.git`, `.tanstack`, `.val`, `.output`) are tooling too.
@@ -2686,11 +2725,15 @@ async function buildArtifacts(options) {
2686
2725
  sources: onDisk,
2687
2726
  assets
2688
2727
  } = readProjectFiles(root, builder.isAsset);
2728
+ const studioVersion = installedStudioVersion(root);
2689
2729
  const wiring = builder.isValProject(onDisk) && !builder.isWired(onDisk) ? builder.wireUp(onDisk, {
2690
2730
  project: options.project,
2691
2731
  loader: options.contentHost,
2692
2732
  ...(options.git ? {
2693
2733
  git: options.git
2734
+ } : {}),
2735
+ ...(studioVersion ? {
2736
+ studioVersion
2694
2737
  } : {})
2695
2738
  }) : null;
2696
2739
  // Less the one about the layer, which is the thing this goes on to build.
@@ -2482,6 +2482,45 @@ async function loadBuilder() {
2482
2482
  }
2483
2483
  }
2484
2484
 
2485
+ /**
2486
+ * The `@valbuild/ui` this checkout runs: the one its `@valbuild/tanstack`
2487
+ * resolves, which is a transitive dependency pnpm does not hoist -- so it is
2488
+ * looked for FROM that package, and only then from the project itself. `null`
2489
+ * when neither has one installed.
2490
+ *
2491
+ * Handed to `wireUp`, which declares `@valbuild/ui` for a project that does
2492
+ * not and can only see source files.
2493
+ */
2494
+ function installedStudioVersion(root) {
2495
+ const tanstack = installedPackageDir(root, "@valbuild/tanstack");
2496
+ const ui = (tanstack ? installedPackageDir(tanstack, "@valbuild/ui") : null) ?? installedPackageDir(root, "@valbuild/ui");
2497
+ if (ui === null) return null;
2498
+ try {
2499
+ const manifest = JSON.parse(fs$1.readFileSync(path.join(ui, "package.json"), "utf8"));
2500
+ return typeof manifest === "object" && manifest !== null && "version" in manifest && typeof manifest.version === "string" ? manifest.version : null;
2501
+ } catch {
2502
+ return null;
2503
+ }
2504
+ }
2505
+
2506
+ /**
2507
+ * Where `name` is installed as Node would find it from `from`: in the nearest
2508
+ * `node_modules` upward, through pnpm's symlinks. Walked by hand rather than
2509
+ * with `require.resolve`, which a test runner replaces with its own resolver.
2510
+ */
2511
+ function installedPackageDir(from, name) {
2512
+ let dir = path.resolve(from);
2513
+ for (;;) {
2514
+ const candidate = path.join(dir, "node_modules", name);
2515
+ if (fs$1.existsSync(path.join(candidate, "package.json"))) {
2516
+ return fs$1.realpathSync(candidate);
2517
+ }
2518
+ const parent = path.dirname(dir);
2519
+ if (parent === dir) return null;
2520
+ dir = parent;
2521
+ }
2522
+ }
2523
+
2485
2524
  /**
2486
2525
  * Never the project's own files, at any depth: installed packages. Dot
2487
2526
  * directories (`.git`, `.tanstack`, `.val`, `.output`) are tooling too.
@@ -2651,11 +2690,15 @@ async function buildArtifacts(options) {
2651
2690
  sources: onDisk,
2652
2691
  assets
2653
2692
  } = readProjectFiles(root, builder.isAsset);
2693
+ const studioVersion = installedStudioVersion(root);
2654
2694
  const wiring = builder.isValProject(onDisk) && !builder.isWired(onDisk) ? builder.wireUp(onDisk, {
2655
2695
  project: options.project,
2656
2696
  loader: options.contentHost,
2657
2697
  ...(options.git ? {
2658
2698
  git: options.git
2699
+ } : {}),
2700
+ ...(studioVersion ? {
2701
+ studioVersion
2659
2702
  } : {})
2660
2703
  }) : null;
2661
2704
  // Less the one about the layer, which is the thing this goes on to build.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@valbuild/cli",
3
3
  "private": false,
4
- "version": "0.149.1",
4
+ "version": "0.149.3",
5
5
  "description": "Val CLI tools",
6
6
  "repository": {
7
7
  "type": "git",
@@ -26,10 +26,10 @@
26
26
  "picocolors": "^1.1.1",
27
27
  "zod": "^4.4.3",
28
28
  "zod-validation-error": "^5.0.0",
29
- "@valbuild/core": "0.148.7",
30
29
  "@valbuild/eslint-plugin": "0.125.0",
31
- "@valbuild/language-server": "0.149.1",
32
- "@valbuild/server": "0.149.1",
30
+ "@valbuild/language-server": "0.149.3",
31
+ "@valbuild/core": "0.148.7",
32
+ "@valbuild/server": "0.149.3",
33
33
  "@valbuild/shared": "0.148.7"
34
34
  },
35
35
  "peerDependencies": {
@@ -38,7 +38,7 @@
38
38
  "rolldown": ">=1.2.5",
39
39
  "@tanstack/router-generator": ">=1.167.0",
40
40
  "@tanstack/router-plugin": ">=1.168.0",
41
- "@valbuild/tanstack-build": "^0.148.5"
41
+ "@valbuild/tanstack-build": "^0.149.2"
42
42
  },
43
43
  "peerDependenciesMeta": {
44
44
  "@valbuild/tanstack-build": {
@@ -70,7 +70,7 @@
70
70
  "prettier": "~3.8.5",
71
71
  "rolldown": "^1.2.5",
72
72
  "tsx": "^4.23.12",
73
- "@valbuild/tanstack-build": "0.148.5"
73
+ "@valbuild/tanstack-build": "0.149.2"
74
74
  },
75
75
  "scripts": {
76
76
  "start": "tsx src/cli.ts --",
@@ -74,6 +74,54 @@ async function loadBuilder(): Promise<
74
74
  }
75
75
  }
76
76
 
77
+ /**
78
+ * The `@valbuild/ui` this checkout runs: the one its `@valbuild/tanstack`
79
+ * resolves, which is a transitive dependency pnpm does not hoist -- so it is
80
+ * looked for FROM that package, and only then from the project itself. `null`
81
+ * when neither has one installed.
82
+ *
83
+ * Handed to `wireUp`, which declares `@valbuild/ui` for a project that does
84
+ * not and can only see source files.
85
+ */
86
+ export function installedStudioVersion(root: string): string | null {
87
+ const tanstack = installedPackageDir(root, "@valbuild/tanstack");
88
+ const ui =
89
+ (tanstack ? installedPackageDir(tanstack, "@valbuild/ui") : null) ??
90
+ installedPackageDir(root, "@valbuild/ui");
91
+ if (ui === null) return null;
92
+ try {
93
+ const manifest: unknown = JSON.parse(
94
+ fs.readFileSync(path.join(ui, "package.json"), "utf8"),
95
+ );
96
+ return typeof manifest === "object" &&
97
+ manifest !== null &&
98
+ "version" in manifest &&
99
+ typeof manifest.version === "string"
100
+ ? manifest.version
101
+ : null;
102
+ } catch {
103
+ return null;
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Where `name` is installed as Node would find it from `from`: in the nearest
109
+ * `node_modules` upward, through pnpm's symlinks. Walked by hand rather than
110
+ * with `require.resolve`, which a test runner replaces with its own resolver.
111
+ */
112
+ function installedPackageDir(from: string, name: string): string | null {
113
+ let dir = path.resolve(from);
114
+ for (;;) {
115
+ const candidate = path.join(dir, "node_modules", name);
116
+ if (fs.existsSync(path.join(candidate, "package.json"))) {
117
+ return fs.realpathSync(candidate);
118
+ }
119
+ const parent = path.dirname(dir);
120
+ if (parent === dir) return null;
121
+ dir = parent;
122
+ }
123
+ }
124
+
77
125
  /**
78
126
  * Never the project's own files, at any depth: installed packages. Dot
79
127
  * directories (`.git`, `.tanstack`, `.val`, `.output`) are tooling too.
@@ -254,12 +302,14 @@ export async function buildArtifacts(options: {
254
302
  * same thing for a record that is already wired.
255
303
  */
256
304
  const { sources: onDisk, assets } = readProjectFiles(root, builder.isAsset);
305
+ const studioVersion = installedStudioVersion(root);
257
306
  const wiring =
258
307
  builder.isValProject(onDisk) && !builder.isWired(onDisk)
259
308
  ? builder.wireUp(onDisk, {
260
309
  project: options.project,
261
310
  loader: options.contentHost,
262
311
  ...(options.git ? { git: options.git } : {}),
312
+ ...(studioVersion ? { studioVersion } : {}),
263
313
  })
264
314
  : null;
265
315
  // Less the one about the layer, which is the thing this goes on to build.
@@ -0,0 +1,59 @@
1
+ import fs from "fs";
2
+ import os from "os";
3
+ import path from "path";
4
+ import { installedStudioVersion } from "./buildArtifacts";
5
+
6
+ /**
7
+ * The `@valbuild/ui` a checkout runs is the one its `@valbuild/tanstack`
8
+ * resolves. pnpm does not hoist a transitive dependency, so it sits beside
9
+ * tanstack rather than at the project's root -- and a root copy, where there
10
+ * is one, is not necessarily the Studio that runs.
11
+ */
12
+
13
+ let root: string;
14
+
15
+ function writePackage(dir: string, name: string, version: string) {
16
+ fs.mkdirSync(dir, { recursive: true });
17
+ fs.writeFileSync(
18
+ path.join(dir, "package.json"),
19
+ JSON.stringify({ name, version }),
20
+ );
21
+ }
22
+
23
+ beforeEach(() => {
24
+ root = fs.mkdtempSync(path.join(os.tmpdir(), "val-studio-version-"));
25
+ writePackage(root, "a-site", "0.0.0");
26
+ });
27
+
28
+ afterEach(() => {
29
+ fs.rmSync(root, { recursive: true, force: true });
30
+ });
31
+
32
+ test("is the @valbuild/ui that @valbuild/tanstack resolves", () => {
33
+ const tanstack = path.join(root, "node_modules", "@valbuild", "tanstack");
34
+ writePackage(tanstack, "@valbuild/tanstack", "0.149.1");
35
+ writePackage(
36
+ path.join(tanstack, "node_modules", "@valbuild", "ui"),
37
+ "@valbuild/ui",
38
+ "0.149.1",
39
+ );
40
+ writePackage(
41
+ path.join(root, "node_modules", "@valbuild", "ui"),
42
+ "@valbuild/ui",
43
+ "0.148.7",
44
+ );
45
+ expect(installedStudioVersion(root)).toBe("0.149.1");
46
+ });
47
+
48
+ test("is the project's own @valbuild/ui without @valbuild/tanstack", () => {
49
+ writePackage(
50
+ path.join(root, "node_modules", "@valbuild", "ui"),
51
+ "@valbuild/ui",
52
+ "0.149.1",
53
+ );
54
+ expect(installedStudioVersion(root)).toBe("0.149.1");
55
+ });
56
+
57
+ test("is null when nothing is installed", () => {
58
+ expect(installedStudioVersion(root)).toBeNull();
59
+ });