veryfront 0.0.82 → 0.0.83

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 (120) hide show
  1. package/README.md +15 -1
  2. package/esm/deno.js +1 -1
  3. package/esm/proxy/cache/index.d.ts +41 -0
  4. package/esm/proxy/cache/index.d.ts.map +1 -0
  5. package/esm/proxy/cache/index.js +75 -0
  6. package/esm/proxy/cache/memory-cache.d.ts +18 -0
  7. package/esm/proxy/cache/memory-cache.d.ts.map +1 -0
  8. package/esm/proxy/cache/memory-cache.js +100 -0
  9. package/esm/proxy/cache/redis-cache.d.ts +27 -0
  10. package/esm/proxy/cache/redis-cache.d.ts.map +1 -0
  11. package/esm/proxy/cache/redis-cache.js +183 -0
  12. package/esm/proxy/cache/resilient-cache.d.ts +44 -0
  13. package/esm/proxy/cache/resilient-cache.d.ts.map +1 -0
  14. package/esm/proxy/cache/resilient-cache.js +178 -0
  15. package/esm/proxy/cache/types.d.ts +65 -0
  16. package/esm/proxy/cache/types.d.ts.map +1 -0
  17. package/esm/proxy/cache/types.js +7 -0
  18. package/esm/proxy/handler.d.ts +81 -0
  19. package/esm/proxy/handler.d.ts.map +1 -0
  20. package/esm/proxy/handler.js +417 -0
  21. package/esm/proxy/logger.d.ts +29 -0
  22. package/esm/proxy/logger.d.ts.map +1 -0
  23. package/esm/proxy/logger.js +258 -0
  24. package/esm/proxy/oauth-client.d.ts +15 -0
  25. package/esm/proxy/oauth-client.d.ts.map +1 -0
  26. package/esm/proxy/oauth-client.js +52 -0
  27. package/esm/proxy/token-manager.d.ts +59 -0
  28. package/esm/proxy/token-manager.d.ts.map +1 -0
  29. package/esm/proxy/token-manager.js +125 -0
  30. package/esm/proxy/tracing.d.ts +39 -0
  31. package/esm/proxy/tracing.d.ts.map +1 -0
  32. package/esm/proxy/tracing.js +194 -0
  33. package/esm/src/cache/backend.d.ts +2 -0
  34. package/esm/src/cache/backend.d.ts.map +1 -1
  35. package/esm/src/cache/backend.js +2 -0
  36. package/esm/src/cache/cache-key-builder.d.ts +0 -4
  37. package/esm/src/cache/cache-key-builder.d.ts.map +1 -1
  38. package/esm/src/cache/cache-key-builder.js +0 -6
  39. package/esm/src/cache/multi-tier.d.ts +0 -29
  40. package/esm/src/cache/multi-tier.d.ts.map +1 -1
  41. package/esm/src/cache/multi-tier.js +0 -26
  42. package/esm/src/cli/app/actions.d.ts +26 -0
  43. package/esm/src/cli/app/actions.d.ts.map +1 -0
  44. package/esm/src/cli/app/actions.js +152 -0
  45. package/esm/src/cli/app/components/inline-input.d.ts +35 -0
  46. package/esm/src/cli/app/components/inline-input.d.ts.map +1 -0
  47. package/esm/src/cli/app/components/inline-input.js +220 -0
  48. package/esm/src/cli/app/components/list-select.d.ts +69 -0
  49. package/esm/src/cli/app/components/list-select.d.ts.map +1 -0
  50. package/esm/src/cli/app/components/list-select.js +137 -0
  51. package/esm/src/cli/app/index.d.ts +45 -0
  52. package/esm/src/cli/app/index.d.ts.map +1 -0
  53. package/esm/src/cli/app/index.js +1252 -0
  54. package/esm/src/cli/app/state.d.ts +122 -0
  55. package/esm/src/cli/app/state.d.ts.map +1 -0
  56. package/esm/src/cli/app/state.js +232 -0
  57. package/esm/src/cli/app/views/dashboard.d.ts +19 -0
  58. package/esm/src/cli/app/views/dashboard.d.ts.map +1 -0
  59. package/esm/src/cli/app/views/dashboard.js +178 -0
  60. package/esm/src/cli/index/command-router.d.ts.map +1 -1
  61. package/esm/src/cli/index/command-router.js +9 -39
  62. package/esm/src/cli/index/start-handler.d.ts +3 -0
  63. package/esm/src/cli/index/start-handler.d.ts.map +1 -0
  64. package/esm/src/cli/index/start-handler.js +145 -0
  65. package/esm/src/cli/mcp/index.d.ts +11 -0
  66. package/esm/src/cli/mcp/index.d.ts.map +1 -0
  67. package/esm/src/cli/mcp/index.js +10 -0
  68. package/esm/src/middleware/builtin/security/redis-rate-limit.d.ts +2 -0
  69. package/esm/src/middleware/builtin/security/redis-rate-limit.d.ts.map +1 -1
  70. package/esm/src/middleware/builtin/security/redis-rate-limit.js +23 -9
  71. package/esm/src/modules/react-loader/ssr-module-loader/cache/redis.d.ts +10 -0
  72. package/esm/src/modules/react-loader/ssr-module-loader/cache/redis.d.ts.map +1 -1
  73. package/esm/src/modules/react-loader/ssr-module-loader/cache/redis.js +30 -42
  74. package/esm/src/modules/react-loader/ssr-module-loader/loader.d.ts.map +1 -1
  75. package/esm/src/modules/react-loader/ssr-module-loader/loader.js +34 -13
  76. package/esm/src/platform/adapters/fs/cache/file-cache.d.ts.map +1 -1
  77. package/esm/src/platform/adapters/fs/cache/file-cache.js +9 -3
  78. package/esm/src/server/context/cache-invalidation.d.ts.map +1 -1
  79. package/esm/src/server/context/cache-invalidation.js +4 -0
  80. package/esm/src/server/handlers/dev/dashboard/api.js +4 -0
  81. package/esm/src/server/handlers/dev/projects/ui-handler.d.ts.map +1 -1
  82. package/esm/src/server/handlers/dev/projects/ui-handler.js +6 -0
  83. package/esm/src/transforms/esm/http-cache.d.ts.map +1 -1
  84. package/esm/src/transforms/esm/http-cache.js +139 -64
  85. package/esm/src/utils/index.d.ts +1 -1
  86. package/esm/src/utils/index.d.ts.map +1 -1
  87. package/esm/src/utils/index.js +1 -1
  88. package/package.json +2 -1
  89. package/src/deno.js +1 -1
  90. package/src/proxy/cache/index.ts +93 -0
  91. package/src/proxy/cache/memory-cache.ts +120 -0
  92. package/src/proxy/cache/redis-cache.ts +203 -0
  93. package/src/proxy/cache/resilient-cache.ts +205 -0
  94. package/src/proxy/cache/types.ts +72 -0
  95. package/src/proxy/handler.ts +593 -0
  96. package/src/proxy/logger.ts +329 -0
  97. package/src/proxy/oauth-client.ts +91 -0
  98. package/src/proxy/token-manager.ts +174 -0
  99. package/src/proxy/tracing.ts +237 -0
  100. package/src/src/cache/backend.ts +3 -0
  101. package/src/src/cache/cache-key-builder.ts +0 -9
  102. package/src/src/cache/multi-tier.ts +0 -41
  103. package/src/src/cli/app/actions.ts +190 -0
  104. package/src/src/cli/app/components/inline-input.ts +255 -0
  105. package/src/src/cli/app/components/list-select.ts +215 -0
  106. package/src/src/cli/app/index.ts +1471 -0
  107. package/src/src/cli/app/state.ts +385 -0
  108. package/src/src/cli/app/views/dashboard.ts +212 -0
  109. package/src/src/cli/index/command-router.ts +9 -40
  110. package/src/src/cli/index/start-handler.ts +195 -0
  111. package/src/src/cli/mcp/index.ts +11 -0
  112. package/src/src/middleware/builtin/security/redis-rate-limit.ts +24 -11
  113. package/src/src/modules/react-loader/ssr-module-loader/cache/redis.ts +36 -50
  114. package/src/src/modules/react-loader/ssr-module-loader/loader.ts +38 -14
  115. package/src/src/platform/adapters/fs/cache/file-cache.ts +9 -3
  116. package/src/src/server/context/cache-invalidation.ts +4 -0
  117. package/src/src/server/handlers/dev/dashboard/api.ts +2 -0
  118. package/src/src/server/handlers/dev/projects/ui-handler.ts +6 -0
  119. package/src/src/transforms/esm/http-cache.ts +148 -73
  120. package/src/src/utils/index.ts +0 -1
@@ -0,0 +1,122 @@
1
+ import type { ListItem, ListSelectState } from "./components/list-select.js";
2
+ export type AppView = "dashboard" | "project-detail" | "new-project" | "templates" | "examples" | "auth" | "help";
3
+ export interface ProjectInfo {
4
+ slug: string;
5
+ path: string;
6
+ type: "local" | "example" | "template";
7
+ }
8
+ export interface ServerStatus {
9
+ running: boolean;
10
+ url: string;
11
+ port: number;
12
+ errors: number;
13
+ warnings: number;
14
+ }
15
+ export interface MCPStatus {
16
+ enabled: boolean;
17
+ transport: "stdio" | "http" | null;
18
+ connected: boolean;
19
+ clientName?: string;
20
+ httpPort?: number;
21
+ }
22
+ export interface RemoteState {
23
+ user: {
24
+ email: string;
25
+ name?: string;
26
+ } | null;
27
+ projects: Array<{
28
+ id: string;
29
+ name: string;
30
+ slug: string;
31
+ }>;
32
+ /** Currently focused index in remote projects list */
33
+ focusedIndex: number;
34
+ /** Scroll offset for remote projects list */
35
+ scrollOffset: number;
36
+ }
37
+ export interface InputState {
38
+ active: boolean;
39
+ prompt: string;
40
+ value: string;
41
+ cursorPos: number;
42
+ onSubmit: ((value: string) => void) | null;
43
+ onCancel: (() => void) | null;
44
+ }
45
+ export interface LogMeta {
46
+ method?: string;
47
+ path?: string;
48
+ status?: number;
49
+ durationMs?: number;
50
+ project?: string;
51
+ env?: string;
52
+ releaseId?: string;
53
+ }
54
+ export interface LogEntry {
55
+ time: Date;
56
+ level: "info" | "warn" | "error" | "debug";
57
+ message: string;
58
+ meta?: LogMeta;
59
+ }
60
+ export interface AppState {
61
+ view: AppView;
62
+ previousView: AppView | null;
63
+ server: ServerStatus;
64
+ mcp: MCPStatus;
65
+ remote: RemoteState;
66
+ projects: ListSelectState<ProjectInfo>;
67
+ examples: ListSelectState<ProjectInfo>;
68
+ templates: ListSelectState<ProjectInfo>;
69
+ activeList: "projects" | "examples" | "templates" | "remoteProjects";
70
+ selectedProject: ProjectInfo | null;
71
+ wizard: {
72
+ step: number;
73
+ startType: "scratch" | "template" | "example" | null;
74
+ selectedTemplate: string | null;
75
+ integrations: string[];
76
+ projectName: string;
77
+ };
78
+ input: InputState;
79
+ logs: LogEntry[];
80
+ maxLogs: number;
81
+ logsExpanded: boolean;
82
+ logScroll: number;
83
+ /** Auth provider selection index (0=Google, 1=GitHub, 2=Microsoft) */
84
+ authProviderIndex: number;
85
+ /** New project option index (0=template, 1=example, 2=scratch) */
86
+ newProjectIndex: number;
87
+ }
88
+ export declare function createInitialState(): AppState;
89
+ export type StateUpdater = (state: AppState) => AppState;
90
+ export declare function setProjects(projects: Array<{
91
+ slug: string;
92
+ path: string;
93
+ }>): StateUpdater;
94
+ export declare function setExamples(examples: Array<{
95
+ slug: string;
96
+ path: string;
97
+ description?: string;
98
+ }>): StateUpdater;
99
+ export declare function setTemplates(templates: Array<{
100
+ id: string;
101
+ name: string;
102
+ description: string;
103
+ }>): StateUpdater;
104
+ export declare function updateServer(update: Partial<ServerStatus>): StateUpdater;
105
+ export declare function updateMCP(update: Partial<MCPStatus>): StateUpdater;
106
+ export declare function updateRemote(update: Partial<RemoteState>): StateUpdater;
107
+ export declare function navigateTo(view: AppView): StateUpdater;
108
+ export declare function goBack(): StateUpdater;
109
+ export declare function setActiveList(list: "projects" | "examples" | "templates" | "remoteProjects"): StateUpdater;
110
+ export declare function updateActiveList(updater: (list: ListSelectState<ProjectInfo>) => ListSelectState<ProjectInfo>): StateUpdater;
111
+ export declare function selectProject(project: ProjectInfo | null): StateUpdater;
112
+ export declare function updateWizard(update: Partial<AppState["wizard"]>): StateUpdater;
113
+ export declare function resetWizard(): StateUpdater;
114
+ export declare function startInput(prompt: string, onSubmit: (value: string) => void, onCancel?: () => void, initialValue?: string): StateUpdater;
115
+ export declare function updateInputValue(value: string, cursorPos: number): StateUpdater;
116
+ export declare function endInput(): StateUpdater;
117
+ export declare function addLog(level: LogEntry["level"], message: string, meta?: LogMeta): StateUpdater;
118
+ export declare function clearLogs(): StateUpdater;
119
+ export declare function toggleLogsExpanded(): StateUpdater;
120
+ export declare function scrollLogs(direction: "up" | "down"): StateUpdater;
121
+ export declare function getActiveSelection(state: AppState): ListItem<ProjectInfo> | undefined;
122
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../src/src/cli/app/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,232 @@
1
+ import { createListState } from "./components/list-select.js";
2
+ import { getRuntimeEnv } from "../../config/runtime-env.js";
3
+ import { cwd } from "../../platform/compat/process.js";
4
+ export function createInitialState() {
5
+ return {
6
+ view: "dashboard",
7
+ previousView: null,
8
+ server: {
9
+ running: false,
10
+ url: "http://veryfront.me:8080",
11
+ port: 8080,
12
+ errors: 0,
13
+ warnings: 0,
14
+ },
15
+ mcp: {
16
+ enabled: false,
17
+ transport: null,
18
+ connected: false,
19
+ },
20
+ remote: {
21
+ user: null,
22
+ projects: [],
23
+ focusedIndex: 0,
24
+ scrollOffset: 0,
25
+ },
26
+ projects: createListState([]),
27
+ examples: createListState([]),
28
+ templates: createListState([]),
29
+ activeList: "projects",
30
+ selectedProject: null,
31
+ wizard: {
32
+ step: 0,
33
+ startType: null,
34
+ selectedTemplate: null,
35
+ integrations: [],
36
+ projectName: "",
37
+ },
38
+ input: {
39
+ active: false,
40
+ prompt: "",
41
+ value: "",
42
+ cursorPos: 0,
43
+ onSubmit: null,
44
+ onCancel: null,
45
+ },
46
+ logs: [],
47
+ maxLogs: 100,
48
+ logsExpanded: false,
49
+ logScroll: 0,
50
+ authProviderIndex: 0,
51
+ newProjectIndex: 0,
52
+ };
53
+ }
54
+ export function setProjects(projects) {
55
+ return (state) => ({
56
+ ...state,
57
+ projects: createListState(projects.map((p) => ({
58
+ id: p.slug,
59
+ label: p.slug,
60
+ meta: shortenPath(p.path),
61
+ data: { slug: p.slug, path: p.path, type: "local" },
62
+ }))),
63
+ });
64
+ }
65
+ export function setExamples(examples) {
66
+ return (state) => ({
67
+ ...state,
68
+ examples: createListState(examples.map((e) => ({
69
+ id: e.slug,
70
+ label: e.slug,
71
+ description: e.description,
72
+ data: { slug: e.slug, path: e.path, type: "example" },
73
+ }))),
74
+ });
75
+ }
76
+ export function setTemplates(templates) {
77
+ return (state) => ({
78
+ ...state,
79
+ templates: createListState(templates.map((t) => ({
80
+ id: t.id,
81
+ label: t.name,
82
+ description: t.description,
83
+ data: { slug: t.id, path: "", type: "template" },
84
+ }))),
85
+ });
86
+ }
87
+ export function updateServer(update) {
88
+ return (state) => ({ ...state, server: { ...state.server, ...update } });
89
+ }
90
+ export function updateMCP(update) {
91
+ return (state) => ({ ...state, mcp: { ...state.mcp, ...update } });
92
+ }
93
+ export function updateRemote(update) {
94
+ return (state) => ({ ...state, remote: { ...state.remote, ...update } });
95
+ }
96
+ export function navigateTo(view) {
97
+ return (state) => ({ ...state, view, previousView: state.view });
98
+ }
99
+ export function goBack() {
100
+ return (state) => ({
101
+ ...state,
102
+ view: state.previousView ?? "dashboard",
103
+ previousView: null,
104
+ });
105
+ }
106
+ export function setActiveList(list) {
107
+ return (state) => ({ ...state, activeList: list });
108
+ }
109
+ export function updateActiveList(updater) {
110
+ return (state) => {
111
+ const key = state.activeList;
112
+ // remoteProjects is not a ListSelectState, skip update
113
+ if (key === "remoteProjects")
114
+ return state;
115
+ return { ...state, [key]: updater(state[key]) };
116
+ };
117
+ }
118
+ export function selectProject(project) {
119
+ return (state) => {
120
+ if (!project)
121
+ return { ...state, selectedProject: null };
122
+ return {
123
+ ...state,
124
+ selectedProject: project,
125
+ view: "project-detail",
126
+ previousView: state.view,
127
+ };
128
+ };
129
+ }
130
+ export function updateWizard(update) {
131
+ return (state) => ({ ...state, wizard: { ...state.wizard, ...update } });
132
+ }
133
+ export function resetWizard() {
134
+ return (state) => ({
135
+ ...state,
136
+ wizard: {
137
+ step: 0,
138
+ startType: null,
139
+ selectedTemplate: null,
140
+ integrations: [],
141
+ projectName: "",
142
+ },
143
+ });
144
+ }
145
+ export function startInput(prompt, onSubmit, onCancel, initialValue) {
146
+ return (state) => ({
147
+ ...state,
148
+ input: {
149
+ active: true,
150
+ prompt,
151
+ value: initialValue ?? "",
152
+ cursorPos: initialValue?.length ?? 0,
153
+ onSubmit,
154
+ onCancel: onCancel ?? null,
155
+ },
156
+ });
157
+ }
158
+ export function updateInputValue(value, cursorPos) {
159
+ return (state) => ({
160
+ ...state,
161
+ input: { ...state.input, value, cursorPos },
162
+ });
163
+ }
164
+ export function endInput() {
165
+ return (state) => ({
166
+ ...state,
167
+ input: {
168
+ active: false,
169
+ prompt: "",
170
+ value: "",
171
+ cursorPos: 0,
172
+ onSubmit: null,
173
+ onCancel: null,
174
+ },
175
+ });
176
+ }
177
+ export function addLog(level, message, meta) {
178
+ return (state) => {
179
+ const logs = [...state.logs, { time: new Date(), level, message, meta }];
180
+ if (logs.length > state.maxLogs)
181
+ logs.shift();
182
+ return { ...state, logs };
183
+ };
184
+ }
185
+ export function clearLogs() {
186
+ return (state) => ({ ...state, logs: [], logScroll: 0 });
187
+ }
188
+ export function toggleLogsExpanded() {
189
+ return (state) => ({
190
+ ...state,
191
+ logsExpanded: !state.logsExpanded,
192
+ logScroll: 0,
193
+ });
194
+ }
195
+ export function scrollLogs(direction) {
196
+ return (state) => {
197
+ if (!state.logsExpanded)
198
+ return state;
199
+ const maxScroll = Math.max(0, state.logs.length - 5);
200
+ let newScroll = state.logScroll;
201
+ if (direction === "up") {
202
+ newScroll = Math.min(maxScroll, state.logScroll + 1);
203
+ }
204
+ else {
205
+ newScroll = Math.max(0, state.logScroll - 1);
206
+ }
207
+ return { ...state, logScroll: newScroll };
208
+ };
209
+ }
210
+ function shortenPath(path, env = getRuntimeEnv()) {
211
+ // Prefer relative path to cwd
212
+ const currentDir = cwd();
213
+ if (path.startsWith(currentDir + "/")) {
214
+ return "./" + path.slice(currentDir.length + 1);
215
+ }
216
+ if (path === currentDir) {
217
+ return "./";
218
+ }
219
+ // Fall back to ~ for home
220
+ const home = env.homeDir ?? "";
221
+ if (home && path.startsWith(home)) {
222
+ return `~${path.slice(home.length)}`;
223
+ }
224
+ return path;
225
+ }
226
+ export function getActiveSelection(state) {
227
+ // remoteProjects is not a ListSelectState
228
+ if (state.activeList === "remoteProjects")
229
+ return undefined;
230
+ const list = state[state.activeList];
231
+ return list.items[list.selectedIndex];
232
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Dashboard View
3
+ *
4
+ * Main view showing server status, projects, and quick actions.
5
+ */
6
+ import type { AppState } from "../state.js";
7
+ /**
8
+ * Render the dashboard view
9
+ */
10
+ export declare function renderDashboard(state: AppState): string;
11
+ /**
12
+ * Render a boxed dashboard (alternative style)
13
+ */
14
+ export declare function renderDashboardBoxed(state: AppState): string;
15
+ /**
16
+ * Render empty state when no projects found
17
+ */
18
+ export declare function renderEmptyState(): string;
19
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../../../../src/src/cli/app/views/dashboard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CA4EvD;AAsFD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAY5D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAazC"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Dashboard View
3
+ *
4
+ * Main view showing server status, projects, and quick actions.
5
+ */
6
+ import { box } from "../../ui/box.js";
7
+ import { brand, dim, error, muted, success } from "../../ui/colors.js";
8
+ import { getTerminalWidth } from "../../ui/layout.js";
9
+ import { getAgentFaceWithText } from "../../ui/dot-matrix.js";
10
+ import { renderList } from "../components/list-select.js";
11
+ /**
12
+ * Render the dashboard view
13
+ */
14
+ export function renderDashboard(state) {
15
+ const termWidth = Math.min(getTerminalWidth() - 4, 80);
16
+ const maxListWidth = termWidth - 4;
17
+ const lines = [];
18
+ lines.push(renderBanner(state), "");
19
+ const hasProjects = state.projects.items.length > 0;
20
+ const hasExamples = state.examples.items.length > 0;
21
+ const hasRemoteProjects = state.remote.user && state.remote.projects.length > 0;
22
+ if (hasProjects) {
23
+ const isActive = state.activeList === "projects";
24
+ lines.push(renderSection("Local Projects", state.projects.items.length, isActive));
25
+ lines.push(renderList(state.projects, {
26
+ maxWidth: maxListWidth,
27
+ visibleCount: 5,
28
+ showNumbers: true,
29
+ showSelection: isActive,
30
+ }), "");
31
+ }
32
+ // Remote projects (when logged in)
33
+ if (hasRemoteProjects) {
34
+ const isRemoteActive = state.activeList === "remoteProjects";
35
+ const visibleCount = 5;
36
+ const start = state.remote.scrollOffset;
37
+ const end = Math.min(start + visibleCount, state.remote.projects.length);
38
+ const visibleProjects = state.remote.projects.slice(start, end);
39
+ lines.push(renderSection("Remote Projects", state.remote.projects.length, isRemoteActive));
40
+ if (start > 0) {
41
+ lines.push(` ${dim("↑ more above")}`);
42
+ }
43
+ visibleProjects.forEach((p, i) => {
44
+ const actualIndex = start + i;
45
+ const isFocused = isRemoteActive && actualIndex === state.remote.focusedIndex;
46
+ const cursor = isFocused ? brand("›") : " ";
47
+ // Show number 1-9 or letter a-z for 10+
48
+ const displayNum = actualIndex + 1;
49
+ const shortcut = displayNum <= 9
50
+ ? String(displayNum)
51
+ : String.fromCharCode(96 + displayNum - 9); // 10='a', 11='b', etc.
52
+ const num = isFocused ? brand(`[${shortcut}]`) : dim(`[${shortcut}]`);
53
+ const label = isFocused ? p.slug : dim(p.slug);
54
+ lines.push(`${cursor} ${num} ${label}`);
55
+ });
56
+ if (end < state.remote.projects.length) {
57
+ lines.push(` ${dim("↓ more below")}`);
58
+ }
59
+ lines.push("");
60
+ }
61
+ if (hasExamples) {
62
+ const isActive = state.activeList === "examples";
63
+ lines.push(renderSection("Examples", state.examples.items.length, isActive));
64
+ lines.push(renderList(state.examples, {
65
+ maxWidth: maxListWidth,
66
+ visibleCount: 5,
67
+ showNumbers: true,
68
+ showSelection: isActive,
69
+ }), "");
70
+ }
71
+ lines.push(renderHelpBar(state));
72
+ return lines.join("\n");
73
+ }
74
+ /**
75
+ * Render the banner with agent face and server info
76
+ */
77
+ function renderBanner(state) {
78
+ const serverDot = state.server.running ? success("●") : error("●");
79
+ const mcpDot = state.mcp.enabled ? success("●") : dim("○");
80
+ const textLines = [];
81
+ textLines.push(`${serverDot} ${dim("Server running")}`);
82
+ textLines.push(` ${brand(state.server.url)}`);
83
+ if (state.mcp.enabled) {
84
+ textLines.push(`${mcpDot} ${dim("MCP")}`);
85
+ if (state.mcp.transport === "http") {
86
+ const port = state.mcp.httpPort ?? 9999;
87
+ textLines.push(` ${brand(`http://veryfront.me:${port}/mcp`)}`);
88
+ }
89
+ else {
90
+ textLines.push(` ${dim("stdio")}`);
91
+ }
92
+ }
93
+ const { errors, warnings } = state.server;
94
+ if (errors > 0 || warnings > 0) {
95
+ const parts = [];
96
+ if (errors > 0)
97
+ parts.push(error(`${errors} errors`));
98
+ if (warnings > 0)
99
+ parts.push(muted(`${warnings} warnings`));
100
+ textLines.push(parts.join(" "));
101
+ }
102
+ return getAgentFaceWithText(textLines, {
103
+ litColor: "\x1b[38;2;252;143;93m", // Veryfront brand orange
104
+ });
105
+ }
106
+ /**
107
+ * Render a section header
108
+ */
109
+ function renderSection(title, count, isActive = true) {
110
+ const indicator = isActive ? brand("›") : " ";
111
+ const titleText = isActive ? title : dim(title);
112
+ return ` ${indicator} ${titleText} ${dim(`(${count})`)}`;
113
+ }
114
+ /**
115
+ * Render the help bar at the bottom
116
+ */
117
+ function renderHelpBar(state) {
118
+ const parts = [];
119
+ const hasProjects = state.projects.items.length > 0;
120
+ const hasExamples = state.examples.items.length > 0;
121
+ const hasRemoteProjects = state.remote.user && state.remote.projects.length > 0;
122
+ // Count sections for tab switching
123
+ const sectionCount = [hasProjects, hasExamples, hasRemoteProjects].filter(Boolean).length;
124
+ if (sectionCount > 1) {
125
+ parts.push(dim("tab switch"));
126
+ }
127
+ parts.push(dim("↑↓ nav"));
128
+ if (hasProjects || hasExamples || hasRemoteProjects) {
129
+ parts.push(dim("o open"), dim("s studio"), dim("i ide"));
130
+ }
131
+ if (!state.remote.user) {
132
+ parts.push(dim("a login"));
133
+ }
134
+ else {
135
+ // Show context-aware actions based on active list
136
+ if (state.activeList === "projects") {
137
+ parts.push(dim("p pull"), dim("u push"));
138
+ }
139
+ else if (state.activeList === "remoteProjects") {
140
+ parts.push(dim("p pull"));
141
+ }
142
+ parts.push(dim("n new"), dim("x logout"));
143
+ }
144
+ parts.push(dim("? help"), dim("q quit"));
145
+ return ` ${parts.join(" ")}`;
146
+ }
147
+ /**
148
+ * Render a boxed dashboard (alternative style)
149
+ */
150
+ export function renderDashboardBoxed(state) {
151
+ const termWidth = Math.min(getTerminalWidth() - 4, 80);
152
+ const content = renderDashboard(state);
153
+ return box(content, {
154
+ style: "rounded",
155
+ title: "Veryfront",
156
+ titleColor: "\x1b[38;2;252;143;93m",
157
+ width: termWidth,
158
+ paddingX: 1,
159
+ paddingY: 0,
160
+ });
161
+ }
162
+ /**
163
+ * Render empty state when no projects found
164
+ */
165
+ export function renderEmptyState() {
166
+ return [
167
+ "",
168
+ ` ${dim("No projects found.")}`,
169
+ "",
170
+ ` ${dim("Get started:")}`,
171
+ ` ${brand("[n]")} Create a new project`,
172
+ ` ${brand("[t]")} Browse templates`,
173
+ "",
174
+ ` ${dim("Or run with a project directory:")}`,
175
+ ` ${muted("deno task start --project ./my-project")}`,
176
+ "",
177
+ ].join("\n");
178
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"command-router.d.ts","sourceRoot":"","sources":["../../../../src/src/cli/index/command-router.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAwCH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAsD7C;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAuZlE"}
1
+ {"version":3,"file":"command-router.d.ts","sourceRoot":"","sources":["../../../../src/src/cli/index/command-router.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAwCH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAsD7C;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAwXlE"}
@@ -22,7 +22,7 @@ import { mergeCommand, parseMergeArgs } from "../commands/merge.js";
22
22
  import { deployCommand, parseDeployArgs } from "../commands/deploy.js";
23
23
  import { parseUpArgs, upCommand } from "../commands/up.js";
24
24
  import { newCommand, parseNewArgs } from "../commands/new.js";
25
- import { promptProjectName, showMainMenu } from "../commands/main.js";
25
+ import { promptProjectName } from "../commands/main.js";
26
26
  import { issuesCommand } from "../commands/issues.js";
27
27
  import { login, logout, whoami } from "../auth/index.js";
28
28
  import { COMMANDS } from "../help/command-definitions.js";
@@ -32,7 +32,7 @@ import { handleBuildCommand } from "./build-handler.js";
32
32
  import { handleDevCommand } from "./dev-handler.js";
33
33
  import { handleGenerateCommand } from "./generate-handler.js";
34
34
  import { handleStudioCommand } from "./studio-handler.js";
35
- import { createMCPServer } from "../mcp/server.js";
35
+ import { handleStartCommand } from "./start-handler.js";
36
36
  /**
37
37
  * Handle validation errors using central COMMANDS registry for usage
38
38
  */
@@ -371,11 +371,10 @@ export async function routeCommand(args) {
371
371
  break;
372
372
  }
373
373
  case "mcp": {
374
- const server = await createMCPServer({ stdio: true });
375
- await new Promise(() => {
376
- /* never resolve - stdio loop runs until stdin closes */
377
- });
378
- await server.stop();
374
+ const { createMCPServer } = await import("../mcp/server.js");
375
+ const mcpServer = await createMCPServer({ stdio: true });
376
+ await new Promise(() => { });
377
+ await mcpServer.stop();
379
378
  break;
380
379
  }
381
380
  case "issues":
@@ -385,39 +384,10 @@ export async function routeCommand(args) {
385
384
  showHelp();
386
385
  exitProcess(0);
387
386
  return;
388
- case undefined: {
389
- const action = await showMainMenu();
390
- switch (action) {
391
- case "new": {
392
- const name = await promptProjectName();
393
- if (name) {
394
- await newCommand(name, {});
395
- }
396
- break;
397
- }
398
- case "dev":
399
- await handleDevCommand(args);
400
- break;
401
- case "deploy": {
402
- const result = parseDeployArgs(args);
403
- if (result.success) {
404
- await deployCommand(result.data);
405
- }
406
- break;
407
- }
408
- case "login":
409
- await login();
410
- break;
411
- case "help":
412
- showHelp();
413
- break;
414
- case "exit":
415
- case null:
416
- exitProcess(0);
417
- break;
418
- }
387
+ case undefined:
388
+ // Default: run full TUI dashboard (like `deno task start`)
389
+ await handleStartCommand(args);
419
390
  break;
420
- }
421
391
  default:
422
392
  cliLogger.error(`Unknown command: ${command}\n`);
423
393
  showHelp();
@@ -0,0 +1,3 @@
1
+ import type { ParsedArgs } from "./types.js";
2
+ export declare function handleStartCommand(args: ParsedArgs): Promise<void>;
3
+ //# sourceMappingURL=start-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/cli/index/start-handler.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAkH7C,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAkExE"}