zero-query 1.1.1 → 1.2.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/LICENSE +21 -21
- package/README.md +2 -0
- package/cli/args.js +33 -33
- package/cli/commands/build-api.js +443 -442
- package/cli/commands/build.js +254 -247
- package/cli/commands/bundle.js +1228 -1224
- package/cli/commands/create.js +137 -121
- package/cli/commands/dev/devtools/index.js +56 -56
- package/cli/commands/dev/devtools/js/components.js +49 -49
- package/cli/commands/dev/devtools/js/core.js +423 -423
- package/cli/commands/dev/devtools/js/elements.js +421 -421
- package/cli/commands/dev/devtools/js/network.js +166 -166
- package/cli/commands/dev/devtools/js/performance.js +73 -73
- package/cli/commands/dev/devtools/js/router.js +105 -105
- package/cli/commands/dev/devtools/js/source.js +132 -132
- package/cli/commands/dev/devtools/js/stats.js +35 -35
- package/cli/commands/dev/devtools/js/tabs.js +79 -79
- package/cli/commands/dev/devtools/panel.html +95 -95
- package/cli/commands/dev/devtools/styles.css +244 -244
- package/cli/commands/dev/index.js +107 -107
- package/cli/commands/dev/logger.js +75 -75
- package/cli/commands/dev/overlay.js +858 -858
- package/cli/commands/dev/server.js +220 -220
- package/cli/commands/dev/validator.js +94 -94
- package/cli/commands/dev/watcher.js +172 -172
- package/cli/help.js +114 -112
- package/cli/index.js +52 -52
- package/cli/scaffold/default/LICENSE +21 -21
- package/cli/scaffold/default/app/app.js +207 -207
- package/cli/scaffold/default/app/components/about.js +201 -201
- package/cli/scaffold/default/app/components/api-demo.js +143 -143
- package/cli/scaffold/default/app/components/contact-card.js +231 -231
- package/cli/scaffold/default/app/components/contacts/contacts.css +706 -706
- package/cli/scaffold/default/app/components/contacts/contacts.html +200 -200
- package/cli/scaffold/default/app/components/contacts/contacts.js +196 -196
- package/cli/scaffold/default/app/components/counter.js +127 -127
- package/cli/scaffold/default/app/components/home.js +249 -249
- package/cli/scaffold/default/app/components/not-found.js +16 -16
- package/cli/scaffold/default/app/components/playground/playground.css +115 -115
- package/cli/scaffold/default/app/components/playground/playground.html +161 -161
- package/cli/scaffold/default/app/components/playground/playground.js +116 -116
- package/cli/scaffold/default/app/components/todos.js +225 -225
- package/cli/scaffold/default/app/components/toolkit/toolkit.css +97 -97
- package/cli/scaffold/default/app/components/toolkit/toolkit.html +146 -146
- package/cli/scaffold/default/app/components/toolkit/toolkit.js +280 -280
- package/cli/scaffold/default/app/routes.js +15 -15
- package/cli/scaffold/default/app/store.js +101 -101
- package/cli/scaffold/default/global.css +552 -552
- package/cli/scaffold/default/index.html +99 -99
- package/cli/scaffold/minimal/app/app.js +85 -85
- package/cli/scaffold/minimal/app/components/about.js +68 -68
- package/cli/scaffold/minimal/app/components/counter.js +122 -122
- package/cli/scaffold/minimal/app/components/home.js +68 -68
- package/cli/scaffold/minimal/app/components/not-found.js +16 -16
- package/cli/scaffold/minimal/app/routes.js +9 -9
- package/cli/scaffold/minimal/app/store.js +36 -36
- package/cli/scaffold/minimal/global.css +300 -300
- package/cli/scaffold/minimal/index.html +44 -44
- package/cli/scaffold/ssr/app/app.js +41 -41
- package/cli/scaffold/ssr/app/components/about.js +55 -55
- package/cli/scaffold/ssr/app/components/blog/index.js +65 -65
- package/cli/scaffold/ssr/app/components/blog/post.js +86 -86
- package/cli/scaffold/ssr/app/components/home.js +37 -37
- package/cli/scaffold/ssr/app/components/not-found.js +15 -15
- package/cli/scaffold/ssr/app/routes.js +8 -8
- package/cli/scaffold/ssr/global.css +228 -228
- package/cli/scaffold/ssr/index.html +37 -37
- package/cli/scaffold/ssr/package.json +8 -8
- package/cli/scaffold/ssr/server/data/posts.js +144 -144
- package/cli/scaffold/ssr/server/index.js +213 -213
- package/cli/scaffold/webrtc/app/app.js +11 -0
- package/cli/scaffold/webrtc/app/components/video-room.js +295 -0
- package/cli/scaffold/webrtc/app/lib/room.js +252 -0
- package/cli/scaffold/webrtc/assets/.gitkeep +0 -0
- package/cli/scaffold/webrtc/global.css +250 -0
- package/cli/scaffold/webrtc/index.html +21 -0
- package/cli/utils.js +305 -287
- package/dist/API.md +661 -0
- package/dist/zquery.dist.zip +0 -0
- package/dist/zquery.js +10313 -6614
- package/dist/zquery.min.js +8 -631
- package/index.d.ts +570 -371
- package/index.js +311 -240
- package/package.json +76 -70
- package/src/component.js +1709 -1691
- package/src/core.js +921 -921
- package/src/diff.js +497 -497
- package/src/errors.js +209 -209
- package/src/expression.js +922 -922
- package/src/http.js +242 -242
- package/src/package.json +1 -1
- package/src/reactive.js +255 -255
- package/src/router.js +843 -843
- package/src/ssr.js +418 -418
- package/src/store.js +318 -318
- package/src/utils.js +515 -515
- package/src/webrtc/e2ee.js +351 -0
- package/src/webrtc/errors.js +116 -0
- package/src/webrtc/ice.js +301 -0
- package/src/webrtc/index.js +131 -0
- package/src/webrtc/joinToken.js +119 -0
- package/src/webrtc/observe.js +172 -0
- package/src/webrtc/peer.js +351 -0
- package/src/webrtc/reactive.js +268 -0
- package/src/webrtc/room.js +625 -0
- package/src/webrtc/sdp.js +302 -0
- package/src/webrtc/sfu/index.js +43 -0
- package/src/webrtc/sfu/livekit.js +131 -0
- package/src/webrtc/sfu/mediasoup.js +150 -0
- package/src/webrtc/signaling.js +373 -0
- package/src/webrtc/turn.js +237 -0
- package/tests/_helpers/webrtcFakes.js +289 -0
- package/tests/audit.test.js +4158 -4158
- package/tests/cli.test.js +1136 -1103
- package/tests/compare.test.js +497 -486
- package/tests/component.test.js +3969 -3938
- package/tests/core.test.js +1910 -1910
- package/tests/dev-server.test.js +489 -489
- package/tests/diff.test.js +1416 -1416
- package/tests/docs.test.js +1664 -1650
- package/tests/electron-features.test.js +864 -864
- package/tests/errors.test.js +619 -619
- package/tests/expression.test.js +1056 -1056
- package/tests/http.test.js +648 -648
- package/tests/reactive.test.js +819 -819
- package/tests/router.test.js +2327 -2327
- package/tests/ssr.test.js +870 -870
- package/tests/store.test.js +830 -830
- package/tests/test-minifier.js +153 -153
- package/tests/test-ssr.js +27 -27
- package/tests/utils.test.js +1377 -1377
- package/tests/webrtc/e2ee.test.js +283 -0
- package/tests/webrtc/ice.test.js +202 -0
- package/tests/webrtc/joinToken.test.js +89 -0
- package/tests/webrtc/observe.test.js +111 -0
- package/tests/webrtc/peer.test.js +373 -0
- package/tests/webrtc/reactive.test.js +235 -0
- package/tests/webrtc/room.test.js +406 -0
- package/tests/webrtc/sdp.test.js +151 -0
- package/tests/webrtc/sfu-livekit.test.js +119 -0
- package/tests/webrtc/sfu.test.js +160 -0
- package/tests/webrtc/signaling.test.js +251 -0
- package/tests/webrtc/turn.test.js +256 -0
- package/types/collection.d.ts +383 -383
- package/types/component.d.ts +186 -186
- package/types/errors.d.ts +135 -135
- package/types/http.d.ts +92 -92
- package/types/misc.d.ts +201 -201
- package/types/reactive.d.ts +98 -98
- package/types/router.d.ts +190 -190
- package/types/ssr.d.ts +102 -102
- package/types/store.d.ts +146 -146
- package/types/utils.d.ts +245 -245
- package/types/webrtc.d.ts +653 -0
package/src/errors.js
CHANGED
|
@@ -1,209 +1,209 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* zQuery Errors - Structured error handling system
|
|
3
|
-
*
|
|
4
|
-
* Provides typed error classes and a configurable error handler so that
|
|
5
|
-
* errors surface consistently across all modules (reactive, component,
|
|
6
|
-
* router, store, expression parser, HTTP, etc.).
|
|
7
|
-
*
|
|
8
|
-
* Default behaviour: errors are logged via console.warn/error.
|
|
9
|
-
* Users can override with $.onError(handler) to integrate with their
|
|
10
|
-
* own logging, crash-reporting, or UI notification system.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
// Error codes - every zQuery error has a unique code for programmatic use
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
export const ErrorCode = Object.freeze({
|
|
17
|
-
// Reactive
|
|
18
|
-
REACTIVE_CALLBACK: 'ZQ_REACTIVE_CALLBACK',
|
|
19
|
-
SIGNAL_CALLBACK: 'ZQ_SIGNAL_CALLBACK',
|
|
20
|
-
EFFECT_EXEC: 'ZQ_EFFECT_EXEC',
|
|
21
|
-
|
|
22
|
-
// Expression parser
|
|
23
|
-
EXPR_PARSE: 'ZQ_EXPR_PARSE',
|
|
24
|
-
EXPR_EVAL: 'ZQ_EXPR_EVAL',
|
|
25
|
-
EXPR_UNSAFE_ACCESS: 'ZQ_EXPR_UNSAFE_ACCESS',
|
|
26
|
-
|
|
27
|
-
// Component
|
|
28
|
-
COMP_INVALID_NAME: 'ZQ_COMP_INVALID_NAME',
|
|
29
|
-
COMP_NOT_FOUND: 'ZQ_COMP_NOT_FOUND',
|
|
30
|
-
COMP_MOUNT_TARGET: 'ZQ_COMP_MOUNT_TARGET',
|
|
31
|
-
COMP_RENDER: 'ZQ_COMP_RENDER',
|
|
32
|
-
COMP_LIFECYCLE: 'ZQ_COMP_LIFECYCLE',
|
|
33
|
-
COMP_RESOURCE: 'ZQ_COMP_RESOURCE',
|
|
34
|
-
COMP_DIRECTIVE: 'ZQ_COMP_DIRECTIVE',
|
|
35
|
-
|
|
36
|
-
// Router
|
|
37
|
-
ROUTER_LOAD: 'ZQ_ROUTER_LOAD',
|
|
38
|
-
ROUTER_GUARD: 'ZQ_ROUTER_GUARD',
|
|
39
|
-
ROUTER_RESOLVE: 'ZQ_ROUTER_RESOLVE',
|
|
40
|
-
|
|
41
|
-
// Store
|
|
42
|
-
STORE_ACTION: 'ZQ_STORE_ACTION',
|
|
43
|
-
STORE_MIDDLEWARE: 'ZQ_STORE_MIDDLEWARE',
|
|
44
|
-
STORE_SUBSCRIBE: 'ZQ_STORE_SUBSCRIBE',
|
|
45
|
-
|
|
46
|
-
// HTTP
|
|
47
|
-
HTTP_REQUEST: 'ZQ_HTTP_REQUEST',
|
|
48
|
-
HTTP_TIMEOUT: 'ZQ_HTTP_TIMEOUT',
|
|
49
|
-
HTTP_INTERCEPTOR: 'ZQ_HTTP_INTERCEPTOR',
|
|
50
|
-
HTTP_PARSE: 'ZQ_HTTP_PARSE',
|
|
51
|
-
|
|
52
|
-
// SSR
|
|
53
|
-
SSR_RENDER: 'ZQ_SSR_RENDER',
|
|
54
|
-
SSR_COMPONENT: 'ZQ_SSR_COMPONENT',
|
|
55
|
-
SSR_HYDRATION: 'ZQ_SSR_HYDRATION',
|
|
56
|
-
SSR_PAGE: 'ZQ_SSR_PAGE',
|
|
57
|
-
|
|
58
|
-
// General
|
|
59
|
-
INVALID_ARGUMENT: 'ZQ_INVALID_ARGUMENT',
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
// ---------------------------------------------------------------------------
|
|
64
|
-
// ZQueryError - custom error class
|
|
65
|
-
// ---------------------------------------------------------------------------
|
|
66
|
-
export class ZQueryError extends Error {
|
|
67
|
-
/**
|
|
68
|
-
* @param {string} code - one of ErrorCode values
|
|
69
|
-
* @param {string} message - human-readable description
|
|
70
|
-
* @param {object} [context] - extra data (component name, expression, etc.)
|
|
71
|
-
* @param {Error} [cause] - original error
|
|
72
|
-
*/
|
|
73
|
-
constructor(code, message, context = {}, cause) {
|
|
74
|
-
super(message);
|
|
75
|
-
this.name = 'ZQueryError';
|
|
76
|
-
this.code = code;
|
|
77
|
-
this.context = context;
|
|
78
|
-
if (cause) this.cause = cause;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// ---------------------------------------------------------------------------
|
|
84
|
-
// Global error handler
|
|
85
|
-
// ---------------------------------------------------------------------------
|
|
86
|
-
let _errorHandlers = [];
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Register a global error handler.
|
|
90
|
-
* Called whenever zQuery catches an error internally.
|
|
91
|
-
* Multiple handlers are supported - each receives the error.
|
|
92
|
-
* Pass `null` to clear all handlers.
|
|
93
|
-
*
|
|
94
|
-
* @param {Function|null} handler - (error: ZQueryError) => void
|
|
95
|
-
* @returns {Function} unsubscribe function to remove this handler
|
|
96
|
-
*/
|
|
97
|
-
export function onError(handler) {
|
|
98
|
-
if (handler === null) {
|
|
99
|
-
_errorHandlers = [];
|
|
100
|
-
return () => {};
|
|
101
|
-
}
|
|
102
|
-
if (typeof handler !== 'function') return () => {};
|
|
103
|
-
_errorHandlers.push(handler);
|
|
104
|
-
return () => {
|
|
105
|
-
const idx = _errorHandlers.indexOf(handler);
|
|
106
|
-
if (idx !== -1) _errorHandlers.splice(idx, 1);
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Report an error through the global handler and console.
|
|
112
|
-
* Non-throwing - used for recoverable errors in callbacks, lifecycle hooks, etc.
|
|
113
|
-
*
|
|
114
|
-
* @param {string} code - ErrorCode
|
|
115
|
-
* @param {string} message
|
|
116
|
-
* @param {object} [context]
|
|
117
|
-
* @param {Error} [cause]
|
|
118
|
-
*/
|
|
119
|
-
export function reportError(code, message, context = {}, cause) {
|
|
120
|
-
const err = cause instanceof ZQueryError
|
|
121
|
-
? cause
|
|
122
|
-
: new ZQueryError(code, message, context, cause);
|
|
123
|
-
|
|
124
|
-
// Notify all registered handlers
|
|
125
|
-
for (const handler of _errorHandlers) {
|
|
126
|
-
try { handler(err); } catch { /* prevent handler from crashing framework */ }
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Always log for developer visibility
|
|
130
|
-
console.error(`[zQuery ${code}] ${message}`, context, cause || '');
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Wrap a callback so that thrown errors are caught, reported, and don't crash
|
|
135
|
-
* the current execution context.
|
|
136
|
-
*
|
|
137
|
-
* @param {Function} fn
|
|
138
|
-
* @param {string} code - ErrorCode to use if the callback throws
|
|
139
|
-
* @param {object} [context]
|
|
140
|
-
* @returns {Function}
|
|
141
|
-
*/
|
|
142
|
-
export function guardCallback(fn, code, context = {}) {
|
|
143
|
-
return (...args) => {
|
|
144
|
-
try {
|
|
145
|
-
return fn(...args);
|
|
146
|
-
} catch (err) {
|
|
147
|
-
reportError(code, err.message || 'Callback error', context, err);
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Validate a required value is defined and of the expected type.
|
|
154
|
-
* Throws ZQueryError on failure (for fast-fail at API boundaries).
|
|
155
|
-
*
|
|
156
|
-
* @param {*} value
|
|
157
|
-
* @param {string} name - parameter name for error message
|
|
158
|
-
* @param {string} expectedType - 'string', 'function', 'object', etc.
|
|
159
|
-
*/
|
|
160
|
-
export function validate(value, name, expectedType) {
|
|
161
|
-
if (value === undefined || value === null) {
|
|
162
|
-
throw new ZQueryError(
|
|
163
|
-
ErrorCode.INVALID_ARGUMENT,
|
|
164
|
-
`"${name}" is required but got ${value}`
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
if (expectedType && typeof value !== expectedType) {
|
|
168
|
-
throw new ZQueryError(
|
|
169
|
-
ErrorCode.INVALID_ARGUMENT,
|
|
170
|
-
`"${name}" must be a ${expectedType}, got ${typeof value}`
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Format a ZQueryError into a structured object suitable for overlays/logging.
|
|
177
|
-
* @param {ZQueryError|Error} err
|
|
178
|
-
* @returns {{ code: string, type: string, message: string, context: object, stack: string }}
|
|
179
|
-
*/
|
|
180
|
-
export function formatError(err) {
|
|
181
|
-
const isZQ = err instanceof ZQueryError;
|
|
182
|
-
return {
|
|
183
|
-
code: isZQ ? err.code : '',
|
|
184
|
-
type: isZQ ? 'ZQueryError' : (err.name || 'Error'),
|
|
185
|
-
message: err.message || 'Unknown error',
|
|
186
|
-
context: isZQ ? err.context : {},
|
|
187
|
-
stack: err.stack || '',
|
|
188
|
-
cause: err.cause ? formatError(err.cause) : null,
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Async version of guardCallback - wraps an async function so that
|
|
194
|
-
* rejections are caught, reported, and don't crash execution.
|
|
195
|
-
*
|
|
196
|
-
* @param {Function} fn - async function
|
|
197
|
-
* @param {string} code - ErrorCode to use
|
|
198
|
-
* @param {object} [context]
|
|
199
|
-
* @returns {Function}
|
|
200
|
-
*/
|
|
201
|
-
export function guardAsync(fn, code, context = {}) {
|
|
202
|
-
return async (...args) => {
|
|
203
|
-
try {
|
|
204
|
-
return await fn(...args);
|
|
205
|
-
} catch (err) {
|
|
206
|
-
reportError(code, err.message || 'Async callback error', context, err);
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* zQuery Errors - Structured error handling system
|
|
3
|
+
*
|
|
4
|
+
* Provides typed error classes and a configurable error handler so that
|
|
5
|
+
* errors surface consistently across all modules (reactive, component,
|
|
6
|
+
* router, store, expression parser, HTTP, etc.).
|
|
7
|
+
*
|
|
8
|
+
* Default behaviour: errors are logged via console.warn/error.
|
|
9
|
+
* Users can override with $.onError(handler) to integrate with their
|
|
10
|
+
* own logging, crash-reporting, or UI notification system.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Error codes - every zQuery error has a unique code for programmatic use
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
export const ErrorCode = Object.freeze({
|
|
17
|
+
// Reactive
|
|
18
|
+
REACTIVE_CALLBACK: 'ZQ_REACTIVE_CALLBACK',
|
|
19
|
+
SIGNAL_CALLBACK: 'ZQ_SIGNAL_CALLBACK',
|
|
20
|
+
EFFECT_EXEC: 'ZQ_EFFECT_EXEC',
|
|
21
|
+
|
|
22
|
+
// Expression parser
|
|
23
|
+
EXPR_PARSE: 'ZQ_EXPR_PARSE',
|
|
24
|
+
EXPR_EVAL: 'ZQ_EXPR_EVAL',
|
|
25
|
+
EXPR_UNSAFE_ACCESS: 'ZQ_EXPR_UNSAFE_ACCESS',
|
|
26
|
+
|
|
27
|
+
// Component
|
|
28
|
+
COMP_INVALID_NAME: 'ZQ_COMP_INVALID_NAME',
|
|
29
|
+
COMP_NOT_FOUND: 'ZQ_COMP_NOT_FOUND',
|
|
30
|
+
COMP_MOUNT_TARGET: 'ZQ_COMP_MOUNT_TARGET',
|
|
31
|
+
COMP_RENDER: 'ZQ_COMP_RENDER',
|
|
32
|
+
COMP_LIFECYCLE: 'ZQ_COMP_LIFECYCLE',
|
|
33
|
+
COMP_RESOURCE: 'ZQ_COMP_RESOURCE',
|
|
34
|
+
COMP_DIRECTIVE: 'ZQ_COMP_DIRECTIVE',
|
|
35
|
+
|
|
36
|
+
// Router
|
|
37
|
+
ROUTER_LOAD: 'ZQ_ROUTER_LOAD',
|
|
38
|
+
ROUTER_GUARD: 'ZQ_ROUTER_GUARD',
|
|
39
|
+
ROUTER_RESOLVE: 'ZQ_ROUTER_RESOLVE',
|
|
40
|
+
|
|
41
|
+
// Store
|
|
42
|
+
STORE_ACTION: 'ZQ_STORE_ACTION',
|
|
43
|
+
STORE_MIDDLEWARE: 'ZQ_STORE_MIDDLEWARE',
|
|
44
|
+
STORE_SUBSCRIBE: 'ZQ_STORE_SUBSCRIBE',
|
|
45
|
+
|
|
46
|
+
// HTTP
|
|
47
|
+
HTTP_REQUEST: 'ZQ_HTTP_REQUEST',
|
|
48
|
+
HTTP_TIMEOUT: 'ZQ_HTTP_TIMEOUT',
|
|
49
|
+
HTTP_INTERCEPTOR: 'ZQ_HTTP_INTERCEPTOR',
|
|
50
|
+
HTTP_PARSE: 'ZQ_HTTP_PARSE',
|
|
51
|
+
|
|
52
|
+
// SSR
|
|
53
|
+
SSR_RENDER: 'ZQ_SSR_RENDER',
|
|
54
|
+
SSR_COMPONENT: 'ZQ_SSR_COMPONENT',
|
|
55
|
+
SSR_HYDRATION: 'ZQ_SSR_HYDRATION',
|
|
56
|
+
SSR_PAGE: 'ZQ_SSR_PAGE',
|
|
57
|
+
|
|
58
|
+
// General
|
|
59
|
+
INVALID_ARGUMENT: 'ZQ_INVALID_ARGUMENT',
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
// ZQueryError - custom error class
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
export class ZQueryError extends Error {
|
|
67
|
+
/**
|
|
68
|
+
* @param {string} code - one of ErrorCode values
|
|
69
|
+
* @param {string} message - human-readable description
|
|
70
|
+
* @param {object} [context] - extra data (component name, expression, etc.)
|
|
71
|
+
* @param {Error} [cause] - original error
|
|
72
|
+
*/
|
|
73
|
+
constructor(code, message, context = {}, cause) {
|
|
74
|
+
super(message);
|
|
75
|
+
this.name = 'ZQueryError';
|
|
76
|
+
this.code = code;
|
|
77
|
+
this.context = context;
|
|
78
|
+
if (cause) this.cause = cause;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// Global error handler
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
let _errorHandlers = [];
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Register a global error handler.
|
|
90
|
+
* Called whenever zQuery catches an error internally.
|
|
91
|
+
* Multiple handlers are supported - each receives the error.
|
|
92
|
+
* Pass `null` to clear all handlers.
|
|
93
|
+
*
|
|
94
|
+
* @param {Function|null} handler - (error: ZQueryError) => void
|
|
95
|
+
* @returns {Function} unsubscribe function to remove this handler
|
|
96
|
+
*/
|
|
97
|
+
export function onError(handler) {
|
|
98
|
+
if (handler === null) {
|
|
99
|
+
_errorHandlers = [];
|
|
100
|
+
return () => {};
|
|
101
|
+
}
|
|
102
|
+
if (typeof handler !== 'function') return () => {};
|
|
103
|
+
_errorHandlers.push(handler);
|
|
104
|
+
return () => {
|
|
105
|
+
const idx = _errorHandlers.indexOf(handler);
|
|
106
|
+
if (idx !== -1) _errorHandlers.splice(idx, 1);
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Report an error through the global handler and console.
|
|
112
|
+
* Non-throwing - used for recoverable errors in callbacks, lifecycle hooks, etc.
|
|
113
|
+
*
|
|
114
|
+
* @param {string} code - ErrorCode
|
|
115
|
+
* @param {string} message
|
|
116
|
+
* @param {object} [context]
|
|
117
|
+
* @param {Error} [cause]
|
|
118
|
+
*/
|
|
119
|
+
export function reportError(code, message, context = {}, cause) {
|
|
120
|
+
const err = cause instanceof ZQueryError
|
|
121
|
+
? cause
|
|
122
|
+
: new ZQueryError(code, message, context, cause);
|
|
123
|
+
|
|
124
|
+
// Notify all registered handlers
|
|
125
|
+
for (const handler of _errorHandlers) {
|
|
126
|
+
try { handler(err); } catch { /* prevent handler from crashing framework */ }
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Always log for developer visibility
|
|
130
|
+
console.error(`[zQuery ${code}] ${message}`, context, cause || '');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Wrap a callback so that thrown errors are caught, reported, and don't crash
|
|
135
|
+
* the current execution context.
|
|
136
|
+
*
|
|
137
|
+
* @param {Function} fn
|
|
138
|
+
* @param {string} code - ErrorCode to use if the callback throws
|
|
139
|
+
* @param {object} [context]
|
|
140
|
+
* @returns {Function}
|
|
141
|
+
*/
|
|
142
|
+
export function guardCallback(fn, code, context = {}) {
|
|
143
|
+
return (...args) => {
|
|
144
|
+
try {
|
|
145
|
+
return fn(...args);
|
|
146
|
+
} catch (err) {
|
|
147
|
+
reportError(code, err.message || 'Callback error', context, err);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Validate a required value is defined and of the expected type.
|
|
154
|
+
* Throws ZQueryError on failure (for fast-fail at API boundaries).
|
|
155
|
+
*
|
|
156
|
+
* @param {*} value
|
|
157
|
+
* @param {string} name - parameter name for error message
|
|
158
|
+
* @param {string} expectedType - 'string', 'function', 'object', etc.
|
|
159
|
+
*/
|
|
160
|
+
export function validate(value, name, expectedType) {
|
|
161
|
+
if (value === undefined || value === null) {
|
|
162
|
+
throw new ZQueryError(
|
|
163
|
+
ErrorCode.INVALID_ARGUMENT,
|
|
164
|
+
`"${name}" is required but got ${value}`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
if (expectedType && typeof value !== expectedType) {
|
|
168
|
+
throw new ZQueryError(
|
|
169
|
+
ErrorCode.INVALID_ARGUMENT,
|
|
170
|
+
`"${name}" must be a ${expectedType}, got ${typeof value}`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Format a ZQueryError into a structured object suitable for overlays/logging.
|
|
177
|
+
* @param {ZQueryError|Error} err
|
|
178
|
+
* @returns {{ code: string, type: string, message: string, context: object, stack: string }}
|
|
179
|
+
*/
|
|
180
|
+
export function formatError(err) {
|
|
181
|
+
const isZQ = err instanceof ZQueryError;
|
|
182
|
+
return {
|
|
183
|
+
code: isZQ ? err.code : '',
|
|
184
|
+
type: isZQ ? 'ZQueryError' : (err.name || 'Error'),
|
|
185
|
+
message: err.message || 'Unknown error',
|
|
186
|
+
context: isZQ ? err.context : {},
|
|
187
|
+
stack: err.stack || '',
|
|
188
|
+
cause: err.cause ? formatError(err.cause) : null,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Async version of guardCallback - wraps an async function so that
|
|
194
|
+
* rejections are caught, reported, and don't crash execution.
|
|
195
|
+
*
|
|
196
|
+
* @param {Function} fn - async function
|
|
197
|
+
* @param {string} code - ErrorCode to use
|
|
198
|
+
* @param {object} [context]
|
|
199
|
+
* @returns {Function}
|
|
200
|
+
*/
|
|
201
|
+
export function guardAsync(fn, code, context = {}) {
|
|
202
|
+
return async (...args) => {
|
|
203
|
+
try {
|
|
204
|
+
return await fn(...args);
|
|
205
|
+
} catch (err) {
|
|
206
|
+
reportError(code, err.message || 'Async callback error', context, err);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
}
|