veryfront 0.1.1193 → 0.1.1195
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/esm/cli/app/actions.d.ts +27 -10
- package/esm/cli/app/actions.d.ts.map +1 -1
- package/esm/cli/app/actions.js +115 -89
- package/esm/cli/app/components/list-select.d.ts.map +1 -1
- package/esm/cli/app/components/list-select.js +7 -4
- package/esm/cli/app/index.d.ts +2 -4
- package/esm/cli/app/index.d.ts.map +1 -1
- package/esm/cli/app/index.js +3 -5
- package/esm/cli/app/key-reducer.d.ts +74 -0
- package/esm/cli/app/key-reducer.d.ts.map +1 -0
- package/esm/cli/app/key-reducer.js +229 -0
- package/esm/cli/app/operations/project-creation.d.ts.map +1 -1
- package/esm/cli/app/operations/project-creation.js +2 -8
- package/esm/cli/app/shell.d.ts +4 -1
- package/esm/cli/app/shell.d.ts.map +1 -1
- package/esm/cli/app/shell.js +135 -322
- package/esm/cli/app/startup.d.ts +33 -4
- package/esm/cli/app/startup.d.ts.map +1 -1
- package/esm/cli/app/startup.js +63 -24
- package/esm/cli/app/state.d.ts +29 -33
- package/esm/cli/app/state.d.ts.map +1 -1
- package/esm/cli/app/state.js +40 -70
- package/esm/cli/app/types.d.ts +3 -2
- package/esm/cli/app/types.d.ts.map +1 -1
- package/esm/cli/app/utils.d.ts +1 -2
- package/esm/cli/app/utils.d.ts.map +1 -1
- package/esm/cli/app/utils.js +0 -29
- package/esm/cli/app/views/dashboard.d.ts.map +1 -1
- package/esm/cli/app/views/dashboard.js +22 -43
- package/esm/cli/app/views/help.js +1 -1
- package/esm/cli/commands/start/command.d.ts +13 -0
- package/esm/cli/commands/start/command.d.ts.map +1 -1
- package/esm/cli/commands/start/command.js +142 -83
- package/esm/cli/ui/layout.d.ts +10 -0
- package/esm/cli/ui/layout.d.ts.map +1 -1
- package/esm/cli/ui/layout.js +14 -2
- package/esm/deno.js +1 -1
- package/esm/src/agent/hosted/veryfront-cloud-agent-service.d.ts.map +1 -1
- package/esm/src/agent/hosted/veryfront-cloud-agent-service.js +1 -2
- package/esm/src/html/hydration-script-builder/hydration-runtime.generated.js +1 -1
- package/esm/src/platform/compat/http/pinned-fetch.d.ts +32 -0
- package/esm/src/platform/compat/http/pinned-fetch.d.ts.map +1 -1
- package/esm/src/platform/compat/http/pinned-fetch.js +52 -1
- package/esm/src/security/sandbox/worker-egress-guard.d.ts.map +1 -1
- package/esm/src/security/sandbox/worker-egress-guard.js +14 -2
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +8 -8
- package/esm/cli/app/handlers/remote-navigation.d.ts +0 -20
- package/esm/cli/app/handlers/remote-navigation.d.ts.map +0 -1
- package/esm/cli/app/handlers/remote-navigation.js +0 -51
- package/esm/cli/app/handlers/view-handlers.d.ts +0 -36
- package/esm/cli/app/handlers/view-handlers.d.ts.map +0 -1
- package/esm/cli/app/handlers/view-handlers.js +0 -130
package/esm/cli/app/actions.d.ts
CHANGED
|
@@ -1,21 +1,38 @@
|
|
|
1
1
|
/**************************
|
|
2
2
|
* CLI App Actions
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Opening a project in the browser, Studio, or an IDE. Everything that leaves
|
|
5
|
+
* the process, spawning commands, opening URLs, touching disk, goes through
|
|
6
|
+
* the LauncherHost seam, so IDE detection order, the Windows/POSIX split, and
|
|
7
|
+
* the settings-file bootstrap are all reachable from a test.
|
|
8
|
+
*
|
|
9
|
+
* Two adapters justify the seam: the platform host in production, a fake in
|
|
10
|
+
* tests.
|
|
6
11
|
**************************/
|
|
7
12
|
import type { ProjectInfo } from "./state.js";
|
|
8
|
-
import { type EnvironmentConfig } from "../../src/config/index.js";
|
|
9
13
|
export type IDE = "cursor" | "code" | "zed" | "idea" | "webstorm";
|
|
10
14
|
export interface ActionResult {
|
|
11
15
|
success: boolean;
|
|
12
16
|
message?: string;
|
|
13
17
|
}
|
|
14
|
-
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
/** Everything the launcher needs from the outside world. */
|
|
19
|
+
export interface LauncherHost {
|
|
20
|
+
openUrl(url: string): Promise<void>;
|
|
21
|
+
/** Whether `command` is on PATH. */
|
|
22
|
+
commandExists(command: string): Promise<boolean>;
|
|
23
|
+
/** Run `command`; resolves to whether it succeeded. */
|
|
24
|
+
run(command: string, args: string[]): Promise<boolean>;
|
|
25
|
+
/** Create `path` with `contents` if it does not already exist. */
|
|
26
|
+
ensureFile(path: string, contents: string): Promise<void>;
|
|
27
|
+
homeDir(): string;
|
|
28
|
+
}
|
|
29
|
+
export interface Launcher {
|
|
30
|
+
openInBrowser(project: ProjectInfo, port: number): Promise<ActionResult>;
|
|
31
|
+
openInStudio(project: ProjectInfo): Promise<ActionResult>;
|
|
32
|
+
openInIDE(project: ProjectInfo, ide?: IDE): Promise<ActionResult>;
|
|
33
|
+
openMCPSettings(): Promise<ActionResult>;
|
|
34
|
+
}
|
|
35
|
+
export declare function createLauncher(host: LauncherHost): Launcher;
|
|
36
|
+
/** The production host: real processes, real browser, real disk. */
|
|
37
|
+
export declare function createPlatformHost(): LauncherHost;
|
|
21
38
|
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/cli/app/actions.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/cli/app/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;4BAU4B;AAO5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,MAAM,MAAM,GAAG,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,4DAA4D;AAC5D,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,oCAAoC;IACpC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,uDAAuD;IACvD,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,kEAAkE;IAClE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,OAAO,IAAI,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACzE,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1D,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAClE,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;CAC1C;AAqBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAwF3D;AAED,oEAAoE;AACpE,wBAAgB,kBAAkB,IAAI,YAAY,CAqCjD"}
|
package/esm/cli/app/actions.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
/**************************
|
|
2
2
|
* CLI App Actions
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Opening a project in the browser, Studio, or an IDE. Everything that leaves
|
|
5
|
+
* the process, spawning commands, opening URLs, touching disk, goes through
|
|
6
|
+
* the LauncherHost seam, so IDE detection order, the Windows/POSIX split, and
|
|
7
|
+
* the settings-file bootstrap are all reachable from a test.
|
|
8
|
+
*
|
|
9
|
+
* Two adapters justify the seam: the platform host in production, a fake in
|
|
10
|
+
* tests.
|
|
6
11
|
**************************/
|
|
7
12
|
import { openBrowser } from "../auth/browser.js";
|
|
8
13
|
import { createFileSystem } from "../../src/platform/index.js";
|
|
9
14
|
import { getOsType, runCommand } from "../../src/platform/index.js";
|
|
10
15
|
import { formatError } from "../utils/string.js";
|
|
11
|
-
import { join } from "../../src/platform/compat/path/index.js";
|
|
16
|
+
import { dirname, join } from "../../src/platform/compat/path/index.js";
|
|
12
17
|
import { getEnvironmentConfig } from "../../src/config/index.js";
|
|
13
18
|
const IDE_COMMANDS = {
|
|
14
19
|
cursor: "cursor",
|
|
@@ -24,97 +29,118 @@ const IDE_NAMES = {
|
|
|
24
29
|
idea: "IntelliJ IDEA",
|
|
25
30
|
webstorm: "WebStorm",
|
|
26
31
|
};
|
|
32
|
+
/** First match wins. */
|
|
27
33
|
const IDE_DETECTION_ORDER = ["cursor", "code", "zed", "idea", "webstorm"];
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
async function runCommandLocal(cmd, args) {
|
|
39
|
-
try {
|
|
40
|
-
const result = await runCommand(cmd, { args });
|
|
41
|
-
return result.success;
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
export async function openInBrowser(project, port) {
|
|
48
|
-
const url = `http://${project.slug}.veryfront.me:${port}`;
|
|
49
|
-
try {
|
|
50
|
-
await openBrowser(url);
|
|
51
|
-
return { success: true, message: `Opened ${url}` };
|
|
52
|
-
}
|
|
53
|
-
catch (error) {
|
|
54
|
-
return { success: false, message: `Failed to open browser: ${formatError(error)}` };
|
|
34
|
+
export function createLauncher(host) {
|
|
35
|
+
async function open(url, describe) {
|
|
36
|
+
try {
|
|
37
|
+
await host.openUrl(url);
|
|
38
|
+
return { success: true, message: describe(url) };
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
return { success: false, message: `Failed to open: ${formatError(error)}` };
|
|
42
|
+
}
|
|
55
43
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return
|
|
44
|
+
async function preferredIDE() {
|
|
45
|
+
for (const ide of IDE_DETECTION_ORDER) {
|
|
46
|
+
if (await host.commandExists(IDE_COMMANDS[ide]))
|
|
47
|
+
return ide;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
62
50
|
}
|
|
63
|
-
|
|
64
|
-
|
|
51
|
+
async function openPath(path, ide) {
|
|
52
|
+
const target = ide ?? (await preferredIDE());
|
|
53
|
+
if (!target)
|
|
54
|
+
return { ok: false, name: "" };
|
|
55
|
+
const ok = await host.run(IDE_COMMANDS[target], [path]);
|
|
56
|
+
return { ok, name: IDE_NAMES[target] };
|
|
65
57
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
58
|
+
async function openFileInIDE(path) {
|
|
59
|
+
const { ok, name } = await openPath(path);
|
|
60
|
+
if (!name) {
|
|
61
|
+
return {
|
|
62
|
+
success: false,
|
|
63
|
+
message: "No supported IDE found. Install VS Code, Cursor, or Zed.",
|
|
64
|
+
};
|
|
72
65
|
}
|
|
66
|
+
return ok
|
|
67
|
+
? { success: true, message: `Opened in ${name}` }
|
|
68
|
+
: { success: false, message: `Failed to open ${name}` };
|
|
73
69
|
}
|
|
74
|
-
return
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
70
|
+
return {
|
|
71
|
+
openInBrowser(project, port) {
|
|
72
|
+
return open(`http://${project.slug}.veryfront.me:${port}`, (url) => `Opened ${url}`);
|
|
73
|
+
},
|
|
74
|
+
openInStudio(project) {
|
|
75
|
+
return open(`https://veryfront.com/projects/${project.slug}`, () => `Opened Studio for ${project.slug}`);
|
|
76
|
+
},
|
|
77
|
+
async openInIDE(project, ide) {
|
|
78
|
+
const { ok, name } = await openPath(project.path, ide);
|
|
79
|
+
if (!name) {
|
|
80
|
+
return {
|
|
81
|
+
success: false,
|
|
82
|
+
message: "No supported IDE found. Install VS Code, Cursor, or Zed.",
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return ok
|
|
86
|
+
? { success: true, message: `Opened ${project.slug} in ${name}` }
|
|
87
|
+
: { success: false, message: `Failed to open ${name}` };
|
|
88
|
+
},
|
|
89
|
+
async openMCPSettings() {
|
|
90
|
+
const home = host.homeDir().trim();
|
|
91
|
+
if (!home) {
|
|
92
|
+
// Joining "" would write .claude/settings.json into the current
|
|
93
|
+
// directory and still report success.
|
|
94
|
+
return { success: false, message: "Could not determine your home directory." };
|
|
95
|
+
}
|
|
96
|
+
const settingsPath = join(home, ".claude", "settings.json");
|
|
97
|
+
// Every launcher method reports failure through ActionResult. Letting a
|
|
98
|
+
// write error escape instead would reject inside the shell's key
|
|
99
|
+
// handling, where it surfaces as a dead keypress rather than a log line.
|
|
100
|
+
try {
|
|
101
|
+
await host.ensureFile(settingsPath, `${JSON.stringify({ mcpServers: {} }, null, 2)}\n`);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
return { success: false, message: `Failed to write settings: ${formatError(error)}` };
|
|
105
|
+
}
|
|
106
|
+
return openFileInIDE(settingsPath);
|
|
107
|
+
},
|
|
108
|
+
};
|
|
94
109
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
110
|
+
/** The production host: real processes, real browser, real disk. */
|
|
111
|
+
export function createPlatformHost() {
|
|
112
|
+
return {
|
|
113
|
+
openUrl: (url) => openBrowser(url),
|
|
114
|
+
async commandExists(command) {
|
|
115
|
+
const probe = getOsType() === "windows" ? "where" : "which";
|
|
116
|
+
try {
|
|
117
|
+
const result = await runCommand(probe, { args: [command] });
|
|
118
|
+
return result.success;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
async run(command, args) {
|
|
125
|
+
try {
|
|
126
|
+
const result = await runCommand(command, { args });
|
|
127
|
+
return result.success;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
async ensureFile(path, contents) {
|
|
134
|
+
const fs = createFileSystem();
|
|
135
|
+
try {
|
|
136
|
+
await fs.mkdir(dirname(path), { recursive: true });
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Already exists
|
|
140
|
+
}
|
|
141
|
+
if (!(await fs.exists(path)))
|
|
142
|
+
await fs.writeTextFile(path, contents);
|
|
143
|
+
},
|
|
144
|
+
homeDir: () => getEnvironmentConfig().homeDir ?? "",
|
|
145
|
+
};
|
|
120
146
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-select.d.ts","sourceRoot":"","sources":["../../../../src/cli/app/components/list-select.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,OAAO;IACnC,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,IAAI,CAAC,EAAE,CAAC,CAAC;CACV;AAED,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0BAA0B;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,4BAA4B;IAC5B,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,eAAe,CAAC,CAAC,CAAC,CAE3E;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAQvE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EACzB,YAAY,SAAK,GAChB,eAAe,CAAC,CAAC,CAAC,CAcpB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EACzB,GAAG,EAAE,MAAM,GACV,eAAe,CAAC,CAAC,CAAC,CAIpB;
|
|
1
|
+
{"version":3,"file":"list-select.d.ts","sourceRoot":"","sources":["../../../../src/cli/app/components/list-select.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,OAAO;IACnC,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,IAAI,CAAC,EAAE,CAAC,CAAC;CACV;AAED,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0BAA0B;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,4BAA4B;IAC5B,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,eAAe,CAAC,CAAC,CAAC,CAE3E;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAQvE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EACzB,YAAY,SAAK,GAChB,eAAe,CAAC,CAAC,CAAC,CAcpB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EACzB,GAAG,EAAE,MAAM,GACV,eAAe,CAAC,CAAC,CAAC,CAIpB;AAYD;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EACzB,OAAO,GAAE,iBAAsB,GAC9B,MAAM,CAmFR"}
|
|
@@ -49,12 +49,15 @@ export function selectByNumber(state, num) {
|
|
|
49
49
|
return state;
|
|
50
50
|
return { ...state, selectedIndex: index };
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Only 1-9 are offered. Letters would collide with the action keys the
|
|
54
|
+
* dashboard already binds (a, i, o, p, s, u, x…), so an item past the ninth
|
|
55
|
+
* shows no shortcut and is reached with the arrow keys.
|
|
56
|
+
*/
|
|
52
57
|
function getShortcut(displayNum) {
|
|
53
|
-
if (displayNum <= 0 || displayNum >
|
|
58
|
+
if (displayNum <= 0 || displayNum > 9)
|
|
54
59
|
return undefined;
|
|
55
|
-
|
|
56
|
-
return String(displayNum);
|
|
57
|
-
return String.fromCharCode(96 + displayNum - 9); // 10='a', 11='b', etc.
|
|
60
|
+
return String(displayNum);
|
|
58
61
|
}
|
|
59
62
|
/**
|
|
60
63
|
* Render the list as a string
|
package/esm/cli/app/index.d.ts
CHANGED
|
@@ -4,10 +4,8 @@
|
|
|
4
4
|
* Interactive app-like CLI experience with dashboard and project navigation.
|
|
5
5
|
*/
|
|
6
6
|
export { createApp } from "./shell.js";
|
|
7
|
-
export {
|
|
7
|
+
export { startStartupProgress, type StartupProgress } from "./startup.js";
|
|
8
8
|
export type { App, AppConfig } from "./types.js";
|
|
9
9
|
export type { AppState, LogMeta, ProjectInfo, StateUpdater } from "./state.js";
|
|
10
|
-
export
|
|
11
|
-
export * from "./actions.js";
|
|
12
|
-
export * from "./components/list-select.js";
|
|
10
|
+
export { type Effect, type KeyEnv, type KeyResult, reduceKey } from "./key-reducer.js";
|
|
13
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/app/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/app/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAG1E,YAAY,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/E,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC"}
|
package/esm/cli/app/index.js
CHANGED
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
// Core app
|
|
7
7
|
export { createApp } from "./shell.js";
|
|
8
|
-
export {
|
|
9
|
-
//
|
|
10
|
-
export
|
|
11
|
-
export * from "./actions.js";
|
|
12
|
-
export * from "./components/list-select.js";
|
|
8
|
+
export { startStartupProgress } from "./startup.js";
|
|
9
|
+
// Key transition (the app's decision surface)
|
|
10
|
+
export { reduceKey } from "./key-reducer.js";
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key Transition
|
|
3
|
+
*
|
|
4
|
+
* The single owner of "what does this key press do?". A pure function of
|
|
5
|
+
* (state, key) that settles into the next state plus the effects the shell
|
|
6
|
+
* should perform. Nothing here touches the terminal, the network, or the
|
|
7
|
+
* clock, so every key path is reachable from a test through this one
|
|
8
|
+
* interface, the same one the shell uses.
|
|
9
|
+
*
|
|
10
|
+
* Effects are data, never callbacks. The shell performs them; this module
|
|
11
|
+
* decides them.
|
|
12
|
+
*/
|
|
13
|
+
import type { InitTemplate } from "../commands/init/types.js";
|
|
14
|
+
import { type AppState, type ProjectInfo } from "./state.js";
|
|
15
|
+
export declare const KEY_UP = "\u001B[A";
|
|
16
|
+
export declare const KEY_DOWN = "\u001B[B";
|
|
17
|
+
export declare const KEY_ESCAPE = "\u001B";
|
|
18
|
+
export declare const KEY_ENTER = "\r";
|
|
19
|
+
export declare const KEY_NEWLINE = "\n";
|
|
20
|
+
export declare const KEY_CTRL_C = "\u0003";
|
|
21
|
+
export declare const KEY_TAB = "\t";
|
|
22
|
+
export type AuthProvider = "google" | "github" | "microsoft";
|
|
23
|
+
export declare const AUTH_PROVIDERS: AuthProvider[];
|
|
24
|
+
/** Work the shell performs on the reducer's behalf. */
|
|
25
|
+
export type Effect = {
|
|
26
|
+
kind: "exit";
|
|
27
|
+
} | {
|
|
28
|
+
kind: "open-browser";
|
|
29
|
+
project: ProjectInfo;
|
|
30
|
+
} | {
|
|
31
|
+
kind: "open-studio";
|
|
32
|
+
project: ProjectInfo;
|
|
33
|
+
} | {
|
|
34
|
+
kind: "open-ide";
|
|
35
|
+
project: ProjectInfo;
|
|
36
|
+
} | {
|
|
37
|
+
kind: "pull";
|
|
38
|
+
project: ProjectInfo;
|
|
39
|
+
} | {
|
|
40
|
+
kind: "push";
|
|
41
|
+
project: ProjectInfo;
|
|
42
|
+
} | {
|
|
43
|
+
kind: "login";
|
|
44
|
+
provider: AuthProvider;
|
|
45
|
+
} | {
|
|
46
|
+
kind: "logout";
|
|
47
|
+
} | {
|
|
48
|
+
kind: "open-mcp-settings";
|
|
49
|
+
} | {
|
|
50
|
+
kind: "create-project";
|
|
51
|
+
template: InitTemplate;
|
|
52
|
+
name: string;
|
|
53
|
+
};
|
|
54
|
+
export interface KeyResult {
|
|
55
|
+
state: AppState;
|
|
56
|
+
effects: Effect[];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The impure facts the transition needs. Injected rather than reached for, so
|
|
60
|
+
* the reducer stays a pure function and tests can pin the suggestion.
|
|
61
|
+
*/
|
|
62
|
+
export interface KeyEnv {
|
|
63
|
+
/** Pre-filled value for the project-name prompt. */
|
|
64
|
+
suggestProjectName: () => string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Reduce one key press against the current state.
|
|
68
|
+
*
|
|
69
|
+
* The returned state is always the state to adopt, there is no second write
|
|
70
|
+
* path. Callers assign it and run the effects; they never mutate state
|
|
71
|
+
* themselves.
|
|
72
|
+
*/
|
|
73
|
+
export declare function reduceKey(state: AppState, key: string, env: KeyEnv): KeyResult;
|
|
74
|
+
//# sourceMappingURL=key-reducer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-reducer.d.ts","sourceRoot":"","sources":["../../../src/cli/app/key-reducer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAEL,KAAK,QAAQ,EAKb,KAAK,WAAW,EAQjB,MAAM,YAAY,CAAC;AASpB,eAAO,MAAM,MAAM,aAAW,CAAC;AAC/B,eAAO,MAAM,QAAQ,aAAW,CAAC;AACjC,eAAO,MAAM,UAAU,WAAS,CAAC;AACjC,eAAO,MAAM,SAAS,OAAO,CAAC;AAC9B,eAAO,MAAM,WAAW,OAAO,CAAC;AAChC,eAAO,MAAM,UAAU,WAAS,CAAC;AACjC,eAAO,MAAM,OAAO,OAAO,CAAC;AAK5B,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE7D,eAAO,MAAM,cAAc,EAAE,YAAY,EAAsC,CAAC;AAEhF,uDAAuD;AACvD,MAAM,MAAM,MAAM,GACd;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,oDAAoD;IACpD,kBAAkB,EAAE,MAAM,MAAM,CAAC;CAClC;AAID;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAwB9E"}
|