round-core 0.1.2 → 0.1.3
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 +13 -8
- package/src/cli.js +609 -0
- package/src/compiler/index.js +2 -0
- package/src/compiler/transformer.js +525 -0
- package/src/compiler/vite-plugin.d.ts +8 -0
- package/src/compiler/vite-plugin.js +472 -0
- package/src/index.js +42 -0
- package/src/runtime/context.js +101 -0
- package/src/runtime/dom.js +401 -0
- package/src/runtime/error-boundary.js +48 -0
- package/src/runtime/error-reporter.js +13 -0
- package/src/runtime/error-store.js +85 -0
- package/src/runtime/errors.js +152 -0
- package/src/runtime/lifecycle.js +140 -0
- package/src/runtime/router.js +475 -0
- package/src/runtime/signals.js +484 -0
- package/src/runtime/store.js +215 -0
- package/src/runtime/suspense.js +128 -0
- package/dist/cli.js +0 -607
- package/dist/index.js +0 -2071
- package/dist/vite-plugin.js +0 -883
- /package/{dist → src}/index.d.ts +0 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { createElement } from './dom.js';
|
|
2
|
+
import { clearErrors, useErrors, reportError } from './error-store.js';
|
|
3
|
+
|
|
4
|
+
export { reportError } from './error-store.js';
|
|
5
|
+
|
|
6
|
+
export function ErrorProvider(props = {}) {
|
|
7
|
+
return createElement('span', { style: { display: 'contents' } }, () => {
|
|
8
|
+
const list = useErrors()();
|
|
9
|
+
if (!Array.isArray(list) || list.length === 0) return props.children ?? null;
|
|
10
|
+
|
|
11
|
+
const first = list[0];
|
|
12
|
+
|
|
13
|
+
return createElement(
|
|
14
|
+
'div',
|
|
15
|
+
{
|
|
16
|
+
style: {
|
|
17
|
+
position: 'fixed',
|
|
18
|
+
inset: '0',
|
|
19
|
+
zIndex: 2147483647,
|
|
20
|
+
display: 'flex',
|
|
21
|
+
alignItems: 'center',
|
|
22
|
+
justifyContent: 'center',
|
|
23
|
+
padding: '24px',
|
|
24
|
+
background: 'rgba(17, 24, 39, 0.72)',
|
|
25
|
+
backdropFilter: 'blur(10px)',
|
|
26
|
+
WebkitBackdropFilter: 'blur(10px)'
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
createElement(
|
|
30
|
+
'div',
|
|
31
|
+
{
|
|
32
|
+
style: {
|
|
33
|
+
width: 'min(900px, 100%)',
|
|
34
|
+
borderRadius: '14px',
|
|
35
|
+
border: '1px solid rgba(255,255,255,0.12)',
|
|
36
|
+
background: 'rgba(0,0,0,0.55)',
|
|
37
|
+
boxShadow: '0 30px 80px rgba(0,0,0,0.55)',
|
|
38
|
+
color: '#fff',
|
|
39
|
+
overflow: 'hidden'
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
createElement(
|
|
43
|
+
'div',
|
|
44
|
+
{
|
|
45
|
+
style: {
|
|
46
|
+
padding: '14px 16px',
|
|
47
|
+
display: 'flex',
|
|
48
|
+
alignItems: 'center',
|
|
49
|
+
gap: '10px',
|
|
50
|
+
borderBottom: '1px solid rgba(255,255,255,0.10)',
|
|
51
|
+
background: 'linear-gradient(180deg, rgba(255,255,255,0.06), rgba(255,255,255,0))'
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
createElement('div', {
|
|
55
|
+
style: {
|
|
56
|
+
width: '10px',
|
|
57
|
+
height: '10px',
|
|
58
|
+
borderRadius: '999px',
|
|
59
|
+
background: '#ef4444',
|
|
60
|
+
boxShadow: '0 0 0 4px rgba(239,68,68,0.18)'
|
|
61
|
+
}
|
|
62
|
+
}),
|
|
63
|
+
createElement('strong', { style: { fontFamily: 'ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial' } }, 'Round Error'),
|
|
64
|
+
createElement('span', { style: { opacity: 0.75, fontFamily: 'ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Arial', fontSize: '12px' } }, new Date(first.time).toLocaleString()),
|
|
65
|
+
createElement('button', {
|
|
66
|
+
style: {
|
|
67
|
+
marginLeft: 'auto',
|
|
68
|
+
border: '1px solid rgba(255,255,255,0.16)',
|
|
69
|
+
background: 'rgba(255,255,255,0.08)',
|
|
70
|
+
color: '#fff',
|
|
71
|
+
padding: '8px 10px',
|
|
72
|
+
borderRadius: '10px',
|
|
73
|
+
cursor: 'pointer'
|
|
74
|
+
},
|
|
75
|
+
onMouseOver: (e) => { try { e.currentTarget.style.background = 'rgba(255,255,255,0.12)'; } catch { } },
|
|
76
|
+
onMouseOut: (e) => { try { e.currentTarget.style.background = 'rgba(255,255,255,0.08)'; } catch { } },
|
|
77
|
+
onClick: () => clearErrors()
|
|
78
|
+
}, 'Dismiss')
|
|
79
|
+
),
|
|
80
|
+
createElement(
|
|
81
|
+
'div',
|
|
82
|
+
{
|
|
83
|
+
style: {
|
|
84
|
+
padding: '16px',
|
|
85
|
+
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
createElement('div', { style: { fontSize: '14px', fontWeight: '700' } }, String(first.message ?? 'Error')),
|
|
89
|
+
createElement(
|
|
90
|
+
'div',
|
|
91
|
+
{ style: { marginTop: '10px', opacity: 0.85, fontSize: '12px', lineHeight: '18px' } },
|
|
92
|
+
first.component ? createElement('div', null, createElement('span', { style: { opacity: 0.75 } }, 'Component: '), String(first.component)) : null,
|
|
93
|
+
first.phase ? createElement('div', null, createElement('span', { style: { opacity: 0.75 } }, 'Phase: '), String(first.phase)) : null
|
|
94
|
+
),
|
|
95
|
+
first.stack
|
|
96
|
+
? createElement('pre', {
|
|
97
|
+
style: {
|
|
98
|
+
marginTop: '12px',
|
|
99
|
+
padding: '12px',
|
|
100
|
+
borderRadius: '12px',
|
|
101
|
+
background: 'rgba(0,0,0,0.55)',
|
|
102
|
+
border: '1px solid rgba(255,255,255,0.10)',
|
|
103
|
+
whiteSpace: 'pre-wrap',
|
|
104
|
+
fontSize: '12px',
|
|
105
|
+
lineHeight: '18px',
|
|
106
|
+
overflow: 'auto',
|
|
107
|
+
maxHeight: '55vh'
|
|
108
|
+
}
|
|
109
|
+
}, String(first.stack))
|
|
110
|
+
: null
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function initErrorHandling(container) {
|
|
118
|
+
if (typeof document === 'undefined') return;
|
|
119
|
+
if (!container || !(container instanceof Element)) return;
|
|
120
|
+
|
|
121
|
+
if (!document.querySelector('[data-round-error-style="1"]')) {
|
|
122
|
+
const style = document.createElement('style');
|
|
123
|
+
style.setAttribute('data-round-error-style', '1');
|
|
124
|
+
style.textContent = `
|
|
125
|
+
[data-round-error-root="1"] pre{scrollbar-width:thin;scrollbar-color:rgba(255,255,255,0.28) rgba(255,255,255,0.06);}
|
|
126
|
+
[data-round-error-root="1"] pre::-webkit-scrollbar{width:10px;height:10px;}
|
|
127
|
+
[data-round-error-root="1"] pre::-webkit-scrollbar-track{background:rgba(255,255,255,0.06);border-radius:999px;}
|
|
128
|
+
[data-round-error-root="1"] pre::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.22);border-radius:999px;border:2px solid rgba(0,0,0,0.35);}
|
|
129
|
+
[data-round-error-root="1"] pre::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,0.32);}
|
|
130
|
+
`.trim();
|
|
131
|
+
document.head.appendChild(style);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!document.querySelector('[data-round-error-root="1"]')) {
|
|
135
|
+
const root = document.createElement('div');
|
|
136
|
+
root.setAttribute('data-round-error-root', '1');
|
|
137
|
+
container.appendChild(root);
|
|
138
|
+
root.appendChild(createElement(ErrorProvider, null));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!window.__round_error_handlers_installed) {
|
|
142
|
+
window.__round_error_handlers_installed = true;
|
|
143
|
+
|
|
144
|
+
window.addEventListener('error', (e) => {
|
|
145
|
+
reportError(e?.error ?? e?.message ?? e, { phase: 'window.error' });
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
window.addEventListener('unhandledrejection', (e) => {
|
|
149
|
+
reportError(e?.reason ?? e, { phase: 'window.unhandledrejection' });
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { reportErrorSafe } from './error-reporter.js';
|
|
2
|
+
|
|
3
|
+
const componentStack = [];
|
|
4
|
+
|
|
5
|
+
export function getCurrentComponent() {
|
|
6
|
+
return componentStack[componentStack.length - 1];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function runInLifecycle(componentInstance, fn) {
|
|
10
|
+
componentStack.push(componentInstance);
|
|
11
|
+
try {
|
|
12
|
+
return fn();
|
|
13
|
+
} finally {
|
|
14
|
+
componentStack.pop();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function createComponentInstance() {
|
|
19
|
+
return {
|
|
20
|
+
mountHooks: [],
|
|
21
|
+
unmountHooks: [],
|
|
22
|
+
updateHooks: [],
|
|
23
|
+
nodes: [],
|
|
24
|
+
isMounted: false,
|
|
25
|
+
mountTimerId: null
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function onMount(fn) {
|
|
30
|
+
const component = getCurrentComponent();
|
|
31
|
+
if (component) {
|
|
32
|
+
component.mountHooks.push(fn);
|
|
33
|
+
} else {
|
|
34
|
+
try {
|
|
35
|
+
fn();
|
|
36
|
+
} catch (e) {
|
|
37
|
+
reportErrorSafe(e, { phase: 'onMount' });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function onUnmount(fn) {
|
|
43
|
+
const component = getCurrentComponent();
|
|
44
|
+
if (component) {
|
|
45
|
+
component.unmountHooks.push(fn);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const onCleanup = onUnmount;
|
|
50
|
+
|
|
51
|
+
export function onUpdate(fn) {
|
|
52
|
+
const component = getCurrentComponent();
|
|
53
|
+
if (component) {
|
|
54
|
+
component.updateHooks.push(fn);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function mountComponent(component) {
|
|
59
|
+
if (component.isMounted) return;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const root = component?.nodes?.[0];
|
|
63
|
+
if (root && root instanceof Node && root.isConnected === false) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
component.isMounted = true;
|
|
70
|
+
component.mountHooks.forEach(hook => {
|
|
71
|
+
try {
|
|
72
|
+
const cleanup = hook();
|
|
73
|
+
if (typeof cleanup === 'function') {
|
|
74
|
+
component.unmountHooks.push(cleanup);
|
|
75
|
+
}
|
|
76
|
+
} catch (e) {
|
|
77
|
+
reportErrorSafe(e, { phase: 'mount', component: component.name ?? null });
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function unmountComponent(component) {
|
|
83
|
+
if (!component.isMounted) return;
|
|
84
|
+
|
|
85
|
+
if (component.mountTimerId != null) {
|
|
86
|
+
try {
|
|
87
|
+
clearTimeout(component.mountTimerId);
|
|
88
|
+
} catch {
|
|
89
|
+
}
|
|
90
|
+
component.mountTimerId = null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
component.isMounted = false;
|
|
94
|
+
component.unmountHooks.forEach(hook => {
|
|
95
|
+
try {
|
|
96
|
+
hook();
|
|
97
|
+
} catch (e) {
|
|
98
|
+
reportErrorSafe(e, { phase: 'unmount', component: component.name ?? null });
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function triggerUpdate(component) {
|
|
104
|
+
if (!component.isMounted) return;
|
|
105
|
+
component.updateHooks.forEach(hook => {
|
|
106
|
+
try {
|
|
107
|
+
hook();
|
|
108
|
+
} catch (e) {
|
|
109
|
+
reportErrorSafe(e, { phase: 'update', component: component.name ?? null });
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const observer = (typeof MutationObserver !== 'undefined')
|
|
115
|
+
? new MutationObserver((mutations) => {
|
|
116
|
+
mutations.forEach(mutation => {
|
|
117
|
+
if (mutation.removedNodes.length > 0) {
|
|
118
|
+
mutation.removedNodes.forEach(node => {
|
|
119
|
+
if (node._componentInstance) {
|
|
120
|
+
unmountComponent(node._componentInstance);
|
|
121
|
+
}
|
|
122
|
+
cleanupNodeRecursively(node);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
})
|
|
127
|
+
: null;
|
|
128
|
+
|
|
129
|
+
function cleanupNodeRecursively(node) {
|
|
130
|
+
if (node._componentInstance) {
|
|
131
|
+
unmountComponent(node._componentInstance);
|
|
132
|
+
}
|
|
133
|
+
node.childNodes.forEach(cleanupNodeRecursively);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function initLifecycleRoot(rootNode) {
|
|
137
|
+
if (!rootNode) return;
|
|
138
|
+
if (!observer) return;
|
|
139
|
+
observer.observe(rootNode, { childList: true, subtree: true });
|
|
140
|
+
}
|