@aspectly/transports 0.1.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.
Files changed (55) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +368 -0
  3. package/dist/BaseTransport-CxzIr1Ds.d.mts +80 -0
  4. package/dist/BaseTransport-CxzIr1Ds.d.ts +80 -0
  5. package/dist/cefsharp.d.mts +37 -0
  6. package/dist/cefsharp.d.ts +37 -0
  7. package/dist/cefsharp.js +65 -0
  8. package/dist/cefsharp.js.map +1 -0
  9. package/dist/cefsharp.mjs +62 -0
  10. package/dist/cefsharp.mjs.map +1 -0
  11. package/dist/iframe.d.mts +35 -0
  12. package/dist/iframe.d.ts +35 -0
  13. package/dist/iframe.js +75 -0
  14. package/dist/iframe.js.map +1 -0
  15. package/dist/iframe.mjs +72 -0
  16. package/dist/iframe.mjs.map +1 -0
  17. package/dist/index.d.mts +85 -0
  18. package/dist/index.d.ts +85 -0
  19. package/dist/index.js +374 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/index.mjs +358 -0
  22. package/dist/index.mjs.map +1 -0
  23. package/dist/react-native.d.mts +36 -0
  24. package/dist/react-native.d.ts +36 -0
  25. package/dist/react-native.js +65 -0
  26. package/dist/react-native.js.map +1 -0
  27. package/dist/react-native.mjs +62 -0
  28. package/dist/react-native.mjs.map +1 -0
  29. package/dist/window.d.mts +36 -0
  30. package/dist/window.d.ts +36 -0
  31. package/dist/window.js +79 -0
  32. package/dist/window.js.map +1 -0
  33. package/dist/window.mjs +76 -0
  34. package/dist/window.mjs.map +1 -0
  35. package/package.json +97 -0
  36. package/src/BaseTransport.test.ts +60 -0
  37. package/src/BaseTransport.ts +27 -0
  38. package/src/TransportRegistry.test.ts +345 -0
  39. package/src/TransportRegistry.ts +120 -0
  40. package/src/cefsharp.ts +3 -0
  41. package/src/iframe.ts +3 -0
  42. package/src/index.ts +26 -0
  43. package/src/react-native.ts +3 -0
  44. package/src/transports/CefSharpTransport.test.ts +187 -0
  45. package/src/transports/CefSharpTransport.ts +73 -0
  46. package/src/transports/IframeTransport.test.ts +212 -0
  47. package/src/transports/IframeTransport.ts +79 -0
  48. package/src/transports/NullTransport.test.ts +64 -0
  49. package/src/transports/NullTransport.ts +27 -0
  50. package/src/transports/PostMessageTransport.ts +50 -0
  51. package/src/transports/ReactNativeTransport.test.ts +196 -0
  52. package/src/transports/ReactNativeTransport.ts +73 -0
  53. package/src/transports/WindowTransport.ts +84 -0
  54. package/src/types.ts +69 -0
  55. package/src/window.ts +3 -0
@@ -0,0 +1,36 @@
1
+ import { B as BaseTransport, T as TransportListener, a as TransportUnsubscribe, b as TransportDetector } from './BaseTransport-CxzIr1Ds.js';
2
+ export { c as Transport } from './BaseTransport-CxzIr1Ds.js';
3
+
4
+ /**
5
+ * Transport for popup windows opened via window.open()
6
+ * Used when web content is displayed in a child window
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * // In child window (opened via window.open())
11
+ * import { WindowTransport } from '@aspectly/transports/window';
12
+ *
13
+ * const transport = new WindowTransport();
14
+ * if (transport.isAvailable()) {
15
+ * transport.send(JSON.stringify({ type: 'hello' }));
16
+ * }
17
+ * ```
18
+ */
19
+ declare class WindowTransport extends BaseTransport {
20
+ readonly name = "window";
21
+ private readonly targetOrigin;
22
+ /**
23
+ * Create a window transport
24
+ * @param targetOrigin Origin to send messages to (default: '*')
25
+ */
26
+ constructor(targetOrigin?: string);
27
+ isAvailable(): boolean;
28
+ send(message: string): void;
29
+ subscribe(listener: TransportListener): TransportUnsubscribe;
30
+ }
31
+ /**
32
+ * Detector for auto-detection registry
33
+ */
34
+ declare const windowDetector: TransportDetector;
35
+
36
+ export { TransportListener, TransportUnsubscribe, WindowTransport, windowDetector };
package/dist/window.js ADDED
@@ -0,0 +1,79 @@
1
+ 'use strict';
2
+
3
+ // src/BaseTransport.ts
4
+ var BaseTransport = class {
5
+ /**
6
+ * Helper to check if window is defined (for SSR safety)
7
+ */
8
+ hasWindow() {
9
+ return typeof window !== "undefined";
10
+ }
11
+ /**
12
+ * Helper to safely get window object
13
+ */
14
+ getWindow() {
15
+ return this.hasWindow() ? window : null;
16
+ }
17
+ };
18
+
19
+ // src/transports/WindowTransport.ts
20
+ var WindowTransport = class extends BaseTransport {
21
+ /**
22
+ * Create a window transport
23
+ * @param targetOrigin Origin to send messages to (default: '*')
24
+ */
25
+ constructor(targetOrigin = "*") {
26
+ super();
27
+ this.name = "window";
28
+ this.targetOrigin = targetOrigin;
29
+ }
30
+ isAvailable() {
31
+ const win = this.getWindow();
32
+ if (!win) return false;
33
+ return win.opener !== null && !win.opener.closed;
34
+ }
35
+ send(message) {
36
+ const win = this.getWindow();
37
+ if (!win) {
38
+ console.warn("[WindowTransport] Window is not available");
39
+ return;
40
+ }
41
+ if (!win.opener || win.opener.closed) {
42
+ console.warn("[WindowTransport] Opener window is not available");
43
+ return;
44
+ }
45
+ win.opener.postMessage(message, this.targetOrigin);
46
+ }
47
+ subscribe(listener) {
48
+ const win = this.getWindow();
49
+ if (!win) {
50
+ return () => {
51
+ };
52
+ }
53
+ const handler = (event) => {
54
+ if (typeof event.data === "string") {
55
+ listener(event.data);
56
+ }
57
+ };
58
+ win.addEventListener("message", handler);
59
+ return () => win.removeEventListener("message", handler);
60
+ }
61
+ };
62
+ var windowDetector = {
63
+ name: "window",
64
+ priority: 70,
65
+ // Below iframe (80), above postmessage (10)
66
+ detect: () => {
67
+ try {
68
+ return typeof window !== "undefined" && window.opener != null && !window.opener.closed;
69
+ } catch {
70
+ return false;
71
+ }
72
+ },
73
+ createTransport: () => new WindowTransport()
74
+ };
75
+
76
+ exports.WindowTransport = WindowTransport;
77
+ exports.windowDetector = windowDetector;
78
+ //# sourceMappingURL=window.js.map
79
+ //# sourceMappingURL=window.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/BaseTransport.ts","../src/transports/WindowTransport.ts"],"names":[],"mappings":";;;AAMO,IAAe,gBAAf,MAAkD;AAAA;AAAA;AAAA;AAAA,EAU7C,SAAA,GAAqB;AAC7B,IAAA,OAAO,OAAO,MAAA,KAAW,WAAA;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKU,SAAA,GAA2B;AACnC,IAAA,OAAO,IAAA,CAAK,SAAA,EAAU,GAAI,MAAA,GAAS,IAAA;AAAA,EACrC;AACF,CAAA;;;ACRO,IAAM,eAAA,GAAN,cAA8B,aAAA,CAAc;AAAA;AAAA;AAAA;AAAA;AAAA,EAQjD,WAAA,CAAY,eAAuB,GAAA,EAAK;AACtC,IAAA,KAAA,EAAM;AARR,IAAA,IAAA,CAAS,IAAA,GAAO,QAAA;AASd,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AAAA,EACtB;AAAA,EAEA,WAAA,GAAuB;AACrB,IAAA,MAAM,GAAA,GAAM,KAAK,SAAA,EAAU;AAC3B,IAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AACjB,IAAA,OAAO,GAAA,CAAI,MAAA,KAAW,IAAA,IAAQ,CAAC,IAAI,MAAA,CAAO,MAAA;AAAA,EAC5C;AAAA,EAEA,KAAK,OAAA,EAAuB;AAC1B,IAAA,MAAM,GAAA,GAAM,KAAK,SAAA,EAAU;AAC3B,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,OAAA,CAAQ,KAAK,2CAA2C,CAAA;AACxD,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,GAAA,CAAI,MAAA,IAAU,GAAA,CAAI,OAAO,MAAA,EAAQ;AACpC,MAAA,OAAA,CAAQ,KAAK,kDAAkD,CAAA;AAC/D,MAAA;AAAA,IACF;AACA,IAAA,GAAA,CAAI,MAAA,CAAO,WAAA,CAAY,OAAA,EAAS,IAAA,CAAK,YAAY,CAAA;AAAA,EACnD;AAAA,EAEA,UAAU,QAAA,EAAmD;AAC3D,IAAA,MAAM,GAAA,GAAM,KAAK,SAAA,EAAU;AAC3B,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,OAAO,MAAM;AAAA,MAAC,CAAA;AAAA,IAChB;AAEA,IAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KAA8B;AAC7C,MAAA,IAAI,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,EAAU;AAClC,QAAA,QAAA,CAAS,MAAM,IAAI,CAAA;AAAA,MACrB;AAAA,IACF,CAAA;AAEA,IAAA,GAAA,CAAI,gBAAA,CAAiB,WAAW,OAAO,CAAA;AACvC,IAAA,OAAO,MAAM,GAAA,CAAI,mBAAA,CAAoB,SAAA,EAAW,OAAO,CAAA;AAAA,EACzD;AACF;AAKO,IAAM,cAAA,GAAoC;AAAA,EAC/C,IAAA,EAAM,QAAA;AAAA,EACN,QAAA,EAAU,EAAA;AAAA;AAAA,EACV,QAAQ,MAAM;AACZ,IAAA,IAAI;AACF,MAAA,OAAO,OAAO,WAAW,WAAA,IACvB,MAAA,CAAO,UAAU,IAAA,IACjB,CAAC,OAAO,MAAA,CAAO,MAAA;AAAA,IACnB,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF,CAAA;AAAA,EACA,eAAA,EAAiB,MAAM,IAAI,eAAA;AAC7B","file":"window.js","sourcesContent":["import type { Transport, TransportListener, TransportUnsubscribe } from './types';\r\n\r\n/**\r\n * Abstract base class for transports\r\n * Provides common functionality for message handling\r\n */\r\nexport abstract class BaseTransport implements Transport {\r\n abstract readonly name: string;\r\n\r\n abstract isAvailable(): boolean;\r\n abstract send(message: string): void;\r\n abstract subscribe(listener: TransportListener): TransportUnsubscribe;\r\n\r\n /**\r\n * Helper to check if window is defined (for SSR safety)\r\n */\r\n protected hasWindow(): boolean {\r\n return typeof window !== 'undefined';\r\n }\r\n\r\n /**\r\n * Helper to safely get window object\r\n */\r\n protected getWindow(): Window | null {\r\n return this.hasWindow() ? window : null;\r\n }\r\n}\r\n","import { BaseTransport } from '../BaseTransport';\nimport type { TransportListener, TransportUnsubscribe, TransportDetector } from '../types';\n\n/**\n * Transport for popup windows opened via window.open()\n * Used when web content is displayed in a child window\n *\n * @example\n * ```typescript\n * // In child window (opened via window.open())\n * import { WindowTransport } from '@aspectly/transports/window';\n *\n * const transport = new WindowTransport();\n * if (transport.isAvailable()) {\n * transport.send(JSON.stringify({ type: 'hello' }));\n * }\n * ```\n */\nexport class WindowTransport extends BaseTransport {\n readonly name = 'window';\n private readonly targetOrigin: string;\n\n /**\n * Create a window transport\n * @param targetOrigin Origin to send messages to (default: '*')\n */\n constructor(targetOrigin: string = '*') {\n super();\n this.targetOrigin = targetOrigin;\n }\n\n isAvailable(): boolean {\n const win = this.getWindow();\n if (!win) return false;\n return win.opener !== null && !win.opener.closed;\n }\n\n send(message: string): void {\n const win = this.getWindow();\n if (!win) {\n console.warn('[WindowTransport] Window is not available');\n return;\n }\n if (!win.opener || win.opener.closed) {\n console.warn('[WindowTransport] Opener window is not available');\n return;\n }\n win.opener.postMessage(message, this.targetOrigin);\n }\n\n subscribe(listener: TransportListener): TransportUnsubscribe {\n const win = this.getWindow();\n if (!win) {\n return () => {};\n }\n\n const handler = (event: MessageEvent): void => {\n if (typeof event.data === 'string') {\n listener(event.data);\n }\n };\n\n win.addEventListener('message', handler);\n return () => win.removeEventListener('message', handler);\n }\n}\n\n/**\n * Detector for auto-detection registry\n */\nexport const windowDetector: TransportDetector = {\n name: 'window',\n priority: 70, // Below iframe (80), above postmessage (10)\n detect: () => {\n try {\n return typeof window !== 'undefined' &&\n window.opener != null &&\n !window.opener.closed;\n } catch {\n return false;\n }\n },\n createTransport: () => new WindowTransport(),\n};\n"]}
@@ -0,0 +1,76 @@
1
+ // src/BaseTransport.ts
2
+ var BaseTransport = class {
3
+ /**
4
+ * Helper to check if window is defined (for SSR safety)
5
+ */
6
+ hasWindow() {
7
+ return typeof window !== "undefined";
8
+ }
9
+ /**
10
+ * Helper to safely get window object
11
+ */
12
+ getWindow() {
13
+ return this.hasWindow() ? window : null;
14
+ }
15
+ };
16
+
17
+ // src/transports/WindowTransport.ts
18
+ var WindowTransport = class extends BaseTransport {
19
+ /**
20
+ * Create a window transport
21
+ * @param targetOrigin Origin to send messages to (default: '*')
22
+ */
23
+ constructor(targetOrigin = "*") {
24
+ super();
25
+ this.name = "window";
26
+ this.targetOrigin = targetOrigin;
27
+ }
28
+ isAvailable() {
29
+ const win = this.getWindow();
30
+ if (!win) return false;
31
+ return win.opener !== null && !win.opener.closed;
32
+ }
33
+ send(message) {
34
+ const win = this.getWindow();
35
+ if (!win) {
36
+ console.warn("[WindowTransport] Window is not available");
37
+ return;
38
+ }
39
+ if (!win.opener || win.opener.closed) {
40
+ console.warn("[WindowTransport] Opener window is not available");
41
+ return;
42
+ }
43
+ win.opener.postMessage(message, this.targetOrigin);
44
+ }
45
+ subscribe(listener) {
46
+ const win = this.getWindow();
47
+ if (!win) {
48
+ return () => {
49
+ };
50
+ }
51
+ const handler = (event) => {
52
+ if (typeof event.data === "string") {
53
+ listener(event.data);
54
+ }
55
+ };
56
+ win.addEventListener("message", handler);
57
+ return () => win.removeEventListener("message", handler);
58
+ }
59
+ };
60
+ var windowDetector = {
61
+ name: "window",
62
+ priority: 70,
63
+ // Below iframe (80), above postmessage (10)
64
+ detect: () => {
65
+ try {
66
+ return typeof window !== "undefined" && window.opener != null && !window.opener.closed;
67
+ } catch {
68
+ return false;
69
+ }
70
+ },
71
+ createTransport: () => new WindowTransport()
72
+ };
73
+
74
+ export { WindowTransport, windowDetector };
75
+ //# sourceMappingURL=window.mjs.map
76
+ //# sourceMappingURL=window.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/BaseTransport.ts","../src/transports/WindowTransport.ts"],"names":[],"mappings":";AAMO,IAAe,gBAAf,MAAkD;AAAA;AAAA;AAAA;AAAA,EAU7C,SAAA,GAAqB;AAC7B,IAAA,OAAO,OAAO,MAAA,KAAW,WAAA;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKU,SAAA,GAA2B;AACnC,IAAA,OAAO,IAAA,CAAK,SAAA,EAAU,GAAI,MAAA,GAAS,IAAA;AAAA,EACrC;AACF,CAAA;;;ACRO,IAAM,eAAA,GAAN,cAA8B,aAAA,CAAc;AAAA;AAAA;AAAA;AAAA;AAAA,EAQjD,WAAA,CAAY,eAAuB,GAAA,EAAK;AACtC,IAAA,KAAA,EAAM;AARR,IAAA,IAAA,CAAS,IAAA,GAAO,QAAA;AASd,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AAAA,EACtB;AAAA,EAEA,WAAA,GAAuB;AACrB,IAAA,MAAM,GAAA,GAAM,KAAK,SAAA,EAAU;AAC3B,IAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AACjB,IAAA,OAAO,GAAA,CAAI,MAAA,KAAW,IAAA,IAAQ,CAAC,IAAI,MAAA,CAAO,MAAA;AAAA,EAC5C;AAAA,EAEA,KAAK,OAAA,EAAuB;AAC1B,IAAA,MAAM,GAAA,GAAM,KAAK,SAAA,EAAU;AAC3B,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,OAAA,CAAQ,KAAK,2CAA2C,CAAA;AACxD,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,GAAA,CAAI,MAAA,IAAU,GAAA,CAAI,OAAO,MAAA,EAAQ;AACpC,MAAA,OAAA,CAAQ,KAAK,kDAAkD,CAAA;AAC/D,MAAA;AAAA,IACF;AACA,IAAA,GAAA,CAAI,MAAA,CAAO,WAAA,CAAY,OAAA,EAAS,IAAA,CAAK,YAAY,CAAA;AAAA,EACnD;AAAA,EAEA,UAAU,QAAA,EAAmD;AAC3D,IAAA,MAAM,GAAA,GAAM,KAAK,SAAA,EAAU;AAC3B,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,OAAO,MAAM;AAAA,MAAC,CAAA;AAAA,IAChB;AAEA,IAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KAA8B;AAC7C,MAAA,IAAI,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,EAAU;AAClC,QAAA,QAAA,CAAS,MAAM,IAAI,CAAA;AAAA,MACrB;AAAA,IACF,CAAA;AAEA,IAAA,GAAA,CAAI,gBAAA,CAAiB,WAAW,OAAO,CAAA;AACvC,IAAA,OAAO,MAAM,GAAA,CAAI,mBAAA,CAAoB,SAAA,EAAW,OAAO,CAAA;AAAA,EACzD;AACF;AAKO,IAAM,cAAA,GAAoC;AAAA,EAC/C,IAAA,EAAM,QAAA;AAAA,EACN,QAAA,EAAU,EAAA;AAAA;AAAA,EACV,QAAQ,MAAM;AACZ,IAAA,IAAI;AACF,MAAA,OAAO,OAAO,WAAW,WAAA,IACvB,MAAA,CAAO,UAAU,IAAA,IACjB,CAAC,OAAO,MAAA,CAAO,MAAA;AAAA,IACnB,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF,CAAA;AAAA,EACA,eAAA,EAAiB,MAAM,IAAI,eAAA;AAC7B","file":"window.mjs","sourcesContent":["import type { Transport, TransportListener, TransportUnsubscribe } from './types';\r\n\r\n/**\r\n * Abstract base class for transports\r\n * Provides common functionality for message handling\r\n */\r\nexport abstract class BaseTransport implements Transport {\r\n abstract readonly name: string;\r\n\r\n abstract isAvailable(): boolean;\r\n abstract send(message: string): void;\r\n abstract subscribe(listener: TransportListener): TransportUnsubscribe;\r\n\r\n /**\r\n * Helper to check if window is defined (for SSR safety)\r\n */\r\n protected hasWindow(): boolean {\r\n return typeof window !== 'undefined';\r\n }\r\n\r\n /**\r\n * Helper to safely get window object\r\n */\r\n protected getWindow(): Window | null {\r\n return this.hasWindow() ? window : null;\r\n }\r\n}\r\n","import { BaseTransport } from '../BaseTransport';\nimport type { TransportListener, TransportUnsubscribe, TransportDetector } from '../types';\n\n/**\n * Transport for popup windows opened via window.open()\n * Used when web content is displayed in a child window\n *\n * @example\n * ```typescript\n * // In child window (opened via window.open())\n * import { WindowTransport } from '@aspectly/transports/window';\n *\n * const transport = new WindowTransport();\n * if (transport.isAvailable()) {\n * transport.send(JSON.stringify({ type: 'hello' }));\n * }\n * ```\n */\nexport class WindowTransport extends BaseTransport {\n readonly name = 'window';\n private readonly targetOrigin: string;\n\n /**\n * Create a window transport\n * @param targetOrigin Origin to send messages to (default: '*')\n */\n constructor(targetOrigin: string = '*') {\n super();\n this.targetOrigin = targetOrigin;\n }\n\n isAvailable(): boolean {\n const win = this.getWindow();\n if (!win) return false;\n return win.opener !== null && !win.opener.closed;\n }\n\n send(message: string): void {\n const win = this.getWindow();\n if (!win) {\n console.warn('[WindowTransport] Window is not available');\n return;\n }\n if (!win.opener || win.opener.closed) {\n console.warn('[WindowTransport] Opener window is not available');\n return;\n }\n win.opener.postMessage(message, this.targetOrigin);\n }\n\n subscribe(listener: TransportListener): TransportUnsubscribe {\n const win = this.getWindow();\n if (!win) {\n return () => {};\n }\n\n const handler = (event: MessageEvent): void => {\n if (typeof event.data === 'string') {\n listener(event.data);\n }\n };\n\n win.addEventListener('message', handler);\n return () => win.removeEventListener('message', handler);\n }\n}\n\n/**\n * Detector for auto-detection registry\n */\nexport const windowDetector: TransportDetector = {\n name: 'window',\n priority: 70, // Below iframe (80), above postmessage (10)\n detect: () => {\n try {\n return typeof window !== 'undefined' &&\n window.opener != null &&\n !window.opener.closed;\n } catch {\n return false;\n }\n },\n createTransport: () => new WindowTransport(),\n};\n"]}
package/package.json ADDED
@@ -0,0 +1,97 @@
1
+ {
2
+ "name": "@aspectly/transports",
3
+ "version": "0.1.0",
4
+ "description": "Transport layer for Aspectly bridge - platform detection and message passing",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.mts",
12
+ "default": "./dist/index.mjs"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ },
19
+ "./cefsharp": {
20
+ "import": {
21
+ "types": "./dist/cefsharp.d.mts",
22
+ "default": "./dist/cefsharp.mjs"
23
+ },
24
+ "require": {
25
+ "types": "./dist/cefsharp.d.ts",
26
+ "default": "./dist/cefsharp.js"
27
+ }
28
+ },
29
+ "./react-native": {
30
+ "import": {
31
+ "types": "./dist/react-native.d.mts",
32
+ "default": "./dist/react-native.mjs"
33
+ },
34
+ "require": {
35
+ "types": "./dist/react-native.d.ts",
36
+ "default": "./dist/react-native.js"
37
+ }
38
+ },
39
+ "./iframe": {
40
+ "import": {
41
+ "types": "./dist/iframe.d.mts",
42
+ "default": "./dist/iframe.mjs"
43
+ },
44
+ "require": {
45
+ "types": "./dist/iframe.d.ts",
46
+ "default": "./dist/iframe.js"
47
+ }
48
+ },
49
+ "./window": {
50
+ "import": {
51
+ "types": "./dist/window.d.mts",
52
+ "default": "./dist/window.mjs"
53
+ },
54
+ "require": {
55
+ "types": "./dist/window.d.ts",
56
+ "default": "./dist/window.js"
57
+ }
58
+ }
59
+ },
60
+ "files": [
61
+ "dist",
62
+ "src"
63
+ ],
64
+ "sideEffects": false,
65
+ "keywords": [
66
+ "aspectly",
67
+ "bridge",
68
+ "transport",
69
+ "cefsharp",
70
+ "webview",
71
+ "iframe",
72
+ "postmessage"
73
+ ],
74
+ "author": "Zhan Isaakian <jeanisahkyan@gmail.com>",
75
+ "license": "MIT",
76
+ "repository": {
77
+ "type": "git",
78
+ "url": "https://github.com/JeanIsahakyan/aspectly",
79
+ "directory": "packages/transports"
80
+ },
81
+ "publishConfig": {
82
+ "access": "public"
83
+ },
84
+ "devDependencies": {
85
+ "tsup": "^8.0.1",
86
+ "typescript": "^5.3.2",
87
+ "rimraf": "^5.0.5"
88
+ },
89
+ "scripts": {
90
+ "build": "tsup",
91
+ "dev": "tsup --watch",
92
+ "typecheck": "tsc --noEmit",
93
+ "lint": "eslint src --ext .ts,.tsx",
94
+ "clean": "rimraf dist",
95
+ "test": "vitest run"
96
+ }
97
+ }
@@ -0,0 +1,60 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { BaseTransport } from './BaseTransport';
3
+ import type { TransportListener, TransportUnsubscribe } from './types';
4
+
5
+ /**
6
+ * Concrete test implementation of BaseTransport
7
+ */
8
+ class TestTransport extends BaseTransport {
9
+ readonly name = 'test';
10
+
11
+ isAvailable(): boolean {
12
+ return this.hasWindow();
13
+ }
14
+
15
+ send(_message: string): void {
16
+ // No-op for testing
17
+ }
18
+
19
+ subscribe(_listener: TransportListener): TransportUnsubscribe {
20
+ return () => {};
21
+ }
22
+ }
23
+
24
+ describe('BaseTransport', () => {
25
+ it('should have hasWindow() return true in jsdom environment', () => {
26
+ const transport = new TestTransport();
27
+ expect(transport.isAvailable()).toBe(true);
28
+ });
29
+
30
+ it('should have getWindow() return window object in jsdom environment', () => {
31
+ const transport = new TestTransport();
32
+ // Using any to access protected method for testing
33
+ const win = (transport as any).getWindow();
34
+ expect(win).toBe(window);
35
+ });
36
+
37
+ it('should require abstract name property', () => {
38
+ const transport = new TestTransport();
39
+ expect(transport.name).toBe('test');
40
+ });
41
+
42
+ it('should require abstract isAvailable method', () => {
43
+ const transport = new TestTransport();
44
+ expect(typeof transport.isAvailable).toBe('function');
45
+ expect(typeof transport.isAvailable()).toBe('boolean');
46
+ });
47
+
48
+ it('should require abstract send method', () => {
49
+ const transport = new TestTransport();
50
+ expect(typeof transport.send).toBe('function');
51
+ expect(() => transport.send('test')).not.toThrow();
52
+ });
53
+
54
+ it('should require abstract subscribe method', () => {
55
+ const transport = new TestTransport();
56
+ expect(typeof transport.subscribe).toBe('function');
57
+ const unsubscribe = transport.subscribe(() => {});
58
+ expect(typeof unsubscribe).toBe('function');
59
+ });
60
+ });
@@ -0,0 +1,27 @@
1
+ import type { Transport, TransportListener, TransportUnsubscribe } from './types';
2
+
3
+ /**
4
+ * Abstract base class for transports
5
+ * Provides common functionality for message handling
6
+ */
7
+ export abstract class BaseTransport implements Transport {
8
+ abstract readonly name: string;
9
+
10
+ abstract isAvailable(): boolean;
11
+ abstract send(message: string): void;
12
+ abstract subscribe(listener: TransportListener): TransportUnsubscribe;
13
+
14
+ /**
15
+ * Helper to check if window is defined (for SSR safety)
16
+ */
17
+ protected hasWindow(): boolean {
18
+ return typeof window !== 'undefined';
19
+ }
20
+
21
+ /**
22
+ * Helper to safely get window object
23
+ */
24
+ protected getWindow(): Window | null {
25
+ return this.hasWindow() ? window : null;
26
+ }
27
+ }