@moneysiren/app 0.1.0-alpha.9

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 (140) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +45 -0
  3. package/dist/apps/cli/src/cli.d.ts +59 -0
  4. package/dist/apps/cli/src/cli.js +199 -0
  5. package/dist/apps/cli/src/commands/dashboard.d.ts +3 -0
  6. package/dist/apps/cli/src/commands/dashboard.js +239 -0
  7. package/dist/apps/cli/src/commands/doctor.d.ts +3 -0
  8. package/dist/apps/cli/src/commands/doctor.js +25 -0
  9. package/dist/apps/cli/src/commands/init.d.ts +3 -0
  10. package/dist/apps/cli/src/commands/init.js +18 -0
  11. package/dist/apps/cli/src/commands/install.d.ts +3 -0
  12. package/dist/apps/cli/src/commands/install.js +244 -0
  13. package/dist/apps/cli/src/commands/modes.d.ts +3 -0
  14. package/dist/apps/cli/src/commands/modes.js +73 -0
  15. package/dist/apps/cli/src/commands/notify.d.ts +3 -0
  16. package/dist/apps/cli/src/commands/notify.js +430 -0
  17. package/dist/apps/cli/src/commands/report.d.ts +3 -0
  18. package/dist/apps/cli/src/commands/report.js +206 -0
  19. package/dist/apps/cli/src/commands/runtime.d.ts +10 -0
  20. package/dist/apps/cli/src/commands/runtime.js +499 -0
  21. package/dist/apps/cli/src/commands/shared.d.ts +9 -0
  22. package/dist/apps/cli/src/commands/shared.js +29 -0
  23. package/dist/apps/cli/src/commands/summary.d.ts +3 -0
  24. package/dist/apps/cli/src/commands/summary.js +15 -0
  25. package/dist/apps/cli/src/commands/sync.d.ts +3 -0
  26. package/dist/apps/cli/src/commands/sync.js +393 -0
  27. package/dist/apps/cli/src/commands/theme.d.ts +3 -0
  28. package/dist/apps/cli/src/commands/theme.js +181 -0
  29. package/dist/apps/cli/src/desktop-runtime.d.ts +54 -0
  30. package/dist/apps/cli/src/desktop-runtime.js +720 -0
  31. package/dist/apps/cli/src/home.d.ts +7 -0
  32. package/dist/apps/cli/src/home.js +124 -0
  33. package/dist/apps/cli/src/index.d.ts +3 -0
  34. package/dist/apps/cli/src/index.js +14 -0
  35. package/dist/apps/cli/src/install-profile.d.ts +35 -0
  36. package/dist/apps/cli/src/install-profile.js +124 -0
  37. package/dist/apps/cli/src/install-selector.d.ts +10 -0
  38. package/dist/apps/cli/src/install-selector.js +66 -0
  39. package/dist/apps/cli/src/interactive.d.ts +3 -0
  40. package/dist/apps/cli/src/interactive.js +32 -0
  41. package/dist/apps/cli/src/postinstall.d.ts +3 -0
  42. package/dist/apps/cli/src/postinstall.js +42 -0
  43. package/dist/apps/cli/src/release-installer.d.ts +57 -0
  44. package/dist/apps/cli/src/release-installer.js +432 -0
  45. package/dist/apps/cli/src/runtime-adapter.d.ts +24 -0
  46. package/dist/apps/cli/src/runtime-adapter.js +185 -0
  47. package/dist/apps/cli/src/slash.d.ts +15 -0
  48. package/dist/apps/cli/src/slash.js +229 -0
  49. package/dist/apps/cli/src/summary-model.d.ts +51 -0
  50. package/dist/apps/cli/src/summary-model.js +136 -0
  51. package/dist/apps/cli/src/theme.d.ts +18 -0
  52. package/dist/apps/cli/src/theme.js +118 -0
  53. package/dist/apps/cli/src/version.d.ts +2 -0
  54. package/dist/apps/cli/src/version.js +2 -0
  55. package/dist/packages/config/src/index.d.ts +3 -0
  56. package/dist/packages/config/src/index.js +3 -0
  57. package/dist/packages/config/src/load.d.ts +3 -0
  58. package/dist/packages/config/src/load.js +80 -0
  59. package/dist/packages/config/src/schema.d.ts +49 -0
  60. package/dist/packages/config/src/schema.js +28 -0
  61. package/dist/packages/connectors/aws/src/cost-explorer.d.ts +34 -0
  62. package/dist/packages/connectors/aws/src/cost-explorer.js +43 -0
  63. package/dist/packages/connectors/aws/src/index.d.ts +35 -0
  64. package/dist/packages/connectors/aws/src/index.js +67 -0
  65. package/dist/packages/connectors/aws/src/normalize.d.ts +69 -0
  66. package/dist/packages/connectors/aws/src/normalize.js +141 -0
  67. package/dist/packages/connectors/aws/src/sdk-client.d.ts +6 -0
  68. package/dist/packages/connectors/aws/src/sdk-client.js +21 -0
  69. package/dist/packages/connectors/cloudflare/src/client.d.ts +23 -0
  70. package/dist/packages/connectors/cloudflare/src/client.js +107 -0
  71. package/dist/packages/connectors/cloudflare/src/index.d.ts +33 -0
  72. package/dist/packages/connectors/cloudflare/src/index.js +81 -0
  73. package/dist/packages/connectors/cloudflare/src/normalize.d.ts +113 -0
  74. package/dist/packages/connectors/cloudflare/src/normalize.js +288 -0
  75. package/dist/packages/connectors/mock/src/index.d.ts +58 -0
  76. package/dist/packages/connectors/mock/src/index.js +66 -0
  77. package/dist/packages/connectors/openai/src/index.d.ts +55 -0
  78. package/dist/packages/connectors/openai/src/index.js +169 -0
  79. package/dist/packages/connectors/openai/src/normalize.d.ts +91 -0
  80. package/dist/packages/connectors/openai/src/normalize.js +180 -0
  81. package/dist/packages/connectors/supabase/src/client.d.ts +22 -0
  82. package/dist/packages/connectors/supabase/src/client.js +132 -0
  83. package/dist/packages/connectors/supabase/src/index.d.ts +33 -0
  84. package/dist/packages/connectors/supabase/src/index.js +87 -0
  85. package/dist/packages/connectors/supabase/src/normalize.d.ts +106 -0
  86. package/dist/packages/connectors/supabase/src/normalize.js +266 -0
  87. package/dist/packages/core/src/collector.d.ts +12 -0
  88. package/dist/packages/core/src/collector.js +68 -0
  89. package/dist/packages/core/src/index.d.ts +5 -0
  90. package/dist/packages/core/src/index.js +4 -0
  91. package/dist/packages/core/src/provider.d.ts +18 -0
  92. package/dist/packages/core/src/provider.js +2 -0
  93. package/dist/packages/core/src/risk-engine.d.ts +9 -0
  94. package/dist/packages/core/src/risk-engine.js +4 -0
  95. package/dist/packages/core/src/snapshots.d.ts +49 -0
  96. package/dist/packages/core/src/snapshots.js +9 -0
  97. package/dist/packages/db/src/client.d.ts +11 -0
  98. package/dist/packages/db/src/client.js +14 -0
  99. package/dist/packages/db/src/index.d.ts +6 -0
  100. package/dist/packages/db/src/index.js +6 -0
  101. package/dist/packages/db/src/local-store.d.ts +161 -0
  102. package/dist/packages/db/src/local-store.js +623 -0
  103. package/dist/packages/db/src/migrate.d.ts +17 -0
  104. package/dist/packages/db/src/migrate.js +35 -0
  105. package/dist/packages/db/src/schema.d.ts +5 -0
  106. package/dist/packages/db/src/schema.js +120 -0
  107. package/dist/packages/db/src/sqlite-bin.d.ts +3 -0
  108. package/dist/packages/db/src/sqlite-bin.js +16 -0
  109. package/dist/packages/local-api/src/index.d.ts +2 -0
  110. package/dist/packages/local-api/src/index.js +2 -0
  111. package/dist/packages/local-api/src/server.d.ts +36 -0
  112. package/dist/packages/local-api/src/server.js +310 -0
  113. package/dist/packages/report/src/daily.d.ts +24 -0
  114. package/dist/packages/report/src/daily.js +9 -0
  115. package/dist/packages/report/src/index.d.ts +4 -0
  116. package/dist/packages/report/src/index.js +4 -0
  117. package/dist/packages/report/src/korean.d.ts +3 -0
  118. package/dist/packages/report/src/korean.js +62 -0
  119. package/dist/packages/report/src/slack.d.ts +34 -0
  120. package/dist/packages/report/src/slack.js +134 -0
  121. package/dist/packages/runtime/src/index.d.ts +2 -0
  122. package/dist/packages/runtime/src/index.js +2 -0
  123. package/dist/packages/runtime/src/runtime.d.ts +26 -0
  124. package/dist/packages/runtime/src/runtime.js +182 -0
  125. package/dist/packages/view-model/src/hud-model.d.ts +74 -0
  126. package/dist/packages/view-model/src/hud-model.js +295 -0
  127. package/dist/packages/view-model/src/index.d.ts +6 -0
  128. package/dist/packages/view-model/src/index.js +6 -0
  129. package/dist/packages/view-model/src/notification-preferences-model.d.ts +75 -0
  130. package/dist/packages/view-model/src/notification-preferences-model.js +400 -0
  131. package/dist/packages/view-model/src/notification-preferences.d.ts +6 -0
  132. package/dist/packages/view-model/src/notification-preferences.js +36 -0
  133. package/dist/packages/view-model/src/sync-state.d.ts +47 -0
  134. package/dist/packages/view-model/src/sync-state.js +140 -0
  135. package/dist/packages/view-model/src/usage-progress.d.ts +22 -0
  136. package/dist/packages/view-model/src/usage-progress.js +57 -0
  137. package/dist/packages/view-model/src/view-model.d.ts +215 -0
  138. package/dist/packages/view-model/src/view-model.js +826 -0
  139. package/package.json +40 -0
  140. package/scripts/postinstall.mjs +69 -0
@@ -0,0 +1,499 @@
1
+ import { createFallbackDesktopRuntimeAdapter, } from "../desktop-runtime.js";
2
+ import { createFallbackLocalRuntimeAdapter, } from "../runtime-adapter.js";
3
+ import { removeRuntimeLock } from "../../../../packages/runtime/src/index.js";
4
+ const SERVE_USAGE = "Usage: moneysiren serve [--port <port>]";
5
+ const START_USAGE = "Usage: msiren start [--port <port>] [--open|--no-open] [--hud]";
6
+ const HUD_USAGE = "Usage: msiren hud [--port <port>]";
7
+ const STATUS_USAGE = "Usage: msiren status";
8
+ const STOP_USAGE = "Usage: msiren stop [--web|--hud|--api|--all]";
9
+ const RESTART_USAGE = "Usage: msiren restart [--port <port>] [--open|--no-open] [--hud]";
10
+ const OPEN_USAGE = "Usage: moneysiren open";
11
+ const DESKTOP_USAGE = "Usage: moneysiren desktop status";
12
+ export async function runServeCommand(args, context) {
13
+ if (args.includes("--help") || args.includes("-h")) {
14
+ context.stdout(SERVE_USAGE);
15
+ return 0;
16
+ }
17
+ const parsed = parseServeArgs(args);
18
+ if (parsed === undefined) {
19
+ context.stderr(SERVE_USAGE);
20
+ return 1;
21
+ }
22
+ const result = await runtimeAdapter(context).startRuntime({
23
+ headless: false,
24
+ ...(parsed.port === undefined ? {} : { port: parsed.port }),
25
+ });
26
+ return writeStartRuntimeResult(context, result, "MoneySiren local runtime");
27
+ }
28
+ export async function runStatusCommand(args, context) {
29
+ if (args.includes("--help") || args.includes("-h")) {
30
+ context.stdout(STATUS_USAGE);
31
+ return 0;
32
+ }
33
+ if (args.length > 0) {
34
+ context.stderr(STATUS_USAGE);
35
+ return 1;
36
+ }
37
+ const desktop = await desktopRuntimeAdapter(context).status();
38
+ const api = await runtimeAdapter(context).findRuntime();
39
+ context.stdout("MoneySiren status");
40
+ writeDesktopProcessStatus(context, "Web runtime", desktop.web);
41
+ writeDesktopProcessStatus(context, "HUD", desktop.hud);
42
+ context.stdout(`Desktop state: ${desktop.statePath}`);
43
+ if (api === null) {
44
+ context.stdout("Local API runtime: not running");
45
+ return 0;
46
+ }
47
+ const healthy = await runtimeAdapter(context).assertRuntimeHealthy(api);
48
+ context.stdout(`Local API runtime: ${healthy ? "healthy" : "unhealthy"}`);
49
+ context.stdout(` PID: ${api.pid}`);
50
+ context.stdout(` URL: ${api.baseUrl}`);
51
+ return healthy ? 0 : 1;
52
+ }
53
+ export async function runStartCommand(args, context) {
54
+ if (args.includes("--help") || args.includes("-h")) {
55
+ context.stdout(START_USAGE);
56
+ return 0;
57
+ }
58
+ const parsed = parseStartArgs(args);
59
+ if (parsed === undefined) {
60
+ context.stderr(START_USAGE);
61
+ return 1;
62
+ }
63
+ const adapter = desktopRuntimeAdapter(context);
64
+ const web = await adapter.startWebRuntime({
65
+ openBrowser: parsed.openBrowser,
66
+ ...(parsed.port === undefined ? {} : { port: parsed.port }),
67
+ });
68
+ const webExitCode = writeDesktopRuntimeResult(context, web, "MoneySiren dashboard runtime");
69
+ if (webExitCode !== 0) {
70
+ return webExitCode;
71
+ }
72
+ if (web.status !== "unavailable" && parsed.openBrowser) {
73
+ await context.openUrl(web.dashboardUrl);
74
+ context.stdout(`Dashboard URL: ${web.dashboardUrl}`);
75
+ }
76
+ if (!parsed.launchHud) {
77
+ context.stdout("HUD: run `msiren hud` to open the floating desktop widget.");
78
+ return 0;
79
+ }
80
+ const hud = await adapter.startHud({
81
+ ...(parsed.port === undefined ? {} : { port: parsed.port }),
82
+ });
83
+ return writeDesktopShellResult(context, hud, "MoneySiren HUD");
84
+ }
85
+ export async function runStopCommand(args, context) {
86
+ if (args.includes("--help") || args.includes("-h")) {
87
+ context.stdout(STOP_USAGE);
88
+ return 0;
89
+ }
90
+ const selection = parseStopArgs(args);
91
+ if (selection === undefined) {
92
+ context.stderr(STOP_USAGE);
93
+ return 1;
94
+ }
95
+ context.stdout("MoneySiren stop");
96
+ const desktopResults = await desktopRuntimeAdapter(context).stop({
97
+ hud: selection.hud,
98
+ web: selection.web,
99
+ });
100
+ for (const result of desktopResults) {
101
+ writeStopDesktopRuntimeResult(context, result);
102
+ }
103
+ let exitCode = desktopResults.some((result) => result.status === "failed") ? 1 : 0;
104
+ if (selection.api) {
105
+ const apiResult = await stopLocalApiRuntime(context);
106
+ context.stdout(`Local API runtime: ${apiResult.status}`);
107
+ context.stdout(` ${apiResult.detail}`);
108
+ if (apiResult.pid !== undefined) {
109
+ context.stdout(` PID: ${apiResult.pid}`);
110
+ }
111
+ if (apiResult.status === "failed") {
112
+ exitCode = 1;
113
+ }
114
+ }
115
+ return exitCode;
116
+ }
117
+ export async function runRestartCommand(args, context) {
118
+ if (args.includes("--help") || args.includes("-h")) {
119
+ context.stdout(RESTART_USAGE);
120
+ return 0;
121
+ }
122
+ const parsed = parseStartArgs(args);
123
+ if (parsed === undefined) {
124
+ context.stderr(RESTART_USAGE);
125
+ return 1;
126
+ }
127
+ const stopExitCode = await runStopCommand(["--web", "--hud"], context);
128
+ if (stopExitCode !== 0) {
129
+ return stopExitCode;
130
+ }
131
+ return runStartCommand(args, context);
132
+ }
133
+ export async function runHudCommand(args, context) {
134
+ if (args.includes("--help") || args.includes("-h")) {
135
+ context.stdout(HUD_USAGE);
136
+ return 0;
137
+ }
138
+ const parsed = parseHudArgs(args);
139
+ if (parsed === undefined) {
140
+ context.stderr(HUD_USAGE);
141
+ return 1;
142
+ }
143
+ const adapter = desktopRuntimeAdapter(context);
144
+ const web = await adapter.startWebRuntime({
145
+ openBrowser: false,
146
+ ...(parsed.port === undefined ? {} : { port: parsed.port }),
147
+ });
148
+ const webExitCode = writeDesktopRuntimeResult(context, web, "MoneySiren dashboard runtime");
149
+ if (webExitCode !== 0) {
150
+ return webExitCode;
151
+ }
152
+ const hud = await adapter.startHud({
153
+ ...(parsed.port === undefined ? {} : { port: parsed.port }),
154
+ });
155
+ return writeDesktopShellResult(context, hud, "MoneySiren HUD");
156
+ }
157
+ async function stopLocalApiRuntime(context) {
158
+ const adapter = runtimeAdapter(context);
159
+ const runtime = await adapter.findRuntime();
160
+ if (runtime === null) {
161
+ return {
162
+ status: "not-running",
163
+ detail: "No managed local API runtime lock was found.",
164
+ };
165
+ }
166
+ try {
167
+ process.kill(runtime.pid, "SIGTERM");
168
+ await waitForProcessExit(runtime.pid, 3_000);
169
+ if (isProcessAlive(runtime.pid)) {
170
+ return {
171
+ status: "failed",
172
+ detail: "Local API runtime did not exit after SIGTERM.",
173
+ pid: runtime.pid,
174
+ };
175
+ }
176
+ await removeRuntimeLock({
177
+ cwd: context.cwd,
178
+ env: context.env,
179
+ });
180
+ return {
181
+ status: "stopped",
182
+ detail: "Managed local API runtime stopped.",
183
+ pid: runtime.pid,
184
+ };
185
+ }
186
+ catch (error) {
187
+ if (isNodeError(error) && error.code === "ESRCH") {
188
+ await removeRuntimeLock({
189
+ cwd: context.cwd,
190
+ env: context.env,
191
+ });
192
+ return {
193
+ status: "stale",
194
+ detail: "Removed stale local API runtime lock.",
195
+ pid: runtime.pid,
196
+ };
197
+ }
198
+ return {
199
+ status: "failed",
200
+ detail: error instanceof Error ? error.message : String(error),
201
+ pid: runtime.pid,
202
+ };
203
+ }
204
+ }
205
+ export async function runOpenCommand(args, context) {
206
+ if (args.includes("--help") || args.includes("-h")) {
207
+ context.stdout(OPEN_USAGE);
208
+ return 0;
209
+ }
210
+ if (args.length > 0) {
211
+ context.stderr(OPEN_USAGE);
212
+ return 1;
213
+ }
214
+ const adapter = runtimeAdapter(context);
215
+ const runtime = await findHealthyRuntime(adapter);
216
+ const startResult = runtime === null
217
+ ? await adapter.startRuntime({
218
+ headless: true,
219
+ })
220
+ : {
221
+ status: "running",
222
+ runtime,
223
+ };
224
+ if (startResult.status === "unavailable") {
225
+ return writeStartRuntimeResult(context, startResult, "MoneySiren open");
226
+ }
227
+ context.stdout("MoneySiren local API runtime ready");
228
+ context.stdout(`Runtime: ${startResult.status}`);
229
+ context.stdout(`Local API URL: ${startResult.runtime.baseUrl}`);
230
+ context.stdout("Dashboard UI: not opened because this runtime URL is a JSON API.");
231
+ context.stdout("Start the web dashboard:");
232
+ context.stdout(" pnpm --filter @moneysiren/web dev");
233
+ context.stdout("Then open: http://localhost:3000");
234
+ return 0;
235
+ }
236
+ export async function runDesktopCommand(args, context) {
237
+ const [subcommand, ...rest] = args;
238
+ if (subcommand === "--help" || subcommand === "-h" || subcommand === "help") {
239
+ context.stdout(DESKTOP_USAGE);
240
+ return 0;
241
+ }
242
+ if (subcommand !== "status" || rest.length > 0) {
243
+ context.stderr(DESKTOP_USAGE);
244
+ return 1;
245
+ }
246
+ const adapter = runtimeAdapter(context);
247
+ const runtime = await adapter.findRuntime();
248
+ context.stdout("MoneySiren desktop status");
249
+ if (runtime === null) {
250
+ context.stdout("Runtime: not running");
251
+ context.stdout("Runtime lock: not found");
252
+ context.stdout("Desktop shell: not detected by CLI");
253
+ context.stdout("Next step: run `moneysiren serve` or start the native tray app.");
254
+ return 0;
255
+ }
256
+ const healthy = await adapter.assertRuntimeHealthy(runtime);
257
+ context.stdout(`Runtime: ${healthy ? "healthy" : "unhealthy"}`);
258
+ context.stdout(`Base URL: ${runtime.baseUrl}`);
259
+ context.stdout(`PID: ${runtime.pid}`);
260
+ context.stdout(`Started at: ${runtime.startedAt}`);
261
+ context.stdout(`Version: ${runtime.version}`);
262
+ context.stdout("Desktop shell: not detected by CLI");
263
+ return healthy ? 0 : 1;
264
+ }
265
+ function runtimeAdapter(context) {
266
+ return context.localRuntime ?? createFallbackLocalRuntimeAdapter(context);
267
+ }
268
+ function desktopRuntimeAdapter(context) {
269
+ return context.desktopRuntime ?? createFallbackDesktopRuntimeAdapter(context);
270
+ }
271
+ async function findHealthyRuntime(adapter) {
272
+ const runtime = await adapter.findRuntime();
273
+ if (runtime === null) {
274
+ return null;
275
+ }
276
+ return await adapter.assertRuntimeHealthy(runtime) ? runtime : null;
277
+ }
278
+ function writeStartRuntimeResult(context, result, heading) {
279
+ if (result.status !== "unavailable") {
280
+ context.stdout(heading);
281
+ context.stdout(`Runtime: ${result.status}`);
282
+ context.stdout(`Base URL: ${result.runtime.baseUrl}`);
283
+ context.stdout(`PID: ${result.runtime.pid}`);
284
+ return 0;
285
+ }
286
+ context.stderr(`${heading}: unavailable`);
287
+ context.stderr(result.reason);
288
+ for (const line of result.guidance) {
289
+ context.stderr(line);
290
+ }
291
+ return 1;
292
+ }
293
+ function writeDesktopRuntimeResult(context, result, heading) {
294
+ if (result.status !== "unavailable") {
295
+ context.stdout(heading);
296
+ context.stdout(`Runtime: ${result.status}`);
297
+ context.stdout(`Dashboard URL: ${result.dashboardUrl}`);
298
+ if (result.pid !== undefined) {
299
+ context.stdout(`PID: ${result.pid}`);
300
+ }
301
+ for (const note of result.notes) {
302
+ context.stdout(`Note: ${note}`);
303
+ }
304
+ return 0;
305
+ }
306
+ context.stderr(`${heading}: unavailable`);
307
+ context.stderr(result.reason);
308
+ for (const line of result.guidance) {
309
+ context.stderr(line);
310
+ }
311
+ return 1;
312
+ }
313
+ function writeDesktopShellResult(context, result, heading) {
314
+ if (result.status !== "unavailable") {
315
+ context.stdout(heading);
316
+ context.stdout(`Desktop shell: ${result.status}`);
317
+ if (result.pid !== undefined) {
318
+ context.stdout(`PID: ${result.pid}`);
319
+ }
320
+ for (const note of result.notes) {
321
+ context.stdout(`Note: ${note}`);
322
+ }
323
+ return 0;
324
+ }
325
+ context.stderr(`${heading}: unavailable`);
326
+ context.stderr(result.reason);
327
+ for (const line of result.guidance) {
328
+ context.stderr(line);
329
+ }
330
+ return 1;
331
+ }
332
+ function writeDesktopProcessStatus(context, label, status) {
333
+ context.stdout(`${label}: ${status.status}`);
334
+ if (status.pid !== undefined) {
335
+ context.stdout(` PID: ${status.pid}`);
336
+ }
337
+ context.stdout(` ${status.detail}`);
338
+ }
339
+ function writeStopDesktopRuntimeResult(context, result) {
340
+ const label = result.target === "web" ? "Web runtime" : "HUD";
341
+ context.stdout(`${label}: ${result.status}`);
342
+ context.stdout(` ${result.detail}`);
343
+ if (result.pid !== undefined) {
344
+ context.stdout(` PID: ${result.pid}`);
345
+ }
346
+ }
347
+ function parseServeArgs(args) {
348
+ let port;
349
+ for (let index = 0; index < args.length; index += 1) {
350
+ const arg = args[index];
351
+ if (arg === "--port") {
352
+ const value = args[index + 1];
353
+ if (value === undefined || value.startsWith("--")) {
354
+ return undefined;
355
+ }
356
+ port = parsePort(value);
357
+ index += 1;
358
+ continue;
359
+ }
360
+ if (arg?.startsWith("--port=")) {
361
+ port = parsePort(arg.slice("--port=".length));
362
+ continue;
363
+ }
364
+ return undefined;
365
+ }
366
+ if (port === undefined) {
367
+ return {};
368
+ }
369
+ return Number.isSafeInteger(port) && port > 0 && port <= 65_535 ? { port } : undefined;
370
+ }
371
+ function parseStopArgs(args) {
372
+ let web = false;
373
+ let hud = false;
374
+ let api = false;
375
+ let all = false;
376
+ for (const arg of args) {
377
+ if (arg === "--web") {
378
+ web = true;
379
+ }
380
+ else if (arg === "--hud") {
381
+ hud = true;
382
+ }
383
+ else if (arg === "--api") {
384
+ api = true;
385
+ }
386
+ else if (arg === "--all") {
387
+ all = true;
388
+ }
389
+ else {
390
+ return undefined;
391
+ }
392
+ }
393
+ if (all || (!web && !hud && !api)) {
394
+ return {
395
+ api: true,
396
+ hud: true,
397
+ web: true,
398
+ };
399
+ }
400
+ return {
401
+ api,
402
+ hud,
403
+ web,
404
+ };
405
+ }
406
+ function parseStartArgs(args) {
407
+ let launchHud = false;
408
+ let openBrowser = true;
409
+ let port;
410
+ for (let index = 0; index < args.length; index += 1) {
411
+ const arg = args[index];
412
+ if (arg === "--hud") {
413
+ launchHud = true;
414
+ continue;
415
+ }
416
+ if (arg === "--open") {
417
+ openBrowser = true;
418
+ continue;
419
+ }
420
+ if (arg === "--no-open") {
421
+ openBrowser = false;
422
+ continue;
423
+ }
424
+ if (arg === "--port") {
425
+ const value = args[index + 1];
426
+ if (value === undefined || value.startsWith("--")) {
427
+ return undefined;
428
+ }
429
+ port = parsePort(value);
430
+ index += 1;
431
+ continue;
432
+ }
433
+ if (arg?.startsWith("--port=")) {
434
+ port = parsePort(arg.slice("--port=".length));
435
+ continue;
436
+ }
437
+ return undefined;
438
+ }
439
+ if (port !== undefined && (!Number.isSafeInteger(port) || port <= 0 || port > 65_535)) {
440
+ return undefined;
441
+ }
442
+ return {
443
+ launchHud,
444
+ openBrowser,
445
+ ...(port === undefined ? {} : { port }),
446
+ };
447
+ }
448
+ function parseHudArgs(args) {
449
+ let port;
450
+ for (let index = 0; index < args.length; index += 1) {
451
+ const arg = args[index];
452
+ if (arg === "--port") {
453
+ const value = args[index + 1];
454
+ if (value === undefined || value.startsWith("--")) {
455
+ return undefined;
456
+ }
457
+ port = parsePort(value);
458
+ index += 1;
459
+ continue;
460
+ }
461
+ if (arg?.startsWith("--port=")) {
462
+ port = parsePort(arg.slice("--port=".length));
463
+ continue;
464
+ }
465
+ return undefined;
466
+ }
467
+ if (port !== undefined && (!Number.isSafeInteger(port) || port <= 0 || port > 65_535)) {
468
+ return undefined;
469
+ }
470
+ return port === undefined ? {} : { port };
471
+ }
472
+ function parsePort(value) {
473
+ return Number.parseInt(value, 10);
474
+ }
475
+ function isProcessAlive(pid) {
476
+ if (pid <= 0) {
477
+ return false;
478
+ }
479
+ try {
480
+ process.kill(pid, 0);
481
+ return true;
482
+ }
483
+ catch (error) {
484
+ return isNodeError(error) && error.code === "EPERM";
485
+ }
486
+ }
487
+ async function waitForProcessExit(pid, timeoutMs) {
488
+ const deadline = Date.now() + timeoutMs;
489
+ while (Date.now() < deadline) {
490
+ if (!isProcessAlive(pid)) {
491
+ return;
492
+ }
493
+ await new Promise((resolveTimeout) => setTimeout(resolveTimeout, 100));
494
+ }
495
+ }
496
+ function isNodeError(value) {
497
+ return value instanceof Error && "code" in value;
498
+ }
499
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1,9 @@
1
+ import { type MoneySirenConfig } from "../../../../packages/config/src/index.js";
2
+ export interface ParsedFlagResult {
3
+ value?: string;
4
+ remainingArgs: string[];
5
+ }
6
+ export declare function loadCliConfig(env: Record<string, string | undefined>): MoneySirenConfig;
7
+ export declare function resolveDbPath(cwd: string, configuredDbPath: string): string;
8
+ export declare function readFlag(args: readonly string[], flagName: string): ParsedFlagResult;
9
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1,29 @@
1
+ import { isAbsolute, join } from "node:path";
2
+ import { loadMoneySirenConfig } from "../../../../packages/config/src/index.js";
3
+ export function loadCliConfig(env) {
4
+ return loadMoneySirenConfig(env);
5
+ }
6
+ export function resolveDbPath(cwd, configuredDbPath) {
7
+ return isAbsolute(configuredDbPath) ? configuredDbPath : join(cwd, configuredDbPath);
8
+ }
9
+ export function readFlag(args, flagName) {
10
+ const remainingArgs = [];
11
+ let value;
12
+ for (let index = 0; index < args.length; index += 1) {
13
+ const arg = args[index];
14
+ if (arg === flagName) {
15
+ value = args[index + 1];
16
+ index += 1;
17
+ continue;
18
+ }
19
+ if (arg?.startsWith(`${flagName}=`)) {
20
+ value = arg.slice(flagName.length + 1);
21
+ continue;
22
+ }
23
+ if (arg !== undefined) {
24
+ remainingArgs.push(arg);
25
+ }
26
+ }
27
+ return value === undefined ? { remainingArgs } : { value, remainingArgs };
28
+ }
29
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1,3 @@
1
+ import type { CliExecutionContext } from "../cli.js";
2
+ export declare function runSummaryCommand(args: readonly string[], context: CliExecutionContext): Promise<number>;
3
+ //# sourceMappingURL=summary.d.ts.map
@@ -0,0 +1,15 @@
1
+ import { readSanitizedSummary } from "../summary-model.js";
2
+ const SUMMARY_USAGE = "Usage: moneysiren summary --json";
3
+ export async function runSummaryCommand(args, context) {
4
+ if (args.includes("--help") || args.includes("-h")) {
5
+ context.stdout(SUMMARY_USAGE);
6
+ return 0;
7
+ }
8
+ if (args.length !== 1 || args[0] !== "--json") {
9
+ context.stderr(SUMMARY_USAGE);
10
+ return 1;
11
+ }
12
+ context.stdout(JSON.stringify(await readSanitizedSummary(context), null, 2));
13
+ return 0;
14
+ }
15
+ //# sourceMappingURL=summary.js.map
@@ -0,0 +1,3 @@
1
+ import type { CliExecutionContext } from "../cli.js";
2
+ export declare function runSyncCommand(args: readonly string[], context: CliExecutionContext): Promise<number>;
3
+ //# sourceMappingURL=sync.d.ts.map