Skip to content

Commit 91a13ca

Browse files
authored
feat: use file watchers to track the LS CLI status (#48)
License status for LS CLI is now checked via file watchers instead of periodic checks. <!-- GitButler Footer Boundary Top --> --- This is **part 2 of 2 in a stack** made with GitButler: - <kbd>&nbsp;2&nbsp;</kbd> #48 👈 - <kbd>&nbsp;1&nbsp;</kbd> #47 <!-- GitButler Footer Boundary Bottom -->
1 parent 53f1bc5 commit 91a13ca

File tree

3 files changed

+56
-4
lines changed

3 files changed

+56
-4
lines changed

src/utils/license.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,36 @@
1+
import { homedir, platform } from "node:os";
2+
import { join } from "node:path";
3+
14
import type { CancellationToken, LogOutputChannel } from "vscode";
25

36
import { execLocalStack } from "./cli.ts";
47

8+
/**
9+
* See https://github.com/localstack/localstack/blob/de861e1f656a52eaa090b061bd44fc1a7069715e/localstack-core/localstack/utils/files.py#L38-L55.
10+
* @returns The cache directory for the current platform.
11+
*/
12+
const cacheDirectory = () => {
13+
switch (platform()) {
14+
case "win32":
15+
return join(process.env.LOCALAPPDATA!, "cache");
16+
case "darwin":
17+
return join(homedir(), "Library", "Caches");
18+
default:
19+
return process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache");
20+
}
21+
};
22+
23+
/**
24+
* The file that contains the license information of the LocalStack CLI.
25+
*
26+
* The license file is stored in the cache directory for the current platform.
27+
*/
28+
export const LICENSE_FILENAME = join(
29+
cacheDirectory(),
30+
"localstack-cli",
31+
"license.json",
32+
);
33+
534
const LICENSE_VALIDITY_MARKER = "license validity: valid";
635

736
export async function checkIsLicenseValid(outputChannel: LogOutputChannel) {

src/utils/setup-status.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from "./configure-aws.ts";
1414
import { createEmitter } from "./emitter.ts";
1515
import { immediateOnce } from "./immediate-once.ts";
16+
import { checkIsLicenseValid, LICENSE_FILENAME } from "./license.ts";
1617
import type { UnwrapPromise } from "./promises.ts";
1718
import { checkSetupStatus } from "./setup.ts";
1819
import type { TimeTracker } from "./time-tracker.ts";
@@ -39,6 +40,7 @@ export async function createSetupStatusTracker(
3940
const awsProfileTracker = createAwsProfileStatusTracker(outputChannel);
4041
const localStackAuthenticationTracker =
4142
createLocalStackAuthenticationStatusTracker(outputChannel);
43+
const licenseTracker = createLicenseStatusTracker(outputChannel);
4244
const end = Date.now();
4345
outputChannel.trace(
4446
`[setup-status]: Initialized dependencies in ${ms(end - start, { long: true })}`,
@@ -51,6 +53,7 @@ export async function createSetupStatusTracker(
5153
Object.values(statuses),
5254
awsProfileTracker.status() === "ok",
5355
localStackAuthenticationTracker.status() === "ok",
56+
licenseTracker.status() === "ok",
5457
].some((check) => check === false);
5558

5659
const newStatus = setupRequired ? "setup_required" : "ok";
@@ -75,6 +78,10 @@ export async function createSetupStatusTracker(
7578
checkStatus();
7679
});
7780

81+
licenseTracker.onChange(() => {
82+
checkStatus();
83+
});
84+
7885
let timeout: NodeJS.Timeout | undefined;
7986
const startChecking = () => {
8087
checkStatus();
@@ -225,3 +232,22 @@ function createLocalStackAuthenticationStatusTracker(
225232
async () => ((await checkIsAuthenticated()) ? "ok" : "setup_required"),
226233
);
227234
}
235+
236+
/**
237+
* Creates a status tracker that monitors the LocalStack license file for changes.
238+
* When the file is changed, the provided check function is called to determine the current setup status.
239+
* Emits status changes to registered listeners.
240+
*
241+
* @param outputChannel - Channel for logging output and trace messages.
242+
* @returns A {@link StatusTracker} instance for querying status, subscribing to changes, and disposing resources.
243+
*/
244+
function createLicenseStatusTracker(
245+
outputChannel: LogOutputChannel,
246+
): StatusTracker {
247+
return createFileStatusTracker(
248+
outputChannel,
249+
"[setup-status.license]",
250+
[LICENSE_FILENAME],
251+
async () => ((await checkIsLicenseValid(outputChannel)) ? "ok" : "setup_required"),
252+
);
253+
}

src/utils/setup.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,15 @@ import { LOCALSTACK_DOCKER_IMAGE_NAME } from "../constants.ts";
55

66
import { exec } from "./exec.ts";
77
import { checkLocalstackInstalled } from "./install.ts";
8-
import { checkIsLicenseValid } from "./license.ts";
98
import { spawn } from "./spawn.ts";
109

1110
export async function checkSetupStatus(outputChannel: LogOutputChannel) {
12-
const [isInstalled, isLicenseValid] = await Promise.all([
11+
const [isInstalled] = await Promise.all([
1312
checkLocalstackInstalled(outputChannel),
14-
checkIsLicenseValid(outputChannel),
1513
]);
1614

1715
return {
1816
isInstalled,
19-
isLicenseValid,
2017
};
2118
}
2219

0 commit comments

Comments
 (0)