Skip to content

Commit e5185f4

Browse files
committed
wip
1 parent aefe72f commit e5185f4

File tree

7 files changed

+72
-256
lines changed

7 files changed

+72
-256
lines changed

package.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,6 @@
5555
"title": "Run Setup Wizard",
5656
"category": "LocalStack"
5757
},
58-
{
59-
"command": "localstack.refreshStatusBar",
60-
"title": "Refresh Status Bar",
61-
"category": "LocalStack",
62-
"enablement": "false"
63-
},
6458
{
6559
"command": "localstack.showCommands",
6660
"title": "Show Commands",

src/plugins/status-bar.ts

Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -79,48 +79,16 @@ export default createPlugin(
7979
}),
8080
);
8181

82-
// context.subscriptions.push(
83-
// commands.registerCommand("localstack.refreshStatusBar", () => {
84-
// const setupStatus = setupStatusTracker.status();
85-
// const localStackStatus = localStackStatusTracker.status();
86-
// const localStackInstalled = cliStatusTracker.status() === "ok"
87-
88-
// statusBarItem.command = "localstack.showCommands";
89-
// statusBarItem.backgroundColor =
90-
// setupStatus === "setup_required"
91-
// ? new ThemeColor("statusBarItem.errorBackground")
92-
// : undefined;
93-
94-
// const shouldSpin =
95-
// localStackStatus === "starting" || localStackStatus === "stopping";
96-
// const icon =
97-
// setupStatus === "setup_required"
98-
// ? "$(error)"
99-
// : shouldSpin
100-
// ? "$(sync~spin)"
101-
// : "$(localstack-logo)";
102-
103-
// const statusText = localStackInstalled
104-
// ? `${localStackStatus}`
105-
// : "not installed";
106-
// statusBarItem.text = `${icon} LocalStack: ${statusText}`;
107-
108-
// statusBarItem.tooltip = "Show LocalStack commands";
109-
// statusBarItem.show();
110-
// }),
111-
// );
112-
113-
const refreshStatusBar = immediateOnce(() => {
114-
// await commands.executeCommand("localstack.refreshStatusBar");
82+
const renderStatusBar = immediateOnce(() => {
11583
const setupStatus = setupStatusTracker.status();
11684
const localStackStatus = localStackStatusTracker.status();
11785
const cliStatus = cliStatusTracker.status();
86+
outputChannel.trace(
87+
`[status-bar] setupStatus=${setupStatus} localStackStatus=${localStackStatus} cliStatus=${cliStatus}`,
88+
);
11889

119-
if (
120-
setupStatus === undefined ||
121-
localStackStatus === undefined ||
122-
cliStatus === undefined
123-
) {
90+
// Skip rendering the status bar if any of the status checks is not ready.
91+
if (setupStatus === undefined || cliStatus === undefined) {
12492
return;
12593
}
12694

@@ -151,12 +119,12 @@ export default createPlugin(
151119

152120
localStackStatusTracker.onChange(() => {
153121
outputChannel.trace("[status-bar]: localStackStatusTracker changed");
154-
refreshStatusBar();
122+
renderStatusBar();
155123
});
156124

157125
setupStatusTracker.onChange(() => {
158126
outputChannel.trace("[status-bar]: setupStatusTracker changed");
159-
refreshStatusBar();
127+
renderStatusBar();
160128
});
161129
},
162130
);

src/utils/cli.ts

Lines changed: 3 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import EventEmitter from "node:events";
21
import { constants } from "node:fs";
32
import { access } from "node:fs/promises";
43
import { isAbsolute } from "node:path";
@@ -9,11 +8,9 @@ import type { CancellationToken, LogOutputChannel, Disposable } from "vscode";
98

109
import { CLI_PATHS, LOCALSTACK_DOCKER_IMAGE_NAME } from "../constants.ts";
1110

12-
import { createEmitter, createValueEmitter } from "./emitter.ts";
13-
import type { Callback } from "./emitter.ts";
11+
import { createValueEmitter } from "./emitter.ts";
1412
import { exec } from "./exec.ts";
1513
import { immediateOnce } from "./immediate-once.ts";
16-
import { setIntervalPromise } from "./promises.ts";
1714
import type { SetupStatus } from "./setup-status.ts";
1815
import { spawn } from "./spawn.ts";
1916
import type { SpawnOptions } from "./spawn.ts";
@@ -100,16 +97,6 @@ async function findLocalStack(): Promise<CliCheckResult> {
10097
executable,
10198
upToDate,
10299
};
103-
// const {found, executable, upToDate} = await verifyLocalStackCli(customLocation);
104-
// if (!found) {
105-
// throw new Error(`Configured LocalStack CLI location '${customLocation}' does not exist`);
106-
// }
107-
// if (!executable) {
108-
// throw new Error(`Configured LocalStack CLI location '${customLocation}' is not executable`);
109-
// }
110-
// if (!upToDate) {
111-
// throw new Error(`Configured LocalStack CLI location '${customLocation}' is outdated (version < 4)`);
112-
// }
113100
}
114101

115102
// Fall back to default search paths
@@ -175,71 +162,17 @@ export const spawnLocalStack = async (
175162
export type LocalStackCliStatus = "not_found" | "outdated" | "ok";
176163

177164
export interface LocalStackCliTracker extends Disposable {
178-
// setupStatus(): SetupStatus | undefined;
179-
// onSetupStatusChange(
180-
// callback: (status: SetupStatus | undefined) => void,
181-
// ): void;
182-
// cli(): CliCheckResult | undefined;
183-
// onCliChange(callback: (cli: CliCheckResult | undefined) => void): void;
184-
// cliStatus(): LocalStackCliStatus | undefined;
185-
// onCliStatusChange(callback: (status: LocalStackCliStatus) => void): void;
186-
187165
status(): SetupStatus | undefined;
188166
onStatusChange(callback: (status: SetupStatus | undefined) => void): void;
189167
cliPath(): string | undefined;
190168
onCliPathChange(callback: (cliPath: string | undefined) => void): void;
191169
}
192170

193-
function areCliCheckResultsDifferent(
194-
resultA: CliCheckResult | undefined,
195-
resultB: CliCheckResult | undefined,
196-
): boolean {
197-
if (resultA?.cliPath !== resultB?.cliPath) {
198-
return true;
199-
}
200-
if (resultA?.found !== resultB?.found) {
201-
return true;
202-
}
203-
if (resultA?.executable !== resultB?.executable) {
204-
return true;
205-
}
206-
return false;
207-
}
208-
209-
function statusFromCliCheckResult(
210-
cli: CliCheckResult | undefined,
211-
): LocalStackCliStatus {
212-
if (!cli?.found || !cli.executable) {
213-
return "not_found";
214-
}
215-
if (cli.upToDate === false) {
216-
return "outdated";
217-
}
218-
return "ok";
219-
}
220-
221171
export function createCliStatusTracker(
222172
outputChannel: LogOutputChannel,
223173
): LocalStackCliTracker {
224-
// const emitter = new EventEmitter<{
225-
// setupStatus: [SetupStatus | undefined];
226-
// cliStatus: [LocalStackCliStatus | undefined];
227-
// cli: [CliCheckResult | undefined];
228-
// }>();
229-
230-
// emitter.emit("setupStatus", )
231-
232174
const status = createValueEmitter<SetupStatus>();
233175
const cliPath = createValueEmitter<string | undefined>();
234-
// const cliStatus = createValueEmitter<LocalStackCliStatus>();
235-
236-
// const statusEmitter = createEmitter<LocalStackCliStatus>(outputChannel);
237-
// let currentStatus: LocalStackCliStatus | undefined;
238-
239-
// let currentCli: CliCheckResult | undefined;
240-
// const cliPathEmitter = createEmitter<CliCheckResult | undefined>(
241-
// outputChannel,
242-
// );
243176

244177
const track = immediateOnce(async () => {
245178
const newCli = await findLocalStack().catch(() => undefined);
@@ -251,17 +184,6 @@ export function createCliStatusTracker(
251184
: "setup_required",
252185
);
253186
cliPath.setValue(newCli?.cliPath);
254-
255-
// if (areCliCheckResultsDifferent(currentCli, newCli)) {
256-
// currentCli = newCli;
257-
// void cliPathEmitter.emit(currentCli);
258-
// }
259-
260-
// const newStatus = statusFromCliCheckResult(newCli);
261-
// if (currentStatus !== newStatus) {
262-
// currentStatus = newStatus;
263-
// void statusEmitter.emit(newStatus);
264-
// }
265187
});
266188

267189
const watcher = watch(
@@ -290,35 +212,17 @@ export function createCliStatusTracker(
290212
track();
291213

292214
return {
293-
// cli() {
294-
// return currentCli;
295-
// },
296-
// onCliChange(callback) {
297-
// cliPathEmitter.on(callback);
298-
// if (currentCli) {
299-
// callback(currentCli);
300-
// }
301-
// },
302-
// cliStatus() {
303-
// return currentStatus;
304-
// },
305-
// onCliStatusChange(callback) {
306-
// statusEmitter.on(callback);
307-
// if (currentStatus) {
308-
// callback(currentStatus);
309-
// }
310-
// },
311215
cliPath() {
312216
return cliPath.value();
313217
},
314218
onCliPathChange(callback) {
315-
cliPath.on(callback);
219+
cliPath.onChange(callback);
316220
},
317221
status() {
318222
return status.value();
319223
},
320224
onStatusChange(callback) {
321-
status.on(callback);
225+
status.onChange(callback);
322226
},
323227
async dispose() {
324228
await watcher.close();

src/utils/container-status.ts

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,49 @@ import { exec, spawn } from "node:child_process";
33
import type { Disposable, LogOutputChannel } from "vscode";
44
import * as z from "zod/v4-mini";
55

6-
import { createEmitter } from "./emitter.ts";
6+
import { createValueEmitter } from "./emitter.ts";
77
import { JsonLinesStream } from "./json-lines-stream.ts";
88
import type { TimeTracker } from "./time-tracker.ts";
99

1010
export type ContainerStatus = "running" | "stopping" | "stopped";
1111

1212
export interface ContainerStatusTracker extends Disposable {
13-
status(): ContainerStatus;
14-
onChange(callback: (status: ContainerStatus) => void): void;
13+
status(): ContainerStatus | undefined;
14+
onChange(callback: (status: ContainerStatus | undefined) => void): void;
1515
}
1616

1717
/**
1818
* Checks the status of a docker container in realtime.
1919
*/
20-
export async function createContainerStatusTracker(
20+
export function createContainerStatusTracker(
2121
containerName: string,
2222
outputChannel: LogOutputChannel,
2323
timeTracker: TimeTracker,
24-
): Promise<ContainerStatusTracker> {
25-
let status: ContainerStatus | undefined;
26-
const emitter = createEmitter<ContainerStatus>(outputChannel);
24+
): ContainerStatusTracker {
25+
const status = createValueEmitter<ContainerStatus>();
2726

2827
const disposable = listenToContainerStatus(
2928
containerName,
3029
outputChannel,
3130
(newStatus) => {
32-
if (status !== newStatus) {
33-
status = newStatus;
34-
void emitter.emit(status);
35-
}
31+
status.setValue(newStatus);
3632
},
3733
);
3834

39-
await timeTracker.run("container-status.getContainerStatus", async () => {
35+
void timeTracker.run("container-status.getContainerStatus", async () => {
4036
await getContainerStatus(containerName).then((newStatus) => {
41-
status ??= newStatus;
42-
void emitter.emit(status);
37+
if (status.value() !== undefined) {
38+
status.setValue(newStatus);
39+
}
4340
});
4441
});
4542

4643
return {
4744
status() {
48-
// biome-ignore lint/style/noNonNullAssertion: false positive
49-
return status!;
45+
return status.value();
5046
},
5147
onChange(callback) {
52-
emitter.on(callback);
53-
if (status) {
54-
callback(status);
55-
}
48+
status.onChange(callback);
5649
},
5750
dispose() {
5851
disposable.dispose();

src/utils/emitter.ts

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,11 @@
1-
import type { LogOutputChannel } from "vscode";
2-
31
import { immediateOnce } from "./immediate-once.ts";
42

53
export type Callback<T> = (value: T) => Promise<void> | void;
64

7-
export interface Emitter<T> {
8-
on(callback: Callback<T>): void;
9-
emit(value: T): Promise<void>;
10-
}
11-
12-
export function createEmitter<T>(outputChannel: LogOutputChannel): Emitter<T> {
13-
const callbacks: Callback<T>[] = [];
14-
15-
return {
16-
on(callback) {
17-
callbacks.push(callback);
18-
},
19-
async emit(value) {
20-
for (const callback of callbacks) {
21-
try {
22-
await callback(value);
23-
} catch (error) {
24-
outputChannel.error(error instanceof Error ? error : String(error));
25-
}
26-
}
27-
},
28-
};
29-
}
30-
315
export interface ValueEmitter<T> {
326
value(): T | undefined;
337
setValue(value: T): void;
34-
on(callback: Callback<T>): void;
8+
onChange(callback: Callback<T>): void;
359
}
3610

3711
export function createValueEmitter<T>(): ValueEmitter<T> {
@@ -56,8 +30,11 @@ export function createValueEmitter<T>(): ValueEmitter<T> {
5630
emit();
5731
}
5832
},
59-
on(callback) {
33+
onChange(callback) {
6034
callbacks.push(callback);
35+
if (currentValue) {
36+
void Promise.resolve(callback(currentValue)).catch(() => {});
37+
}
6138
},
6239
};
6340
}

0 commit comments

Comments
 (0)