@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);
@@ -1293,10 +1396,27 @@ class Engine {
1293
1396
  throw classifyEngineError(err);
1294
1397
  }
1295
1398
  }
1399
+ _onErrorHandler;
1400
+ setOnError(handler) {
1401
+ this._onErrorHandler = handler;
1402
+ }
1296
1403
  onAction(actionName, handler) {
1297
1404
  const engine = this.ensureInitialized();
1405
+ const handleError = (err) => {
1406
+ log3.error("Action handler error:", err);
1407
+ if (this._onErrorHandler) {
1408
+ this._onErrorHandler(err instanceof Error ? err : new Error(String(err)));
1409
+ }
1410
+ };
1298
1411
  engine.onAction(actionName, (action) => {
1299
- Promise.resolve(handler(action)).catch((err) => log3.error("Action handler error:", err));
1412
+ try {
1413
+ const result = handler(action);
1414
+ if (result && typeof result.catch === "function") {
1415
+ result.catch(handleError);
1416
+ }
1417
+ } catch (err) {
1418
+ handleError(err);
1419
+ }
1300
1420
  });
1301
1421
  }
1302
1422
  setModule(name, actions, stateKeys, initialState) {
@@ -1315,6 +1435,19 @@ class Engine {
1315
1435
  const engine = this.ensureInitialized();
1316
1436
  return engine.debugParseComponent(source);
1317
1437
  }
1438
+ setContext(name, data) {
1439
+ const engine = this.ensureInitialized();
1440
+ try {
1441
+ engine.setContext(name, unwrapForWasm(data));
1442
+ } catch (err) {
1443
+ throw classifyEngineError(err);
1444
+ }
1445
+ log3.debug(`Data source "${name}" context set`);
1446
+ }
1447
+ removeContext(name) {
1448
+ const engine = this.ensureInitialized();
1449
+ engine.removeContext(name);
1450
+ }
1318
1451
  }
1319
1452
 
1320
1453
  // src/remote/server.ts
@@ -1577,6 +1710,8 @@ async function discoverComponents(baseDir, options = {}) {
1577
1710
  const module = moduleExport.default;
1578
1711
  if (module && typeof module === "object" && module.template) {
1579
1712
  addSingleFileComponent(baseName, modulePath, module.template);
1713
+ } else if (module && typeof module === "object") {
1714
+ frameworkLoggers.discovery.warn(`Skipping "${entry.name}": has .ui() pattern but module has no .template property. Did you forget to call .ui(hypen\`...\`)?`);
1580
1715
  }
1581
1716
  } catch (e) {
1582
1717
  log4(`Failed to import potential single-file component: ${entry.name}`, e);
@@ -1754,8 +1889,10 @@ class RemoteServer {
1754
1889
  return;
1755
1890
  engine.setComponentResolver((componentName, _contextPath) => {
1756
1891
  const comp = this._discoveredComponents.get(componentName);
1757
- if (!comp)
1892
+ if (!comp) {
1893
+ log4.warn(`Component "${componentName}" not found. Available: ${Array.from(this._discoveredComponents.keys()).join(", ") || "(none)"}`);
1758
1894
  return null;
1895
+ }
1759
1896
  return {
1760
1897
  source: comp.template,
1761
1898
  path: componentName
@@ -1966,6 +2103,10 @@ class RemoteServer {
1966
2103
  return;
1967
2104
  let restored = false;
1968
2105
  const restore = (state) => {
2106
+ if (state === null || typeof state !== "object") {
2107
+ log4.warn("restore() called with non-object state, ignoring:", typeof state);
2108
+ return;
2109
+ }
1969
2110
  restored = true;
1970
2111
  clientData.moduleInstance.updateState(state);
1971
2112
  };
@@ -2126,4 +2267,4 @@ export {
2126
2267
  RemoteServer
2127
2268
  };
2128
2269
 
2129
- //# debugId=E039307432F8950364756E2164756E21
2270
+ //# debugId=23B2AD6EC2DA1C3B64756E2164756E21