@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,7 @@
1
+ import type { Theme } from "./theme.js";
2
+ export declare function renderHomeScreen(input: {
3
+ version: string;
4
+ theme: Theme;
5
+ }): string;
6
+ export declare function renderHelpScreen(version: string): string;
7
+ //# sourceMappingURL=home.d.ts.map
@@ -0,0 +1,124 @@
1
+ export function renderHomeScreen(input) {
2
+ const { theme, version } = input;
3
+ return [
4
+ `${theme.brand("MoneySiren")} ${theme.muted(version)}`,
5
+ "Local-first cloud/SaaS usage, status, and expected billing.",
6
+ "",
7
+ theme.heading("Slash commands"),
8
+ ` ${theme.command("/help")} Show CLI usage and slash guide`,
9
+ ` ${theme.command("/version")} Print the installed CLI version`,
10
+ ` ${theme.command("/doctor")} Check local readiness without printing secrets`,
11
+ ` ${theme.command("/install")} Choose CLI, web dashboard, and HUD components`,
12
+ ` ${theme.command("/modes")} Show the CLI, web, and desktop modes`,
13
+ ` ${theme.command("/start")} Start the installed dashboard runtime`,
14
+ ` ${theme.command("/hud")} Start the installed runtime and open HUD`,
15
+ ` ${theme.command("/status")} Show managed web, HUD, and local API runtime status`,
16
+ ` ${theme.command("/stop")} Stop managed web, HUD, and local API runtimes`,
17
+ ` ${theme.command("/init")} Create local SQLite storage`,
18
+ ` ${theme.command("/dashboard")} Check the local dashboard API`,
19
+ ` ${theme.command("/dashboard check")} Same as /dashboard`,
20
+ ` ${theme.command("/summary json")} Print sanitized local summary JSON`,
21
+ ` ${theme.command("/notify dry-run")} Preview a sanitized notification digest`,
22
+ ` ${theme.command("/notify prefs")} List local notification defaults`,
23
+ ` ${theme.command("/desktop status")} Check local runtime status`,
24
+ ` ${theme.command("/theme preview")} Preview the active CLI image-reference theme`,
25
+ ` ${theme.command("/sync mock")} Sync fake local review snapshots`,
26
+ ` ${theme.command("/sync aws")} Sync AWS Cost Explorer snapshots`,
27
+ ` ${theme.command("/sync openai")} Sync OpenAI usage/cost snapshots`,
28
+ ` ${theme.command("/sync supabase")} Sync Supabase usage/health snapshots`,
29
+ ` ${theme.command("/sync cloudflare")} Sync Cloudflare billing/usage snapshots`,
30
+ ` ${theme.command("/report ko")} Render the Korean daily report`,
31
+ ` ${theme.command("/quit")} Exit the slash prompt`,
32
+ "",
33
+ theme.heading("Classic CLI"),
34
+ " msiren start",
35
+ " msiren hud",
36
+ " msiren status",
37
+ " msiren stop",
38
+ " msiren install --all",
39
+ "",
40
+ theme.heading("Full command"),
41
+ " moneysiren doctor",
42
+ " moneysiren install",
43
+ " moneysiren install --status",
44
+ " moneysiren modes",
45
+ " moneysiren init",
46
+ " moneysiren serve [--port <port>]",
47
+ " moneysiren stop [--web|--hud|--api|--all]",
48
+ " moneysiren restart [--port <port>] [--open|--no-open] [--hud]",
49
+ " moneysiren open",
50
+ " moneysiren sync --provider mock",
51
+ " moneysiren summary --json",
52
+ " moneysiren notify once --dry-run",
53
+ " moneysiren notify prefs list",
54
+ " moneysiren desktop status",
55
+ " moneysiren report daily --lang ko",
56
+ " moneysiren dashboard check",
57
+ " moneysiren theme preview",
58
+ " moneysiren theme image-prompt",
59
+ " moneysiren theme image-generate",
60
+ "",
61
+ theme.warning("Security"),
62
+ " Home/help does not call provider APIs, read secret values, create .env, or enable telemetry.",
63
+ ].join("\n");
64
+ }
65
+ export function renderHelpScreen(version) {
66
+ return `MoneySiren ${version}
67
+
68
+ Local-first cloud/SaaS usage, status, and expected billing dashboard.
69
+
70
+ Short command:
71
+ msiren start
72
+ msiren hud
73
+ msiren install --all
74
+
75
+ Usage:
76
+ moneysiren
77
+ moneysiren --help
78
+ moneysiren --version
79
+ moneysiren init
80
+ moneysiren install [--status|--all|--cli|--web|--hud|--no-cli|--no-web|--no-hud]
81
+ moneysiren doctor
82
+ moneysiren modes
83
+ moneysiren start [--port <port>] [--open|--no-open] [--hud]
84
+ moneysiren hud [--port <port>]
85
+ moneysiren status
86
+ moneysiren stop [--web|--hud|--api|--all]
87
+ moneysiren restart [--port <port>] [--open|--no-open] [--hud]
88
+ moneysiren dashboard check [--url <local-dashboard-url>]
89
+ moneysiren serve [--port <port>]
90
+ moneysiren open
91
+ moneysiren theme preview
92
+ moneysiren theme image-prompt
93
+ moneysiren theme image-generate [--out <png> --theme-out <json> --model <model>]
94
+ moneysiren sync --provider <mock|aws|openai|supabase|cloudflare>
95
+ moneysiren summary --json
96
+ moneysiren notify once --dry-run
97
+ moneysiren notify prefs list
98
+ moneysiren desktop status
99
+ moneysiren report daily --lang ko [--send slack]
100
+
101
+ Slash commands:
102
+ moneysiren /help
103
+ moneysiren /version
104
+ moneysiren /doctor
105
+ moneysiren /install
106
+ moneysiren /modes
107
+ moneysiren /start
108
+ moneysiren /hud
109
+ moneysiren /status
110
+ moneysiren /stop [--web|--hud|--api|--all]
111
+ moneysiren /init
112
+ moneysiren /dashboard
113
+ moneysiren /dashboard check
114
+ moneysiren /summary json
115
+ moneysiren /notify dry-run
116
+ moneysiren /notify prefs
117
+ moneysiren /desktop status
118
+ moneysiren /theme <preview|image-prompt|image-generate>
119
+ moneysiren /sync <mock|aws|openai|supabase|cloudflare>
120
+ moneysiren /report ko
121
+ moneysiren /quit
122
+ `;
123
+ }
124
+ //# sourceMappingURL=home.js.map
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from "./cli.js";
3
+ const result = await runCli(process.argv.slice(2), {
4
+ cwd: process.cwd(),
5
+ env: process.env,
6
+ stdin: process.stdin,
7
+ output: process.stdout,
8
+ stdinIsTTY: process.stdin.isTTY,
9
+ stdoutIsTTY: process.stdout.isTTY,
10
+ stdout: (line) => console.log(line),
11
+ stderr: (line) => console.error(line),
12
+ });
13
+ process.exitCode = result.exitCode;
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,35 @@
1
+ export declare const INSTALL_SURFACES: readonly ["cli", "web", "hud"];
2
+ export declare const DEFAULT_INSTALL_SURFACES: readonly InstallSurface[];
3
+ export type InstallSurface = (typeof INSTALL_SURFACES)[number];
4
+ export type InstallProfileSource = "cli" | "postinstall";
5
+ export interface InstallProfile {
6
+ version: 1;
7
+ selectedSurfaces: readonly InstallSurface[];
8
+ recommendedDefault: boolean;
9
+ localOnly: true;
10
+ secretsReturned: false;
11
+ source: InstallProfileSource;
12
+ installedAt: string;
13
+ updatedAt: string;
14
+ }
15
+ export interface InstallProfileFileOptions {
16
+ env?: Record<string, string | undefined>;
17
+ now?: () => Date;
18
+ path?: string;
19
+ platform?: NodeJS.Platform;
20
+ }
21
+ export declare function resolveInstallProfilePath(options?: InstallProfileFileOptions): string;
22
+ export declare function readInstallProfileFile(options?: InstallProfileFileOptions): Promise<InstallProfile | null>;
23
+ export declare function writeInstallProfileFile(input: {
24
+ selectedSurfaces: readonly InstallSurface[];
25
+ source: InstallProfileSource;
26
+ recommendedDefault?: boolean;
27
+ }, options?: InstallProfileFileOptions): Promise<InstallProfile>;
28
+ export declare function parseInstallProfile(value: unknown): InstallProfile | null;
29
+ export declare function parseInstallSurfaces(value: unknown): readonly InstallSurface[];
30
+ export declare function normalizeInstallSurfaces(values: readonly InstallSurface[]): readonly InstallSurface[];
31
+ export declare function isRecommendedInstallSelection(values: readonly InstallSurface[]): boolean;
32
+ export declare function formatInstallSurfaces(values: readonly InstallSurface[]): string;
33
+ export declare function installSurfaceLabel(surface: InstallSurface): string;
34
+ export declare function isInstallSurface(value: unknown): value is InstallSurface;
35
+ //# sourceMappingURL=install-profile.d.ts.map
@@ -0,0 +1,124 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { dirname, isAbsolute, join, posix, win32 } from "node:path";
4
+ export const INSTALL_SURFACES = ["cli", "web", "hud"];
5
+ export const DEFAULT_INSTALL_SURFACES = INSTALL_SURFACES;
6
+ const INSTALL_PROFILE_ENV_KEY = "MONEYSIREN_INSTALL_PROFILE_PATH";
7
+ export function resolveInstallProfilePath(options = {}) {
8
+ if (options.path !== undefined && options.path.trim().length > 0) {
9
+ return resolveInstallPath(options.path, process.cwd());
10
+ }
11
+ const env = options.env ?? process.env;
12
+ const configuredPath = env[INSTALL_PROFILE_ENV_KEY];
13
+ if (configuredPath !== undefined && configuredPath.trim().length > 0) {
14
+ return resolveInstallPath(configuredPath, process.cwd());
15
+ }
16
+ return defaultInstallProfilePath(env, options.platform ?? process.platform);
17
+ }
18
+ export async function readInstallProfileFile(options = {}) {
19
+ try {
20
+ return parseInstallProfile(JSON.parse(await readFile(resolveInstallProfilePath(options), "utf8")));
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ export async function writeInstallProfileFile(input, options = {}) {
27
+ const existing = await readInstallProfileFile(options);
28
+ const now = (options.now ?? (() => new Date()))().toISOString();
29
+ const profile = {
30
+ version: 1,
31
+ selectedSurfaces: normalizeInstallSurfaces(input.selectedSurfaces),
32
+ recommendedDefault: input.recommendedDefault ?? isRecommendedInstallSelection(input.selectedSurfaces),
33
+ localOnly: true,
34
+ secretsReturned: false,
35
+ source: input.source,
36
+ installedAt: existing?.installedAt ?? now,
37
+ updatedAt: now,
38
+ };
39
+ const path = resolveInstallProfilePath(options);
40
+ await mkdir(dirname(path), { recursive: true });
41
+ await writeFile(path, `${JSON.stringify(profile, null, 2)}\n`, "utf8");
42
+ return profile;
43
+ }
44
+ export function parseInstallProfile(value) {
45
+ if (!isRecord(value) || value.version !== 1) {
46
+ return null;
47
+ }
48
+ const selectedSurfaces = parseInstallSurfaces(value.selectedSurfaces);
49
+ if (selectedSurfaces.length === 0) {
50
+ return null;
51
+ }
52
+ return {
53
+ version: 1,
54
+ selectedSurfaces,
55
+ recommendedDefault: typeof value.recommendedDefault === "boolean"
56
+ ? value.recommendedDefault
57
+ : isRecommendedInstallSelection(selectedSurfaces),
58
+ localOnly: true,
59
+ secretsReturned: false,
60
+ source: value.source === "postinstall" ? "postinstall" : "cli",
61
+ installedAt: typeof value.installedAt === "string" ? value.installedAt : "",
62
+ updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : "",
63
+ };
64
+ }
65
+ export function parseInstallSurfaces(value) {
66
+ if (!Array.isArray(value)) {
67
+ return [];
68
+ }
69
+ return normalizeInstallSurfaces(value.filter(isInstallSurface));
70
+ }
71
+ export function normalizeInstallSurfaces(values) {
72
+ const selected = new Set(values);
73
+ return INSTALL_SURFACES.filter((surface) => selected.has(surface));
74
+ }
75
+ export function isRecommendedInstallSelection(values) {
76
+ const selected = normalizeInstallSurfaces(values);
77
+ return selected.length === INSTALL_SURFACES.length &&
78
+ INSTALL_SURFACES.every((surface, index) => selected[index] === surface);
79
+ }
80
+ export function formatInstallSurfaces(values) {
81
+ return normalizeInstallSurfaces(values).map(installSurfaceLabel).join(", ");
82
+ }
83
+ export function installSurfaceLabel(surface) {
84
+ if (surface === "cli") {
85
+ return "CLI";
86
+ }
87
+ if (surface === "web") {
88
+ return "Web dashboard";
89
+ }
90
+ return "HUD";
91
+ }
92
+ export function isInstallSurface(value) {
93
+ return typeof value === "string" && INSTALL_SURFACES.includes(value);
94
+ }
95
+ function defaultInstallProfilePath(env, platform) {
96
+ if (platform === "darwin") {
97
+ return joinForPlatform(platform, resolveHomeDirectory(env), "Library", "Application Support", "MoneySiren", "install-profile.json");
98
+ }
99
+ if (platform === "win32") {
100
+ return joinForPlatform(platform, resolveWindowsAppDataDirectory(env), "MoneySiren", "install-profile.json");
101
+ }
102
+ const configHome = trimToNull(env.XDG_CONFIG_HOME) ?? joinForPlatform(platform, resolveHomeDirectory(env), ".config");
103
+ return joinForPlatform(platform, configHome, "moneysiren", "install-profile.json");
104
+ }
105
+ function resolveInstallPath(path, cwd) {
106
+ return isAbsolute(path) ? path : join(cwd, path);
107
+ }
108
+ function resolveWindowsAppDataDirectory(env) {
109
+ return trimToNull(env.APPDATA) ?? win32.join(resolveHomeDirectory(env), "AppData", "Roaming");
110
+ }
111
+ function resolveHomeDirectory(env) {
112
+ return trimToNull(env.HOME) ?? trimToNull(env.USERPROFILE) ?? homedir();
113
+ }
114
+ function trimToNull(value) {
115
+ const trimmed = value?.trim();
116
+ return trimmed === undefined || trimmed.length === 0 ? null : trimmed;
117
+ }
118
+ function joinForPlatform(platform, ...segments) {
119
+ return platform === "win32" ? win32.join(...segments) : posix.join(...segments);
120
+ }
121
+ function isRecord(value) {
122
+ return typeof value === "object" && value !== null && !Array.isArray(value);
123
+ }
124
+ //# sourceMappingURL=install-profile.js.map
@@ -0,0 +1,10 @@
1
+ import { type InstallSurface } from "./install-profile.js";
2
+ export interface InstallSelectionPromptOptions {
3
+ stdin: NodeJS.ReadableStream;
4
+ output: NodeJS.WritableStream;
5
+ }
6
+ export declare function promptForInstallSurfaces(options: InstallSelectionPromptOptions): Promise<readonly InstallSurface[]>;
7
+ export declare function parseInstallSurfaceSelection(input: string): readonly InstallSurface[] | null;
8
+ export declare function formatInstallSelectionLine(selectedSurfaces: readonly InstallSurface[]): string;
9
+ export declare function installSelectionHelp(): string;
10
+ //# sourceMappingURL=install-selector.d.ts.map
@@ -0,0 +1,66 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ import { DEFAULT_INSTALL_SURFACES, INSTALL_SURFACES, formatInstallSurfaces, installSurfaceLabel, isInstallSurface, normalizeInstallSurfaces, } from "./install-profile.js";
3
+ export async function promptForInstallSurfaces(options) {
4
+ options.output.write([
5
+ "MoneySiren setup",
6
+ "Recommended default: CLI, Web dashboard, HUD",
7
+ "Select components to enable after npm install:",
8
+ " 1. CLI",
9
+ " 2. Web dashboard",
10
+ " 3. HUD",
11
+ "",
12
+ ].join("\n"));
13
+ options.output.write("\n");
14
+ const readline = createInterface({
15
+ input: options.stdin,
16
+ output: options.output,
17
+ });
18
+ try {
19
+ const answer = await readline.question("Choose components [1,2,3] (Enter = all recommended): ");
20
+ const selected = parseInstallSurfaceSelection(answer);
21
+ if (selected === null) {
22
+ options.output.write("Invalid selection. Using recommended default: CLI, Web dashboard, HUD\n");
23
+ return DEFAULT_INSTALL_SURFACES;
24
+ }
25
+ return selected;
26
+ }
27
+ finally {
28
+ readline.close();
29
+ }
30
+ }
31
+ export function parseInstallSurfaceSelection(input) {
32
+ const trimmed = input.trim().toLowerCase();
33
+ if (trimmed.length === 0 || trimmed === "all" || trimmed === "recommended") {
34
+ return DEFAULT_INSTALL_SURFACES;
35
+ }
36
+ const selected = trimmed
37
+ .split(/[\s,;]+/)
38
+ .filter((token) => token.length > 0)
39
+ .map(selectionTokenToSurface);
40
+ if (selected.some((surface) => surface === null)) {
41
+ return null;
42
+ }
43
+ const normalized = normalizeInstallSurfaces(selected.filter((surface) => surface !== null));
44
+ return normalized.length === 0 ? null : normalized;
45
+ }
46
+ export function formatInstallSelectionLine(selectedSurfaces) {
47
+ return `Selected components: ${formatInstallSurfaces(selectedSurfaces)}`;
48
+ }
49
+ export function installSelectionHelp() {
50
+ return INSTALL_SURFACES
51
+ .map((surface, index) => ` ${index + 1}. ${installSurfaceLabel(surface)}`)
52
+ .join("\n");
53
+ }
54
+ function selectionTokenToSurface(token) {
55
+ if (token === "1") {
56
+ return "cli";
57
+ }
58
+ if (token === "2") {
59
+ return "web";
60
+ }
61
+ if (token === "3") {
62
+ return "hud";
63
+ }
64
+ return isInstallSurface(token) ? token : null;
65
+ }
66
+ //# sourceMappingURL=install-selector.js.map
@@ -0,0 +1,3 @@
1
+ import type { CliExecutionContext } from "./cli.js";
2
+ export declare function runSlashPrompt(context: CliExecutionContext, execute: (args: readonly string[]) => Promise<number>): Promise<number>;
3
+ //# sourceMappingURL=interactive.d.ts.map
@@ -0,0 +1,32 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ import { isSlashQuit, parseSlashInput } from "./slash.js";
3
+ export async function runSlashPrompt(context, execute) {
4
+ if (context.stdin === undefined || context.output === undefined) {
5
+ return 0;
6
+ }
7
+ const prompt = context.theme.command("moneysiren> ");
8
+ const readline = createInterface({
9
+ input: context.stdin,
10
+ output: context.output,
11
+ terminal: false,
12
+ historySize: 0,
13
+ });
14
+ context.stdout("Slash prompt ready. Type /help for commands or /quit to exit.");
15
+ try {
16
+ let lastExitCode = 0;
17
+ while (true) {
18
+ const args = parseSlashInput(await readline.question(prompt));
19
+ if (args.length === 0) {
20
+ continue;
21
+ }
22
+ lastExitCode = await execute(args);
23
+ if (isSlashQuit(args)) {
24
+ return lastExitCode;
25
+ }
26
+ }
27
+ }
28
+ finally {
29
+ readline.close();
30
+ }
31
+ }
32
+ //# sourceMappingURL=interactive.js.map
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=postinstall.d.ts.map
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ import { DEFAULT_INSTALL_SURFACES, writeInstallProfileFile } from "./install-profile.js";
3
+ import { formatInstallSelectionLine, promptForInstallSurfaces } from "./install-selector.js";
4
+ const selectedSurfaces = await selectSurfaces();
5
+ try {
6
+ const profile = await writeInstallProfileFile({
7
+ selectedSurfaces,
8
+ source: "postinstall",
9
+ recommendedDefault: selectedSurfaces.length === DEFAULT_INSTALL_SURFACES.length,
10
+ });
11
+ console.log("MoneySiren setup profile saved.");
12
+ console.log(formatInstallSelectionLine(profile.selectedSurfaces));
13
+ console.log("Run `msiren install --status` to review, `msiren install` to change it, or `msiren start` after installing release assets.");
14
+ }
15
+ catch (error) {
16
+ console.warn(`MoneySiren setup profile skipped: ${error instanceof Error ? error.message : String(error)}`);
17
+ }
18
+ async function selectSurfaces() {
19
+ if (isTruthy(process.env.MONEYSIREN_SKIP_POSTINSTALL)) {
20
+ return DEFAULT_INSTALL_SURFACES;
21
+ }
22
+ if (!shouldPrompt()) {
23
+ return DEFAULT_INSTALL_SURFACES;
24
+ }
25
+ return promptForInstallSurfaces({
26
+ stdin: process.stdin,
27
+ output: process.stdout,
28
+ });
29
+ }
30
+ function shouldPrompt() {
31
+ return Boolean(process.stdin.isTTY) &&
32
+ Boolean(process.stdout.isTTY) &&
33
+ !isTruthy(process.env.CI);
34
+ }
35
+ function isTruthy(value) {
36
+ if (value === undefined) {
37
+ return false;
38
+ }
39
+ const normalized = value.trim().toLowerCase();
40
+ return normalized.length > 0 && normalized !== "0" && normalized !== "false" && normalized !== "no";
41
+ }
42
+ //# sourceMappingURL=postinstall.js.map
@@ -0,0 +1,57 @@
1
+ import type { InstallSurface } from "./install-profile.js";
2
+ export declare const DEFAULT_RELEASE_REPOSITORY = "ztwz11/moneysiren";
3
+ export declare const DEFAULT_RELEASE_TAG = "v0.1.0-alpha.9";
4
+ export interface ReleaseInstallOptions {
5
+ env?: Record<string, string | undefined>;
6
+ fetchImpl: typeof fetch;
7
+ installDir?: string;
8
+ now?: () => Date;
9
+ platform?: NodeJS.Platform;
10
+ repository?: string;
11
+ selectedSurfaces: readonly InstallSurface[];
12
+ signatureVerifier?: ReleaseAssetSignatureVerifier;
13
+ tag?: string;
14
+ trustedWindowsSignerThumbprints?: readonly string[];
15
+ }
16
+ export interface ReleaseInstallResult {
17
+ repository: string;
18
+ tag: string;
19
+ installDir: string;
20
+ releaseUrl: string;
21
+ assets: readonly InstalledReleaseAsset[];
22
+ }
23
+ export interface InstalledReleaseAsset {
24
+ surface: Exclude<InstallSurface, "cli">;
25
+ name: string;
26
+ path: string;
27
+ size: number;
28
+ sha256: string;
29
+ checksumVerified: boolean;
30
+ signatureVerified: boolean;
31
+ signatureStatus: string;
32
+ }
33
+ export interface ReleaseAssetSignatureVerifier {
34
+ verify(input: ReleaseAssetSignatureVerificationInput): Promise<ReleaseAssetSignatureVerificationResult>;
35
+ }
36
+ export interface ReleaseAssetSignatureVerificationInput {
37
+ assetName: string;
38
+ env: Record<string, string | undefined>;
39
+ expectedSignerThumbprints?: readonly string[];
40
+ path: string;
41
+ platform: NodeJS.Platform;
42
+ surface: Exclude<InstallSurface, "cli">;
43
+ tag: string;
44
+ }
45
+ export interface ReleaseAssetSignatureVerificationResult {
46
+ verified: boolean;
47
+ status: string;
48
+ message: string;
49
+ }
50
+ export declare function installReleaseAssets(options: ReleaseInstallOptions): Promise<ReleaseInstallResult>;
51
+ export declare function resolveReleaseInstallDir(input?: {
52
+ env?: Record<string, string | undefined>;
53
+ installDir?: string;
54
+ platform?: NodeJS.Platform;
55
+ tag?: string;
56
+ }): string;
57
+ //# sourceMappingURL=release-installer.d.ts.map