@moneysiren/cli 0.1.0-alpha.1 → 0.1.0-alpha.2
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/README.md +2 -2
- package/dist/apps/cli/src/cli.d.ts +3 -0
- package/dist/apps/cli/src/cli.js +9 -2
- package/dist/apps/cli/src/commands/modes.js +13 -11
- package/dist/apps/cli/src/commands/runtime.d.ts +2 -0
- package/dist/apps/cli/src/commands/runtime.js +167 -0
- package/dist/apps/cli/src/desktop-runtime.d.ts +31 -0
- package/dist/apps/cli/src/desktop-runtime.js +441 -0
- package/dist/apps/cli/src/home.js +16 -0
- package/dist/apps/cli/src/postinstall.js +1 -1
- package/dist/apps/cli/src/release-installer.d.ts +1 -1
- package/dist/apps/cli/src/release-installer.js +2 -2
- package/dist/apps/cli/src/slash.js +12 -0
- package/dist/apps/cli/src/version.d.ts +1 -1
- package/dist/apps/cli/src/version.js +1 -1
- package/dist/packages/config/src/load.js +3 -0
- package/dist/packages/config/src/schema.d.ts +3 -0
- package/dist/packages/config/src/schema.js +3 -0
- package/dist/packages/local-api/src/server.js +1 -1
- package/dist/packages/view-model/src/hud-model.d.ts +74 -0
- package/dist/packages/view-model/src/hud-model.js +295 -0
- package/dist/packages/view-model/src/index.d.ts +5 -2
- package/dist/packages/view-model/src/index.js +4 -1
- package/dist/packages/view-model/src/notification-preferences-model.d.ts +30 -2
- package/dist/packages/view-model/src/notification-preferences-model.js +183 -1
- package/dist/packages/view-model/src/notification-preferences.d.ts +1 -1
- package/dist/packages/view-model/src/notification-preferences.js +1 -1
- package/dist/packages/view-model/src/sync-state.d.ts +47 -0
- package/dist/packages/view-model/src/sync-state.js +140 -0
- package/dist/packages/view-model/src/usage-progress.d.ts +22 -0
- package/dist/packages/view-model/src/usage-progress.js +57 -0
- package/dist/packages/view-model/src/view-model.d.ts +22 -0
- package/dist/packages/view-model/src/view-model.js +142 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ Install the generated tarball into a temporary project:
|
|
|
67
67
|
mkdir -p /tmp/moneysiren-alpha-review
|
|
68
68
|
cd /tmp/moneysiren-alpha-review
|
|
69
69
|
npm init -y
|
|
70
|
-
npm install /path/to/moneysiren-cli-0.1.0-alpha.
|
|
70
|
+
npm install /path/to/moneysiren-cli-0.1.0-alpha.2.tgz
|
|
71
71
|
npm exec moneysiren
|
|
72
72
|
npm exec moneysiren -- --version
|
|
73
73
|
npm exec moneysiren -- /version
|
|
@@ -83,7 +83,7 @@ PowerShell equivalent for the temporary project:
|
|
|
83
83
|
New-Item -ItemType Directory -Force -Path $env:TEMP\moneysiren-alpha-review
|
|
84
84
|
Set-Location $env:TEMP\moneysiren-alpha-review
|
|
85
85
|
npm init -y
|
|
86
|
-
npm install C:\path\to\moneysiren-cli-0.1.0-alpha.
|
|
86
|
+
npm install C:\path\to\moneysiren-cli-0.1.0-alpha.2.tgz
|
|
87
87
|
npm exec moneysiren
|
|
88
88
|
npm exec moneysiren -- --version
|
|
89
89
|
npm exec moneysiren -- modes
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type CliLocalRuntimeAdapter } from "./runtime-adapter.js";
|
|
2
|
+
import type { CliDesktopRuntimeAdapter } from "./desktop-runtime.js";
|
|
2
3
|
import { type Theme } from "./theme.js";
|
|
3
4
|
import type { SlackReportTransport } from "../../../packages/report/src/index.js";
|
|
4
5
|
import type { AwsCostExplorerClientAdapter } from "../../../packages/connectors/aws/src/index.js";
|
|
@@ -23,6 +24,7 @@ export interface CliRuntime {
|
|
|
23
24
|
liveClients?: CliLiveClients;
|
|
24
25
|
fetch?: typeof fetch;
|
|
25
26
|
localRuntime?: CliLocalRuntimeAdapter;
|
|
27
|
+
desktopRuntime?: CliDesktopRuntimeAdapter;
|
|
26
28
|
openUrl?: (url: string) => Promise<void> | void;
|
|
27
29
|
}
|
|
28
30
|
export interface CliLiveClients {
|
|
@@ -46,6 +48,7 @@ export interface CliExecutionContext {
|
|
|
46
48
|
interactive: boolean;
|
|
47
49
|
theme: Theme;
|
|
48
50
|
localRuntime?: CliLocalRuntimeAdapter;
|
|
51
|
+
desktopRuntime?: CliDesktopRuntimeAdapter;
|
|
49
52
|
}
|
|
50
53
|
export interface CliResult {
|
|
51
54
|
exitCode: number;
|
package/dist/apps/cli/src/cli.js
CHANGED
|
@@ -5,7 +5,7 @@ import { runInstallCommand } from "./commands/install.js";
|
|
|
5
5
|
import { runModesCommand } from "./commands/modes.js";
|
|
6
6
|
import { runNotifyCommand } from "./commands/notify.js";
|
|
7
7
|
import { runReportCommand } from "./commands/report.js";
|
|
8
|
-
import { runDesktopCommand, runOpenCommand, runServeCommand } from "./commands/runtime.js";
|
|
8
|
+
import { runDesktopCommand, runHudCommand, runOpenCommand, runServeCommand, runStartCommand } from "./commands/runtime.js";
|
|
9
9
|
import { runSummaryCommand } from "./commands/summary.js";
|
|
10
10
|
import { runSyncCommand } from "./commands/sync.js";
|
|
11
11
|
import { runThemeCommand } from "./commands/theme.js";
|
|
@@ -61,6 +61,7 @@ export async function runCli(args, runtime = {}) {
|
|
|
61
61
|
}),
|
|
62
62
|
theme,
|
|
63
63
|
...(runtime.localRuntime === undefined ? {} : { localRuntime: runtime.localRuntime }),
|
|
64
|
+
...(runtime.desktopRuntime === undefined ? {} : { desktopRuntime: runtime.desktopRuntime }),
|
|
64
65
|
};
|
|
65
66
|
context.stdin = runtime.stdin ?? process.stdin;
|
|
66
67
|
context.output = runtime.output ?? process.stdout;
|
|
@@ -130,6 +131,12 @@ async function dispatchCommand(args, context) {
|
|
|
130
131
|
if (command === "serve") {
|
|
131
132
|
return runServeCommand(rest, context);
|
|
132
133
|
}
|
|
134
|
+
if (command === "start") {
|
|
135
|
+
return runStartCommand(rest, context);
|
|
136
|
+
}
|
|
137
|
+
if (command === "hud") {
|
|
138
|
+
return runHudCommand(rest, context);
|
|
139
|
+
}
|
|
133
140
|
if (command === "open") {
|
|
134
141
|
return runOpenCommand(rest, context);
|
|
135
142
|
}
|
|
@@ -152,7 +159,7 @@ async function dispatchCommand(args, context) {
|
|
|
152
159
|
return runThemeCommand(rest, context);
|
|
153
160
|
}
|
|
154
161
|
context.stderr(`Unknown command: ${command}`);
|
|
155
|
-
context.stderr("Run `moneysiren --help` for usage.");
|
|
162
|
+
context.stderr("Run `msiren --help` or `moneysiren --help` for usage.");
|
|
156
163
|
return 1;
|
|
157
164
|
}
|
|
158
165
|
async function dispatchSlashCommand(args, context) {
|
|
@@ -17,28 +17,30 @@ export async function runModesCommand(args, context) {
|
|
|
17
17
|
context.stdout(`Platform: ${platformLabel()}`);
|
|
18
18
|
context.stdout(`Install profile: ${formatInstallSurfaces(selectedSurfaces)}${profile === null ? " (recommended default)" : ""}`);
|
|
19
19
|
context.stdout("npm install: npm install -g @moneysiren/cli@alpha");
|
|
20
|
+
context.stdout("Short command: msiren");
|
|
20
21
|
context.stdout(`Runtime lock: ${runtimeLockHint()}`);
|
|
21
22
|
context.stdout("");
|
|
22
23
|
context.stdout("1. CLI automation");
|
|
23
24
|
context.stdout(` Status: ${surfaceStatus("cli", selectedSurfaces)} from the npm CLI package`);
|
|
24
|
-
context.stdout(" Try:
|
|
25
|
-
context.stdout(" Try:
|
|
25
|
+
context.stdout(" Try: msiren doctor");
|
|
26
|
+
context.stdout(" Try: msiren sync --provider mock");
|
|
26
27
|
context.stdout("");
|
|
27
28
|
context.stdout("2. Local web dashboard/runtime");
|
|
28
29
|
context.stdout(` Status: ${surfaceStatus("web", selectedSurfaces)} GitHub Release web runtime archive is installed by the CLI`);
|
|
29
|
-
context.stdout(" Install:
|
|
30
|
-
context.stdout(" Try:
|
|
31
|
-
context.stdout(" Try:
|
|
32
|
-
context.stdout(" Note:
|
|
30
|
+
context.stdout(" Install: msiren install --web");
|
|
31
|
+
context.stdout(" Try: msiren start");
|
|
32
|
+
context.stdout(" Try: msiren dashboard check");
|
|
33
|
+
context.stdout(" Note: msiren start runs the installed GitHub Release web runtime.");
|
|
33
34
|
context.stdout("");
|
|
34
35
|
context.stdout("3. Desktop tray/notifier");
|
|
35
36
|
context.stdout(` Status: ${surfaceStatus("hud", selectedSurfaces)} Windows/macOS target is the thin Tauri tray shell from GitHub Releases`);
|
|
36
|
-
context.stdout(" Install:
|
|
37
|
-
context.stdout(" Try:
|
|
38
|
-
context.stdout(" Try:
|
|
37
|
+
context.stdout(" Install: msiren install --hud");
|
|
38
|
+
context.stdout(" Try: msiren hud");
|
|
39
|
+
context.stdout(" Try: msiren desktop status");
|
|
40
|
+
context.stdout(" Try: msiren notify once --dry-run");
|
|
39
41
|
context.stdout("");
|
|
40
|
-
context.stdout("Install recommended set:
|
|
41
|
-
context.stdout("Change selection only:
|
|
42
|
+
context.stdout("Install recommended set: msiren install --all");
|
|
43
|
+
context.stdout("Change selection only: msiren install --profile-only");
|
|
42
44
|
return 0;
|
|
43
45
|
}
|
|
44
46
|
function surfaceStatus(surface, selectedSurfaces) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { CliExecutionContext } from "../cli.js";
|
|
2
2
|
export declare function runServeCommand(args: readonly string[], context: CliExecutionContext): Promise<number>;
|
|
3
|
+
export declare function runStartCommand(args: readonly string[], context: CliExecutionContext): Promise<number>;
|
|
4
|
+
export declare function runHudCommand(args: readonly string[], context: CliExecutionContext): Promise<number>;
|
|
3
5
|
export declare function runOpenCommand(args: readonly string[], context: CliExecutionContext): Promise<number>;
|
|
4
6
|
export declare function runDesktopCommand(args: readonly string[], context: CliExecutionContext): Promise<number>;
|
|
5
7
|
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { createFallbackDesktopRuntimeAdapter, } from "../desktop-runtime.js";
|
|
1
2
|
import { createFallbackLocalRuntimeAdapter, } from "../runtime-adapter.js";
|
|
2
3
|
const SERVE_USAGE = "Usage: moneysiren serve [--port <port>]";
|
|
4
|
+
const START_USAGE = "Usage: msiren start [--port <port>] [--open|--no-open] [--hud]";
|
|
5
|
+
const HUD_USAGE = "Usage: msiren hud [--port <port>]";
|
|
3
6
|
const OPEN_USAGE = "Usage: moneysiren open";
|
|
4
7
|
const DESKTOP_USAGE = "Usage: moneysiren desktop status";
|
|
5
8
|
export async function runServeCommand(args, context) {
|
|
@@ -18,6 +21,62 @@ export async function runServeCommand(args, context) {
|
|
|
18
21
|
});
|
|
19
22
|
return writeStartRuntimeResult(context, result, "MoneySiren local runtime");
|
|
20
23
|
}
|
|
24
|
+
export async function runStartCommand(args, context) {
|
|
25
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
26
|
+
context.stdout(START_USAGE);
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
const parsed = parseStartArgs(args);
|
|
30
|
+
if (parsed === undefined) {
|
|
31
|
+
context.stderr(START_USAGE);
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
const adapter = desktopRuntimeAdapter(context);
|
|
35
|
+
const web = await adapter.startWebRuntime({
|
|
36
|
+
openBrowser: parsed.openBrowser,
|
|
37
|
+
...(parsed.port === undefined ? {} : { port: parsed.port }),
|
|
38
|
+
});
|
|
39
|
+
const webExitCode = writeDesktopRuntimeResult(context, web, "MoneySiren dashboard runtime");
|
|
40
|
+
if (webExitCode !== 0) {
|
|
41
|
+
return webExitCode;
|
|
42
|
+
}
|
|
43
|
+
if (web.status !== "unavailable" && parsed.openBrowser) {
|
|
44
|
+
await context.openUrl(web.dashboardUrl);
|
|
45
|
+
context.stdout(`Dashboard URL: ${web.dashboardUrl}`);
|
|
46
|
+
}
|
|
47
|
+
if (!parsed.launchHud) {
|
|
48
|
+
context.stdout("HUD: run `msiren hud` to open the floating desktop widget.");
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
const hud = await adapter.startHud({
|
|
52
|
+
...(parsed.port === undefined ? {} : { port: parsed.port }),
|
|
53
|
+
});
|
|
54
|
+
return writeDesktopShellResult(context, hud, "MoneySiren HUD");
|
|
55
|
+
}
|
|
56
|
+
export async function runHudCommand(args, context) {
|
|
57
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
58
|
+
context.stdout(HUD_USAGE);
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
const parsed = parseHudArgs(args);
|
|
62
|
+
if (parsed === undefined) {
|
|
63
|
+
context.stderr(HUD_USAGE);
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
66
|
+
const adapter = desktopRuntimeAdapter(context);
|
|
67
|
+
const web = await adapter.startWebRuntime({
|
|
68
|
+
openBrowser: false,
|
|
69
|
+
...(parsed.port === undefined ? {} : { port: parsed.port }),
|
|
70
|
+
});
|
|
71
|
+
const webExitCode = writeDesktopRuntimeResult(context, web, "MoneySiren dashboard runtime");
|
|
72
|
+
if (webExitCode !== 0) {
|
|
73
|
+
return webExitCode;
|
|
74
|
+
}
|
|
75
|
+
const hud = await adapter.startHud({
|
|
76
|
+
...(parsed.port === undefined ? {} : { port: parsed.port }),
|
|
77
|
+
});
|
|
78
|
+
return writeDesktopShellResult(context, hud, "MoneySiren HUD");
|
|
79
|
+
}
|
|
21
80
|
export async function runOpenCommand(args, context) {
|
|
22
81
|
if (args.includes("--help") || args.includes("-h")) {
|
|
23
82
|
context.stdout(OPEN_USAGE);
|
|
@@ -81,6 +140,9 @@ export async function runDesktopCommand(args, context) {
|
|
|
81
140
|
function runtimeAdapter(context) {
|
|
82
141
|
return context.localRuntime ?? createFallbackLocalRuntimeAdapter(context);
|
|
83
142
|
}
|
|
143
|
+
function desktopRuntimeAdapter(context) {
|
|
144
|
+
return context.desktopRuntime ?? createFallbackDesktopRuntimeAdapter(context);
|
|
145
|
+
}
|
|
84
146
|
async function findHealthyRuntime(adapter) {
|
|
85
147
|
const runtime = await adapter.findRuntime();
|
|
86
148
|
if (runtime === null) {
|
|
@@ -103,6 +165,45 @@ function writeStartRuntimeResult(context, result, heading) {
|
|
|
103
165
|
}
|
|
104
166
|
return 1;
|
|
105
167
|
}
|
|
168
|
+
function writeDesktopRuntimeResult(context, result, heading) {
|
|
169
|
+
if (result.status !== "unavailable") {
|
|
170
|
+
context.stdout(heading);
|
|
171
|
+
context.stdout(`Runtime: ${result.status}`);
|
|
172
|
+
context.stdout(`Dashboard URL: ${result.dashboardUrl}`);
|
|
173
|
+
if (result.pid !== undefined) {
|
|
174
|
+
context.stdout(`PID: ${result.pid}`);
|
|
175
|
+
}
|
|
176
|
+
for (const note of result.notes) {
|
|
177
|
+
context.stdout(`Note: ${note}`);
|
|
178
|
+
}
|
|
179
|
+
return 0;
|
|
180
|
+
}
|
|
181
|
+
context.stderr(`${heading}: unavailable`);
|
|
182
|
+
context.stderr(result.reason);
|
|
183
|
+
for (const line of result.guidance) {
|
|
184
|
+
context.stderr(line);
|
|
185
|
+
}
|
|
186
|
+
return 1;
|
|
187
|
+
}
|
|
188
|
+
function writeDesktopShellResult(context, result, heading) {
|
|
189
|
+
if (result.status !== "unavailable") {
|
|
190
|
+
context.stdout(heading);
|
|
191
|
+
context.stdout(`Desktop shell: ${result.status}`);
|
|
192
|
+
if (result.pid !== undefined) {
|
|
193
|
+
context.stdout(`PID: ${result.pid}`);
|
|
194
|
+
}
|
|
195
|
+
for (const note of result.notes) {
|
|
196
|
+
context.stdout(`Note: ${note}`);
|
|
197
|
+
}
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
context.stderr(`${heading}: unavailable`);
|
|
201
|
+
context.stderr(result.reason);
|
|
202
|
+
for (const line of result.guidance) {
|
|
203
|
+
context.stderr(line);
|
|
204
|
+
}
|
|
205
|
+
return 1;
|
|
206
|
+
}
|
|
106
207
|
function parseServeArgs(args) {
|
|
107
208
|
let port;
|
|
108
209
|
for (let index = 0; index < args.length; index += 1) {
|
|
@@ -127,6 +228,72 @@ function parseServeArgs(args) {
|
|
|
127
228
|
}
|
|
128
229
|
return Number.isSafeInteger(port) && port > 0 && port <= 65_535 ? { port } : undefined;
|
|
129
230
|
}
|
|
231
|
+
function parseStartArgs(args) {
|
|
232
|
+
let launchHud = false;
|
|
233
|
+
let openBrowser = true;
|
|
234
|
+
let port;
|
|
235
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
236
|
+
const arg = args[index];
|
|
237
|
+
if (arg === "--hud") {
|
|
238
|
+
launchHud = true;
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (arg === "--open") {
|
|
242
|
+
openBrowser = true;
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
if (arg === "--no-open") {
|
|
246
|
+
openBrowser = false;
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
if (arg === "--port") {
|
|
250
|
+
const value = args[index + 1];
|
|
251
|
+
if (value === undefined || value.startsWith("--")) {
|
|
252
|
+
return undefined;
|
|
253
|
+
}
|
|
254
|
+
port = parsePort(value);
|
|
255
|
+
index += 1;
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (arg?.startsWith("--port=")) {
|
|
259
|
+
port = parsePort(arg.slice("--port=".length));
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
if (port !== undefined && (!Number.isSafeInteger(port) || port <= 0 || port > 65_535)) {
|
|
265
|
+
return undefined;
|
|
266
|
+
}
|
|
267
|
+
return {
|
|
268
|
+
launchHud,
|
|
269
|
+
openBrowser,
|
|
270
|
+
...(port === undefined ? {} : { port }),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
function parseHudArgs(args) {
|
|
274
|
+
let port;
|
|
275
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
276
|
+
const arg = args[index];
|
|
277
|
+
if (arg === "--port") {
|
|
278
|
+
const value = args[index + 1];
|
|
279
|
+
if (value === undefined || value.startsWith("--")) {
|
|
280
|
+
return undefined;
|
|
281
|
+
}
|
|
282
|
+
port = parsePort(value);
|
|
283
|
+
index += 1;
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (arg?.startsWith("--port=")) {
|
|
287
|
+
port = parsePort(arg.slice("--port=".length));
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
return undefined;
|
|
291
|
+
}
|
|
292
|
+
if (port !== undefined && (!Number.isSafeInteger(port) || port <= 0 || port > 65_535)) {
|
|
293
|
+
return undefined;
|
|
294
|
+
}
|
|
295
|
+
return port === undefined ? {} : { port };
|
|
296
|
+
}
|
|
130
297
|
function parsePort(value) {
|
|
131
298
|
return Number.parseInt(value, 10);
|
|
132
299
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CliExecutionContext } from "./cli.js";
|
|
2
|
+
export interface StartWebRuntimeOptions {
|
|
3
|
+
openBrowser: boolean;
|
|
4
|
+
port?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface StartHudOptions {
|
|
7
|
+
port?: number;
|
|
8
|
+
}
|
|
9
|
+
export type DesktopRuntimeResult = {
|
|
10
|
+
status: "running" | "started";
|
|
11
|
+
dashboardUrl: string;
|
|
12
|
+
pid?: number;
|
|
13
|
+
notes: readonly string[];
|
|
14
|
+
} | DesktopRuntimeUnavailableResult;
|
|
15
|
+
export type DesktopShellResult = {
|
|
16
|
+
status: "opened" | "started";
|
|
17
|
+
executablePath: string;
|
|
18
|
+
pid?: number;
|
|
19
|
+
notes: readonly string[];
|
|
20
|
+
} | DesktopRuntimeUnavailableResult;
|
|
21
|
+
export interface DesktopRuntimeUnavailableResult {
|
|
22
|
+
status: "unavailable";
|
|
23
|
+
reason: string;
|
|
24
|
+
guidance: readonly string[];
|
|
25
|
+
}
|
|
26
|
+
export interface CliDesktopRuntimeAdapter {
|
|
27
|
+
startWebRuntime(options: StartWebRuntimeOptions): Promise<DesktopRuntimeResult>;
|
|
28
|
+
startHud(options: StartHudOptions): Promise<DesktopShellResult>;
|
|
29
|
+
}
|
|
30
|
+
export declare function createFallbackDesktopRuntimeAdapter(context: CliExecutionContext): CliDesktopRuntimeAdapter;
|
|
31
|
+
//# sourceMappingURL=desktop-runtime.d.ts.map
|