@superblocksteam/sdk 2.0.82 → 2.0.83-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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/cli-replacement/automatic-upgrades.d.ts +0 -6
- package/dist/cli-replacement/automatic-upgrades.d.ts.map +1 -1
- package/dist/cli-replacement/automatic-upgrades.js +5 -27
- package/dist/cli-replacement/automatic-upgrades.js.map +1 -1
- package/dist/cli-replacement/dev.d.mts.map +1 -1
- package/dist/cli-replacement/dev.mjs +260 -217
- package/dist/cli-replacement/dev.mjs.map +1 -1
- package/dist/cli-replacement/version-detection.d.ts +71 -0
- package/dist/cli-replacement/version-detection.d.ts.map +1 -0
- package/dist/cli-replacement/version-detection.js +186 -0
- package/dist/cli-replacement/version-detection.js.map +1 -0
- package/dist/cli-replacement/version-detection.test.d.ts +5 -0
- package/dist/cli-replacement/version-detection.test.d.ts.map +1 -0
- package/dist/cli-replacement/version-detection.test.js +257 -0
- package/dist/cli-replacement/version-detection.test.js.map +1 -0
- package/dist/dev-utils/dev-server.mjs +133 -115
- package/dist/dev-utils/dev-server.mjs.map +1 -1
- package/dist/telemetry/index.d.ts +4 -4
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/index.js +92 -64
- package/dist/telemetry/index.js.map +1 -1
- package/dist/telemetry/index.test.d.ts +2 -0
- package/dist/telemetry/index.test.d.ts.map +1 -0
- package/dist/telemetry/index.test.js +93 -0
- package/dist/telemetry/index.test.js.map +1 -0
- package/dist/telemetry/local-obs.d.ts +73 -0
- package/dist/telemetry/local-obs.d.ts.map +1 -0
- package/dist/telemetry/local-obs.js +107 -0
- package/dist/telemetry/local-obs.js.map +1 -0
- package/dist/telemetry/util.d.ts +1 -2
- package/dist/telemetry/util.d.ts.map +1 -1
- package/dist/telemetry/util.js +26 -4
- package/dist/telemetry/util.js.map +1 -1
- package/package.json +6 -5
- package/src/cli-replacement/automatic-upgrades.ts +10 -42
- package/src/cli-replacement/dev.mts +336 -281
- package/src/cli-replacement/version-detection.test.ts +336 -0
- package/src/cli-replacement/version-detection.ts +220 -0
- package/src/dev-utils/dev-server.mts +149 -127
- package/src/telemetry/index.test.ts +130 -0
- package/src/telemetry/index.ts +105 -83
- package/src/telemetry/local-obs.ts +138 -0
- package/src/telemetry/util.ts +27 -4
- package/tsconfig.tsbuildinfo +1 -1
- 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 @@
|
|
|
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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"}
|