Skip to content

Commit 89b4859

Browse files
committed
separate devserver things into devlib
1 parent dbafd1e commit 89b4859

File tree

2 files changed

+148
-132
lines changed

2 files changed

+148
-132
lines changed

devserver.ts

Lines changed: 9 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import { createServer } from "vite";
2-
import Chafa from "chafa-wasm";
3-
import { promisify } from "node:util";
42
import fs from "node:fs/promises";
53
import { stdout } from "node:process";
64
import chalk from "chalk";
75
import { execSync } from "node:child_process";
86
import http from "node:http";
97
import path from "node:path";
108
import { createReadStream } from "node:fs";
11-
import rspack from "@rspack/core";
129
import rspackConfig from "./rspack.config.ts";
1310
import { server as wisp } from "@mercuryworkshop/wisp-js/server";
14-
15-
const chafa = await Chafa();
16-
const imageToAnsi = promisify(chafa.imageToAnsi);
11+
import {
12+
black,
13+
logSuccess,
14+
printBanner,
15+
resetSuccessLog,
16+
runRspack,
17+
} from "./packages/scramjet/devlib.ts";
1718

1819
const image = await fs.readFile(
1920
"./packages/scramjet/assets/scramjet-mini-noalpha.png"
@@ -63,44 +64,6 @@ const server = await createServer({
6364

6465
await server.listen();
6566

66-
const imageWidth = 10;
67-
const totalWidth = 60;
68-
const { ansi: rawAnsi } = await imageToAnsi(image.buffer, {
69-
format: chafa.ChafaPixelMode.CHAFA_PIXEL_MODE_SYMBOLS.value,
70-
width: imageWidth,
71-
fontRatio: 0.5,
72-
colors: chafa.ChafaCanvasMode.CHAFA_CANVAS_MODE_TRUECOLOR.value,
73-
colorExtractor: chafa.ChafaColorExtractor.CHAFA_COLOR_EXTRACTOR_AVERAGE.value,
74-
colorSpace: chafa.ChafaColorSpace.CHAFA_COLOR_SPACE_RGB.value,
75-
symbols: "block+border+space-wide-inverted",
76-
fill: "full",
77-
fg: 0xffffff,
78-
bg: 0x000001,
79-
fgOnly: false,
80-
dither: chafa.ChafaDitherMode.CHAFA_DITHER_MODE_NONE.value,
81-
ditherGrainWidth: 4,
82-
ditherGrainHeight: 4,
83-
ditherIntensity: 1.0,
84-
preprocess: true,
85-
threshold: 0.5,
86-
optimize: 5,
87-
work: 5,
88-
});
89-
90-
function stripAnsi(s: string) {
91-
return s.replace(/\x1b\[[0-9;]*m/g, "");
92-
}
93-
94-
const ansiLines = rawAnsi.split(/\r?\n/).filter((l) => l.length > 0);
95-
const contentWidth = ansiLines.reduce((max, line) => {
96-
const w = stripAnsi(line).length;
97-
return w > max ? w : max;
98-
}, 0);
99-
100-
function black() {
101-
return chalk.bgHex("000001");
102-
}
103-
10467
const accent = (text: string) => chalk.hex("#f1855bff").bold(text);
10568
const highlight = (text: string) => chalk.hex("#fdd76cff").bold(text);
10669
const urlColor = (text: string) => chalk.hex("#64DFDF").underline(text);
@@ -127,70 +90,7 @@ const lines = [
12790
black()(chalk.dim(`[${branch}] ${commit} scramjet/${version}`)),
12891
];
12992

130-
const PAD_LEFT = 2;
131-
const PAD_TOP = 1;
132-
const PAD_BOTTOM = 1;
133-
134-
function blackSpaces(count: number) {
135-
count = Math.abs(count);
136-
return black()(" ".repeat(count));
137-
}
138-
139-
let out = "";
140-
out += (blackSpaces(totalWidth) + "\n").repeat(PAD_TOP);
141-
142-
for (let i = 0; i < ansiLines.length; i++) {
143-
out += blackSpaces(PAD_LEFT);
144-
145-
const line = ansiLines[i];
146-
const text = lines[i];
147-
const strippedLen = stripAnsi(line).length;
148-
const extraSpaces = contentWidth - strippedLen;
149-
150-
if (text) {
151-
const textpad = 2;
152-
out +=
153-
line +
154-
blackSpaces(textpad) +
155-
text +
156-
blackSpaces(
157-
extraSpaces +
158-
totalWidth -
159-
contentWidth -
160-
PAD_LEFT -
161-
textpad -
162-
stripAnsi(text).length
163-
);
164-
} else {
165-
out +=
166-
line + blackSpaces(extraSpaces + totalWidth - contentWidth - PAD_LEFT);
167-
}
168-
out += "\n";
169-
}
170-
out += (blackSpaces(totalWidth) + "\n").repeat(PAD_BOTTOM);
171-
172-
stdout.write("\x1b[2J\x1b[H");
173-
stdout.write(out);
174-
175-
let successCount = 0;
176-
let lastSuccessCollapsed = false;
177-
178-
function resetSuccessLog() {
179-
successCount = 0;
180-
lastSuccessCollapsed = false;
181-
}
182-
183-
function logSuccess() {
184-
successCount += 1;
185-
const suffix = successCount > 1 ? chalk.dim(` (x${successCount})`) : "";
186-
if (lastSuccessCollapsed && stdout.isTTY) {
187-
stdout.moveCursor(0, -1);
188-
stdout.clearLine(0);
189-
stdout.cursorTo(0);
190-
}
191-
stdout.write(`${chalk.green("Compiled successfully.")}${suffix}\n`);
192-
lastSuccessCollapsed = true;
193-
}
93+
printBanner(image, lines);
19494

19595
const MIME_TYPES: Record<string, string> = {
19696
".html": "text/html; charset=utf-8",
@@ -302,27 +202,4 @@ staticServer.listen(Number(ISOLATION_PORT), () => {
302202
resetSuccessLog();
303203
});
304204

305-
const compiler = rspack(rspackConfig);
306-
compiler.watch({}, (err, stats) => {
307-
if (err) {
308-
resetSuccessLog();
309-
stdout.write(chalk.red("Build failed:\n"));
310-
stdout.write(err.message + "\n");
311-
return;
312-
}
313-
if (!stats) return;
314-
315-
const statList = Array.isArray((stats as any).stats)
316-
? (stats as any).stats
317-
: [stats];
318-
319-
for (const stat of statList) {
320-
const text = stat.toString({ colors: false, modules: false });
321-
if (text.includes("compiled successfully")) {
322-
logSuccess();
323-
} else {
324-
resetSuccessLog();
325-
console.log(text);
326-
}
327-
}
328-
});
205+
runRspack(rspackConfig);

packages/scramjet/devlib.ts

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import chalk from "chalk";
2+
import Chafa from "chafa-wasm";
3+
import { promisify } from "node:util";
4+
const chafa = await Chafa();
5+
const imageToAnsi = promisify(chafa.imageToAnsi);
6+
import { stdout } from "node:process";
7+
import rspack from "@rspack/core";
8+
9+
export function black() {
10+
return chalk.bgHex("000001");
11+
}
12+
export async function printBanner(image: Buffer, lines: string[]) {
13+
const imageWidth = 10;
14+
const totalWidth = 60;
15+
const { ansi: rawAnsi } = await imageToAnsi(image.buffer, {
16+
format: chafa.ChafaPixelMode.CHAFA_PIXEL_MODE_SYMBOLS.value,
17+
width: imageWidth,
18+
fontRatio: 0.5,
19+
colors: chafa.ChafaCanvasMode.CHAFA_CANVAS_MODE_TRUECOLOR.value,
20+
colorExtractor:
21+
chafa.ChafaColorExtractor.CHAFA_COLOR_EXTRACTOR_AVERAGE.value,
22+
colorSpace: chafa.ChafaColorSpace.CHAFA_COLOR_SPACE_RGB.value,
23+
symbols: "block+border+space-wide-inverted",
24+
fill: "full",
25+
fg: 0xffffff,
26+
bg: 0x000001,
27+
fgOnly: false,
28+
dither: chafa.ChafaDitherMode.CHAFA_DITHER_MODE_NONE.value,
29+
ditherGrainWidth: 4,
30+
ditherGrainHeight: 4,
31+
ditherIntensity: 1.0,
32+
preprocess: true,
33+
threshold: 0.5,
34+
optimize: 5,
35+
work: 5,
36+
});
37+
38+
function stripAnsi(s: string) {
39+
return s.replace(/\x1b\[[0-9;]*m/g, "");
40+
}
41+
42+
const ansiLines = rawAnsi.split(/\r?\n/).filter((l) => l.length > 0);
43+
const contentWidth = ansiLines.reduce((max, line) => {
44+
const w = stripAnsi(line).length;
45+
return w > max ? w : max;
46+
}, 0);
47+
48+
const PAD_LEFT = 2;
49+
const PAD_TOP = 1;
50+
const PAD_BOTTOM = 1;
51+
52+
function blackSpaces(count: number) {
53+
count = Math.abs(count);
54+
return black()(" ".repeat(count));
55+
}
56+
57+
let out = "";
58+
out += (blackSpaces(totalWidth) + "\n").repeat(PAD_TOP);
59+
60+
for (let i = 0; i < ansiLines.length; i++) {
61+
out += blackSpaces(PAD_LEFT);
62+
63+
const line = ansiLines[i];
64+
const text = lines[i];
65+
const strippedLen = stripAnsi(line).length;
66+
const extraSpaces = contentWidth - strippedLen;
67+
68+
if (text) {
69+
const textpad = 2;
70+
out +=
71+
line +
72+
blackSpaces(textpad) +
73+
text +
74+
blackSpaces(
75+
extraSpaces +
76+
totalWidth -
77+
contentWidth -
78+
PAD_LEFT -
79+
textpad -
80+
stripAnsi(text).length
81+
);
82+
} else {
83+
out +=
84+
line + blackSpaces(extraSpaces + totalWidth - contentWidth - PAD_LEFT);
85+
}
86+
out += "\n";
87+
}
88+
out += (blackSpaces(totalWidth) + "\n").repeat(PAD_BOTTOM);
89+
90+
stdout.write("\x1b[2J\x1b[H");
91+
stdout.write(out);
92+
}
93+
94+
let successCount = 0;
95+
let lastSuccessCollapsed = false;
96+
97+
export function resetSuccessLog() {
98+
successCount = 0;
99+
lastSuccessCollapsed = false;
100+
}
101+
102+
export function logSuccess() {
103+
successCount += 1;
104+
const suffix = successCount > 1 ? chalk.dim(` (x${successCount})`) : "";
105+
if (lastSuccessCollapsed && stdout.isTTY) {
106+
stdout.moveCursor(0, -1);
107+
stdout.clearLine(0);
108+
stdout.cursorTo(0);
109+
}
110+
stdout.write(`${chalk.green("Compiled successfully.")}${suffix}\n`);
111+
lastSuccessCollapsed = true;
112+
}
113+
114+
export function runRspack(rspackConfig: any) {
115+
const compiler = rspack(rspackConfig);
116+
compiler.watch({}, (err, stats) => {
117+
if (err) {
118+
resetSuccessLog();
119+
stdout.write(chalk.red("Build failed:\n"));
120+
stdout.write(err.message + "\n");
121+
return;
122+
}
123+
if (!stats) return;
124+
125+
const statList = Array.isArray((stats as any).stats)
126+
? (stats as any).stats
127+
: [stats];
128+
129+
for (const stat of statList) {
130+
const text = stat.toString({ colors: false, modules: false });
131+
if (text.includes("compiled successfully")) {
132+
logSuccess();
133+
} else {
134+
resetSuccessLog();
135+
console.log(text);
136+
}
137+
}
138+
});
139+
}

0 commit comments

Comments
 (0)