bun-dev-server 0.5.0 → 0.7.0
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/dist/bunServeConfig.d.ts +4 -2
- package/dist/index.js +89 -70
- package/package.json +3 -3
package/dist/bunServeConfig.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type BuildConfig, type TLSOptions } from "bun";
|
|
2
|
-
export interface BunDevServerConfig extends Partial<
|
|
2
|
+
export interface BunDevServerConfig extends Partial<BunServeConfig> {
|
|
3
3
|
port: number;
|
|
4
4
|
buildConfig: BuildConfig;
|
|
5
5
|
watchDir: string;
|
|
@@ -14,6 +14,7 @@ export interface BunDevServerConfig extends Partial<BunDevServerSocketConfig> {
|
|
|
14
14
|
manifestName?: string;
|
|
15
15
|
manifestWithHash?: boolean;
|
|
16
16
|
hotReload?: "plugin" | "footer";
|
|
17
|
+
logRequests?: boolean;
|
|
17
18
|
reloadOnChange?: boolean;
|
|
18
19
|
/**
|
|
19
20
|
* The path to the directory to serve files from.
|
|
@@ -25,8 +26,9 @@ export interface BunDevServerConfig extends Partial<BunDevServerSocketConfig> {
|
|
|
25
26
|
serveOutputEjs?: string;
|
|
26
27
|
serveOutputHtml?: string;
|
|
27
28
|
}
|
|
28
|
-
export interface
|
|
29
|
+
export interface BunServeConfig {
|
|
29
30
|
port: number;
|
|
30
31
|
tls?: TLSOptions;
|
|
31
32
|
websocketPath?: string;
|
|
33
|
+
static?: Record<`/${string}`, Response>;
|
|
32
34
|
}
|
package/dist/index.js
CHANGED
|
@@ -966,7 +966,7 @@ var indexHTMLTemplate_default = `<!DOCTYPE html>\r
|
|
|
966
966
|
`;
|
|
967
967
|
|
|
968
968
|
// src/server.ts
|
|
969
|
-
import { watch, readdir,
|
|
969
|
+
import { watch, readdir, access, readFile as readFile2, constants } from "fs/promises";
|
|
970
970
|
|
|
971
971
|
// src/bunClientHmr.ts
|
|
972
972
|
function hotReload() {
|
|
@@ -1187,82 +1187,27 @@ async function startBunDevServer(serverConfig) {
|
|
|
1187
1187
|
port: finalConfig.port,
|
|
1188
1188
|
development: true,
|
|
1189
1189
|
tls: finalConfig.tls,
|
|
1190
|
+
static: {
|
|
1191
|
+
"/favicon.ico": withCORSHeaders(new Response("", { status: 404 })),
|
|
1192
|
+
...finalConfig.static
|
|
1193
|
+
},
|
|
1190
1194
|
async fetch(req, server) {
|
|
1191
1195
|
if (req.method === "OPTIONS") {
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
return response;
|
|
1195
|
-
}
|
|
1196
|
-
if (req.url.toLowerCase().endsWith("/favicon.ico")) {
|
|
1197
|
-
const response = new Response("", { status: 404 });
|
|
1198
|
-
augumentHeaders(req, response);
|
|
1199
|
-
return response;
|
|
1196
|
+
finalConfig.logRequests && console.log(`${200} ${req.url} OPTIONS`);
|
|
1197
|
+
return withCORSHeaders(new Response("", { status: 200 }), req);
|
|
1200
1198
|
}
|
|
1201
1199
|
if (req.url.toLowerCase().endsWith(finalConfig.websocketPath)) {
|
|
1200
|
+
finalConfig.logRequests && console.log(`${req.url} Socket Upgrade`);
|
|
1202
1201
|
if (server.upgrade(req)) {
|
|
1203
1202
|
return;
|
|
1204
1203
|
}
|
|
1205
1204
|
}
|
|
1206
1205
|
const url = new URL(req.url);
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
if (objThere) {
|
|
1211
|
-
try {
|
|
1212
|
-
await readFile2(destinationPath + requestPath);
|
|
1213
|
-
} catch (e) {
|
|
1214
|
-
if (e.code === "EISDIR") {
|
|
1215
|
-
isDirectory = true;
|
|
1216
|
-
} else {
|
|
1217
|
-
throw e;
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
} else {
|
|
1221
|
-
const response = new Response("", { status: 404 });
|
|
1222
|
-
augumentHeaders(req, response);
|
|
1223
|
-
return response;
|
|
1224
|
-
}
|
|
1225
|
-
if (!isDirectory) {
|
|
1226
|
-
try {
|
|
1227
|
-
const fl = Bun.file(destinationPath + requestPath);
|
|
1228
|
-
const response = new Response(fl);
|
|
1229
|
-
augumentHeaders(req, response);
|
|
1230
|
-
return response;
|
|
1231
|
-
} catch (e) {
|
|
1232
|
-
if (e.code === "ENOENT") {
|
|
1233
|
-
const response = new Response("", { status: 404 });
|
|
1234
|
-
augumentHeaders(req, response);
|
|
1235
|
-
return response;
|
|
1236
|
-
} else {
|
|
1237
|
-
throw e;
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
try {
|
|
1242
|
-
const allEntries = await readdir(destinationPath + requestPath, {
|
|
1243
|
-
withFileTypes: true
|
|
1244
|
-
});
|
|
1245
|
-
const dirs = allEntries.filter((entry) => entry.isDirectory()).map((entry) => {
|
|
1246
|
-
return {
|
|
1247
|
-
requestPath: requestPath === "/" ? "" : requestPath,
|
|
1248
|
-
name: entry.name
|
|
1249
|
-
};
|
|
1250
|
-
});
|
|
1251
|
-
const files = allEntries.filter((entry) => entry.isFile()).map((entry) => {
|
|
1252
|
-
return {
|
|
1253
|
-
requestPath: requestPath === "/" ? "" : requestPath,
|
|
1254
|
-
name: entry.name
|
|
1255
|
-
};
|
|
1256
|
-
});
|
|
1257
|
-
const rnd = import_ejs.render(finalConfig.serveOutputEjs, { dirs, files });
|
|
1258
|
-
const response = new Response(rnd, { headers: { "Content-Type": "text/html" } });
|
|
1259
|
-
augumentHeaders(req, response);
|
|
1260
|
-
return response;
|
|
1261
|
-
} catch {
|
|
1262
|
-
const response = new Response("Not Found", { status: 404 });
|
|
1263
|
-
augumentHeaders(req, response);
|
|
1264
|
-
return response;
|
|
1206
|
+
let requestPath = url.pathname;
|
|
1207
|
+
if (requestPath.toLowerCase() === "/index.html") {
|
|
1208
|
+
requestPath = "/";
|
|
1265
1209
|
}
|
|
1210
|
+
return handlePathRequest(requestPath, req, finalConfig, destinationPath);
|
|
1266
1211
|
},
|
|
1267
1212
|
websocket: {
|
|
1268
1213
|
open(ws) {
|
|
@@ -1294,6 +1239,11 @@ var debouncedbuildAndNotify = import_debounce.default(async (finalConfig, destin
|
|
|
1294
1239
|
bunServer.publish("message", JSON.stringify({ type: "reload" }));
|
|
1295
1240
|
}
|
|
1296
1241
|
}, watchDelay, { immediate: true });
|
|
1242
|
+
function handleErrorResponse(req, err) {
|
|
1243
|
+
const msg = `Error while processing request ${req.url}`;
|
|
1244
|
+
console.error(msg, err);
|
|
1245
|
+
return withCORSHeaders(new Response(msg, { status: 500 }), req);
|
|
1246
|
+
}
|
|
1297
1247
|
function publishOutputLogs(bunServer, output, event) {
|
|
1298
1248
|
output.logs.forEach(console.log);
|
|
1299
1249
|
bunServer.publish("message", JSON.stringify({ type: "message", message: `[Bun HMR] ${event.filename} ${event.eventType}` }));
|
|
@@ -1320,10 +1270,11 @@ function publishIndexHTML(destinationPath, template, output, _event) {
|
|
|
1320
1270
|
}
|
|
1321
1271
|
Bun.write(destinationPath + "/index.html", import_ejs.render(template, { hashedImports }));
|
|
1322
1272
|
}
|
|
1323
|
-
function
|
|
1324
|
-
response.headers.set("Access-Control-Allow-Origin", request
|
|
1325
|
-
response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
1273
|
+
function withCORSHeaders(response, request) {
|
|
1274
|
+
response.headers.set("Access-Control-Allow-Origin", request?.headers.get("origin") ?? "*");
|
|
1275
|
+
response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
|
|
1326
1276
|
response.headers.set("Access-Control-Allow-Credentials", "true");
|
|
1277
|
+
return response;
|
|
1327
1278
|
}
|
|
1328
1279
|
async function cleanDirectory(dst) {
|
|
1329
1280
|
const { stderr, exitCode } = await $2`rm -rf ${dst}/*`.nothrow();
|
|
@@ -1347,6 +1298,74 @@ function convertBytes(bytes) {
|
|
|
1347
1298
|
}
|
|
1348
1299
|
return (bytes / Math.pow(1024, i)).toFixed(1) + " " + sizes[i];
|
|
1349
1300
|
}
|
|
1301
|
+
async function handlePathRequest(requestPath, req, finalConfig, destinationPath) {
|
|
1302
|
+
const fsPath = destinationPath + requestPath;
|
|
1303
|
+
const objThere = await checkObjectExists(fsPath, req);
|
|
1304
|
+
let isDirectory = false;
|
|
1305
|
+
if (objThere) {
|
|
1306
|
+
try {
|
|
1307
|
+
await readFile2(fsPath);
|
|
1308
|
+
} catch (e) {
|
|
1309
|
+
if (e.code === "EISDIR") {
|
|
1310
|
+
isDirectory = true;
|
|
1311
|
+
} else {
|
|
1312
|
+
throw e;
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
} else {
|
|
1316
|
+
finalConfig.logRequests && console.log(`${404} ${req.url}`);
|
|
1317
|
+
return withCORSHeaders(new Response("", { status: 404 }), req);
|
|
1318
|
+
}
|
|
1319
|
+
if (!isDirectory) {
|
|
1320
|
+
try {
|
|
1321
|
+
const fl = Bun.file(fsPath);
|
|
1322
|
+
finalConfig.logRequests && console.log(`${200} ${req.url}`);
|
|
1323
|
+
return withCORSHeaders(new Response(fl), req);
|
|
1324
|
+
} catch (e) {
|
|
1325
|
+
if (e?.code === "ENOENT") {
|
|
1326
|
+
finalConfig.logRequests && console.log(`${404} ${req.url}`);
|
|
1327
|
+
return withCORSHeaders(new Response("", { status: 404 }), req);
|
|
1328
|
+
} else {
|
|
1329
|
+
return handleErrorResponse(req, e);
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
try {
|
|
1334
|
+
const allEntries = await readdir(fsPath, {
|
|
1335
|
+
withFileTypes: true
|
|
1336
|
+
});
|
|
1337
|
+
const dirs = allEntries.filter((entry) => entry.isDirectory()).map((entry) => {
|
|
1338
|
+
return {
|
|
1339
|
+
requestPath: requestPath === "/" ? "" : requestPath,
|
|
1340
|
+
name: entry.name
|
|
1341
|
+
};
|
|
1342
|
+
});
|
|
1343
|
+
const files = allEntries.filter((entry) => entry.isFile()).map((entry) => {
|
|
1344
|
+
return {
|
|
1345
|
+
requestPath: requestPath === "/" ? "" : requestPath,
|
|
1346
|
+
name: entry.name
|
|
1347
|
+
};
|
|
1348
|
+
});
|
|
1349
|
+
const rnd = import_ejs.render(finalConfig.serveOutputEjs, { dirs, files });
|
|
1350
|
+
finalConfig.logRequests && console.log(`${200} ${req.url}`);
|
|
1351
|
+
return withCORSHeaders(new Response(rnd, { headers: { "Content-Type": "text/html" } }), req);
|
|
1352
|
+
} catch (err) {
|
|
1353
|
+
return handleErrorResponse(req, err);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
async function checkObjectExists(fsPath, req) {
|
|
1357
|
+
try {
|
|
1358
|
+
await access(fsPath, constants.R_OK);
|
|
1359
|
+
return true;
|
|
1360
|
+
} catch (e) {
|
|
1361
|
+
if (e?.code === "ENOENT") {
|
|
1362
|
+
return false;
|
|
1363
|
+
}
|
|
1364
|
+
const msg = `Error while accessing path ${fsPath}`;
|
|
1365
|
+
console.error(msg, e);
|
|
1366
|
+
return false;
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1350
1369
|
export {
|
|
1351
1370
|
startBunDevServer,
|
|
1352
1371
|
getBunHMRFooter,
|
package/package.json
CHANGED
|
@@ -21,18 +21,18 @@
|
|
|
21
21
|
"exports": {
|
|
22
22
|
".": "./dist/index.js"
|
|
23
23
|
},
|
|
24
|
-
"version": "0.
|
|
24
|
+
"version": "0.7.0",
|
|
25
25
|
"module": "index.ts",
|
|
26
26
|
"type": "module",
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"scripts": {
|
|
29
|
-
"
|
|
29
|
+
"build": "bun run ./build.ts"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/bun": "latest"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"typescript": "^5.7.
|
|
35
|
+
"typescript": "^5.7.3"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@types/ejs": "^3.1.5",
|