@superblocksteam/sdk 2.0.83 → 2.0.84-next.1

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.
Files changed (46) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/cli-replacement/automatic-upgrades.d.ts +0 -6
  3. package/dist/cli-replacement/automatic-upgrades.d.ts.map +1 -1
  4. package/dist/cli-replacement/automatic-upgrades.js +5 -27
  5. package/dist/cli-replacement/automatic-upgrades.js.map +1 -1
  6. package/dist/cli-replacement/dev.d.mts.map +1 -1
  7. package/dist/cli-replacement/dev.mjs +260 -217
  8. package/dist/cli-replacement/dev.mjs.map +1 -1
  9. package/dist/cli-replacement/version-detection.d.ts +71 -0
  10. package/dist/cli-replacement/version-detection.d.ts.map +1 -0
  11. package/dist/cli-replacement/version-detection.js +186 -0
  12. package/dist/cli-replacement/version-detection.js.map +1 -0
  13. package/dist/cli-replacement/version-detection.test.d.ts +5 -0
  14. package/dist/cli-replacement/version-detection.test.d.ts.map +1 -0
  15. package/dist/cli-replacement/version-detection.test.js +257 -0
  16. package/dist/cli-replacement/version-detection.test.js.map +1 -0
  17. package/dist/dev-utils/dev-server.mjs +133 -115
  18. package/dist/dev-utils/dev-server.mjs.map +1 -1
  19. package/dist/telemetry/index.d.ts +4 -4
  20. package/dist/telemetry/index.d.ts.map +1 -1
  21. package/dist/telemetry/index.js +92 -64
  22. package/dist/telemetry/index.js.map +1 -1
  23. package/dist/telemetry/index.test.d.ts +2 -0
  24. package/dist/telemetry/index.test.d.ts.map +1 -0
  25. package/dist/telemetry/index.test.js +93 -0
  26. package/dist/telemetry/index.test.js.map +1 -0
  27. package/dist/telemetry/local-obs.d.ts +73 -0
  28. package/dist/telemetry/local-obs.d.ts.map +1 -0
  29. package/dist/telemetry/local-obs.js +107 -0
  30. package/dist/telemetry/local-obs.js.map +1 -0
  31. package/dist/telemetry/util.d.ts +1 -2
  32. package/dist/telemetry/util.d.ts.map +1 -1
  33. package/dist/telemetry/util.js +26 -4
  34. package/dist/telemetry/util.js.map +1 -1
  35. package/package.json +6 -5
  36. package/src/cli-replacement/automatic-upgrades.ts +10 -42
  37. package/src/cli-replacement/dev.mts +336 -281
  38. package/src/cli-replacement/version-detection.test.ts +336 -0
  39. package/src/cli-replacement/version-detection.ts +220 -0
  40. package/src/dev-utils/dev-server.mts +149 -127
  41. package/src/telemetry/index.test.ts +130 -0
  42. package/src/telemetry/index.ts +105 -83
  43. package/src/telemetry/local-obs.ts +138 -0
  44. package/src/telemetry/util.ts +27 -4
  45. package/tsconfig.tsbuildinfo +1 -1
  46. package/turbo.json +20 -2
@@ -0,0 +1,71 @@
1
+ /**
2
+ * CLI version detection with environment-aware caching.
3
+ *
4
+ * This module provides cached CLI version detection optimized for different
5
+ * environments:
6
+ * - Docker/CSB: Reads from SUPERBLOCKS_CLI_VERSION env var (instant, ~0ms)
7
+ * - Local: Caches subprocess result (6s first call, 0ms subsequent calls)
8
+ *
9
+ * The caching strategy eliminates duplicate subprocess executions that previously
10
+ * caused ~12s delays during dev server startup.
11
+ */
12
+ /**
13
+ * Package version information returned by version detection.
14
+ */
15
+ export interface PackageVersionInfo {
16
+ /** Semantic version string (e.g., "2.0.0-next.1") */
17
+ version: string;
18
+ /** Optional package alias for ephemeral builds (e.g., "@superblocksteam/cli-ephemeral") */
19
+ alias?: string;
20
+ }
21
+ /**
22
+ * Gets the current CLI version with caching.
23
+ *
24
+ * Detection strategy (in order):
25
+ * 1. Return cached value if available (only successful detections are cached)
26
+ * 2. Docker/CSB: Read from SUPERBLOCKS_CLI_VERSION env var (~0ms)
27
+ * 3. Local: Execute subprocess and cache result (~6s first call, ~0ms subsequent)
28
+ *
29
+ * The cache is shared across all callers, eliminating duplicate subprocess
30
+ * executions. This reduces dev server startup from ~12s to ~6s (local) or
31
+ * ~0s (Docker).
32
+ *
33
+ * Note: Failures are NOT cached, allowing recovery from transient issues
34
+ * (network glitches, filesystem races) without requiring a dev server restart.
35
+ *
36
+ * @returns PackageVersionInfo if CLI version can be detected, undefined otherwise
37
+ *
38
+ * @example
39
+ * // First call in Docker - instant
40
+ * const version = await getCurrentCliVersion();
41
+ * // Returns: { version: "2.0.0-next.1" }
42
+ *
43
+ * @example
44
+ * // First call locally - slow (~6s)
45
+ * const version1 = await getCurrentCliVersion();
46
+ * // Second call - instant (cached)
47
+ * const version2 = await getCurrentCliVersion();
48
+ */
49
+ export declare function getCurrentCliVersion(): Promise<PackageVersionInfo | undefined>;
50
+ /**
51
+ * Clears the cached CLI version, optionally setting it to a known value.
52
+ *
53
+ * This is used after CLI upgrades to update the cache with the newly installed
54
+ * version, avoiding the need for subprocess detection. If a version is provided,
55
+ * the cache is set to that version; otherwise, the cache is cleared and the next
56
+ * call to getCurrentCliVersion() will re-detect.
57
+ *
58
+ * @param newVersion - Optional version info to set the cache to (e.g., after upgrade)
59
+ *
60
+ * @example
61
+ * // After upgrading CLI to a known version
62
+ * clearCliVersionCache({ version: "2.0.0-next.2" });
63
+ * const version = await getCurrentCliVersion(); // Returns cached version instantly
64
+ *
65
+ * @example
66
+ * // Clear cache completely (for tests)
67
+ * clearCliVersionCache();
68
+ * const version = await getCurrentCliVersion(); // Will re-detect
69
+ */
70
+ export declare function clearCliVersionCache(newVersion?: PackageVersionInfo): void;
71
+ //# sourceMappingURL=version-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-detection.d.ts","sourceRoot":"","sources":["../../src/cli-replacement/version-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAwGD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CACnD,kBAAkB,GAAG,SAAS,CAC/B,CA4BA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAM1E"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * CLI version detection with environment-aware caching.
3
+ *
4
+ * This module provides cached CLI version detection optimized for different
5
+ * environments:
6
+ * - Docker/CSB: Reads from SUPERBLOCKS_CLI_VERSION env var (instant, ~0ms)
7
+ * - Local: Caches subprocess result (6s first call, 0ms subsequent calls)
8
+ *
9
+ * The caching strategy eliminates duplicate subprocess executions that previously
10
+ * caused ~12s delays during dev server startup.
11
+ */
12
+ import * as child_process from "node:child_process";
13
+ import { promisify } from "node:util";
14
+ import { isNativeError } from "node:util/types";
15
+ import { getLogger } from "../telemetry/logging.js";
16
+ const exec = promisify(child_process.exec);
17
+ const execFile = promisify(child_process.execFile);
18
+ const logger = getLogger();
19
+ /**
20
+ * Module-level cache for CLI version.
21
+ * - undefined: Not yet fetched
22
+ * - null: Fetch attempted but failed
23
+ * - PackageVersionInfo: Successfully fetched
24
+ */
25
+ let cachedCliVersion = undefined;
26
+ /**
27
+ * Detects if running in Docker/CSB environment.
28
+ *
29
+ * @returns true if SUPERBLOCKS_IS_CSB environment variable is set to "true"
30
+ */
31
+ function isDockerEnvironment() {
32
+ return process.env.SUPERBLOCKS_IS_CSB === "true";
33
+ }
34
+ /**
35
+ * Reads CLI version from SUPERBLOCKS_CLI_VERSION environment variable.
36
+ *
37
+ * This is the fast path for Docker/CSB environments where the version
38
+ * is injected at build time.
39
+ *
40
+ * @returns PackageVersionInfo if env var is set, undefined otherwise
41
+ */
42
+ function getVersionFromEnvironment() {
43
+ const envVersion = process.env.SUPERBLOCKS_CLI_VERSION;
44
+ if (!envVersion)
45
+ return undefined;
46
+ // Detect ephemeral builds by SNAPSHOT in version string
47
+ const isEphemeral = envVersion.includes("SNAPSHOT");
48
+ return {
49
+ version: envVersion,
50
+ alias: isEphemeral ? "@superblocksteam/cli-ephemeral" : undefined,
51
+ };
52
+ }
53
+ /**
54
+ * Detects CLI version by spawning subprocesses.
55
+ *
56
+ * This is the slow path (~6s) used in local development environments.
57
+ * It executes two commands:
58
+ * 1. `which superblocks` (or `where` on Windows) - Find CLI binary in PATH
59
+ * 2. `superblocks version --json` - Execute CLI to get version
60
+ *
61
+ * @returns PackageVersionInfo if CLI is found and version can be read, undefined otherwise
62
+ */
63
+ async function getVersionFromSubprocess() {
64
+ try {
65
+ const command = process.platform === "win32" ? "where" : "which";
66
+ const { stdout } = await exec(`${command} superblocks`);
67
+ const superblocksPath = stdout.trim().split("\n")[0]; // Take first line only
68
+ if (!superblocksPath)
69
+ return undefined;
70
+ // Use execFile to properly handle paths with spaces (e.g., "C:\Program Files\...")
71
+ const { stdout: versionOutput } = await execFile(superblocksPath, [
72
+ "version",
73
+ "--json",
74
+ ]);
75
+ const json = JSON.parse(versionOutput);
76
+ // Extract version from string like:
77
+ // - "@superblocksteam/cli/2.0.0-next.1"
78
+ // - "@superblocksteam/cli-ephemeral/2.0.0-SNAPSHOT.ebd2b86d643331f5"
79
+ const version = json.cliVersion?.replace(/@superblocksteam\/cli(-ephemeral)?\//, "");
80
+ // Detect alias (e.g., cli-ephemeral) for ephemeral builds
81
+ const aliasMatch = json.cliVersion?.match(/@superblocksteam\/([^\/]+)/);
82
+ if (aliasMatch && aliasMatch[1] !== "cli") {
83
+ return {
84
+ version: version,
85
+ alias: `@superblocksteam/${aliasMatch[1]}`,
86
+ };
87
+ }
88
+ return { version };
89
+ }
90
+ catch (error) {
91
+ if (isNativeError(error)) {
92
+ // Expected: CLI not installed (which/where returns empty or command not found)
93
+ if (error.message.includes("not found") ||
94
+ error.message.includes("command not found")) {
95
+ logger.debug("CLI binary not found in PATH");
96
+ return undefined;
97
+ }
98
+ // Unexpected: permission errors, malformed output, etc.
99
+ logger.warn(`Failed to detect CLI version: ${error.message}. Automatic upgrades will be disabled.`);
100
+ }
101
+ return undefined;
102
+ }
103
+ }
104
+ /**
105
+ * Gets the current CLI version with caching.
106
+ *
107
+ * Detection strategy (in order):
108
+ * 1. Return cached value if available (only successful detections are cached)
109
+ * 2. Docker/CSB: Read from SUPERBLOCKS_CLI_VERSION env var (~0ms)
110
+ * 3. Local: Execute subprocess and cache result (~6s first call, ~0ms subsequent)
111
+ *
112
+ * The cache is shared across all callers, eliminating duplicate subprocess
113
+ * executions. This reduces dev server startup from ~12s to ~6s (local) or
114
+ * ~0s (Docker).
115
+ *
116
+ * Note: Failures are NOT cached, allowing recovery from transient issues
117
+ * (network glitches, filesystem races) without requiring a dev server restart.
118
+ *
119
+ * @returns PackageVersionInfo if CLI version can be detected, undefined otherwise
120
+ *
121
+ * @example
122
+ * // First call in Docker - instant
123
+ * const version = await getCurrentCliVersion();
124
+ * // Returns: { version: "2.0.0-next.1" }
125
+ *
126
+ * @example
127
+ * // First call locally - slow (~6s)
128
+ * const version1 = await getCurrentCliVersion();
129
+ * // Second call - instant (cached)
130
+ * const version2 = await getCurrentCliVersion();
131
+ */
132
+ export async function getCurrentCliVersion() {
133
+ // Return cached value if available (only successful detections are cached)
134
+ if (cachedCliVersion !== undefined && cachedCliVersion !== null) {
135
+ return cachedCliVersion;
136
+ }
137
+ // Docker/CSB: Try environment variable first (fast path)
138
+ if (isDockerEnvironment()) {
139
+ cachedCliVersion = getVersionFromEnvironment();
140
+ if (cachedCliVersion) {
141
+ logger.debug(`CLI version from environment: ${cachedCliVersion.version}`);
142
+ return cachedCliVersion;
143
+ }
144
+ }
145
+ // Local: Use subprocess detection (slow path, but cached on success)
146
+ logger.debug("Detecting CLI version via subprocess...");
147
+ const detectedVersion = await getVersionFromSubprocess();
148
+ if (detectedVersion) {
149
+ logger.debug(`CLI version from subprocess: ${detectedVersion.version}`);
150
+ cachedCliVersion = detectedVersion; // Cache successful detection
151
+ }
152
+ else {
153
+ logger.debug("Could not detect CLI version");
154
+ // Don't cache failures - allow retry on next call in case of transient issues
155
+ }
156
+ return detectedVersion;
157
+ }
158
+ /**
159
+ * Clears the cached CLI version, optionally setting it to a known value.
160
+ *
161
+ * This is used after CLI upgrades to update the cache with the newly installed
162
+ * version, avoiding the need for subprocess detection. If a version is provided,
163
+ * the cache is set to that version; otherwise, the cache is cleared and the next
164
+ * call to getCurrentCliVersion() will re-detect.
165
+ *
166
+ * @param newVersion - Optional version info to set the cache to (e.g., after upgrade)
167
+ *
168
+ * @example
169
+ * // After upgrading CLI to a known version
170
+ * clearCliVersionCache({ version: "2.0.0-next.2" });
171
+ * const version = await getCurrentCliVersion(); // Returns cached version instantly
172
+ *
173
+ * @example
174
+ * // Clear cache completely (for tests)
175
+ * clearCliVersionCache();
176
+ * const version = await getCurrentCliVersion(); // Will re-detect
177
+ */
178
+ export function clearCliVersionCache(newVersion) {
179
+ if (newVersion) {
180
+ cachedCliVersion = newVersion;
181
+ }
182
+ else {
183
+ cachedCliVersion = undefined;
184
+ }
185
+ }
186
+ //# sourceMappingURL=version-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-detection.js","sourceRoot":"","sources":["../../src/cli-replacement/version-detection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for CLI version detection with caching.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=version-detection.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-detection.test.d.ts","sourceRoot":"","sources":["../../src/cli-replacement/version-detection.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Tests for CLI version detection with caching.
3
+ */
4
+ import * as child_process from "node:child_process";
5
+ import { describe, it, expect, beforeEach, vi, afterEach } from "vitest";
6
+ import { getCurrentCliVersion, clearCliVersionCache, } from "./version-detection.js";
7
+ // Mock child_process.exec and execFile
8
+ vi.mock("node:child_process", () => ({
9
+ exec: vi.fn(),
10
+ execFile: vi.fn(),
11
+ }));
12
+ // Mock logger to suppress console output during tests
13
+ vi.mock("../telemetry/logging.js", () => ({
14
+ getLogger: () => ({
15
+ debug: vi.fn(),
16
+ warn: vi.fn(),
17
+ error: vi.fn(),
18
+ }),
19
+ }));
20
+ describe("version-detection", () => {
21
+ const originalEnv = process.env;
22
+ beforeEach(() => {
23
+ // Reset environment and cache before each test
24
+ process.env = { ...originalEnv };
25
+ clearCliVersionCache(); // Clear cache
26
+ vi.clearAllMocks();
27
+ });
28
+ afterEach(() => {
29
+ // Restore original environment
30
+ process.env = originalEnv;
31
+ });
32
+ describe("Docker/CSB environment", () => {
33
+ it("should read version from SUPERBLOCKS_CLI_VERSION env var", async () => {
34
+ process.env.SUPERBLOCKS_IS_CSB = "true";
35
+ process.env.SUPERBLOCKS_CLI_VERSION = "2.0.0-next.1";
36
+ const result = await getCurrentCliVersion();
37
+ expect(result).toEqual({
38
+ version: "2.0.0-next.1",
39
+ alias: undefined,
40
+ });
41
+ // Should not call subprocess
42
+ expect(child_process.exec).not.toHaveBeenCalled();
43
+ });
44
+ it("should detect ephemeral builds from SNAPSHOT in version", async () => {
45
+ process.env.SUPERBLOCKS_IS_CSB = "true";
46
+ process.env.SUPERBLOCKS_CLI_VERSION = "2.0.0-SNAPSHOT.ebd2b86d643331f5";
47
+ const result = await getCurrentCliVersion();
48
+ expect(result).toEqual({
49
+ version: "2.0.0-SNAPSHOT.ebd2b86d643331f5",
50
+ alias: "@superblocksteam/cli-ephemeral",
51
+ });
52
+ expect(child_process.exec).not.toHaveBeenCalled();
53
+ });
54
+ it("should fall back to subprocess if env var not set", async () => {
55
+ process.env.SUPERBLOCKS_IS_CSB = "true";
56
+ // No SUPERBLOCKS_CLI_VERSION set
57
+ // Mock subprocess calls
58
+ const execMock = child_process.exec;
59
+ const execFileMock = child_process.execFile;
60
+ execMock.mockImplementationOnce((_cmd, callback) => {
61
+ // which/where command
62
+ callback(null, { stdout: "/usr/local/bin/superblocks\n" });
63
+ });
64
+ execFileMock.mockImplementationOnce((_path, _args, callback) => {
65
+ // version command
66
+ callback(null, {
67
+ stdout: JSON.stringify({
68
+ cliVersion: "@superblocksteam/cli/2.0.0-next.1",
69
+ }),
70
+ });
71
+ });
72
+ const result = await getCurrentCliVersion();
73
+ expect(result).toEqual({
74
+ version: "2.0.0-next.1",
75
+ });
76
+ expect(child_process.exec).toHaveBeenCalledTimes(1);
77
+ expect(child_process.execFile).toHaveBeenCalledTimes(1);
78
+ });
79
+ });
80
+ describe("Local environment", () => {
81
+ beforeEach(() => {
82
+ process.env.SUPERBLOCKS_IS_CSB = "false";
83
+ });
84
+ it("should detect version via subprocess", async () => {
85
+ const execMock = child_process.exec;
86
+ const execFileMock = child_process.execFile;
87
+ execMock.mockImplementationOnce((_cmd, callback) => {
88
+ // which/where command
89
+ callback(null, { stdout: "/usr/local/bin/superblocks\n" });
90
+ });
91
+ execFileMock.mockImplementationOnce((_path, _args, callback) => {
92
+ // version command
93
+ callback(null, {
94
+ stdout: JSON.stringify({
95
+ cliVersion: "@superblocksteam/cli/2.0.0-next.1",
96
+ }),
97
+ });
98
+ });
99
+ const result = await getCurrentCliVersion();
100
+ expect(result).toEqual({
101
+ version: "2.0.0-next.1",
102
+ });
103
+ expect(child_process.exec).toHaveBeenCalledTimes(1);
104
+ expect(child_process.execFile).toHaveBeenCalledTimes(1);
105
+ });
106
+ it("should detect ephemeral builds with alias", async () => {
107
+ const execMock = child_process.exec;
108
+ const execFileMock = child_process.execFile;
109
+ execMock.mockImplementationOnce((_cmd, callback) => {
110
+ callback(null, { stdout: "/usr/local/bin/superblocks\n" });
111
+ });
112
+ execFileMock.mockImplementationOnce((_path, _args, callback) => {
113
+ callback(null, {
114
+ stdout: JSON.stringify({
115
+ cliVersion: "@superblocksteam/cli-ephemeral/2.0.0-SNAPSHOT.ebd2b86d643331f5",
116
+ }),
117
+ });
118
+ });
119
+ const result = await getCurrentCliVersion();
120
+ expect(result).toEqual({
121
+ version: "2.0.0-SNAPSHOT.ebd2b86d643331f5",
122
+ alias: "@superblocksteam/cli-ephemeral",
123
+ });
124
+ });
125
+ it("should use Windows 'where' command on win32", async () => {
126
+ const originalPlatform = process.platform;
127
+ Object.defineProperty(process, "platform", {
128
+ value: "win32",
129
+ configurable: true,
130
+ });
131
+ try {
132
+ const execMock = child_process.exec;
133
+ const execFileMock = child_process.execFile;
134
+ execMock.mockImplementationOnce((cmd, callback) => {
135
+ expect(cmd).toContain("where superblocks");
136
+ callback(null, { stdout: "C:\\Program Files\\superblocks.exe\n" });
137
+ });
138
+ execFileMock.mockImplementationOnce((_path, _args, callback) => {
139
+ callback(null, {
140
+ stdout: JSON.stringify({
141
+ cliVersion: "@superblocksteam/cli/2.0.0-next.1",
142
+ }),
143
+ });
144
+ });
145
+ await getCurrentCliVersion();
146
+ }
147
+ finally {
148
+ // Restore platform
149
+ Object.defineProperty(process, "platform", {
150
+ value: originalPlatform,
151
+ configurable: true,
152
+ });
153
+ }
154
+ });
155
+ it("should return undefined if CLI not found", async () => {
156
+ const execMock = child_process.exec;
157
+ execMock.mockImplementationOnce((_cmd, callback) => {
158
+ callback(null, { stdout: "" }); // Empty output = not found
159
+ });
160
+ const result = await getCurrentCliVersion();
161
+ expect(result).toBeUndefined();
162
+ // Should only call which/where, not version command
163
+ expect(child_process.exec).toHaveBeenCalledTimes(1);
164
+ });
165
+ it("should return undefined on error", async () => {
166
+ const execMock = child_process.exec;
167
+ execMock.mockImplementationOnce((_cmd, callback) => {
168
+ callback(new Error("Command not found"));
169
+ });
170
+ const result = await getCurrentCliVersion();
171
+ expect(result).toBeUndefined();
172
+ });
173
+ });
174
+ describe("Caching behavior", () => {
175
+ beforeEach(() => {
176
+ process.env.SUPERBLOCKS_IS_CSB = "false";
177
+ });
178
+ it("should cache successful subprocess result", async () => {
179
+ const execMock = child_process.exec;
180
+ const execFileMock = child_process.execFile;
181
+ execMock.mockImplementationOnce((_cmd, callback) => {
182
+ callback(null, { stdout: "/usr/local/bin/superblocks\n" });
183
+ });
184
+ execFileMock.mockImplementationOnce((_path, _args, callback) => {
185
+ callback(null, {
186
+ stdout: JSON.stringify({
187
+ cliVersion: "@superblocksteam/cli/2.0.0-next.1",
188
+ }),
189
+ });
190
+ });
191
+ // First call - should execute subprocess
192
+ const result1 = await getCurrentCliVersion();
193
+ expect(result1).toEqual({ version: "2.0.0-next.1" });
194
+ expect(child_process.exec).toHaveBeenCalledTimes(1);
195
+ expect(child_process.execFile).toHaveBeenCalledTimes(1);
196
+ // Second call - should use cache
197
+ const result2 = await getCurrentCliVersion();
198
+ expect(result2).toEqual({ version: "2.0.0-next.1" });
199
+ expect(child_process.exec).toHaveBeenCalledTimes(1); // Still 1, not 2
200
+ expect(child_process.execFile).toHaveBeenCalledTimes(1); // Still 1, not 2
201
+ });
202
+ it("should cache Docker env var result", async () => {
203
+ process.env.SUPERBLOCKS_IS_CSB = "true";
204
+ process.env.SUPERBLOCKS_CLI_VERSION = "2.0.0-next.1";
205
+ // First call
206
+ const result1 = await getCurrentCliVersion();
207
+ expect(result1).toEqual({ version: "2.0.0-next.1", alias: undefined });
208
+ // Second call - should use cache
209
+ const result2 = await getCurrentCliVersion();
210
+ expect(result2).toEqual({ version: "2.0.0-next.1", alias: undefined });
211
+ expect(child_process.exec).not.toHaveBeenCalled();
212
+ });
213
+ it("should NOT cache failures (allows retry on transient errors)", async () => {
214
+ const execMock = child_process.exec;
215
+ execMock
216
+ .mockImplementationOnce((_cmd, callback) => {
217
+ callback(new Error("Not found"));
218
+ })
219
+ .mockImplementationOnce((_cmd, callback) => {
220
+ callback(new Error("Still not found"));
221
+ });
222
+ // First call - should attempt detection and fail
223
+ const result1 = await getCurrentCliVersion();
224
+ expect(result1).toBeUndefined();
225
+ expect(child_process.exec).toHaveBeenCalledTimes(1);
226
+ // Second call - should retry (not cached) since failures aren't cached
227
+ const result2 = await getCurrentCliVersion();
228
+ expect(result2).toBeUndefined();
229
+ expect(child_process.exec).toHaveBeenCalledTimes(2); // Retried!
230
+ });
231
+ it("should re-detect after cache is cleared", async () => {
232
+ const execMock = child_process.exec;
233
+ const execFileMock = child_process.execFile;
234
+ execMock.mockImplementation((_cmd, callback) => {
235
+ callback(null, { stdout: "/usr/local/bin/superblocks\n" });
236
+ });
237
+ execFileMock.mockImplementation((_path, _args, callback) => {
238
+ callback(null, {
239
+ stdout: JSON.stringify({
240
+ cliVersion: "@superblocksteam/cli/2.0.0-next.1",
241
+ }),
242
+ });
243
+ });
244
+ // First detection
245
+ await getCurrentCliVersion();
246
+ expect(child_process.exec).toHaveBeenCalledTimes(1);
247
+ expect(child_process.execFile).toHaveBeenCalledTimes(1);
248
+ // Clear cache
249
+ clearCliVersionCache();
250
+ // Should re-detect
251
+ await getCurrentCliVersion();
252
+ expect(child_process.exec).toHaveBeenCalledTimes(2); // 1 + 1
253
+ expect(child_process.execFile).toHaveBeenCalledTimes(2); // 1 + 1
254
+ });
255
+ });
256
+ });
257
+ //# sourceMappingURL=version-detection.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-detection.test.js","sourceRoot":"","sources":["../../src/cli-replacement/version-detection.test.ts"],"names":[],"mappings":"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"}