@hypen-space/core 0.4.31 → 0.4.35

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 (71) hide show
  1. package/dist/app.d.ts +73 -2
  2. package/dist/app.js +112 -9
  3. package/dist/app.js.map +6 -5
  4. package/dist/components/builtin.js +112 -9
  5. package/dist/components/builtin.js.map +6 -5
  6. package/dist/context.d.ts +8 -0
  7. package/dist/context.js +6 -2
  8. package/dist/context.js.map +3 -3
  9. package/dist/datasource.d.ts +168 -0
  10. package/dist/discovery.js +114 -9
  11. package/dist/discovery.js.map +7 -6
  12. package/dist/disposable.js +6 -2
  13. package/dist/disposable.js.map +2 -2
  14. package/dist/engine.browser.d.ts +15 -0
  15. package/dist/engine.browser.js +19 -2
  16. package/dist/engine.browser.js.map +3 -3
  17. package/dist/engine.d.ts +22 -0
  18. package/dist/engine.js +37 -3
  19. package/dist/engine.js.map +3 -3
  20. package/dist/events.js +6 -2
  21. package/dist/events.js.map +2 -2
  22. package/dist/index.browser.js +295 -179
  23. package/dist/index.browser.js.map +9 -8
  24. package/dist/index.d.ts +3 -1
  25. package/dist/index.js +298 -179
  26. package/dist/index.js.map +10 -9
  27. package/dist/loader.js +6 -2
  28. package/dist/loader.js.map +2 -2
  29. package/dist/logger.js +6 -2
  30. package/dist/logger.js.map +2 -2
  31. package/dist/plugin.js +6 -2
  32. package/dist/plugin.js.map +2 -2
  33. package/dist/remote/client.js +6 -2
  34. package/dist/remote/client.js.map +2 -2
  35. package/dist/remote/index.js +152 -11
  36. package/dist/remote/index.js.map +9 -8
  37. package/dist/remote/server.js +152 -11
  38. package/dist/remote/server.js.map +9 -8
  39. package/dist/renderer.js +6 -2
  40. package/dist/renderer.js.map +2 -2
  41. package/dist/resolver.js +6 -2
  42. package/dist/resolver.js.map +2 -2
  43. package/dist/router.d.ts +9 -0
  44. package/dist/router.js +186 -18
  45. package/dist/router.js.map +6 -5
  46. package/dist/state.js +13 -6
  47. package/dist/state.js.map +3 -3
  48. package/package.json +1 -1
  49. package/src/app.ts +121 -4
  50. package/src/context.ts +10 -2
  51. package/src/datasource.ts +252 -0
  52. package/src/discovery.ts +2 -0
  53. package/src/engine.browser.ts +30 -0
  54. package/src/engine.ts +56 -1
  55. package/src/index.ts +16 -0
  56. package/src/managed-router.ts +3 -0
  57. package/src/remote/server.ts +11 -2
  58. package/src/router.ts +36 -10
  59. package/src/state.ts +10 -3
  60. package/wasm-browser/README.md +10 -10
  61. package/wasm-browser/hypen_engine.d.ts +368 -131
  62. package/wasm-browser/hypen_engine.js +896 -645
  63. package/wasm-browser/hypen_engine_bg.wasm +0 -0
  64. package/wasm-browser/hypen_engine_bg.wasm.d.ts +20 -13
  65. package/wasm-browser/package.json +1 -1
  66. package/wasm-node/README.md +10 -10
  67. package/wasm-node/hypen_engine.d.ts +318 -89
  68. package/wasm-node/hypen_engine.js +832 -613
  69. package/wasm-node/hypen_engine_bg.wasm +0 -0
  70. package/wasm-node/hypen_engine_bg.wasm.d.ts +20 -13
  71. package/wasm-node/package.json +1 -1
@@ -1,11 +1,15 @@
1
1
  var __defProp = Object.defineProperty;
2
+ var __returnValue = (v) => v;
3
+ function __exportSetter(name, newValue) {
4
+ this[name] = __returnValue.bind(null, newValue);
5
+ }
2
6
  var __export = (target, all) => {
3
7
  for (var name in all)
4
8
  __defProp(target, name, {
5
9
  get: all[name],
6
10
  enumerable: true,
7
11
  configurable: true,
8
- set: (newValue) => all[name] = () => newValue
12
+ set: __exportSetter.bind(all, name)
9
13
  });
10
14
  };
11
15
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
@@ -156,9 +160,11 @@ function createObservableState(initialState, options) {
156
160
  notificationPending = false;
157
161
  if (batchDepth === 0) {
158
162
  notifyChange();
159
- }
163
+ } else {}
160
164
  });
161
165
  }
166
+ } else {
167
+ pendingChange = pendingChange || { paths: [], newValues: {} };
162
168
  }
163
169
  }
164
170
  const proxyCache = new WeakMap;
@@ -217,11 +223,12 @@ function createObservableState(initialState, options) {
217
223
  return true;
218
224
  },
219
225
  deleteProperty(obj, prop) {
220
- if (prop in obj) {
221
- delete obj[prop];
226
+ const existed = Object.prototype.hasOwnProperty.call(obj, prop);
227
+ const result = delete obj[prop];
228
+ if (existed) {
222
229
  scheduleBatch();
223
230
  }
224
- return true;
231
+ return result;
225
232
  }
226
233
  });
227
234
  proxyCache.set(target, proxy);
@@ -555,6 +562,59 @@ var init_result = __esm(() => {
555
562
  };
556
563
  });
557
564
 
565
+ // src/datasource.ts
566
+ class DataSourceManager {
567
+ plugins = new Map;
568
+ configs = new Map;
569
+ state = new Map;
570
+ engine;
571
+ constructor(engine) {
572
+ this.engine = engine;
573
+ }
574
+ async use(plugin, config2) {
575
+ const { name } = plugin;
576
+ this.state.set(name, {});
577
+ this.plugins.set(name, plugin);
578
+ this.configs.set(name, config2);
579
+ await plugin.connect(config2, (change) => {
580
+ const current = this.state.get(name) ?? {};
581
+ for (const path of change.paths) {
582
+ if (path in change.values) {
583
+ current[path] = change.values[path];
584
+ }
585
+ }
586
+ this.state.set(name, current);
587
+ this.engine.setContext(name, current);
588
+ });
589
+ }
590
+ get(name) {
591
+ return this.plugins.get(name);
592
+ }
593
+ has(name) {
594
+ return this.plugins.has(name);
595
+ }
596
+ getNames() {
597
+ return Array.from(this.plugins.keys());
598
+ }
599
+ getStatus(name) {
600
+ return this.plugins.get(name)?.status;
601
+ }
602
+ async remove(name) {
603
+ const plugin = this.plugins.get(name);
604
+ if (plugin) {
605
+ await plugin.disconnect();
606
+ this.plugins.delete(name);
607
+ this.configs.delete(name);
608
+ this.state.delete(name);
609
+ this.engine.removeContext(name);
610
+ }
611
+ }
612
+ async disconnectAll() {
613
+ const names = Array.from(this.plugins.keys());
614
+ await Promise.all(names.map((name) => this.remove(name)));
615
+ }
616
+ }
617
+
558
618
  // src/app.ts
559
619
  var exports_app = {};
560
620
  __export(exports_app, {
@@ -576,6 +636,7 @@ class HypenAppBuilder {
576
636
  errorHandler;
577
637
  template;
578
638
  _registry;
639
+ dataSourceEntries = [];
579
640
  constructor(initialState, options, registry) {
580
641
  this.initialState = initialState;
581
642
  this.options = options || {};
@@ -609,10 +670,19 @@ class HypenAppBuilder {
609
670
  this.errorHandler = fn;
610
671
  return this;
611
672
  }
673
+ useDataSource(plugin, config2) {
674
+ this.dataSourceEntries.push({ plugin, config: config2 });
675
+ return this;
676
+ }
612
677
  ui(template) {
613
678
  this.template = template;
614
679
  return this.build();
615
680
  }
681
+ uiFile(path) {
682
+ const fs = (() => ({}));
683
+ this.template = fs.readFileSync(path, "utf-8").trim();
684
+ return this.build();
685
+ }
616
686
  build() {
617
687
  const stateKeys = this.initialState !== null && typeof this.initialState === "object" ? Object.keys(this.initialState) : [];
618
688
  const definition = {
@@ -623,6 +693,7 @@ class HypenAppBuilder {
623
693
  version: this.options.version,
624
694
  initialState: this.initialState,
625
695
  template: this.template,
696
+ dataSources: this.dataSourceEntries.length > 0 ? this.dataSourceEntries : undefined,
626
697
  handlers: {
627
698
  onCreated: this.createdHandler,
628
699
  onAction: this.actionHandlers,
@@ -684,6 +755,8 @@ class HypenModuleInstance {
684
755
  router;
685
756
  globalContext;
686
757
  stateChangeCallbacks = [];
758
+ dataSourceManager;
759
+ dataSourceAccessor = {};
687
760
  constructor(engine, definition, router, globalContext) {
688
761
  this.engine = engine;
689
762
  this.definition = definition;
@@ -713,7 +786,8 @@ class HypenModuleInstance {
713
786
  const result = await this.executeAction(actionName, handler, {
714
787
  action: actionCtx,
715
788
  state: this.state,
716
- context
789
+ context,
790
+ dataSources: this.dataSourceAccessor
717
791
  });
718
792
  if (!result.ok) {
719
793
  const shouldRethrow = await this.handleError(result.error, { actionName });
@@ -756,8 +830,9 @@ class HypenModuleInstance {
756
830
  on: (event, handler) => ctx.on(event, handler),
757
831
  router: this.router
758
832
  };
759
- if (ctx.__hypenEngine) {
760
- api.__hypenEngine = ctx.__hypenEngine;
833
+ const ctxRecord = ctx;
834
+ if (ctxRecord.__hypenEngine) {
835
+ api.__hypenEngine = ctxRecord.__hypenEngine;
761
836
  }
762
837
  return api;
763
838
  }
@@ -804,6 +879,25 @@ class HypenModuleInstance {
804
879
  return false;
805
880
  }
806
881
  async callCreatedHandler() {
882
+ if (this.definition.dataSources?.length) {
883
+ const dsEngine = this.engine;
884
+ this.dataSourceManager = new DataSourceManager(dsEngine);
885
+ for (const { plugin, config: config2 } of this.definition.dataSources) {
886
+ try {
887
+ await this.dataSourceManager.use(plugin, config2);
888
+ this.dataSourceAccessor[plugin.name] = new Proxy(plugin, {
889
+ get(target, prop) {
890
+ if (typeof prop === "string" && !(prop in target)) {
891
+ return (...args) => target.call(prop, ...args);
892
+ }
893
+ return target[prop];
894
+ }
895
+ });
896
+ } catch (e) {
897
+ log2.error(`Failed to connect data source "${plugin.name}":`, e);
898
+ }
899
+ }
900
+ }
807
901
  if (this.definition.handlers.onCreated) {
808
902
  const context = this.globalContext ? this.createGlobalContextAPI() : undefined;
809
903
  try {
@@ -823,6 +917,15 @@ class HypenModuleInstance {
823
917
  async destroy() {
824
918
  if (this.isDestroyed)
825
919
  return;
920
+ if (this.dataSourceManager) {
921
+ try {
922
+ await this.dataSourceManager.disconnectAll();
923
+ } catch (e) {
924
+ log2.error("Error disconnecting data sources:", e);
925
+ }
926
+ this.dataSourceManager = undefined;
927
+ this.dataSourceAccessor = {};
928
+ }
826
929
  if (this.definition.handlers.onDestroyed) {
827
930
  try {
828
931
  await this.definition.handlers.onDestroyed(this.state);
@@ -1827,10 +1930,27 @@ class Engine {
1827
1930
  throw classifyEngineError(err);
1828
1931
  }
1829
1932
  }
1933
+ _onErrorHandler;
1934
+ setOnError(handler) {
1935
+ this._onErrorHandler = handler;
1936
+ }
1830
1937
  onAction(actionName, handler) {
1831
1938
  const engine = this.ensureInitialized();
1939
+ const handleError = (err) => {
1940
+ log5.error("Action handler error:", err);
1941
+ if (this._onErrorHandler) {
1942
+ this._onErrorHandler(err instanceof Error ? err : new Error(String(err)));
1943
+ }
1944
+ };
1832
1945
  engine.onAction(actionName, (action) => {
1833
- Promise.resolve(handler(action)).catch((err) => log5.error("Action handler error:", err));
1946
+ try {
1947
+ const result = handler(action);
1948
+ if (result && typeof result.catch === "function") {
1949
+ result.catch(handleError);
1950
+ }
1951
+ } catch (err) {
1952
+ handleError(err);
1953
+ }
1834
1954
  });
1835
1955
  }
1836
1956
  setModule(name, actions, stateKeys, initialState) {
@@ -1849,6 +1969,19 @@ class Engine {
1849
1969
  const engine = this.ensureInitialized();
1850
1970
  return engine.debugParseComponent(source);
1851
1971
  }
1972
+ setContext(name, data) {
1973
+ const engine = this.ensureInitialized();
1974
+ try {
1975
+ engine.setContext(name, unwrapForWasm(data));
1976
+ } catch (err) {
1977
+ throw classifyEngineError(err);
1978
+ }
1979
+ log5.debug(`Data source "${name}" context set`);
1980
+ }
1981
+ removeContext(name) {
1982
+ const engine = this.ensureInitialized();
1983
+ engine.removeContext(name);
1984
+ }
1852
1985
  }
1853
1986
 
1854
1987
  // src/remote/server.ts
@@ -2111,6 +2244,8 @@ async function discoverComponents(baseDir, options = {}) {
2111
2244
  const module = moduleExport.default;
2112
2245
  if (module && typeof module === "object" && module.template) {
2113
2246
  addSingleFileComponent(baseName, modulePath, module.template);
2247
+ } else if (module && typeof module === "object") {
2248
+ frameworkLoggers.discovery.warn(`Skipping "${entry.name}": has .ui() pattern but module has no .template property. Did you forget to call .ui(hypen\`...\`)?`);
2114
2249
  }
2115
2250
  } catch (e) {
2116
2251
  log6(`Failed to import potential single-file component: ${entry.name}`, e);
@@ -2288,8 +2423,10 @@ class RemoteServer {
2288
2423
  return;
2289
2424
  engine.setComponentResolver((componentName, _contextPath) => {
2290
2425
  const comp = this._discoveredComponents.get(componentName);
2291
- if (!comp)
2426
+ if (!comp) {
2427
+ log6.warn(`Component "${componentName}" not found. Available: ${Array.from(this._discoveredComponents.keys()).join(", ") || "(none)"}`);
2292
2428
  return null;
2429
+ }
2293
2430
  return {
2294
2431
  source: comp.template,
2295
2432
  path: componentName
@@ -2500,6 +2637,10 @@ class RemoteServer {
2500
2637
  return;
2501
2638
  let restored = false;
2502
2639
  const restore = (state) => {
2640
+ if (state === null || typeof state !== "object") {
2641
+ log6.warn("restore() called with non-object state, ignoring:", typeof state);
2642
+ return;
2643
+ }
2503
2644
  restored = true;
2504
2645
  clientData.moduleInstance.updateState(state);
2505
2646
  };
@@ -2662,4 +2803,4 @@ export {
2662
2803
  RemoteEngine
2663
2804
  };
2664
2805
 
2665
- //# debugId=5270F97B82D76CDD64756E2164756E21
2806
+ //# debugId=BB07A59B30B1F5FD64756E2164756E21