@run0/jiki 0.1.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.
Files changed (152) hide show
  1. package/dist/browser-bundle.d.ts +40 -0
  2. package/dist/builtins.d.ts +22 -0
  3. package/dist/code-transform.d.ts +7 -0
  4. package/dist/config/cdn.d.ts +13 -0
  5. package/dist/container.d.ts +101 -0
  6. package/dist/dev-server.d.ts +69 -0
  7. package/dist/errors.d.ts +19 -0
  8. package/dist/frameworks/code-transforms.d.ts +32 -0
  9. package/dist/frameworks/next-api-handler.d.ts +72 -0
  10. package/dist/frameworks/next-dev-server.d.ts +141 -0
  11. package/dist/frameworks/next-html-generator.d.ts +36 -0
  12. package/dist/frameworks/next-route-resolver.d.ts +19 -0
  13. package/dist/frameworks/next-shims.d.ts +78 -0
  14. package/dist/frameworks/remix-dev-server.d.ts +47 -0
  15. package/dist/frameworks/sveltekit-dev-server.d.ts +43 -0
  16. package/dist/frameworks/vite-dev-server.d.ts +50 -0
  17. package/dist/fs-errors.d.ts +36 -0
  18. package/dist/index.cjs +14916 -0
  19. package/dist/index.cjs.map +1 -0
  20. package/dist/index.d.ts +61 -0
  21. package/dist/index.mjs +14898 -0
  22. package/dist/index.mjs.map +1 -0
  23. package/dist/kernel.d.ts +48 -0
  24. package/dist/memfs.d.ts +144 -0
  25. package/dist/metrics.d.ts +78 -0
  26. package/dist/module-resolver.d.ts +60 -0
  27. package/dist/network-interceptor.d.ts +71 -0
  28. package/dist/npm/cache.d.ts +76 -0
  29. package/dist/npm/index.d.ts +60 -0
  30. package/dist/npm/lockfile-reader.d.ts +32 -0
  31. package/dist/npm/pnpm.d.ts +18 -0
  32. package/dist/npm/registry.d.ts +45 -0
  33. package/dist/npm/resolver.d.ts +39 -0
  34. package/dist/npm/sync-installer.d.ts +18 -0
  35. package/dist/npm/tarball.d.ts +4 -0
  36. package/dist/npm/workspaces.d.ts +46 -0
  37. package/dist/persistence.d.ts +94 -0
  38. package/dist/plugin.d.ts +156 -0
  39. package/dist/polyfills/assert.d.ts +30 -0
  40. package/dist/polyfills/child_process.d.ts +116 -0
  41. package/dist/polyfills/chokidar.d.ts +18 -0
  42. package/dist/polyfills/crypto.d.ts +49 -0
  43. package/dist/polyfills/events.d.ts +28 -0
  44. package/dist/polyfills/fs.d.ts +82 -0
  45. package/dist/polyfills/http.d.ts +147 -0
  46. package/dist/polyfills/module.d.ts +29 -0
  47. package/dist/polyfills/net.d.ts +53 -0
  48. package/dist/polyfills/os.d.ts +91 -0
  49. package/dist/polyfills/path.d.ts +96 -0
  50. package/dist/polyfills/perf_hooks.d.ts +21 -0
  51. package/dist/polyfills/process.d.ts +99 -0
  52. package/dist/polyfills/querystring.d.ts +15 -0
  53. package/dist/polyfills/readdirp.d.ts +18 -0
  54. package/dist/polyfills/readline.d.ts +32 -0
  55. package/dist/polyfills/stream.d.ts +106 -0
  56. package/dist/polyfills/stubs.d.ts +737 -0
  57. package/dist/polyfills/tty.d.ts +25 -0
  58. package/dist/polyfills/url.d.ts +41 -0
  59. package/dist/polyfills/util.d.ts +61 -0
  60. package/dist/polyfills/v8.d.ts +43 -0
  61. package/dist/polyfills/vm.d.ts +76 -0
  62. package/dist/polyfills/worker-threads.d.ts +77 -0
  63. package/dist/polyfills/ws.d.ts +32 -0
  64. package/dist/polyfills/zlib.d.ts +87 -0
  65. package/dist/runtime-helpers.d.ts +4 -0
  66. package/dist/runtime-interface.d.ts +39 -0
  67. package/dist/sandbox.d.ts +69 -0
  68. package/dist/server-bridge.d.ts +55 -0
  69. package/dist/shell-commands.d.ts +2 -0
  70. package/dist/shell.d.ts +101 -0
  71. package/dist/transpiler.d.ts +47 -0
  72. package/dist/type-checker.d.ts +57 -0
  73. package/dist/types/package-json.d.ts +17 -0
  74. package/dist/utils/binary-encoding.d.ts +4 -0
  75. package/dist/utils/hash.d.ts +6 -0
  76. package/dist/utils/safe-path.d.ts +6 -0
  77. package/dist/worker-runtime.d.ts +34 -0
  78. package/package.json +59 -0
  79. package/src/browser-bundle.ts +498 -0
  80. package/src/builtins.ts +222 -0
  81. package/src/code-transform.ts +183 -0
  82. package/src/config/cdn.ts +17 -0
  83. package/src/container.ts +343 -0
  84. package/src/dev-server.ts +322 -0
  85. package/src/errors.ts +604 -0
  86. package/src/frameworks/code-transforms.ts +667 -0
  87. package/src/frameworks/next-api-handler.ts +366 -0
  88. package/src/frameworks/next-dev-server.ts +1252 -0
  89. package/src/frameworks/next-html-generator.ts +585 -0
  90. package/src/frameworks/next-route-resolver.ts +521 -0
  91. package/src/frameworks/next-shims.ts +1084 -0
  92. package/src/frameworks/remix-dev-server.ts +163 -0
  93. package/src/frameworks/sveltekit-dev-server.ts +197 -0
  94. package/src/frameworks/vite-dev-server.ts +370 -0
  95. package/src/fs-errors.ts +118 -0
  96. package/src/index.ts +188 -0
  97. package/src/kernel.ts +381 -0
  98. package/src/memfs.ts +1006 -0
  99. package/src/metrics.ts +140 -0
  100. package/src/module-resolver.ts +511 -0
  101. package/src/network-interceptor.ts +143 -0
  102. package/src/npm/cache.ts +172 -0
  103. package/src/npm/index.ts +377 -0
  104. package/src/npm/lockfile-reader.ts +105 -0
  105. package/src/npm/pnpm.ts +108 -0
  106. package/src/npm/registry.ts +120 -0
  107. package/src/npm/resolver.ts +339 -0
  108. package/src/npm/sync-installer.ts +217 -0
  109. package/src/npm/tarball.ts +136 -0
  110. package/src/npm/workspaces.ts +255 -0
  111. package/src/persistence.ts +235 -0
  112. package/src/plugin.ts +293 -0
  113. package/src/polyfills/assert.ts +164 -0
  114. package/src/polyfills/child_process.ts +535 -0
  115. package/src/polyfills/chokidar.ts +52 -0
  116. package/src/polyfills/crypto.ts +433 -0
  117. package/src/polyfills/events.ts +178 -0
  118. package/src/polyfills/fs.ts +297 -0
  119. package/src/polyfills/http.ts +478 -0
  120. package/src/polyfills/module.ts +97 -0
  121. package/src/polyfills/net.ts +123 -0
  122. package/src/polyfills/os.ts +108 -0
  123. package/src/polyfills/path.ts +169 -0
  124. package/src/polyfills/perf_hooks.ts +30 -0
  125. package/src/polyfills/process.ts +349 -0
  126. package/src/polyfills/querystring.ts +66 -0
  127. package/src/polyfills/readdirp.ts +72 -0
  128. package/src/polyfills/readline.ts +80 -0
  129. package/src/polyfills/stream.ts +610 -0
  130. package/src/polyfills/stubs.ts +600 -0
  131. package/src/polyfills/tty.ts +43 -0
  132. package/src/polyfills/url.ts +97 -0
  133. package/src/polyfills/util.ts +173 -0
  134. package/src/polyfills/v8.ts +62 -0
  135. package/src/polyfills/vm.ts +111 -0
  136. package/src/polyfills/worker-threads.ts +189 -0
  137. package/src/polyfills/ws.ts +73 -0
  138. package/src/polyfills/zlib.ts +244 -0
  139. package/src/runtime-helpers.ts +83 -0
  140. package/src/runtime-interface.ts +46 -0
  141. package/src/sandbox.ts +178 -0
  142. package/src/server-bridge.ts +473 -0
  143. package/src/service-worker.ts +153 -0
  144. package/src/shell-commands.ts +708 -0
  145. package/src/shell.ts +795 -0
  146. package/src/transpiler.ts +282 -0
  147. package/src/type-checker.ts +241 -0
  148. package/src/types/package-json.ts +17 -0
  149. package/src/utils/binary-encoding.ts +38 -0
  150. package/src/utils/hash.ts +24 -0
  151. package/src/utils/safe-path.ts +38 -0
  152. package/src/worker-runtime.ts +42 -0
package/src/errors.ts ADDED
@@ -0,0 +1,604 @@
1
+ import type { NodeError } from "./fs-errors";
2
+ import type { BundleError } from "./browser-bundle";
3
+
4
+ export type ErrorCategory =
5
+ | "build"
6
+ | "runtime"
7
+ | "bundle"
8
+ | "install"
9
+ | "filesystem";
10
+
11
+ export interface ContainerError {
12
+ id: string;
13
+ category: ErrorCategory;
14
+ title: string;
15
+ message: string;
16
+ file?: string;
17
+ line?: number;
18
+ column?: number;
19
+ stack?: string;
20
+ timestamp: number;
21
+ raw?: unknown;
22
+ /** Actionable fix suggestions for the error. */
23
+ suggestions?: string[];
24
+ }
25
+
26
+ let errorSeq = 0;
27
+
28
+ function uid(): string {
29
+ return `err_${++errorSeq}_${Date.now().toString(36)}`;
30
+ }
31
+
32
+ const FRIENDLY_FS_CODES: Record<string, string> = {
33
+ ENOENT: "File or directory not found",
34
+ ENOTDIR: "Path is not a directory",
35
+ EISDIR: "Expected a file but found a directory",
36
+ EEXIST: "File already exists",
37
+ ENOTEMPTY: "Directory is not empty",
38
+ ELOOP: "Too many symbolic links",
39
+ };
40
+
41
+ const RUNTIME_ERROR_TITLES: Record<string, string> = {
42
+ ReferenceError: "Reference Error",
43
+ TypeError: "Type Error",
44
+ SyntaxError: "Syntax Error",
45
+ RangeError: "Range Error",
46
+ URIError: "URI Error",
47
+ EvalError: "Eval Error",
48
+ };
49
+
50
+ function extractLocation(stack?: string): {
51
+ file?: string;
52
+ line?: number;
53
+ column?: number;
54
+ } {
55
+ if (!stack) return {};
56
+ const match = stack.match(/(?:at\s+.+?\s+\(|at\s+)(.+?):(\d+):(\d+)/);
57
+ if (match) {
58
+ return {
59
+ file: match[1],
60
+ line: parseInt(match[2], 10),
61
+ column: parseInt(match[3], 10),
62
+ };
63
+ }
64
+ const simpleMatch = stack.match(/(.+?):(\d+):(\d+)/);
65
+ if (simpleMatch) {
66
+ return {
67
+ file: simpleMatch[1],
68
+ line: parseInt(simpleMatch[2], 10),
69
+ column: parseInt(simpleMatch[3], 10),
70
+ };
71
+ }
72
+ return {};
73
+ }
74
+
75
+ function parseBuildError(raw: unknown): Partial<ContainerError> {
76
+ if (raw && typeof raw === "object" && "text" in raw) {
77
+ const msg = raw as {
78
+ text?: string;
79
+ location?: {
80
+ file?: string;
81
+ line?: number;
82
+ column?: number;
83
+ lineText?: string;
84
+ };
85
+ };
86
+ const loc = msg.location;
87
+ let message = msg.text || "Unknown build error";
88
+ if (loc?.lineText) {
89
+ message += `\n\n ${loc.line} | ${loc.lineText}`;
90
+ if (loc.column != null) {
91
+ message += `\n ${" ".repeat(String(loc.line).length)} | ${" ".repeat(loc.column)}^`;
92
+ }
93
+ }
94
+ return {
95
+ title: "Build Error",
96
+ message,
97
+ file: loc?.file,
98
+ line: loc?.line,
99
+ column: loc?.column,
100
+ };
101
+ }
102
+
103
+ if (raw instanceof Error) {
104
+ const loc = extractLocation(raw.stack);
105
+ const isTranspile =
106
+ raw.message.includes("Transform failed") ||
107
+ raw.message.includes("Parse error");
108
+ return {
109
+ title: isTranspile ? "Transpilation Error" : "Build Error",
110
+ message: raw.message,
111
+ stack: raw.stack,
112
+ ...loc,
113
+ };
114
+ }
115
+
116
+ return {
117
+ title: "Build Error",
118
+ message: String(raw),
119
+ };
120
+ }
121
+
122
+ function parseRuntimeError(raw: unknown): Partial<ContainerError> {
123
+ if (raw instanceof Error) {
124
+ const errorType = raw.constructor.name;
125
+ const loc = extractLocation(raw.stack);
126
+ return {
127
+ title: RUNTIME_ERROR_TITLES[errorType] || "Runtime Error",
128
+ message: raw.message,
129
+ stack: raw.stack,
130
+ ...loc,
131
+ };
132
+ }
133
+
134
+ if (raw && typeof raw === "object" && "message" in raw) {
135
+ const err = raw as {
136
+ message: string;
137
+ name?: string;
138
+ stack?: string;
139
+ filename?: string;
140
+ lineno?: number;
141
+ colno?: number;
142
+ };
143
+ const loc = err.filename
144
+ ? { file: err.filename, line: err.lineno, column: err.colno }
145
+ : extractLocation(err.stack);
146
+ return {
147
+ title: RUNTIME_ERROR_TITLES[err.name || ""] || "Runtime Error",
148
+ message: err.message,
149
+ stack: err.stack,
150
+ ...loc,
151
+ };
152
+ }
153
+
154
+ return {
155
+ title: "Runtime Error",
156
+ message: String(raw),
157
+ };
158
+ }
159
+
160
+ function parseBundleError(raw: unknown): Partial<ContainerError> {
161
+ if (raw && typeof raw === "object" && "packageName" in raw) {
162
+ const err = raw as BundleError;
163
+ return {
164
+ title: "Bundle Error",
165
+ message: `Failed to bundle "${err.packageName}": ${err.message}`,
166
+ };
167
+ }
168
+
169
+ if (raw instanceof Error) {
170
+ const pkgMatch = raw.message.match(/Cannot resolve package "([^"]+)"/);
171
+ return {
172
+ title: pkgMatch ? `Cannot resolve "${pkgMatch[1]}"` : "Bundle Error",
173
+ message: raw.message,
174
+ stack: raw.stack,
175
+ };
176
+ }
177
+
178
+ return {
179
+ title: "Bundle Error",
180
+ message: String(raw),
181
+ };
182
+ }
183
+
184
+ function parseInstallError(raw: unknown): Partial<ContainerError> {
185
+ if (raw instanceof Error) {
186
+ const versionMatch = raw.message.match(/No matching version for (.+)/);
187
+ const notFoundMatch = raw.message.match(/Version (.+?) not found for (.+)/);
188
+
189
+ let title = "Install Error";
190
+ if (versionMatch) title = `No matching version: ${versionMatch[1]}`;
191
+ else if (notFoundMatch)
192
+ title = `Version not found: ${notFoundMatch[2]}@${notFoundMatch[1]}`;
193
+ else if (raw.message.includes("fetch")) title = "Network Error";
194
+
195
+ return {
196
+ title,
197
+ message: raw.message,
198
+ stack: raw.stack,
199
+ };
200
+ }
201
+
202
+ return {
203
+ title: "Install Error",
204
+ message: String(raw),
205
+ };
206
+ }
207
+
208
+ function parseFilesystemError(raw: unknown): Partial<ContainerError> {
209
+ const nodeErr = raw as Partial<NodeError>;
210
+ if (nodeErr && typeof nodeErr === "object" && nodeErr.code) {
211
+ const friendly = FRIENDLY_FS_CODES[nodeErr.code] || nodeErr.code;
212
+ return {
213
+ title: friendly,
214
+ message: nodeErr.path
215
+ ? `${friendly}: ${nodeErr.path}`
216
+ : nodeErr.message || friendly,
217
+ file: nodeErr.path,
218
+ };
219
+ }
220
+
221
+ if (raw instanceof Error) {
222
+ return {
223
+ title: "Filesystem Error",
224
+ message: raw.message,
225
+ stack: raw.stack,
226
+ };
227
+ }
228
+
229
+ return {
230
+ title: "Filesystem Error",
231
+ message: String(raw),
232
+ };
233
+ }
234
+
235
+ const PARSERS: Record<
236
+ ErrorCategory,
237
+ (raw: unknown) => Partial<ContainerError>
238
+ > = {
239
+ build: parseBuildError,
240
+ runtime: parseRuntimeError,
241
+ bundle: parseBundleError,
242
+ install: parseInstallError,
243
+ filesystem: parseFilesystemError,
244
+ };
245
+
246
+ /**
247
+ * Generate actionable fix suggestions based on the error message.
248
+ */
249
+ function generateSuggestions(
250
+ category: ErrorCategory,
251
+ message: string,
252
+ ): string[] {
253
+ const suggestions: string[] = [];
254
+ const msg = message.toLowerCase();
255
+
256
+ // "Cannot find module 'X'" → suggest npm install
257
+ const cannotFindModule = message.match(/Cannot find module ['"]([^'"]+)['"]/);
258
+ if (cannotFindModule) {
259
+ const mod = cannotFindModule[1];
260
+ if (!mod.startsWith(".") && !mod.startsWith("/")) {
261
+ const pkg =
262
+ mod.includes("/") && mod.startsWith("@")
263
+ ? mod.split("/").slice(0, 2).join("/")
264
+ : mod.split("/")[0];
265
+ suggestions.push(`Run: npm install ${pkg}`);
266
+ } else {
267
+ suggestions.push(`Check that the file "${mod}" exists`);
268
+ }
269
+ }
270
+
271
+ // "X is not defined" → suggest import
272
+ const notDefined = message.match(/(\w+) is not defined/);
273
+ if (notDefined && category === "runtime") {
274
+ const name = notDefined[1];
275
+ if (/^[A-Z]/.test(name)) {
276
+ suggestions.push(`Did you forget to import ${name}?`);
277
+ }
278
+ }
279
+
280
+ // Transpiler not initialized
281
+ if (msg.includes("transpiler not initialized")) {
282
+ suggestions.push(
283
+ "Call await container.init() before running TypeScript files",
284
+ );
285
+ }
286
+
287
+ // File not pre-transpiled
288
+ if (msg.includes("has not been pre-transpiled")) {
289
+ suggestions.push(
290
+ "Call await container.init() to initialize the transpiler",
291
+ );
292
+ suggestions.push("Or use kernel.prepareFile() to pre-transpile the file");
293
+ }
294
+
295
+ // JSON parse errors
296
+ if (msg.includes("unexpected token") && msg.includes("json")) {
297
+ suggestions.push(
298
+ "Check the JSON file for syntax errors (trailing commas, missing quotes)",
299
+ );
300
+ }
301
+
302
+ // Network/fetch errors during install
303
+ if (
304
+ category === "install" &&
305
+ (msg.includes("fetch") || msg.includes("network"))
306
+ ) {
307
+ suggestions.push("Check your internet connection");
308
+ suggestions.push("The npm registry may be temporarily unavailable");
309
+ }
310
+
311
+ // Version not found
312
+ if (msg.includes("version") && msg.includes("not found")) {
313
+ suggestions.push(
314
+ "Check that the version exists: npm view <package> versions",
315
+ );
316
+ suggestions.push('Try using "latest" instead of a specific version');
317
+ }
318
+
319
+ // Sandbox errors
320
+ if (msg.includes("[sandbox]")) {
321
+ if (msg.includes("read-only")) {
322
+ suggestions.push(
323
+ "The container is in read-only mode — remove sandbox.fs.readOnly to allow writes",
324
+ );
325
+ }
326
+ if (msg.includes("outside allowed paths")) {
327
+ suggestions.push("Add the path to sandbox.fs.allowedPaths");
328
+ }
329
+ if (msg.includes("file count limit")) {
330
+ suggestions.push(
331
+ "Increase sandbox.limits.maxFileCount or clear unused files",
332
+ );
333
+ }
334
+ if (msg.includes("memory limit")) {
335
+ suggestions.push(
336
+ "Increase sandbox.limits.maxMemoryMB or remove large files",
337
+ );
338
+ }
339
+ }
340
+
341
+ return suggestions;
342
+ }
343
+
344
+ export function parseError(
345
+ category: ErrorCategory,
346
+ raw: unknown,
347
+ ): ContainerError {
348
+ const parsed = PARSERS[category](raw);
349
+ const message = parsed.message || String(raw);
350
+ return {
351
+ id: uid(),
352
+ category,
353
+ title: parsed.title || "Error",
354
+ message,
355
+ file: parsed.file,
356
+ line: parsed.line,
357
+ column: parsed.column,
358
+ stack: parsed.stack,
359
+ timestamp: Date.now(),
360
+ raw,
361
+ suggestions: generateSuggestions(category, message),
362
+ };
363
+ }
364
+
365
+ export function formatErrorText(error: ContainerError): string {
366
+ const parts: string[] = [];
367
+
368
+ const tag = `[${error.category.toUpperCase()}]`;
369
+ parts.push(`${tag} ${error.title}`);
370
+
371
+ if (error.file) {
372
+ let loc = error.file;
373
+ if (error.line != null) {
374
+ loc += `:${error.line}`;
375
+ if (error.column != null) loc += `:${error.column}`;
376
+ }
377
+ parts.push(` at ${loc}`);
378
+ }
379
+
380
+ parts.push("");
381
+ parts.push(error.message);
382
+
383
+ if (error.suggestions && error.suggestions.length > 0) {
384
+ parts.push("");
385
+ parts.push("Suggestions:");
386
+ for (const s of error.suggestions) {
387
+ parts.push(` - ${s}`);
388
+ }
389
+ }
390
+
391
+ if (error.stack) {
392
+ parts.push("");
393
+ parts.push(error.stack);
394
+ }
395
+
396
+ return parts.join("\n");
397
+ }
398
+
399
+ export function formatErrorHtml(error: ContainerError): string {
400
+ const esc = (s: string) =>
401
+ s
402
+ .replace(/&/g, "&amp;")
403
+ .replace(/</g, "&lt;")
404
+ .replace(/>/g, "&gt;")
405
+ .replace(/`/g, "&#96;");
406
+
407
+ let loc = "";
408
+ if (error.file) {
409
+ loc = esc(error.file);
410
+ if (error.line != null) {
411
+ loc += `:${error.line}`;
412
+ if (error.column != null) loc += `:${error.column}`;
413
+ }
414
+ loc = `<div style="font-size:11px;color:#fca5a5;margin-top:4px;">${loc}</div>`;
415
+ }
416
+
417
+ let stack = "";
418
+ if (error.stack) {
419
+ stack = `<pre style="font-size:11px;color:#a1a1aa;margin-top:8px;white-space:pre-wrap;max-height:120px;overflow:auto;">${esc(error.stack)}</pre>`;
420
+ }
421
+
422
+ return `<div style="
423
+ font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
424
+ background: #1c1017;
425
+ border: 1px solid #7f1d1d;
426
+ border-radius: 8px;
427
+ padding: 12px 16px;
428
+ color: #fecaca;
429
+ max-width: 480px;
430
+ ">
431
+ <div style="font-weight:600;font-size:13px;color:#fca5a5;">
432
+ ${esc(error.title)}
433
+ </div>
434
+ <div style="font-size:12px;margin-top:6px;color:#e4e4e7;line-height:1.4;">
435
+ ${esc(error.message)}
436
+ </div>
437
+ ${loc}${stack}
438
+ </div>`;
439
+ }
440
+
441
+ export function errorOverlayScript(): string {
442
+ function overlayIIFE() {
443
+ var overlay: HTMLDivElement | null = null;
444
+ var errors: Array<{
445
+ title?: string;
446
+ message: string;
447
+ file?: string | null;
448
+ line?: number | null;
449
+ column?: number | null;
450
+ stack?: string | null;
451
+ }> = [];
452
+
453
+ function esc(s: string) {
454
+ return String(s)
455
+ .replace(/&/g, "&amp;")
456
+ .replace(/</g, "&lt;")
457
+ .replace(/>/g, "&gt;")
458
+ .replace(/`/g, "&#96;");
459
+ }
460
+
461
+ function dismiss() {
462
+ if (overlay) {
463
+ overlay.remove();
464
+ overlay = null;
465
+ }
466
+ }
467
+
468
+ function render() {
469
+ if (errors.length === 0) {
470
+ dismiss();
471
+ return;
472
+ }
473
+
474
+ if (!overlay) {
475
+ overlay = document.createElement("div");
476
+ overlay.id = "__jiki_error_overlay";
477
+ overlay.style.cssText = [
478
+ "position:fixed",
479
+ "bottom:12px",
480
+ "right:12px",
481
+ "z-index:2147483647",
482
+ "max-width:420px",
483
+ "max-height:260px",
484
+ "overflow:auto",
485
+ "font-family:ui-monospace,SFMono-Regular,Menlo,monospace",
486
+ "background:rgba(24,8,14,0.95)",
487
+ "border:1px solid #991b1b",
488
+ "border-radius:10px",
489
+ "padding:10px 14px",
490
+ "color:#fecaca",
491
+ "font-size:12px",
492
+ "line-height:1.4",
493
+ "box-shadow:0 8px 32px rgba(0,0,0,0.5)",
494
+ "backdrop-filter:blur(8px)",
495
+ ].join(";");
496
+ document.body.appendChild(overlay);
497
+ }
498
+
499
+ var last = errors[errors.length - 1];
500
+
501
+ var badge = errors.length > 1 ? " (" + errors.length + ")" : "";
502
+
503
+ var loc = "";
504
+ if (last.file) {
505
+ loc = esc(last.file);
506
+ if (last.line != null) loc += ":" + last.line;
507
+ if (last.column != null) loc += ":" + last.column;
508
+ }
509
+
510
+ var header = document.createElement("div");
511
+ header.style.cssText =
512
+ "display:flex;align-items:center;justify-content:space-between;";
513
+
514
+ var titleEl = document.createElement("div");
515
+ titleEl.style.cssText = "font-weight:600;font-size:12px;color:#fca5a5;";
516
+ titleEl.textContent = (last.title || "Error") + badge;
517
+
518
+ var closeBtn = document.createElement("button");
519
+ closeBtn.style.cssText =
520
+ "background:none;border:none;color:#a1a1aa;cursor:pointer;" +
521
+ "font-size:16px;padding:0 0 0 8px;line-height:1;";
522
+ closeBtn.innerHTML = "&times;";
523
+ closeBtn.addEventListener("click", function () {
524
+ errors = [];
525
+ dismiss();
526
+ });
527
+
528
+ header.appendChild(titleEl);
529
+ header.appendChild(closeBtn);
530
+
531
+ var msgEl = document.createElement("div");
532
+ msgEl.style.cssText =
533
+ "font-size:11px;color:#e4e4e7;margin-top:4px;word-break:break-word;";
534
+ msgEl.textContent = last.message;
535
+
536
+ overlay.innerHTML = "";
537
+ overlay.appendChild(header);
538
+ overlay.appendChild(msgEl);
539
+
540
+ if (loc) {
541
+ var locEl = document.createElement("div");
542
+ locEl.style.cssText = "font-size:10px;color:#fca5a5;margin-top:2px;";
543
+ locEl.textContent = loc;
544
+ overlay.appendChild(locEl);
545
+ }
546
+ }
547
+
548
+ function pushError(data: (typeof errors)[number]) {
549
+ errors.push(data);
550
+ render();
551
+ try {
552
+ window.parent.postMessage(
553
+ {
554
+ type: "__jiki_error",
555
+ error: {
556
+ message: data.message,
557
+ title: data.title,
558
+ file: data.file || null,
559
+ line: data.line || null,
560
+ column: data.column || null,
561
+ stack: data.stack || null,
562
+ },
563
+ },
564
+ "*",
565
+ );
566
+ } catch (_e) {
567
+ /* cross-origin */
568
+ }
569
+ }
570
+
571
+ window.addEventListener("error", function (event: ErrorEvent) {
572
+ var error = event.error;
573
+ var name =
574
+ (error && error.constructor && error.constructor.name) || "Error";
575
+ pushError({
576
+ title:
577
+ name === "Error"
578
+ ? "Runtime Error"
579
+ : name.replace(/([a-z])([A-Z])/g, "$1 $2"),
580
+ message: error ? error.message : event.message || "Unknown error",
581
+ file: event.filename || null,
582
+ line: event.lineno || null,
583
+ column: event.colno || null,
584
+ stack: error && error.stack ? error.stack : null,
585
+ });
586
+ });
587
+
588
+ window.addEventListener(
589
+ "unhandledrejection",
590
+ function (event: PromiseRejectionEvent) {
591
+ var reason = event.reason;
592
+ var msg = reason instanceof Error ? reason.message : String(reason);
593
+ var stack = reason instanceof Error ? reason.stack : null;
594
+ pushError({
595
+ title: "Unhandled Promise Rejection",
596
+ message: msg,
597
+ stack: stack,
598
+ });
599
+ },
600
+ );
601
+ }
602
+
603
+ return "<script>(" + overlayIIFE.toString() + ")()</script>";
604
+ }