idcmd 0.0.11 → 0.0.12

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.
@@ -1,223 +0,0 @@
1
- interface CommandResult {
2
- code: number;
3
- stderr: string;
4
- stdout: string;
5
- }
6
-
7
- const BASE_URL = process.env.IDCMD_SMOKE_BASE_URL ?? "http://127.0.0.1:4000";
8
- const CURL_MAX_TIME_SECONDS = "5";
9
- const READY_TIMEOUT_MS = 60_000;
10
- const READY_INTERVAL_MS = 500;
11
- const SHUTDOWN_TIMEOUT_MS = 5000;
12
-
13
- const delay = (ms: number): Promise<void> => Bun.sleep(ms);
14
-
15
- const runCommand = async (command: string[]): Promise<CommandResult> => {
16
- const proc = Bun.spawn(command, {
17
- cwd: process.cwd(),
18
- stderr: "pipe",
19
- stdout: "pipe",
20
- });
21
- const [stdout, stderr, code] = await Promise.all([
22
- new Response(proc.stdout).text(),
23
- new Response(proc.stderr).text(),
24
- proc.exited,
25
- ]);
26
- return { code, stderr, stdout };
27
- };
28
-
29
- const runCurl = (path: string): Promise<CommandResult> =>
30
- runCommand([
31
- "curl",
32
- "-fsS",
33
- "--max-time",
34
- CURL_MAX_TIME_SECONDS,
35
- `${BASE_URL}${path}`,
36
- ]);
37
-
38
- const assertCommandOk = (label: string, result: CommandResult): void => {
39
- if (result.code === 0) {
40
- return;
41
- }
42
- throw new Error(
43
- [
44
- `${label} failed with exit code ${String(result.code)}.`,
45
- "stdout:",
46
- result.stdout.trim() || "(empty)",
47
- "stderr:",
48
- result.stderr.trim() || "(empty)",
49
- ].join("\n")
50
- );
51
- };
52
-
53
- const expectIncludes = (args: {
54
- haystack: string;
55
- label: string;
56
- needle: string;
57
- }): void => {
58
- if (args.haystack.includes(args.needle)) {
59
- return;
60
- }
61
- throw new Error(`Expected ${args.label} to include ${args.needle}.`);
62
- };
63
-
64
- const waitForReady = async (): Promise<void> => {
65
- const startedAt = Date.now();
66
- let lastFailure = "(no attempts yet)";
67
-
68
- while (Date.now() - startedAt < READY_TIMEOUT_MS) {
69
- const ready = await runCurl("/");
70
- if (ready.code === 0) {
71
- return;
72
- }
73
- lastFailure = ready.stderr.trim() || ready.stdout.trim() || "curl failed";
74
- await delay(READY_INTERVAL_MS);
75
- }
76
-
77
- throw new Error(
78
- `dev server did not become ready within ${String(
79
- READY_TIMEOUT_MS
80
- )}ms. Last curl failure: ${lastFailure}`
81
- );
82
- };
83
-
84
- const shutdownDev = async (
85
- proc: ReturnType<typeof Bun.spawn>
86
- ): Promise<void> => {
87
- try {
88
- proc.kill("SIGTERM");
89
- } catch {
90
- return;
91
- }
92
-
93
- const didExit = await Promise.race([
94
- proc.exited.then(() => true),
95
- delay(SHUTDOWN_TIMEOUT_MS).then(() => false),
96
- ]);
97
- if (!didExit) {
98
- try {
99
- proc.kill("SIGKILL");
100
- } catch {
101
- // ignore
102
- }
103
- await proc.exited;
104
- }
105
- };
106
-
107
- const assertHomeResponse = async (): Promise<void> => {
108
- const home = await runCurl("/");
109
- assertCommandOk("curl /", home);
110
- expectIncludes({ haystack: home.stdout, label: "/", needle: "<html" });
111
- };
112
-
113
- const assertAboutResponse = async (): Promise<void> => {
114
- const about = await runCurl("/about/");
115
- assertCommandOk("curl /about/", about);
116
- if (!about.stdout.includes("# About") && !about.stdout.includes(">About<")) {
117
- throw new Error("Expected /about/ response to include About heading.");
118
- }
119
- };
120
-
121
- const assertLlmsResponse = async (): Promise<void> => {
122
- const llms = await runCurl("/llms.txt");
123
- assertCommandOk("curl /llms.txt", llms);
124
- if (llms.stdout.trim().length === 0 || !llms.stdout.includes("about.md")) {
125
- throw new Error("Expected /llms.txt to be non-empty and include about.md.");
126
- }
127
- };
128
-
129
- const assertApiResponse = async (): Promise<void> => {
130
- const api = await runCurl("/api/hello");
131
- assertCommandOk("curl /api/hello", api);
132
- const payload = JSON.parse(api.stdout) as { message?: string; ok?: boolean };
133
- if (payload.ok !== true || payload.message !== "Hello from idcmd route!") {
134
- throw new Error("Expected /api/hello payload to match template route.");
135
- }
136
- };
137
-
138
- const runSmokeChecks = async (): Promise<void> => {
139
- await assertHomeResponse();
140
- await assertAboutResponse();
141
- await assertLlmsResponse();
142
- await assertApiResponse();
143
- };
144
-
145
- const runProjectCheck = async (): Promise<void> => {
146
- const check = await runCommand([process.execPath, "run", "check"]);
147
- assertCommandOk("bun run check", check);
148
- };
149
-
150
- const startDev = (): {
151
- devProc: ReturnType<typeof Bun.spawn>;
152
- devStderr: Promise<string>;
153
- devStdout: Promise<string>;
154
- } => {
155
- const devProc = Bun.spawn([process.execPath, "run", "dev"], {
156
- cwd: process.cwd(),
157
- stderr: "pipe",
158
- stdout: "pipe",
159
- });
160
- return {
161
- devProc,
162
- devStderr: new Response(devProc.stderr).text(),
163
- devStdout: new Response(devProc.stdout).text(),
164
- };
165
- };
166
-
167
- const logDevFailure = async (args: {
168
- error: unknown;
169
- stderr: Promise<string>;
170
- stdout: Promise<string>;
171
- }): Promise<void> => {
172
- const [stdout, stderr] = await Promise.all([args.stdout, args.stderr]);
173
- const message =
174
- args.error instanceof Error ? args.error.message : String(args.error);
175
- console.error(message);
176
- console.error("dev stdout:");
177
- console.error(stdout.trim() || "(empty)");
178
- console.error("dev stderr:");
179
- console.error(stderr.trim() || "(empty)");
180
- };
181
-
182
- const toErrorMessage = (error: unknown): string => {
183
- if (error instanceof Error) {
184
- return error.message;
185
- }
186
- return String(error);
187
- };
188
-
189
- const runDevSmokeFlow = async (): Promise<number> => {
190
- const { devProc, devStderr, devStdout } = startDev();
191
-
192
- try {
193
- await waitForReady();
194
- await runSmokeChecks();
195
- } catch (error) {
196
- await logDevFailure({ error, stderr: devStderr, stdout: devStdout });
197
- return 1;
198
- } finally {
199
- await shutdownDev(devProc);
200
- }
201
- return 0;
202
- };
203
-
204
- const runPostDevCheck = async (): Promise<number> => {
205
- try {
206
- await runProjectCheck();
207
- return 0;
208
- } catch (error) {
209
- console.error(toErrorMessage(error));
210
- return 1;
211
- }
212
- };
213
-
214
- const main = async (): Promise<number> => {
215
- const smokeCode = await runDevSmokeFlow();
216
- if (smokeCode !== 0) {
217
- return smokeCode;
218
- }
219
- return runPostDevCheck();
220
- };
221
-
222
- const code = await main();
223
- process.exit(code);