@pajh/buldng 0.0.4 → 0.0.6
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 +7 -2
- package/src/MIME.json +11 -0
- package/src/buldng-async.js +20 -0
- package/src/buldng-files.js +59 -0
- package/src/buldng-html.js +262 -0
- package/src/buldng-lib.js +67 -411
- package/src/buldng-modal.ts +348 -0
- package/src/buldng-ops.js +21 -6
- package/src/buldng-typescript.js +77 -0
- package/src/buldng-validate.js +11 -4
- package/src/buldng-web.ts +55 -180
- package/src/buldng.css +130 -0
- package/src/dev-errors.js +16 -0
- package/src/layout-err.ts +171 -0
- package/src/layout.ts +4 -0
- package/src/serve-lib.js +574 -0
- package/src/serve.js +194 -0
- package/src/types/global.d.ts +9 -0
- package/src/wrapper.html +2 -0
- package/src/buldng-dev-errors.js +0 -84
package/src/serve.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// serve.js
|
|
3
|
+
import http from "node:http";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { exec } from "node:child_process";
|
|
7
|
+
import MIME from "./MIME.json" with { type: "json" };
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
createState,
|
|
11
|
+
initHotReload,
|
|
12
|
+
initDevErrors,
|
|
13
|
+
handleHttpRequest,
|
|
14
|
+
processArgs,
|
|
15
|
+
registerInject,
|
|
16
|
+
sanitiseRoot,
|
|
17
|
+
sanitisePort,
|
|
18
|
+
stopHotReload,
|
|
19
|
+
local,
|
|
20
|
+
ARGS
|
|
21
|
+
} from "./serve-lib.js";
|
|
22
|
+
|
|
23
|
+
// --------------------------------------------------
|
|
24
|
+
// CONFIG + STATIC DATA
|
|
25
|
+
// --------------------------------------------------
|
|
26
|
+
|
|
27
|
+
const DEFAULT_PORT = 5173;
|
|
28
|
+
const DEFAULT_ROOT = "dist";
|
|
29
|
+
|
|
30
|
+
// --------------------------------------------------
|
|
31
|
+
// HTML INJECTIONS
|
|
32
|
+
// --------------------------------------------------
|
|
33
|
+
|
|
34
|
+
function registerHtmlInjections(state) {
|
|
35
|
+
|
|
36
|
+
if (state.DEV_ERRORS) {
|
|
37
|
+
console.log("[dev-errors] creating injection for dev-errors.js");
|
|
38
|
+
|
|
39
|
+
// add mapping entry
|
|
40
|
+
state.MAPPINGS.push({
|
|
41
|
+
from: "/dev-errors.js",
|
|
42
|
+
to: "buldng://dev-errors.js",
|
|
43
|
+
type: "file"
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
registerInject(state, "html", "<!--POSTLAYOUT-->", `
|
|
47
|
+
<script type="module" src="/dev-errors.js"></script>
|
|
48
|
+
`, "post");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (state.hotEnabled) {
|
|
52
|
+
registerInject(state, "html", "</head>", `
|
|
53
|
+
<script>
|
|
54
|
+
const es = new EventSource("/__hot");
|
|
55
|
+
es.onmessage = () => location.reload();
|
|
56
|
+
</script>
|
|
57
|
+
`, "pre");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
// --------------------------------------------------
|
|
63
|
+
// INITIALIZATION
|
|
64
|
+
// --------------------------------------------------
|
|
65
|
+
|
|
66
|
+
function init() {
|
|
67
|
+
|
|
68
|
+
processArgs();
|
|
69
|
+
let ROOT = ARGS.get("root");
|
|
70
|
+
let PORT = ARGS.get("port");
|
|
71
|
+
|
|
72
|
+
if (!ROOT) {
|
|
73
|
+
ROOT = DEFAULT_ROOT;
|
|
74
|
+
console.log(`[args] root: ${ROOT} (DEFAULT)`);
|
|
75
|
+
} else {
|
|
76
|
+
console.log(`[args] root: ${ROOT}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
ROOT = sanitiseRoot(ROOT);
|
|
80
|
+
|
|
81
|
+
if (!PORT) {
|
|
82
|
+
PORT = DEFAULT_PORT;
|
|
83
|
+
console.log(`[args] port: ${PORT} (DEFAULT)`);
|
|
84
|
+
} else {
|
|
85
|
+
console.log(`[args] port: ${PORT}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
PORT = sanitisePort(PORT);
|
|
89
|
+
|
|
90
|
+
const state = createState({
|
|
91
|
+
ROOT: ROOT,
|
|
92
|
+
PORT: PORT,
|
|
93
|
+
MAPPINGS: [],
|
|
94
|
+
MIME: MIME,
|
|
95
|
+
LOG_ALL: ARGS.get("log"),
|
|
96
|
+
DEV_ERRORS: ARGS.get("dev-errors"),
|
|
97
|
+
NO_HOT: ARGS.get("no-hot")
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
loadMappings(state);
|
|
101
|
+
initHotReload(state);
|
|
102
|
+
initDevErrors(state);
|
|
103
|
+
registerHtmlInjections(state);
|
|
104
|
+
|
|
105
|
+
return state;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function loadMappings(state) {
|
|
109
|
+
const mapPath = ARGS.get("map");
|
|
110
|
+
|
|
111
|
+
if (!mapPath) {
|
|
112
|
+
console.log("[map] OFF");
|
|
113
|
+
state.MAPPINGS = [];
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
const full = path.resolve(mapPath);
|
|
119
|
+
const json = JSON.parse(fs.readFileSync(full, "utf8"));
|
|
120
|
+
state.MAPPINGS = json;
|
|
121
|
+
console.log(`[map] ${full} (${json.length} rules)`);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.log(`[map] FAILED to load ${mapPath}`);
|
|
124
|
+
process.exit(13);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
// --------------------------------------------------
|
|
130
|
+
// SERVE LOOP (VISIBLE SKELETON)
|
|
131
|
+
// --------------------------------------------------
|
|
132
|
+
|
|
133
|
+
function serve(state) {
|
|
134
|
+
const server = http.createServer((req, res) => {
|
|
135
|
+
// -----------------------------
|
|
136
|
+
// The bones of the loop stay here
|
|
137
|
+
// -----------------------------
|
|
138
|
+
|
|
139
|
+
state.running = true;
|
|
140
|
+
|
|
141
|
+
// 1. Receive request
|
|
142
|
+
const urlPath = req.url;
|
|
143
|
+
|
|
144
|
+
// 2. Delegate to serve-lib.js to produce a response object
|
|
145
|
+
const response = handleHttpRequest(urlPath, req, state);
|
|
146
|
+
|
|
147
|
+
// 3. Send response
|
|
148
|
+
response.send(res);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
let shuttingDown = false;
|
|
152
|
+
const shutdown = () => {
|
|
153
|
+
if (shuttingDown) return;
|
|
154
|
+
shuttingDown = true;
|
|
155
|
+
teardown(state);
|
|
156
|
+
server.close(() => process.exit(0));
|
|
157
|
+
server.closeAllConnections();
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
process.once("SIGTERM", shutdown);
|
|
161
|
+
process.once("SIGINT", shutdown);
|
|
162
|
+
|
|
163
|
+
server.listen(state.PORT, () => {
|
|
164
|
+
console.log(`[serve] root: ${state.ROOT} at http://localhost:${state.PORT}`);
|
|
165
|
+
const browser = ARGS.get("browser");
|
|
166
|
+
if (browser)
|
|
167
|
+
exec(`${browser} http://localhost:${state.PORT}`);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
return server;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// --------------------------------------------------
|
|
174
|
+
// TEARDOWN
|
|
175
|
+
// --------------------------------------------------
|
|
176
|
+
|
|
177
|
+
function teardown(state) {
|
|
178
|
+
state.running = false;
|
|
179
|
+
stopHotReload(state);
|
|
180
|
+
console.log("Server shutting down.");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// --------------------------------------------------
|
|
184
|
+
// MAIN
|
|
185
|
+
// --------------------------------------------------
|
|
186
|
+
|
|
187
|
+
function main() {
|
|
188
|
+
const state = init();
|
|
189
|
+
const server = serve(state);
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
main();
|
package/src/types/global.d.ts
CHANGED
|
@@ -6,5 +6,14 @@ declare global {
|
|
|
6
6
|
a: Promise<void>;
|
|
7
7
|
_resolveA: () => void;
|
|
8
8
|
};
|
|
9
|
+
|
|
10
|
+
__error_handler?: (
|
|
11
|
+
event: ErrorEvent | PromiseRejectionEvent,
|
|
12
|
+
page: string
|
|
13
|
+
) => void;
|
|
14
|
+
|
|
15
|
+
__buldngErrorOverlay?: boolean;
|
|
16
|
+
|
|
17
|
+
__buldng_listenersInstalled?: boolean;
|
|
9
18
|
}
|
|
10
19
|
}
|
package/src/wrapper.html
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
window.__ready.a = new Promise((resolve) => { window.__ready._resolveA = resolve; });
|
|
14
14
|
</script>
|
|
15
15
|
<script type="module" src="/layout.js"></script>
|
|
16
|
+
<!--POSTLAYOUT-->
|
|
16
17
|
<!--SCRIPTS-->
|
|
17
18
|
</head>
|
|
18
19
|
<body>
|
|
@@ -20,5 +21,6 @@
|
|
|
20
21
|
<!-- Project outline (camera-style) will be stitched here -->
|
|
21
22
|
<!--CAMERA-STYLE-->
|
|
22
23
|
</div>
|
|
24
|
+
<div id="b-modal-root"></div>
|
|
23
25
|
</body>
|
|
24
26
|
</html>
|
package/src/buldng-dev-errors.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
// Development-only error overlay installed by the local preview server.
|
|
2
|
-
// The production build never references this file from its HTML.
|
|
3
|
-
|
|
4
|
-
window.__buldngErrorOverlay = true;
|
|
5
|
-
|
|
6
|
-
let shown = false;
|
|
7
|
-
|
|
8
|
-
window.addEventListener("error", (event) => {
|
|
9
|
-
showError(event.error ?? event.message, "error");
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
window.addEventListener("unhandledrejection", (event) => {
|
|
13
|
-
showError(event.reason, "unhandledrejection");
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
function showError(reason, type) {
|
|
17
|
-
if (shown) return;
|
|
18
|
-
shown = true;
|
|
19
|
-
|
|
20
|
-
const message = getMessage(reason);
|
|
21
|
-
const stack = getStack(reason);
|
|
22
|
-
const overlay = document.createElement("aside");
|
|
23
|
-
overlay.id = "buldng-dev-error-overlay";
|
|
24
|
-
overlay.style.cssText = [
|
|
25
|
-
"position: fixed",
|
|
26
|
-
"z-index: 2147483647",
|
|
27
|
-
"left: 1rem",
|
|
28
|
-
"right: 1rem",
|
|
29
|
-
"bottom: 1rem",
|
|
30
|
-
"max-height: 70vh",
|
|
31
|
-
"overflow: auto",
|
|
32
|
-
"padding: 1rem 1.25rem",
|
|
33
|
-
"border: 2px solid #d33",
|
|
34
|
-
"border-radius: 8px",
|
|
35
|
-
"background: #240b0b",
|
|
36
|
-
"color: #fff",
|
|
37
|
-
"font: 16px/1.4 monospace",
|
|
38
|
-
"box-shadow: 0 4px 24px #0008",
|
|
39
|
-
].join(";");
|
|
40
|
-
|
|
41
|
-
const close = document.createElement("button");
|
|
42
|
-
close.type = "button";
|
|
43
|
-
close.textContent = "Close";
|
|
44
|
-
close.style.cssText = "float:right; padding:.35rem .6rem; cursor:pointer";
|
|
45
|
-
close.addEventListener("click", () => overlay.remove());
|
|
46
|
-
|
|
47
|
-
const title = document.createElement("strong");
|
|
48
|
-
title.textContent = "BULDR preview: something broke";
|
|
49
|
-
|
|
50
|
-
const hint = document.createElement("p");
|
|
51
|
-
hint.textContent = `(${type}) Check the DevTools console for the full mapped stack.`;
|
|
52
|
-
|
|
53
|
-
const text = document.createElement("p");
|
|
54
|
-
text.textContent = message;
|
|
55
|
-
|
|
56
|
-
overlay.append(close, title, hint, text);
|
|
57
|
-
if (stack) {
|
|
58
|
-
const details = document.createElement("details");
|
|
59
|
-
const summary = document.createElement("summary");
|
|
60
|
-
summary.textContent = "Raw stack";
|
|
61
|
-
const pre = document.createElement("pre");
|
|
62
|
-
pre.textContent = stack;
|
|
63
|
-
pre.style.cssText = "white-space:pre-wrap; overflow-wrap:anywhere";
|
|
64
|
-
details.append(summary, pre);
|
|
65
|
-
overlay.appendChild(details);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
document.body?.appendChild(overlay);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function getMessage(reason) {
|
|
72
|
-
if (reason instanceof Error && reason.message) return reason.message;
|
|
73
|
-
if (typeof reason === "string" && reason) return reason;
|
|
74
|
-
try {
|
|
75
|
-
const text = JSON.stringify(reason);
|
|
76
|
-
return text || "Unknown error";
|
|
77
|
-
} catch {
|
|
78
|
-
return String(reason) || "Unknown error";
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function getStack(reason) {
|
|
83
|
-
return reason && typeof reason.stack === "string" ? reason.stack : "";
|
|
84
|
-
}
|