@hypen-space/core 0.4.3 → 0.4.11

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 (72) hide show
  1. package/README.md +1 -1
  2. package/dist/app.d.ts +79 -22
  3. package/dist/app.js +248 -155
  4. package/dist/app.js.map +5 -5
  5. package/dist/components/builtin.js +251 -158
  6. package/dist/components/builtin.js.map +6 -6
  7. package/dist/context.js +1 -1
  8. package/dist/context.js.map +1 -1
  9. package/dist/discovery.d.ts +1 -1
  10. package/dist/discovery.js +249 -156
  11. package/dist/discovery.js.map +6 -6
  12. package/dist/disposable.js +1 -1
  13. package/dist/disposable.js.map +1 -1
  14. package/dist/engine.browser.d.ts +6 -0
  15. package/dist/engine.browser.js +192 -5
  16. package/dist/engine.browser.js.map +5 -4
  17. package/dist/engine.d.ts +6 -0
  18. package/dist/engine.js +192 -5
  19. package/dist/engine.js.map +5 -4
  20. package/dist/events.js +1 -1
  21. package/dist/events.js.map +1 -1
  22. package/dist/index.browser.d.ts +1 -1
  23. package/dist/index.browser.js +248 -155
  24. package/dist/index.browser.js.map +6 -6
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.js +254 -158
  27. package/dist/index.js.map +7 -7
  28. package/dist/loader.js +1 -1
  29. package/dist/loader.js.map +1 -1
  30. package/dist/logger.js +245 -0
  31. package/dist/logger.js.map +10 -0
  32. package/dist/managed-router.d.ts +3 -4
  33. package/dist/plugin.js +1 -1
  34. package/dist/plugin.js.map +1 -1
  35. package/dist/remote/client.js +34 -2
  36. package/dist/remote/client.js.map +3 -3
  37. package/dist/remote/index.js +609 -163
  38. package/dist/remote/index.js.map +8 -7
  39. package/dist/remote/server.d.ts +46 -15
  40. package/dist/remote/server.js +609 -163
  41. package/dist/remote/server.js.map +8 -7
  42. package/dist/renderer.js +1 -1
  43. package/dist/renderer.js.map +1 -1
  44. package/dist/result.d.ts +18 -0
  45. package/dist/router.js +1 -1
  46. package/dist/router.js.map +1 -1
  47. package/dist/types.d.ts +1 -1
  48. package/dist/types.js +2 -0
  49. package/dist/types.js.map +9 -0
  50. package/package.json +1 -1
  51. package/src/app.ts +162 -41
  52. package/src/components/builtin.ts +3 -4
  53. package/src/discovery.ts +2 -2
  54. package/src/engine.browser.ts +27 -4
  55. package/src/engine.ts +27 -4
  56. package/src/index.browser.ts +0 -2
  57. package/src/index.ts +3 -2
  58. package/src/managed-router.ts +5 -6
  59. package/src/remote/server.ts +116 -21
  60. package/src/result.ts +48 -0
  61. package/src/types.ts +1 -1
  62. package/wasm-browser/hypen_engine.d.ts +3 -3
  63. package/wasm-browser/hypen_engine.js +73 -66
  64. package/wasm-browser/hypen_engine_bg.wasm +0 -0
  65. package/wasm-browser/hypen_engine_bg.wasm.d.ts +3 -3
  66. package/wasm-browser/package.json +1 -1
  67. package/wasm-node/hypen_engine.js +74 -66
  68. package/wasm-node/hypen_engine_bg.wasm +0 -0
  69. package/wasm-node/hypen_engine_bg.wasm.d.ts +3 -3
  70. package/wasm-node/package.json +1 -1
  71. package/dist/module-registry.d.ts +0 -42
  72. package/src/module-registry.ts +0 -76
package/dist/index.js CHANGED
@@ -275,144 +275,6 @@ var init_state = __esm(() => {
275
275
  RAW_TARGET = Symbol.for("hypen.rawTarget");
276
276
  });
277
277
 
278
- // src/result.ts
279
- function Ok(value) {
280
- return { ok: true, value };
281
- }
282
- function Err(error) {
283
- return { ok: false, error };
284
- }
285
- function isOk(result) {
286
- return result.ok;
287
- }
288
- function isErr(result) {
289
- return !result.ok;
290
- }
291
- async function fromPromise(promise, mapError) {
292
- try {
293
- const value = await promise;
294
- return Ok(value);
295
- } catch (e) {
296
- if (mapError) {
297
- return Err(mapError(e));
298
- }
299
- return Err(e);
300
- }
301
- }
302
- function fromTry(fn, mapError) {
303
- try {
304
- return Ok(fn());
305
- } catch (e) {
306
- if (mapError) {
307
- return Err(mapError(e));
308
- }
309
- return Err(e);
310
- }
311
- }
312
- function map(result, fn) {
313
- if (result.ok) {
314
- return Ok(fn(result.value));
315
- }
316
- return result;
317
- }
318
- function mapErr(result, fn) {
319
- if (!result.ok) {
320
- return Err(fn(result.error));
321
- }
322
- return result;
323
- }
324
- function flatMap(result, fn) {
325
- if (result.ok) {
326
- return fn(result.value);
327
- }
328
- return result;
329
- }
330
- function unwrap(result) {
331
- if (result.ok) {
332
- return result.value;
333
- }
334
- throw result.error;
335
- }
336
- function unwrapOr(result, defaultValue) {
337
- if (result.ok) {
338
- return result.value;
339
- }
340
- return defaultValue;
341
- }
342
- function unwrapOrElse(result, fn) {
343
- if (result.ok) {
344
- return result.value;
345
- }
346
- return fn(result.error);
347
- }
348
- function match(result, handlers) {
349
- if (result.ok) {
350
- return handlers.ok(result.value);
351
- }
352
- return handlers.err(result.error);
353
- }
354
- function all(results) {
355
- const values = [];
356
- for (const result of results) {
357
- if (!result.ok) {
358
- return result;
359
- }
360
- values.push(result.value);
361
- }
362
- return Ok(values);
363
- }
364
- var HypenError, ActionError, ConnectionError, StateError;
365
- var init_result = __esm(() => {
366
- HypenError = class HypenError extends Error {
367
- code;
368
- context;
369
- cause;
370
- constructor(code, message, options) {
371
- super(message);
372
- this.name = "HypenError";
373
- this.code = code;
374
- this.context = options?.context;
375
- this.cause = options?.cause;
376
- Object.setPrototypeOf(this, new.target.prototype);
377
- }
378
- };
379
- ActionError = class ActionError extends HypenError {
380
- actionName;
381
- constructor(actionName, cause) {
382
- super("ACTION_ERROR", `Action handler "${actionName}" failed: ${cause instanceof Error ? cause.message : String(cause)}`, {
383
- context: { actionName },
384
- cause: cause instanceof Error ? cause : undefined
385
- });
386
- this.name = "ActionError";
387
- this.actionName = actionName;
388
- }
389
- };
390
- ConnectionError = class ConnectionError extends HypenError {
391
- url;
392
- attempt;
393
- constructor(url, cause, attempt) {
394
- super("CONNECTION_ERROR", `Connection to "${url}" failed${attempt ? ` (attempt ${attempt})` : ""}: ${cause instanceof Error ? cause.message : String(cause)}`, {
395
- context: { url, attempt },
396
- cause: cause instanceof Error ? cause : undefined
397
- });
398
- this.name = "ConnectionError";
399
- this.url = url;
400
- this.attempt = attempt;
401
- }
402
- };
403
- StateError = class StateError extends HypenError {
404
- path;
405
- constructor(message, path, cause) {
406
- super("STATE_ERROR", message, {
407
- context: { path },
408
- cause: cause instanceof Error ? cause : undefined
409
- });
410
- this.name = "StateError";
411
- this.path = path;
412
- }
413
- };
414
- });
415
-
416
278
  // src/logger.ts
417
279
  function isProduction() {
418
280
  if (typeof process !== "undefined" && process.env) {
@@ -612,6 +474,176 @@ var init_logger = __esm(() => {
612
474
  };
613
475
  });
614
476
 
477
+ // src/result.ts
478
+ function Ok(value) {
479
+ return { ok: true, value };
480
+ }
481
+ function Err(error) {
482
+ return { ok: false, error };
483
+ }
484
+ function isOk(result) {
485
+ return result.ok;
486
+ }
487
+ function isErr(result) {
488
+ return !result.ok;
489
+ }
490
+ async function fromPromise(promise, mapError) {
491
+ try {
492
+ const value = await promise;
493
+ return Ok(value);
494
+ } catch (e) {
495
+ if (mapError) {
496
+ return Err(mapError(e));
497
+ }
498
+ return Err(e);
499
+ }
500
+ }
501
+ function fromTry(fn, mapError) {
502
+ try {
503
+ return Ok(fn());
504
+ } catch (e) {
505
+ if (mapError) {
506
+ return Err(mapError(e));
507
+ }
508
+ return Err(e);
509
+ }
510
+ }
511
+ function map(result, fn) {
512
+ if (result.ok) {
513
+ return Ok(fn(result.value));
514
+ }
515
+ return result;
516
+ }
517
+ function mapErr(result, fn) {
518
+ if (!result.ok) {
519
+ return Err(fn(result.error));
520
+ }
521
+ return result;
522
+ }
523
+ function flatMap(result, fn) {
524
+ if (result.ok) {
525
+ return fn(result.value);
526
+ }
527
+ return result;
528
+ }
529
+ function unwrap(result) {
530
+ if (result.ok) {
531
+ return result.value;
532
+ }
533
+ throw result.error;
534
+ }
535
+ function unwrapOr(result, defaultValue) {
536
+ if (result.ok) {
537
+ return result.value;
538
+ }
539
+ return defaultValue;
540
+ }
541
+ function unwrapOrElse(result, fn) {
542
+ if (result.ok) {
543
+ return result.value;
544
+ }
545
+ return fn(result.error);
546
+ }
547
+ function match(result, handlers) {
548
+ if (result.ok) {
549
+ return handlers.ok(result.value);
550
+ }
551
+ return handlers.err(result.error);
552
+ }
553
+ function all(results) {
554
+ const values = [];
555
+ for (const result of results) {
556
+ if (!result.ok) {
557
+ return result;
558
+ }
559
+ values.push(result.value);
560
+ }
561
+ return Ok(values);
562
+ }
563
+ function classifyEngineError(err) {
564
+ const message = err instanceof Error ? err.message : String(err);
565
+ if (message.startsWith("Parse error:")) {
566
+ return new ParseError(message);
567
+ }
568
+ if (message.startsWith("Invalid state:") || message.startsWith("Invalid state patch:")) {
569
+ return new StateError(message);
570
+ }
571
+ if (message.startsWith("Parent node not found:")) {
572
+ return new RenderError(message);
573
+ }
574
+ return new RenderError(message);
575
+ }
576
+ var HypenError, ActionError, ConnectionError, StateError, ParseError, RenderError;
577
+ var init_result = __esm(() => {
578
+ HypenError = class HypenError extends Error {
579
+ code;
580
+ context;
581
+ cause;
582
+ constructor(code, message, options) {
583
+ super(message);
584
+ this.name = "HypenError";
585
+ this.code = code;
586
+ this.context = options?.context;
587
+ this.cause = options?.cause;
588
+ Object.setPrototypeOf(this, new.target.prototype);
589
+ }
590
+ };
591
+ ActionError = class ActionError extends HypenError {
592
+ actionName;
593
+ constructor(actionName, cause) {
594
+ super("ACTION_ERROR", `Action handler "${actionName}" failed: ${cause instanceof Error ? cause.message : String(cause)}`, {
595
+ context: { actionName },
596
+ cause: cause instanceof Error ? cause : undefined
597
+ });
598
+ this.name = "ActionError";
599
+ this.actionName = actionName;
600
+ }
601
+ };
602
+ ConnectionError = class ConnectionError extends HypenError {
603
+ url;
604
+ attempt;
605
+ constructor(url, cause, attempt) {
606
+ super("CONNECTION_ERROR", `Connection to "${url}" failed${attempt ? ` (attempt ${attempt})` : ""}: ${cause instanceof Error ? cause.message : String(cause)}`, {
607
+ context: { url, attempt },
608
+ cause: cause instanceof Error ? cause : undefined
609
+ });
610
+ this.name = "ConnectionError";
611
+ this.url = url;
612
+ this.attempt = attempt;
613
+ }
614
+ };
615
+ StateError = class StateError extends HypenError {
616
+ path;
617
+ constructor(message, path, cause) {
618
+ super("STATE_ERROR", message, {
619
+ context: { path },
620
+ cause: cause instanceof Error ? cause : undefined
621
+ });
622
+ this.name = "StateError";
623
+ this.path = path;
624
+ }
625
+ };
626
+ ParseError = class ParseError extends HypenError {
627
+ source;
628
+ constructor(message, source, cause) {
629
+ super("PARSE_ERROR", message, {
630
+ context: { source },
631
+ cause: cause instanceof Error ? cause : undefined
632
+ });
633
+ this.name = "ParseError";
634
+ this.source = source;
635
+ }
636
+ };
637
+ RenderError = class RenderError extends HypenError {
638
+ constructor(message, cause) {
639
+ super("RENDER_ERROR", message, {
640
+ cause: cause instanceof Error ? cause : undefined
641
+ });
642
+ this.name = "RenderError";
643
+ }
644
+ };
645
+ });
646
+
615
647
  // src/app.ts
616
648
  var exports_app = {};
617
649
  __export(exports_app, {
@@ -632,9 +664,11 @@ class HypenAppBuilder {
632
664
  expireHandler;
633
665
  errorHandler;
634
666
  template;
635
- constructor(initialState, options) {
667
+ _registry;
668
+ constructor(initialState, options, registry) {
636
669
  this.initialState = initialState;
637
670
  this.options = options || {};
671
+ this._registry = registry;
638
672
  }
639
673
  onCreated(fn) {
640
674
  this.createdHandler = fn;
@@ -670,7 +704,7 @@ class HypenAppBuilder {
670
704
  }
671
705
  build() {
672
706
  const stateKeys = this.initialState !== null && typeof this.initialState === "object" ? Object.keys(this.initialState) : [];
673
- return {
707
+ const definition = {
674
708
  name: this.options.name,
675
709
  actions: Array.from(this.actionHandlers.keys()),
676
710
  stateKeys,
@@ -688,12 +722,46 @@ class HypenAppBuilder {
688
722
  onError: this.errorHandler
689
723
  }
690
724
  };
725
+ if (this.options.name && this._registry) {
726
+ this._registry.set(this.options.name, definition);
727
+ }
728
+ return definition;
691
729
  }
692
730
  }
693
731
 
694
732
  class HypenApp {
733
+ _registry = new Map;
695
734
  defineState(initial, options) {
696
- return new HypenAppBuilder(initial, options);
735
+ return new HypenAppBuilder(initial, options, this._registry);
736
+ }
737
+ module(name) {
738
+ const registry = this._registry;
739
+ return {
740
+ defineState: (initial, options) => {
741
+ return new HypenAppBuilder(initial, { ...options, name }, registry);
742
+ }
743
+ };
744
+ }
745
+ get(name) {
746
+ return this._registry.get(name);
747
+ }
748
+ has(name) {
749
+ return this._registry.has(name);
750
+ }
751
+ get components() {
752
+ return this._registry;
753
+ }
754
+ getNames() {
755
+ return Array.from(this._registry.keys());
756
+ }
757
+ get size() {
758
+ return this._registry.size;
759
+ }
760
+ unregister(name) {
761
+ this._registry.delete(name);
762
+ }
763
+ clear() {
764
+ this._registry.clear();
697
765
  }
698
766
  }
699
767
 
@@ -702,13 +770,13 @@ class HypenModuleInstance {
702
770
  definition;
703
771
  state;
704
772
  isDestroyed = false;
705
- routerContext;
773
+ router;
706
774
  globalContext;
707
775
  stateChangeCallbacks = [];
708
- constructor(engine, definition, routerContext, globalContext) {
776
+ constructor(engine, definition, router, globalContext) {
709
777
  this.engine = engine;
710
778
  this.definition = definition;
711
- this.routerContext = routerContext;
779
+ this.router = router ?? null;
712
780
  this.globalContext = globalContext;
713
781
  const statePrefix = (definition.name || "").toLowerCase();
714
782
  this.state = createObservableState(definition.initialState, {
@@ -730,14 +798,10 @@ class HypenModuleInstance {
730
798
  payload: action.payload,
731
799
  sender: action.sender
732
800
  };
733
- const next = {
734
- router: this.routerContext?.root || null
735
- };
736
801
  const context = this.globalContext ? this.createGlobalContextAPI() : undefined;
737
802
  const result = await this.executeAction(actionName, handler, {
738
803
  action: actionCtx,
739
804
  state: this.state,
740
- next,
741
805
  context
742
806
  });
743
807
  if (!result.ok) {
@@ -750,6 +814,21 @@ class HypenModuleInstance {
750
814
  }
751
815
  });
752
816
  }
817
+ this.engine.onAction("__hypen_bind", (action) => {
818
+ const payload = action.payload;
819
+ if (!payload?.path)
820
+ return;
821
+ const segments = payload.path.split(".");
822
+ let target = this.state;
823
+ for (let i = 0;i < segments.length - 1; i++) {
824
+ const seg = segments[i];
825
+ target = target?.[seg];
826
+ if (target == null)
827
+ return;
828
+ }
829
+ const lastSeg = segments[segments.length - 1];
830
+ target[lastSeg] = payload.value;
831
+ });
753
832
  this.callCreatedHandler();
754
833
  }
755
834
  createGlobalContextAPI() {
@@ -763,11 +842,9 @@ class HypenModuleInstance {
763
842
  getModuleIds: () => ctx.getModuleIds(),
764
843
  getGlobalState: () => ctx.getGlobalState(),
765
844
  emit: (event, payload) => ctx.emit(event, payload),
766
- on: (event, handler) => ctx.on(event, handler)
845
+ on: (event, handler) => ctx.on(event, handler),
846
+ router: this.router
767
847
  };
768
- if (ctx.__router) {
769
- api.__router = ctx.__router;
770
- }
771
848
  if (ctx.__hypenEngine) {
772
849
  api.__hypenEngine = ctx.__hypenEngine;
773
850
  }
@@ -818,7 +895,15 @@ class HypenModuleInstance {
818
895
  async callCreatedHandler() {
819
896
  if (this.definition.handlers.onCreated) {
820
897
  const context = this.globalContext ? this.createGlobalContextAPI() : undefined;
821
- await this.definition.handlers.onCreated(this.state, context);
898
+ try {
899
+ await this.definition.handlers.onCreated(this.state, context);
900
+ } catch (e) {
901
+ const error = e instanceof HypenError ? e : new ActionError("onCreated", e);
902
+ const shouldRethrow = await this.handleError(error, { lifecycle: "created" });
903
+ if (shouldRethrow) {
904
+ throw error;
905
+ }
906
+ }
822
907
  }
823
908
  }
824
909
  onStateChange(callback) {
@@ -828,7 +913,15 @@ class HypenModuleInstance {
828
913
  if (this.isDestroyed)
829
914
  return;
830
915
  if (this.definition.handlers.onDestroyed) {
831
- await this.definition.handlers.onDestroyed(this.state);
916
+ try {
917
+ await this.definition.handlers.onDestroyed(this.state);
918
+ } catch (e) {
919
+ const error = e instanceof HypenError ? e : new ActionError("onDestroyed", e);
920
+ const shouldRethrow = await this.handleError(error, { lifecycle: "destroyed" });
921
+ if (shouldRethrow) {
922
+ throw error;
923
+ }
924
+ }
832
925
  }
833
926
  this.isDestroyed = true;
834
927
  }
@@ -1934,7 +2027,7 @@ var Router = app.defineState({
1934
2027
  log9.error("Requires global context");
1935
2028
  return;
1936
2029
  }
1937
- const router = context.__router;
2030
+ const router = context.router;
1938
2031
  if (!router) {
1939
2032
  log9.error("Router not found in context");
1940
2033
  return;
@@ -1981,7 +2074,7 @@ var Link = app.defineState({
1981
2074
  to: "/",
1982
2075
  isActive: false
1983
2076
  }, { name: "__Link" }).onAction("navigate", ({ state, context }) => {
1984
- const router = context?.__router;
2077
+ const router = context?.router;
1985
2078
  if (!router) {
1986
2079
  log9.error("Link requires router context");
1987
2080
  return;
@@ -1991,7 +2084,7 @@ var Link = app.defineState({
1991
2084
  }).onCreated((state, context) => {
1992
2085
  if (!context)
1993
2086
  return;
1994
- const router = context.__router;
2087
+ const router = context.router;
1995
2088
  if (router) {
1996
2089
  router.onNavigate((routeState) => {
1997
2090
  state.isActive = routeState.currentPath === state.to;
@@ -2228,6 +2321,7 @@ export {
2228
2321
  createEventEmitter,
2229
2322
  configureLogger,
2230
2323
  compositeDisposable,
2324
+ classifyEngineError,
2231
2325
  batchStateUpdates,
2232
2326
  app,
2233
2327
  all,
@@ -2238,7 +2332,9 @@ export {
2238
2332
  Route,
2239
2333
  RetryPresets,
2240
2334
  RetryConditions,
2335
+ RenderError,
2241
2336
  RemoteEngine,
2337
+ ParseError,
2242
2338
  Ok,
2243
2339
  Logger,
2244
2340
  Link,
@@ -2258,4 +2354,4 @@ export {
2258
2354
  ActionError
2259
2355
  };
2260
2356
 
2261
- //# debugId=27843E67245517FE64756E2164756E21
2357
+ //# debugId=6B890301380275E464756E2164756E21