everything-dev 0.3.1 → 0.3.3
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/package.json +1 -1
- package/src/components/dev-view.tsx +254 -243
- package/src/components/streaming-view.ts +128 -97
- package/src/lib/process.ts +1 -0
- package/src/lib/session-recorder/server.ts +225 -224
- package/src/plugin.ts +114 -107
|
@@ -6,115 +6,146 @@ import type { ProcessState, ProcessStatus } from "./dev-view";
|
|
|
6
6
|
const orange = chalk.hex("#ffaa00");
|
|
7
7
|
|
|
8
8
|
export interface StreamingViewHandle {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
updateProcess: (
|
|
10
|
+
name: string,
|
|
11
|
+
status: ProcessStatus,
|
|
12
|
+
message?: string,
|
|
13
|
+
) => void;
|
|
14
|
+
addLog: (source: string, line: string, isError?: boolean) => void;
|
|
15
|
+
unmount: () => Promise<void> | void;
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
const getTimestamp = (): string => {
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
const now = new Date();
|
|
20
|
+
return `${now.getHours().toString().padStart(2, "0")}:${now.getMinutes().toString().padStart(2, "0")}:${now.getSeconds().toString().padStart(2, "0")}`;
|
|
17
21
|
};
|
|
18
22
|
|
|
19
23
|
const write = (text: string) => process.stdout.write(text + "\n");
|
|
20
24
|
|
|
21
|
-
const getServiceColor = (name: string): (s: string) => string => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
const getServiceColor = (name: string): ((s: string) => string) => {
|
|
26
|
+
if (name === "host") return colors.cyan;
|
|
27
|
+
if (name === "ui" || name === "ui-ssr") return colors.magenta;
|
|
28
|
+
if (name === "api") return colors.blue;
|
|
29
|
+
return colors.white;
|
|
26
30
|
};
|
|
27
31
|
|
|
28
32
|
const getStatusIcon = (status: ProcessStatus): string => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
switch (status) {
|
|
34
|
+
case "pending":
|
|
35
|
+
return icons.pending;
|
|
36
|
+
case "starting":
|
|
37
|
+
return icons.scan;
|
|
38
|
+
case "ready":
|
|
39
|
+
return icons.ok;
|
|
40
|
+
case "error":
|
|
41
|
+
return icons.err;
|
|
42
|
+
}
|
|
35
43
|
};
|
|
36
44
|
|
|
37
45
|
export function renderStreamingView(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
initialProcesses: ProcessState[],
|
|
47
|
+
description: string,
|
|
48
|
+
env: Record<string, string>,
|
|
49
|
+
onExit?: () => Promise<void> | void,
|
|
50
|
+
_onExportLogs?: () => Promise<void> | void,
|
|
43
51
|
): StreamingViewHandle {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
52
|
+
const processes = new Map<string, ProcessState>();
|
|
53
|
+
for (const p of initialProcesses) {
|
|
54
|
+
processes.set(p.name, { ...p });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let allReadyPrinted = false;
|
|
58
|
+
const hostProcess = initialProcesses.find((p) => p.name === "host");
|
|
59
|
+
const hostPort = hostProcess?.port || 3000;
|
|
60
|
+
const proxyTarget = env.API_PROXY;
|
|
61
|
+
|
|
62
|
+
console.log();
|
|
63
|
+
console.log(colors.cyan(`${"─".repeat(52)}`));
|
|
64
|
+
console.log(` ${icons.run} ${colors.cyan(description.toUpperCase())}`);
|
|
65
|
+
console.log(colors.cyan(`${"─".repeat(52)}`));
|
|
66
|
+
console.log();
|
|
67
|
+
|
|
68
|
+
if (proxyTarget) {
|
|
69
|
+
console.log(orange(` ${icons.arrow} API PROXY → ${proxyTarget}`));
|
|
70
|
+
console.log();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
for (const proc of initialProcesses) {
|
|
74
|
+
const color = getServiceColor(proc.name);
|
|
75
|
+
const sourceLabel = proc.source ? ` (${proc.source})` : "";
|
|
76
|
+
console.log(
|
|
77
|
+
`${colors.dim(`[${getTimestamp()}]`)} ${color(`[${proc.name.toUpperCase()}]`)} ${icons.pending} waiting${sourceLabel}`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const checkAllReady = () => {
|
|
82
|
+
if (allReadyPrinted) return;
|
|
83
|
+
|
|
84
|
+
const allReady = Array.from(processes.values()).every(
|
|
85
|
+
(p) => p.status === "ready",
|
|
86
|
+
);
|
|
87
|
+
if (allReady) {
|
|
88
|
+
allReadyPrinted = true;
|
|
89
|
+
console.log();
|
|
90
|
+
console.log(colors.dim(`${"─".repeat(52)}`));
|
|
91
|
+
console.log(
|
|
92
|
+
colors.green(`${icons.ok} All ${processes.size} services ready`),
|
|
93
|
+
);
|
|
94
|
+
console.log(colors.green(`${icons.arrow} http://localhost:${hostPort}`));
|
|
95
|
+
console.log(colors.dim(`${"─".repeat(52)}`));
|
|
96
|
+
console.log();
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const updateProcess = (
|
|
101
|
+
name: string,
|
|
102
|
+
status: ProcessStatus,
|
|
103
|
+
message?: string,
|
|
104
|
+
) => {
|
|
105
|
+
const proc = processes.get(name);
|
|
106
|
+
if (!proc) return;
|
|
107
|
+
|
|
108
|
+
proc.status = status;
|
|
109
|
+
if (message) proc.message = message;
|
|
110
|
+
|
|
111
|
+
const color = getServiceColor(name);
|
|
112
|
+
const icon = getStatusIcon(status);
|
|
113
|
+
const statusText =
|
|
114
|
+
status === "ready"
|
|
115
|
+
? "ready"
|
|
116
|
+
: status === "starting"
|
|
117
|
+
? "starting"
|
|
118
|
+
: status === "error"
|
|
119
|
+
? "failed"
|
|
120
|
+
: "waiting";
|
|
121
|
+
const portStr = proc.port > 0 && status === "ready" ? ` :${proc.port}` : "";
|
|
122
|
+
|
|
123
|
+
write(
|
|
124
|
+
`${colors.dim(`[${getTimestamp()}]`)} ${color(`[${name.toUpperCase()}]`)} ${status === "ready" ? colors.green(icon) : status === "error" ? colors.error(icon) : icon} ${statusText}${portStr}`,
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
checkAllReady();
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const addLog = (source: string, line: string, isError = false) => {
|
|
131
|
+
const color = getServiceColor(source);
|
|
132
|
+
const logColor = isError ? colors.error : colors.dim;
|
|
133
|
+
write(
|
|
134
|
+
`${colors.dim(`[${getTimestamp()}]`)} ${color(`[${source.toUpperCase()}]`)} ${colors.dim("│")} ${logColor(linkify(line))}`,
|
|
135
|
+
);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const unmount = () => {
|
|
139
|
+
return onExit?.();
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
process.on("SIGINT", () => {
|
|
143
|
+
console.log();
|
|
144
|
+
console.log(colors.dim(`[${getTimestamp()}] Shutting down...`));
|
|
145
|
+
Promise.resolve(unmount()).then(() => {
|
|
146
|
+
process.exit(0);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
return { updateProcess, addLog, unmount };
|
|
120
151
|
}
|