@hypen-space/core 0.2.12 → 0.3.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/README.md +182 -11
- package/dist/src/app.js +470 -44
- package/dist/src/app.js.map +7 -5
- package/dist/src/components/builtin.js +470 -44
- package/dist/src/components/builtin.js.map +7 -5
- package/dist/src/discovery.js +559 -65
- package/dist/src/discovery.js.map +8 -6
- package/dist/src/engine.js +18 -9
- package/dist/src/engine.js.map +3 -3
- package/dist/src/index.browser.js +862 -81
- package/dist/src/index.browser.js.map +10 -6
- package/dist/src/index.js +1590 -124
- package/dist/src/index.js.map +16 -9
- package/dist/src/remote/client.js +525 -35
- package/dist/src/remote/client.js.map +7 -4
- package/dist/src/remote/index.js +1796 -35
- package/dist/src/remote/index.js.map +13 -4
- package/dist/src/router.js +55 -29
- package/dist/src/router.js.map +3 -3
- package/dist/src/state.js +57 -29
- package/dist/src/state.js.map +3 -3
- package/package.json +8 -2
- package/src/app.ts +292 -13
- package/src/discovery.ts +123 -18
- package/src/disposable.ts +281 -0
- package/src/engine.ts +29 -10
- package/src/hypen.ts +209 -0
- package/src/index.ts +147 -11
- package/src/logger.ts +338 -0
- package/src/remote/client.ts +263 -56
- package/src/remote/index.ts +25 -1
- package/src/remote/server.ts +652 -0
- package/src/remote/session.ts +256 -0
- package/src/remote/types.ts +68 -1
- package/src/result.ts +260 -0
- package/src/retry.ts +306 -0
- package/src/state.ts +103 -45
- package/wasm-browser/README.md +4 -0
- package/wasm-browser/hypen_engine_bg.wasm +0 -0
- package/wasm-browser/package.json +1 -1
- package/wasm-node/README.md +4 -0
- package/wasm-node/hypen_engine_bg.wasm +0 -0
- package/wasm-node/package.json +1 -1
- package/wasm-browser/hypen_engine_bg.js +0 -736
- package/wasm-node/hypen_engine_bg.js +0 -736
|
@@ -15,39 +15,34 @@ function deepClone(obj) {
|
|
|
15
15
|
if (obj === null || typeof obj !== "object") {
|
|
16
16
|
return obj;
|
|
17
17
|
}
|
|
18
|
+
if (typeof obj === "function") {
|
|
19
|
+
return obj;
|
|
20
|
+
}
|
|
21
|
+
if (typeof obj.__getSnapshot === "function") {
|
|
22
|
+
return obj.__getSnapshot();
|
|
23
|
+
}
|
|
24
|
+
if (obj instanceof WeakMap || obj instanceof WeakSet) {
|
|
25
|
+
return obj;
|
|
26
|
+
}
|
|
18
27
|
const visited = new WeakMap;
|
|
19
28
|
function cloneInternal(value) {
|
|
20
29
|
if (value === null || typeof value !== "object") {
|
|
21
30
|
return value;
|
|
22
31
|
}
|
|
32
|
+
if (typeof value === "function") {
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
23
35
|
if (visited.has(value)) {
|
|
24
36
|
return visited.get(value);
|
|
25
37
|
}
|
|
26
|
-
if (value instanceof Date) {
|
|
27
|
-
return new Date(value.getTime());
|
|
28
|
-
}
|
|
29
|
-
if (value instanceof RegExp) {
|
|
30
|
-
return new RegExp(value.source, value.flags);
|
|
31
|
-
}
|
|
32
|
-
if (value instanceof Map) {
|
|
33
|
-
const mapClone = new Map;
|
|
34
|
-
visited.set(value, mapClone);
|
|
35
|
-
for (const [k, v] of value.entries()) {
|
|
36
|
-
mapClone.set(cloneInternal(k), cloneInternal(v));
|
|
37
|
-
}
|
|
38
|
-
return mapClone;
|
|
39
|
-
}
|
|
40
|
-
if (value instanceof Set) {
|
|
41
|
-
const setClone = new Set;
|
|
42
|
-
visited.set(value, setClone);
|
|
43
|
-
for (const item of value.values()) {
|
|
44
|
-
setClone.add(cloneInternal(item));
|
|
45
|
-
}
|
|
46
|
-
return setClone;
|
|
47
|
-
}
|
|
48
38
|
if (value instanceof WeakMap || value instanceof WeakSet) {
|
|
49
39
|
return value;
|
|
50
40
|
}
|
|
41
|
+
if (value instanceof Date || value instanceof RegExp || value instanceof Map || value instanceof Set || ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
|
|
42
|
+
try {
|
|
43
|
+
return structuredClone(value);
|
|
44
|
+
} catch {}
|
|
45
|
+
}
|
|
51
46
|
if (Array.isArray(value)) {
|
|
52
47
|
const arrClone = [];
|
|
53
48
|
visited.set(value, arrClone);
|
|
@@ -59,7 +54,7 @@ function deepClone(obj) {
|
|
|
59
54
|
const objClone = {};
|
|
60
55
|
visited.set(value, objClone);
|
|
61
56
|
for (const key in value) {
|
|
62
|
-
if (
|
|
57
|
+
if (Object.prototype.hasOwnProperty.call(value, key)) {
|
|
63
58
|
objClone[key] = cloneInternal(value[key]);
|
|
64
59
|
}
|
|
65
60
|
}
|
|
@@ -161,12 +156,15 @@ function createObservableState(initialState, options) {
|
|
|
161
156
|
}
|
|
162
157
|
const proxyCache = new WeakMap;
|
|
163
158
|
function createProxy(target, basePath) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
159
|
+
const cached = proxyCache.get(target);
|
|
160
|
+
if (cached)
|
|
161
|
+
return cached;
|
|
167
162
|
const proxy = new Proxy(target, {
|
|
168
163
|
get(obj, prop) {
|
|
169
|
-
|
|
164
|
+
if (prop === IS_PROXY)
|
|
165
|
+
return true;
|
|
166
|
+
if (prop === RAW_TARGET)
|
|
167
|
+
return obj;
|
|
170
168
|
if (prop === "__beginBatch") {
|
|
171
169
|
return () => {
|
|
172
170
|
batchDepth++;
|
|
@@ -183,16 +181,28 @@ function createObservableState(initialState, options) {
|
|
|
183
181
|
if (prop === "__getSnapshot") {
|
|
184
182
|
return () => deepClone(obj);
|
|
185
183
|
}
|
|
184
|
+
const value = obj[prop];
|
|
186
185
|
if (value && typeof value === "object") {
|
|
186
|
+
if (value[IS_PROXY]) {
|
|
187
|
+
return value;
|
|
188
|
+
}
|
|
187
189
|
if (value instanceof Date || value instanceof RegExp || value instanceof Map || value instanceof Set || value instanceof WeakMap || value instanceof WeakSet) {
|
|
188
190
|
return value;
|
|
189
191
|
}
|
|
190
|
-
|
|
192
|
+
const cachedNested = proxyCache.get(value);
|
|
193
|
+
if (cachedNested) {
|
|
194
|
+
return cachedNested;
|
|
195
|
+
}
|
|
196
|
+
const nestedProxy = createProxy(value, basePath ? `${basePath}.${String(prop)}` : String(prop));
|
|
197
|
+
return nestedProxy;
|
|
191
198
|
}
|
|
192
199
|
return value;
|
|
193
200
|
},
|
|
194
201
|
set(obj, prop, value) {
|
|
195
202
|
const oldValue = obj[prop];
|
|
203
|
+
if (value && typeof value === "object" && value[IS_PROXY]) {
|
|
204
|
+
value = value[RAW_TARGET];
|
|
205
|
+
}
|
|
196
206
|
obj[prop] = value;
|
|
197
207
|
if (oldValue !== value) {
|
|
198
208
|
scheduleBatch();
|
|
@@ -233,6 +243,344 @@ function getStateSnapshot(state) {
|
|
|
233
243
|
}
|
|
234
244
|
return deepClone(state);
|
|
235
245
|
}
|
|
246
|
+
function isStateProxy(value) {
|
|
247
|
+
return value !== null && typeof value === "object" && value[IS_PROXY] === true;
|
|
248
|
+
}
|
|
249
|
+
function unwrapProxy(value) {
|
|
250
|
+
if (value !== null && typeof value === "object" && value[IS_PROXY]) {
|
|
251
|
+
return value[RAW_TARGET];
|
|
252
|
+
}
|
|
253
|
+
return value;
|
|
254
|
+
}
|
|
255
|
+
var IS_PROXY, RAW_TARGET;
|
|
256
|
+
var init_state = __esm(() => {
|
|
257
|
+
IS_PROXY = Symbol.for("hypen.isProxy");
|
|
258
|
+
RAW_TARGET = Symbol.for("hypen.rawTarget");
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// src/result.ts
|
|
262
|
+
function Ok(value) {
|
|
263
|
+
return { ok: true, value };
|
|
264
|
+
}
|
|
265
|
+
function Err(error) {
|
|
266
|
+
return { ok: false, error };
|
|
267
|
+
}
|
|
268
|
+
function isOk(result) {
|
|
269
|
+
return result.ok;
|
|
270
|
+
}
|
|
271
|
+
function isErr(result) {
|
|
272
|
+
return !result.ok;
|
|
273
|
+
}
|
|
274
|
+
async function fromPromise(promise, mapError) {
|
|
275
|
+
try {
|
|
276
|
+
const value = await promise;
|
|
277
|
+
return Ok(value);
|
|
278
|
+
} catch (e) {
|
|
279
|
+
if (mapError) {
|
|
280
|
+
return Err(mapError(e));
|
|
281
|
+
}
|
|
282
|
+
return Err(e);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function fromTry(fn, mapError) {
|
|
286
|
+
try {
|
|
287
|
+
return Ok(fn());
|
|
288
|
+
} catch (e) {
|
|
289
|
+
if (mapError) {
|
|
290
|
+
return Err(mapError(e));
|
|
291
|
+
}
|
|
292
|
+
return Err(e);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function map(result, fn) {
|
|
296
|
+
if (result.ok) {
|
|
297
|
+
return Ok(fn(result.value));
|
|
298
|
+
}
|
|
299
|
+
return result;
|
|
300
|
+
}
|
|
301
|
+
function mapErr(result, fn) {
|
|
302
|
+
if (!result.ok) {
|
|
303
|
+
return Err(fn(result.error));
|
|
304
|
+
}
|
|
305
|
+
return result;
|
|
306
|
+
}
|
|
307
|
+
function flatMap(result, fn) {
|
|
308
|
+
if (result.ok) {
|
|
309
|
+
return fn(result.value);
|
|
310
|
+
}
|
|
311
|
+
return result;
|
|
312
|
+
}
|
|
313
|
+
function unwrap(result) {
|
|
314
|
+
if (result.ok) {
|
|
315
|
+
return result.value;
|
|
316
|
+
}
|
|
317
|
+
throw result.error;
|
|
318
|
+
}
|
|
319
|
+
function unwrapOr(result, defaultValue) {
|
|
320
|
+
if (result.ok) {
|
|
321
|
+
return result.value;
|
|
322
|
+
}
|
|
323
|
+
return defaultValue;
|
|
324
|
+
}
|
|
325
|
+
function unwrapOrElse(result, fn) {
|
|
326
|
+
if (result.ok) {
|
|
327
|
+
return result.value;
|
|
328
|
+
}
|
|
329
|
+
return fn(result.error);
|
|
330
|
+
}
|
|
331
|
+
function match(result, handlers) {
|
|
332
|
+
if (result.ok) {
|
|
333
|
+
return handlers.ok(result.value);
|
|
334
|
+
}
|
|
335
|
+
return handlers.err(result.error);
|
|
336
|
+
}
|
|
337
|
+
function all(results) {
|
|
338
|
+
const values = [];
|
|
339
|
+
for (const result of results) {
|
|
340
|
+
if (!result.ok) {
|
|
341
|
+
return result;
|
|
342
|
+
}
|
|
343
|
+
values.push(result.value);
|
|
344
|
+
}
|
|
345
|
+
return Ok(values);
|
|
346
|
+
}
|
|
347
|
+
var HypenError, ActionError, ConnectionError, StateError;
|
|
348
|
+
var init_result = __esm(() => {
|
|
349
|
+
HypenError = class HypenError extends Error {
|
|
350
|
+
code;
|
|
351
|
+
context;
|
|
352
|
+
cause;
|
|
353
|
+
constructor(code, message, options) {
|
|
354
|
+
super(message);
|
|
355
|
+
this.name = "HypenError";
|
|
356
|
+
this.code = code;
|
|
357
|
+
this.context = options?.context;
|
|
358
|
+
this.cause = options?.cause;
|
|
359
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
ActionError = class ActionError extends HypenError {
|
|
363
|
+
actionName;
|
|
364
|
+
constructor(actionName, cause) {
|
|
365
|
+
super("ACTION_ERROR", `Action handler "${actionName}" failed: ${cause instanceof Error ? cause.message : String(cause)}`, {
|
|
366
|
+
context: { actionName },
|
|
367
|
+
cause: cause instanceof Error ? cause : undefined
|
|
368
|
+
});
|
|
369
|
+
this.name = "ActionError";
|
|
370
|
+
this.actionName = actionName;
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
ConnectionError = class ConnectionError extends HypenError {
|
|
374
|
+
url;
|
|
375
|
+
attempt;
|
|
376
|
+
constructor(url, cause, attempt) {
|
|
377
|
+
super("CONNECTION_ERROR", `Connection to "${url}" failed${attempt ? ` (attempt ${attempt})` : ""}: ${cause instanceof Error ? cause.message : String(cause)}`, {
|
|
378
|
+
context: { url, attempt },
|
|
379
|
+
cause: cause instanceof Error ? cause : undefined
|
|
380
|
+
});
|
|
381
|
+
this.name = "ConnectionError";
|
|
382
|
+
this.url = url;
|
|
383
|
+
this.attempt = attempt;
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
StateError = class StateError extends HypenError {
|
|
387
|
+
path;
|
|
388
|
+
constructor(message, path, cause) {
|
|
389
|
+
super("STATE_ERROR", message, {
|
|
390
|
+
context: { path },
|
|
391
|
+
cause: cause instanceof Error ? cause : undefined
|
|
392
|
+
});
|
|
393
|
+
this.name = "StateError";
|
|
394
|
+
this.path = path;
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// src/logger.ts
|
|
400
|
+
function isProduction() {
|
|
401
|
+
if (typeof process !== "undefined" && process.env) {
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
function setLogLevel(level) {
|
|
407
|
+
config.level = level;
|
|
408
|
+
}
|
|
409
|
+
function getLogLevel() {
|
|
410
|
+
return config.level;
|
|
411
|
+
}
|
|
412
|
+
function configureLogger(options) {
|
|
413
|
+
config = { ...config, ...options };
|
|
414
|
+
}
|
|
415
|
+
function enableLogging() {
|
|
416
|
+
config.level = "debug";
|
|
417
|
+
}
|
|
418
|
+
function disableLogging() {
|
|
419
|
+
config.level = "none";
|
|
420
|
+
}
|
|
421
|
+
function shouldLog(level) {
|
|
422
|
+
return LOG_LEVEL_ORDER[level] >= LOG_LEVEL_ORDER[config.level];
|
|
423
|
+
}
|
|
424
|
+
function formatTag(tag, level) {
|
|
425
|
+
const timestamp = config.timestamps ? `${new Date().toISOString()} ` : "";
|
|
426
|
+
if (config.colors && level !== "none") {
|
|
427
|
+
const color = LOG_LEVEL_COLORS[level];
|
|
428
|
+
return `${timestamp}${color}[${tag}]${RESET_COLOR}`;
|
|
429
|
+
}
|
|
430
|
+
return `${timestamp}[${tag}]`;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
class Logger {
|
|
434
|
+
tag;
|
|
435
|
+
constructor(tag) {
|
|
436
|
+
this.tag = tag;
|
|
437
|
+
}
|
|
438
|
+
debug(...args) {
|
|
439
|
+
if (!shouldLog("debug"))
|
|
440
|
+
return;
|
|
441
|
+
if (config.handler) {
|
|
442
|
+
config.handler.debug(this.tag, ...args);
|
|
443
|
+
} else {
|
|
444
|
+
console.log(formatTag(this.tag, "debug"), ...args);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
info(...args) {
|
|
448
|
+
if (!shouldLog("info"))
|
|
449
|
+
return;
|
|
450
|
+
if (config.handler) {
|
|
451
|
+
config.handler.info(this.tag, ...args);
|
|
452
|
+
} else {
|
|
453
|
+
console.info(formatTag(this.tag, "info"), ...args);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
warn(...args) {
|
|
457
|
+
if (!shouldLog("warn"))
|
|
458
|
+
return;
|
|
459
|
+
if (config.handler) {
|
|
460
|
+
config.handler.warn(this.tag, ...args);
|
|
461
|
+
} else {
|
|
462
|
+
console.warn(formatTag(this.tag, "warn"), ...args);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
error(...args) {
|
|
466
|
+
if (!shouldLog("error"))
|
|
467
|
+
return;
|
|
468
|
+
if (config.handler) {
|
|
469
|
+
config.handler.error(this.tag, ...args);
|
|
470
|
+
} else {
|
|
471
|
+
console.error(formatTag(this.tag, "error"), ...args);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
time(label, fn) {
|
|
475
|
+
if (!shouldLog("debug")) {
|
|
476
|
+
return fn();
|
|
477
|
+
}
|
|
478
|
+
const start = performance.now();
|
|
479
|
+
try {
|
|
480
|
+
return fn();
|
|
481
|
+
} finally {
|
|
482
|
+
const duration = performance.now() - start;
|
|
483
|
+
this.debug(`${label}: ${duration.toFixed(2)}ms`);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
async timeAsync(label, fn) {
|
|
487
|
+
if (!shouldLog("debug")) {
|
|
488
|
+
return fn();
|
|
489
|
+
}
|
|
490
|
+
const start = performance.now();
|
|
491
|
+
try {
|
|
492
|
+
return await fn();
|
|
493
|
+
} finally {
|
|
494
|
+
const duration = performance.now() - start;
|
|
495
|
+
this.debug(`${label}: ${duration.toFixed(2)}ms`);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
child(subTag) {
|
|
499
|
+
return new Logger(`${this.tag}:${subTag}`);
|
|
500
|
+
}
|
|
501
|
+
debugIf(condition, ...args) {
|
|
502
|
+
if (condition)
|
|
503
|
+
this.debug(...args);
|
|
504
|
+
}
|
|
505
|
+
warnIf(condition, ...args) {
|
|
506
|
+
if (condition)
|
|
507
|
+
this.warn(...args);
|
|
508
|
+
}
|
|
509
|
+
errorIf(condition, ...args) {
|
|
510
|
+
if (condition)
|
|
511
|
+
this.error(...args);
|
|
512
|
+
}
|
|
513
|
+
loggedOnce = new Set;
|
|
514
|
+
warnOnce(key, ...args) {
|
|
515
|
+
if (this.loggedOnce.has(key))
|
|
516
|
+
return;
|
|
517
|
+
this.loggedOnce.add(key);
|
|
518
|
+
this.warn(...args);
|
|
519
|
+
}
|
|
520
|
+
debugOnce(key, ...args) {
|
|
521
|
+
if (this.loggedOnce.has(key))
|
|
522
|
+
return;
|
|
523
|
+
this.loggedOnce.add(key);
|
|
524
|
+
this.debug(...args);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
function createLogger(tag) {
|
|
528
|
+
return new Logger(tag);
|
|
529
|
+
}
|
|
530
|
+
var LOG_LEVEL_ORDER, LOG_LEVEL_COLORS, RESET_COLOR = "\x1B[0m", config, logger, log, frameworkLoggers;
|
|
531
|
+
var init_logger = __esm(() => {
|
|
532
|
+
LOG_LEVEL_ORDER = {
|
|
533
|
+
debug: 0,
|
|
534
|
+
info: 1,
|
|
535
|
+
warn: 2,
|
|
536
|
+
error: 3,
|
|
537
|
+
none: 4
|
|
538
|
+
};
|
|
539
|
+
LOG_LEVEL_COLORS = {
|
|
540
|
+
debug: "\x1B[36m",
|
|
541
|
+
info: "\x1B[32m",
|
|
542
|
+
warn: "\x1B[33m",
|
|
543
|
+
error: "\x1B[31m"
|
|
544
|
+
};
|
|
545
|
+
config = {
|
|
546
|
+
level: isProduction() ? "error" : "debug",
|
|
547
|
+
colors: true,
|
|
548
|
+
timestamps: false
|
|
549
|
+
};
|
|
550
|
+
logger = createLogger("Hypen");
|
|
551
|
+
log = {
|
|
552
|
+
debug: (tag, ...args) => {
|
|
553
|
+
if (!shouldLog("debug"))
|
|
554
|
+
return;
|
|
555
|
+
console.log(formatTag(tag, "debug"), ...args);
|
|
556
|
+
},
|
|
557
|
+
info: (tag, ...args) => {
|
|
558
|
+
if (!shouldLog("info"))
|
|
559
|
+
return;
|
|
560
|
+
console.info(formatTag(tag, "info"), ...args);
|
|
561
|
+
},
|
|
562
|
+
warn: (tag, ...args) => {
|
|
563
|
+
if (!shouldLog("warn"))
|
|
564
|
+
return;
|
|
565
|
+
console.warn(formatTag(tag, "warn"), ...args);
|
|
566
|
+
},
|
|
567
|
+
error: (tag, ...args) => {
|
|
568
|
+
if (!shouldLog("error"))
|
|
569
|
+
return;
|
|
570
|
+
console.error(formatTag(tag, "error"), ...args);
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
frameworkLoggers = {
|
|
574
|
+
engine: createLogger("Engine"),
|
|
575
|
+
router: createLogger("Router"),
|
|
576
|
+
state: createLogger("State"),
|
|
577
|
+
events: createLogger("Events"),
|
|
578
|
+
remote: createLogger("Remote"),
|
|
579
|
+
renderer: createLogger("Renderer"),
|
|
580
|
+
module: createLogger("Module"),
|
|
581
|
+
lifecycle: createLogger("Lifecycle")
|
|
582
|
+
};
|
|
583
|
+
});
|
|
236
584
|
|
|
237
585
|
// src/app.ts
|
|
238
586
|
var exports_app = {};
|
|
@@ -249,6 +597,11 @@ class HypenAppBuilder {
|
|
|
249
597
|
createdHandler;
|
|
250
598
|
actionHandlers = new Map;
|
|
251
599
|
destroyedHandler;
|
|
600
|
+
disconnectHandler;
|
|
601
|
+
reconnectHandler;
|
|
602
|
+
expireHandler;
|
|
603
|
+
errorHandler;
|
|
604
|
+
template;
|
|
252
605
|
constructor(initialState, options) {
|
|
253
606
|
this.initialState = initialState;
|
|
254
607
|
this.options = options || {};
|
|
@@ -265,6 +618,26 @@ class HypenAppBuilder {
|
|
|
265
618
|
this.destroyedHandler = fn;
|
|
266
619
|
return this;
|
|
267
620
|
}
|
|
621
|
+
onDisconnect(fn) {
|
|
622
|
+
this.disconnectHandler = fn;
|
|
623
|
+
return this;
|
|
624
|
+
}
|
|
625
|
+
onReconnect(fn) {
|
|
626
|
+
this.reconnectHandler = fn;
|
|
627
|
+
return this;
|
|
628
|
+
}
|
|
629
|
+
onExpire(fn) {
|
|
630
|
+
this.expireHandler = fn;
|
|
631
|
+
return this;
|
|
632
|
+
}
|
|
633
|
+
onError(fn) {
|
|
634
|
+
this.errorHandler = fn;
|
|
635
|
+
return this;
|
|
636
|
+
}
|
|
637
|
+
ui(template) {
|
|
638
|
+
this.template = template;
|
|
639
|
+
return this.build();
|
|
640
|
+
}
|
|
268
641
|
build() {
|
|
269
642
|
const stateKeys = this.initialState !== null && typeof this.initialState === "object" ? Object.keys(this.initialState) : [];
|
|
270
643
|
return {
|
|
@@ -274,10 +647,15 @@ class HypenAppBuilder {
|
|
|
274
647
|
persist: this.options.persist,
|
|
275
648
|
version: this.options.version,
|
|
276
649
|
initialState: this.initialState,
|
|
650
|
+
template: this.template,
|
|
277
651
|
handlers: {
|
|
278
652
|
onCreated: this.createdHandler,
|
|
279
653
|
onAction: this.actionHandlers,
|
|
280
|
-
onDestroyed: this.destroyedHandler
|
|
654
|
+
onDestroyed: this.destroyedHandler,
|
|
655
|
+
onDisconnect: this.disconnectHandler,
|
|
656
|
+
onReconnect: this.reconnectHandler,
|
|
657
|
+
onExpire: this.expireHandler,
|
|
658
|
+
onError: this.errorHandler
|
|
281
659
|
}
|
|
282
660
|
};
|
|
283
661
|
}
|
|
@@ -310,9 +688,9 @@ class HypenModuleInstance {
|
|
|
310
688
|
});
|
|
311
689
|
this.engine.setModule(definition.name || "AnonymousModule", definition.actions, definition.stateKeys, getStateSnapshot(this.state));
|
|
312
690
|
for (const [actionName, handler] of definition.handlers.onAction) {
|
|
313
|
-
|
|
691
|
+
log2.debug(`Registering action handler: ${actionName} for module ${definition.name}`);
|
|
314
692
|
this.engine.onAction(actionName, async (action) => {
|
|
315
|
-
|
|
693
|
+
log2.debug(`Action handler fired: ${actionName}`, action);
|
|
316
694
|
const actionCtx = {
|
|
317
695
|
name: action.name,
|
|
318
696
|
payload: action.payload,
|
|
@@ -322,17 +700,19 @@ class HypenModuleInstance {
|
|
|
322
700
|
router: this.routerContext?.root || null
|
|
323
701
|
};
|
|
324
702
|
const context = this.globalContext ? this.createGlobalContextAPI() : undefined;
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
703
|
+
const result = await this.executeAction(actionName, handler, {
|
|
704
|
+
action: actionCtx,
|
|
705
|
+
state: this.state,
|
|
706
|
+
next,
|
|
707
|
+
context
|
|
708
|
+
});
|
|
709
|
+
if (!result.ok) {
|
|
710
|
+
const shouldRethrow = await this.handleError(result.error, { actionName });
|
|
711
|
+
if (shouldRethrow) {
|
|
712
|
+
throw result.error;
|
|
713
|
+
}
|
|
714
|
+
} else {
|
|
715
|
+
log2.debug(`Action handler completed: ${actionName}`);
|
|
336
716
|
}
|
|
337
717
|
});
|
|
338
718
|
}
|
|
@@ -359,6 +739,48 @@ class HypenModuleInstance {
|
|
|
359
739
|
}
|
|
360
740
|
return api;
|
|
361
741
|
}
|
|
742
|
+
async executeAction(actionName, handler, ctx) {
|
|
743
|
+
try {
|
|
744
|
+
const result = handler(ctx);
|
|
745
|
+
await result;
|
|
746
|
+
return Ok(undefined);
|
|
747
|
+
} catch (e) {
|
|
748
|
+
return Err(new ActionError(actionName, e));
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
async handleError(error, context) {
|
|
752
|
+
const errorCtx = {
|
|
753
|
+
error,
|
|
754
|
+
state: this.state,
|
|
755
|
+
actionName: context.actionName,
|
|
756
|
+
lifecycle: context.lifecycle
|
|
757
|
+
};
|
|
758
|
+
if (this.definition.handlers.onError) {
|
|
759
|
+
try {
|
|
760
|
+
const result = await this.definition.handlers.onError(errorCtx);
|
|
761
|
+
if (result && typeof result === "object") {
|
|
762
|
+
if ("handled" in result && result.handled) {
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
if ("rethrow" in result && result.rethrow) {
|
|
766
|
+
return true;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
} catch (handlerError) {
|
|
770
|
+
log2.error("Error in onError handler:", handlerError);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
if (this.globalContext) {
|
|
774
|
+
const eventContext = context.actionName ? `action:${context.actionName}` : context.lifecycle ? `lifecycle:${context.lifecycle}` : "unknown";
|
|
775
|
+
this.globalContext.emit("error", {
|
|
776
|
+
message: error.message,
|
|
777
|
+
error,
|
|
778
|
+
context: eventContext
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
log2.error(`${context.actionName ? `Action "${context.actionName}"` : `Lifecycle "${context.lifecycle}"`} error:`, error);
|
|
782
|
+
return false;
|
|
783
|
+
}
|
|
362
784
|
async callCreatedHandler() {
|
|
363
785
|
if (this.definition.handlers.onCreated) {
|
|
364
786
|
const context = this.globalContext ? this.createGlobalContextAPI() : undefined;
|
|
@@ -386,8 +808,12 @@ class HypenModuleInstance {
|
|
|
386
808
|
Object.assign(this.state, patch);
|
|
387
809
|
}
|
|
388
810
|
}
|
|
389
|
-
var app;
|
|
811
|
+
var log2, app;
|
|
390
812
|
var init_app = __esm(() => {
|
|
813
|
+
init_result();
|
|
814
|
+
init_state();
|
|
815
|
+
init_logger();
|
|
816
|
+
log2 = createLogger("ModuleInstance");
|
|
391
817
|
app = new HypenApp;
|
|
392
818
|
});
|
|
393
819
|
|
|
@@ -472,4 +898,4 @@ export {
|
|
|
472
898
|
Link
|
|
473
899
|
};
|
|
474
900
|
|
|
475
|
-
//# debugId=
|
|
901
|
+
//# debugId=7E3505DBDD2EEAEE64756E2164756E21
|