@trackunit/iris-app-runtime-core 1.15.16 → 1.15.17-alpha-71bd6bc448a.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/index.cjs.js CHANGED
@@ -3,44 +3,98 @@
3
3
  var irisAppRuntimeCoreApi = require('@trackunit/iris-app-runtime-core-api');
4
4
  var penpal = require('penpal');
5
5
 
6
- const doNothingByDefault = () => {
7
- // do nothing by default
6
+ /**
7
+ * Internal storage is type-erased to avoid TypeScript's distributive
8
+ * intersection behavior when indexing by `keyof ChildConnectorApi`. Type safety
9
+ * is enforced at the `setupHostConnector` boundary where the input still
10
+ * satisfies `Partial<ChildConnectorApi>`.
11
+ */
12
+ const subscribers = {};
13
+ const childApiMethodNames = [
14
+ "onFilterBarValuesChanged",
15
+ "onTokenChanged",
16
+ "onAssetSortingStateChanged",
17
+ "onAssetsFilterBarValuesChanged",
18
+ "onCustomersFilterBarValuesChanged",
19
+ "onSitesFilterBarValuesChanged",
20
+ "onTablePersistenceStateChanged",
21
+ "onTimeRangeChanged",
22
+ "onWidgetPollIntervalChanged",
23
+ ];
24
+ const makeDispatcher = (methodName) => (...args) => {
25
+ const handlers = subscribers[methodName];
26
+ if (!handlers || handlers.length === 0) {
27
+ return;
28
+ }
29
+ for (const handler of [...handlers]) {
30
+ try {
31
+ handler(...args);
32
+ }
33
+ catch (error) {
34
+ // eslint-disable-next-line no-console
35
+ console.error(`[iris-app-runtime-core] subscriber for "${methodName}" threw`, error);
36
+ }
37
+ }
8
38
  };
39
+ const dispatchTable = childApiMethodNames.reduce((table, name) => {
40
+ table[name] = makeDispatcher(name);
41
+ return table;
42
+ }, {});
43
+ const singletonConnection = penpal.connectToParent({
44
+ methods: dispatchTable,
45
+ });
46
+ singletonConnection.promise.catch(error => {
47
+ // TODO consider how to handle this catch
48
+ // eslint-disable-next-line no-console
49
+ console.log(error);
50
+ });
9
51
  /**
10
- * Setup using the subscribedMethods to subscribe to events from the host.
52
+ * Register handlers for host-initiated events. Each handler is appended to a
53
+ * shared dispatch table; unlike the previous implementation this does NOT open
54
+ * a new Penpal connection. The returned `destroy()` unregisters only the
55
+ * handlers this call installed and never tears down the shared connection.
11
56
  *
12
- * @param subscribedMethods the methods to subscribe to
13
- * @returns { Connection<HostConnectorApi> } the connection to the host
57
+ * @param subscribedMethods handlers to register on the shared host connection
58
+ * @returns {Connection<HostConnectorApi>} a connection shim sharing the singleton Penpal promise
14
59
  */
15
60
  const setupHostConnector = (subscribedMethods) => {
16
- const methods = {
17
- onFilterBarValuesChanged: doNothingByDefault,
18
- onTokenChanged: doNothingByDefault,
19
- onAssetSortingStateChanged: doNothingByDefault,
20
- onAssetsFilterBarValuesChanged: doNothingByDefault,
21
- onCustomersFilterBarValuesChanged: doNothingByDefault,
22
- onSitesFilterBarValuesChanged: doNothingByDefault,
23
- onTablePersistenceStateChanged: doNothingByDefault,
24
- onTimeRangeChanged: doNothingByDefault,
25
- onWidgetPollIntervalChanged: doNothingByDefault,
26
- ...subscribedMethods,
61
+ const unregisterCallbacks = [];
62
+ for (const key of Object.keys(subscribedMethods)) {
63
+ const handler = subscribedMethods[key];
64
+ if (typeof handler !== "function") {
65
+ continue;
66
+ }
67
+ const erased = handler;
68
+ const list = subscribers[key] ?? [];
69
+ list.push(erased);
70
+ subscribers[key] = list;
71
+ unregisterCallbacks.push(() => {
72
+ const current = subscribers[key];
73
+ if (!current) {
74
+ return;
75
+ }
76
+ const index = current.indexOf(erased);
77
+ if (index >= 0) {
78
+ current.splice(index, 1);
79
+ }
80
+ });
81
+ }
82
+ return {
83
+ promise: singletonConnection.promise,
84
+ destroy: () => {
85
+ for (const unregister of unregisterCallbacks) {
86
+ unregister();
87
+ }
88
+ },
27
89
  };
28
- const connection = penpal.connectToParent({ methods });
29
- connection.promise.catch(err => {
30
- // TODO consider how to handle this catch
31
- // eslint-disable-next-line no-console
32
- console.log(err);
33
- });
34
- return connection;
35
- };
36
- const hostConnector = setupHostConnector({});
90
+ };
37
91
  /**
38
92
  * Gets the host connector.
39
93
  *
40
94
  * @returns { Promise<Connection<HostConnectorApi>> } the connection to the host
41
95
  */
42
96
  const getHostConnector = () => {
43
- return hostConnector.promise;
97
+ return singletonConnection.promise;
44
98
  };
45
99
 
46
100
  /**
package/index.esm.js CHANGED
@@ -1,44 +1,98 @@
1
1
  export * from '@trackunit/iris-app-runtime-core-api';
2
2
  import { connectToParent } from 'penpal';
3
3
 
4
- const doNothingByDefault = () => {
5
- // do nothing by default
4
+ /**
5
+ * Internal storage is type-erased to avoid TypeScript's distributive
6
+ * intersection behavior when indexing by `keyof ChildConnectorApi`. Type safety
7
+ * is enforced at the `setupHostConnector` boundary where the input still
8
+ * satisfies `Partial<ChildConnectorApi>`.
9
+ */
10
+ const subscribers = {};
11
+ const childApiMethodNames = [
12
+ "onFilterBarValuesChanged",
13
+ "onTokenChanged",
14
+ "onAssetSortingStateChanged",
15
+ "onAssetsFilterBarValuesChanged",
16
+ "onCustomersFilterBarValuesChanged",
17
+ "onSitesFilterBarValuesChanged",
18
+ "onTablePersistenceStateChanged",
19
+ "onTimeRangeChanged",
20
+ "onWidgetPollIntervalChanged",
21
+ ];
22
+ const makeDispatcher = (methodName) => (...args) => {
23
+ const handlers = subscribers[methodName];
24
+ if (!handlers || handlers.length === 0) {
25
+ return;
26
+ }
27
+ for (const handler of [...handlers]) {
28
+ try {
29
+ handler(...args);
30
+ }
31
+ catch (error) {
32
+ // eslint-disable-next-line no-console
33
+ console.error(`[iris-app-runtime-core] subscriber for "${methodName}" threw`, error);
34
+ }
35
+ }
6
36
  };
37
+ const dispatchTable = childApiMethodNames.reduce((table, name) => {
38
+ table[name] = makeDispatcher(name);
39
+ return table;
40
+ }, {});
41
+ const singletonConnection = connectToParent({
42
+ methods: dispatchTable,
43
+ });
44
+ singletonConnection.promise.catch(error => {
45
+ // TODO consider how to handle this catch
46
+ // eslint-disable-next-line no-console
47
+ console.log(error);
48
+ });
7
49
  /**
8
- * Setup using the subscribedMethods to subscribe to events from the host.
50
+ * Register handlers for host-initiated events. Each handler is appended to a
51
+ * shared dispatch table; unlike the previous implementation this does NOT open
52
+ * a new Penpal connection. The returned `destroy()` unregisters only the
53
+ * handlers this call installed and never tears down the shared connection.
9
54
  *
10
- * @param subscribedMethods the methods to subscribe to
11
- * @returns { Connection<HostConnectorApi> } the connection to the host
55
+ * @param subscribedMethods handlers to register on the shared host connection
56
+ * @returns {Connection<HostConnectorApi>} a connection shim sharing the singleton Penpal promise
12
57
  */
13
58
  const setupHostConnector = (subscribedMethods) => {
14
- const methods = {
15
- onFilterBarValuesChanged: doNothingByDefault,
16
- onTokenChanged: doNothingByDefault,
17
- onAssetSortingStateChanged: doNothingByDefault,
18
- onAssetsFilterBarValuesChanged: doNothingByDefault,
19
- onCustomersFilterBarValuesChanged: doNothingByDefault,
20
- onSitesFilterBarValuesChanged: doNothingByDefault,
21
- onTablePersistenceStateChanged: doNothingByDefault,
22
- onTimeRangeChanged: doNothingByDefault,
23
- onWidgetPollIntervalChanged: doNothingByDefault,
24
- ...subscribedMethods,
59
+ const unregisterCallbacks = [];
60
+ for (const key of Object.keys(subscribedMethods)) {
61
+ const handler = subscribedMethods[key];
62
+ if (typeof handler !== "function") {
63
+ continue;
64
+ }
65
+ const erased = handler;
66
+ const list = subscribers[key] ?? [];
67
+ list.push(erased);
68
+ subscribers[key] = list;
69
+ unregisterCallbacks.push(() => {
70
+ const current = subscribers[key];
71
+ if (!current) {
72
+ return;
73
+ }
74
+ const index = current.indexOf(erased);
75
+ if (index >= 0) {
76
+ current.splice(index, 1);
77
+ }
78
+ });
79
+ }
80
+ return {
81
+ promise: singletonConnection.promise,
82
+ destroy: () => {
83
+ for (const unregister of unregisterCallbacks) {
84
+ unregister();
85
+ }
86
+ },
25
87
  };
26
- const connection = connectToParent({ methods });
27
- connection.promise.catch(err => {
28
- // TODO consider how to handle this catch
29
- // eslint-disable-next-line no-console
30
- console.log(err);
31
- });
32
- return connection;
33
- };
34
- const hostConnector = setupHostConnector({});
88
+ };
35
89
  /**
36
90
  * Gets the host connector.
37
91
  *
38
92
  * @returns { Promise<Connection<HostConnectorApi>> } the connection to the host
39
93
  */
40
94
  const getHostConnector = () => {
41
- return hostConnector.promise;
95
+ return singletonConnection.promise;
42
96
  };
43
97
 
44
98
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/iris-app-runtime-core",
3
- "version": "1.15.16",
3
+ "version": "1.15.17-alpha-71bd6bc448a.0",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "penpal": "^6.2.2",
11
- "@trackunit/iris-app-runtime-core-api": "1.14.16"
11
+ "@trackunit/iris-app-runtime-core-api": "1.14.17-alpha-71bd6bc448a.0"
12
12
  },
13
13
  "module": "./index.esm.js",
14
14
  "main": "./index.cjs.js",
@@ -1,10 +1,13 @@
1
1
  import { ChildConnectorApi, HostConnectorApi } from "@trackunit/iris-app-runtime-core-api";
2
2
  import { AsyncMethodReturns, Connection, Methods } from "penpal";
3
3
  /**
4
- * Setup using the subscribedMethods to subscribe to events from the host.
4
+ * Register handlers for host-initiated events. Each handler is appended to a
5
+ * shared dispatch table; unlike the previous implementation this does NOT open
6
+ * a new Penpal connection. The returned `destroy()` unregisters only the
7
+ * handlers this call installed and never tears down the shared connection.
5
8
  *
6
- * @param subscribedMethods the methods to subscribe to
7
- * @returns { Connection<HostConnectorApi> } the connection to the host
9
+ * @param subscribedMethods handlers to register on the shared host connection
10
+ * @returns {Connection<HostConnectorApi>} a connection shim sharing the singleton Penpal promise
8
11
  */
9
12
  export declare const setupHostConnector: (subscribedMethods: Partial<ChildConnectorApi> & Methods) => Connection<HostConnectorApi>;
10
13
  /**