@pajh/buldng 0.0.3 → 0.0.5
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 +19 -10
- package/src/MIME.json +11 -0
- package/src/buldng-async.js +20 -0
- package/src/buldng-files.js +58 -0
- package/src/buldng-html.js +262 -0
- package/src/buldng-lib.js +90 -0
- package/src/buldng-modal.ts +348 -0
- package/{dist → src}/buldng-ops.js +8 -8
- package/src/buldng-typescript.js +77 -0
- package/src/buldng-web.ts +142 -0
- package/{dist → src}/buldng.css +130 -0
- package/src/dev-errors.js +16 -0
- package/src/layout-err.ts +171 -0
- package/{dist → src}/layout.ts +4 -0
- package/src/serve-lib.js +567 -0
- package/src/serve.js +193 -0
- package/src/types/global.d.ts +19 -0
- package/{dist → src}/wrapper.html +2 -0
- package/dist/buldng-lib.js +0 -408
- package/dist/types/global.d.ts +0 -10
- /package/{dist → src}/buldng-validate.js +0 -0
- /package/{dist → src}/clean.sh +0 -0
- /package/{dist → src}/init.js +0 -0
- /package/{dist → src}/workfile.js +0 -0
package/{dist → src}/buldng.css
RENAMED
|
@@ -146,3 +146,133 @@ button {
|
|
|
146
146
|
background: var(--button);
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
/* --------------------------------------------------
|
|
150
|
+
MODAL SYSTEM
|
|
151
|
+
-------------------------------------------------- */
|
|
152
|
+
|
|
153
|
+
#b-modal-root {
|
|
154
|
+
position: fixed;
|
|
155
|
+
inset: 0;
|
|
156
|
+
z-index: 1000;
|
|
157
|
+
pointer-events: none;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
#b-modal-root .buldng-modal-backdrop {
|
|
161
|
+
position: absolute;
|
|
162
|
+
inset: 0;
|
|
163
|
+
display: flex;
|
|
164
|
+
align-items: center;
|
|
165
|
+
justify-content: center;
|
|
166
|
+
padding: 20px;
|
|
167
|
+
background: var(--modal-backdrop-color, rgba(0, 0, 0, 0.5));
|
|
168
|
+
pointer-events: auto;
|
|
169
|
+
}
|
|
170
|
+
#b-modal-root .buldng-modal {
|
|
171
|
+
display: flex;
|
|
172
|
+
flex-direction: column;
|
|
173
|
+
width: min(100%, 480px);
|
|
174
|
+
max-height: min(100%, 720px);
|
|
175
|
+
overflow: auto;
|
|
176
|
+
color: var(--text, #222222);
|
|
177
|
+
background: var(--modal-bg, var(--panel, #ffffff));
|
|
178
|
+
border: 2px solid var(--modal-accent-color, #0066cc);
|
|
179
|
+
border-radius: var(--modal-radius, 12px);
|
|
180
|
+
box-shadow: var(--modal-shadow, 0 4px 20px rgba(0, 0, 0, 0.3));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
#b-modal-root .buldng-modal-header {
|
|
184
|
+
display: flex;
|
|
185
|
+
align-items: center;
|
|
186
|
+
gap: 12px;
|
|
187
|
+
padding: var(--modal-padding, 20px) var(--modal-padding, 20px) 0;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
#b-modal-root .buldng-modal-icon {
|
|
191
|
+
display: inline-flex;
|
|
192
|
+
align-items: center;
|
|
193
|
+
justify-content: center;
|
|
194
|
+
flex: 0 0 32px;
|
|
195
|
+
width: 32px;
|
|
196
|
+
height: 32px;
|
|
197
|
+
color: var(--modal-accent-color, #0066cc);
|
|
198
|
+
font-weight: 700;
|
|
199
|
+
border: 2px solid currentColor;
|
|
200
|
+
border-radius: 50%;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
#b-modal-root .buldng-modal-title {
|
|
204
|
+
margin: 0;
|
|
205
|
+
color: inherit;
|
|
206
|
+
font-size: 1.2em;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
#b-modal-root .buldng-modal-content {
|
|
210
|
+
padding: var(--modal-padding, 20px);
|
|
211
|
+
overflow: auto;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
#b-modal-root .buldng-modal-footer {
|
|
215
|
+
display: flex;
|
|
216
|
+
justify-content: flex-end;
|
|
217
|
+
gap: 10px;
|
|
218
|
+
padding: 0 var(--modal-padding, 20px) var(--modal-padding, 20px);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
#b-modal-root .buldng-modal-button {
|
|
222
|
+
min-width: 88px;
|
|
223
|
+
min-height: 44px;
|
|
224
|
+
padding: 8px 16px;
|
|
225
|
+
color: var(--text, #222222);
|
|
226
|
+
font: inherit;
|
|
227
|
+
font-weight: 600;
|
|
228
|
+
background: var(--button, #f0f0f0);
|
|
229
|
+
border: 1px solid var(--line, #9c9c9c);
|
|
230
|
+
border-radius: 4px;
|
|
231
|
+
cursor: pointer;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
#b-modal-root .buldng-modal-button-primary {
|
|
235
|
+
color: #ffffff;
|
|
236
|
+
background: var(--modal-accent-color, #0066cc);
|
|
237
|
+
border-color: var(--modal-accent-color, #0066cc);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
#b-modal-root .buldng-modal-button:focus-visible {
|
|
241
|
+
outline: 3px solid var(--highlight1, #4aa3ff);
|
|
242
|
+
outline-offset: 2px;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
#b-modal-root .buldng-modal.info {
|
|
246
|
+
--modal-accent-color: #0066cc;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
#b-modal-root .buldng-modal.confirmation {
|
|
250
|
+
--modal-accent-color: #444444;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
#b-modal-root .buldng-modal.destructive,
|
|
254
|
+
#b-modal-root .buldng-modal.error {
|
|
255
|
+
--modal-accent-color: #cc0000;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
@media (max-width: 520px) {
|
|
259
|
+
#b-modal-root .buldng-modal-backdrop {
|
|
260
|
+
align-items: flex-end;
|
|
261
|
+
padding: 0;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
#b-modal-root .buldng-modal {
|
|
265
|
+
width: 100%;
|
|
266
|
+
max-height: 90%;
|
|
267
|
+
border-radius: var(--modal-radius, 12px) var(--modal-radius, 12px) 0 0;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
#b-modal-root .buldng-modal-footer {
|
|
271
|
+
flex-direction: column-reverse;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
#b-modal-root .buldng-modal-button {
|
|
275
|
+
width: 100%;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Development-only override. setErrorPage() owns the event listeners.
|
|
2
|
+
console.log("[dev-errors] overriding window.__error_handler");
|
|
3
|
+
|
|
4
|
+
window.__error_handler = (event, page) => {
|
|
5
|
+
const reason =
|
|
6
|
+
event.type === "error"
|
|
7
|
+
? event.error ?? event.message
|
|
8
|
+
: event.reason;
|
|
9
|
+
|
|
10
|
+
const message =
|
|
11
|
+
reason instanceof Error
|
|
12
|
+
? reason.message
|
|
13
|
+
: String(reason || "Unknown error");
|
|
14
|
+
|
|
15
|
+
alert(`BULDR DEV ERROR:\n\n${message}\n\nCheck DevTools for full details.`);
|
|
16
|
+
};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================
|
|
3
|
+
* BULDR PRODUCTION ERROR SUBSYSTEM — layout-err.ts
|
|
4
|
+
* ============================================================
|
|
5
|
+
*
|
|
6
|
+
* This module is bundled ONLY by layout.ts.
|
|
7
|
+
* It owns ALL production error logic:
|
|
8
|
+
* - capturing errors
|
|
9
|
+
* - building payloads
|
|
10
|
+
* - storing payloads
|
|
11
|
+
* - redirecting to the error page
|
|
12
|
+
*
|
|
13
|
+
* buldng-web.ts owns:
|
|
14
|
+
* - reading payloads
|
|
15
|
+
* - consuming payloads
|
|
16
|
+
* - rendering payloads
|
|
17
|
+
* - runtime utilities
|
|
18
|
+
*
|
|
19
|
+
* error-main.ts owns:
|
|
20
|
+
* - UI for the error page
|
|
21
|
+
*
|
|
22
|
+
* ============================================================
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const ERROR_STORAGE_PREFIX = "buldng:error:";
|
|
26
|
+
|
|
27
|
+
// ------------------------------------------------------------
|
|
28
|
+
// PUBLIC API
|
|
29
|
+
// ------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Install the production error handler wrapper.
|
|
33
|
+
* layout.ts calls this once during startup.
|
|
34
|
+
*/
|
|
35
|
+
export function installErrorHandler() {
|
|
36
|
+
window.__error_handler = (event, page) => {
|
|
37
|
+
handleError(event, page);
|
|
38
|
+
};
|
|
39
|
+
console.log("BULDR: Production error handler installed");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ------------------------------------------------------------
|
|
43
|
+
// CORE PRODUCTION LOGIC
|
|
44
|
+
// ------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
function handleError(
|
|
47
|
+
event: ErrorEvent | PromiseRejectionEvent,
|
|
48
|
+
page: string
|
|
49
|
+
) {
|
|
50
|
+
if (window.__buldngErrorOverlay) return;
|
|
51
|
+
|
|
52
|
+
const info =
|
|
53
|
+
event instanceof ErrorEvent
|
|
54
|
+
? {
|
|
55
|
+
type: "error" as const,
|
|
56
|
+
reason: event.error ?? event.message,
|
|
57
|
+
fallbackMessage: event.message,
|
|
58
|
+
}
|
|
59
|
+
: {
|
|
60
|
+
type: "unhandledrejection" as const,
|
|
61
|
+
reason: event.reason,
|
|
62
|
+
fallbackMessage: "Unhandled promise rejection",
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const payload = buildPayload(info);
|
|
66
|
+
const stored = saveErrorPayload(payload);
|
|
67
|
+
|
|
68
|
+
redirect(payload, stored, page);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ------------------------------------------------------------
|
|
72
|
+
// PAYLOAD BUILDING
|
|
73
|
+
// ------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
export type ErrorPayload = {
|
|
76
|
+
id: string;
|
|
77
|
+
type: "error" | "unhandledrejection";
|
|
78
|
+
message: string;
|
|
79
|
+
stack: string;
|
|
80
|
+
time: string;
|
|
81
|
+
url: string;
|
|
82
|
+
userAgent: string;
|
|
83
|
+
platform: string;
|
|
84
|
+
language: string;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
function buildPayload(info: {
|
|
88
|
+
type: ErrorPayload["type"];
|
|
89
|
+
reason: unknown;
|
|
90
|
+
fallbackMessage: string;
|
|
91
|
+
}): ErrorPayload {
|
|
92
|
+
const id = createId();
|
|
93
|
+
const error = info.reason instanceof Error ? info.reason : null;
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
id,
|
|
97
|
+
type: info.type,
|
|
98
|
+
message: getErrorMessage(info.reason, info.fallbackMessage),
|
|
99
|
+
stack: error?.stack ?? getErrorStack(info.reason),
|
|
100
|
+
time: new Date().toISOString(),
|
|
101
|
+
url: location.href,
|
|
102
|
+
userAgent: navigator.userAgent,
|
|
103
|
+
platform: navigator.platform,
|
|
104
|
+
language: navigator.language,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ------------------------------------------------------------
|
|
109
|
+
// REDIRECT
|
|
110
|
+
// ------------------------------------------------------------
|
|
111
|
+
|
|
112
|
+
function redirect(payload: ErrorPayload, stored: boolean, page: string) {
|
|
113
|
+
const destination = new URL(page, location.href);
|
|
114
|
+
|
|
115
|
+
if (stored) {
|
|
116
|
+
destination.searchParams.set("errorId", payload.id);
|
|
117
|
+
} else {
|
|
118
|
+
destination.searchParams.set("type", payload.type);
|
|
119
|
+
destination.searchParams.set("message", payload.message.slice(0, 500));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
window.location.href = destination.href;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ------------------------------------------------------------
|
|
126
|
+
// STORAGE (production only)
|
|
127
|
+
// ------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
function saveErrorPayload(payload: ErrorPayload): boolean {
|
|
130
|
+
try {
|
|
131
|
+
localStorage.setItem(storageKey(payload.id), JSON.stringify(payload));
|
|
132
|
+
return true;
|
|
133
|
+
} catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function storageKey(id: string) {
|
|
139
|
+
return `${ERROR_STORAGE_PREFIX}${id}`;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function createId() {
|
|
143
|
+
if (typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
144
|
+
return `${Date.now().toString(36)}-${Math.random()
|
|
145
|
+
.toString(36)
|
|
146
|
+
.slice(2)}`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ------------------------------------------------------------
|
|
150
|
+
// UTILITIES (production only)
|
|
151
|
+
// ------------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
function getErrorMessage(reason: unknown, fallback: string) {
|
|
154
|
+
if (reason instanceof Error && reason.message) return reason.message;
|
|
155
|
+
if (typeof reason === "string" && reason) return reason;
|
|
156
|
+
|
|
157
|
+
if (reason !== null && reason !== undefined) {
|
|
158
|
+
try {
|
|
159
|
+
const text = JSON.stringify(reason);
|
|
160
|
+
if (text) return text;
|
|
161
|
+
} catch {}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return fallback;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function getErrorStack(reason: unknown) {
|
|
168
|
+
if (!reason || typeof reason !== "object") return "";
|
|
169
|
+
const stack = (reason as { stack?: unknown }).stack;
|
|
170
|
+
return typeof stack === "string" ? stack : "";
|
|
171
|
+
}
|