@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.
- package/LICENSE +20 -0
- package/README.md +368 -0
- package/dist/BaseTransport-CxzIr1Ds.d.mts +80 -0
- package/dist/BaseTransport-CxzIr1Ds.d.ts +80 -0
- package/dist/cefsharp.d.mts +37 -0
- package/dist/cefsharp.d.ts +37 -0
- package/dist/cefsharp.js +65 -0
- package/dist/cefsharp.js.map +1 -0
- package/dist/cefsharp.mjs +62 -0
- package/dist/cefsharp.mjs.map +1 -0
- package/dist/iframe.d.mts +35 -0
- package/dist/iframe.d.ts +35 -0
- package/dist/iframe.js +75 -0
- package/dist/iframe.js.map +1 -0
- package/dist/iframe.mjs +72 -0
- package/dist/iframe.mjs.map +1 -0
- package/dist/index.d.mts +85 -0
- package/dist/index.d.ts +85 -0
- package/dist/index.js +374 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +358 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react-native.d.mts +36 -0
- package/dist/react-native.d.ts +36 -0
- package/dist/react-native.js +65 -0
- package/dist/react-native.js.map +1 -0
- package/dist/react-native.mjs +62 -0
- package/dist/react-native.mjs.map +1 -0
- package/dist/window.d.mts +36 -0
- package/dist/window.d.ts +36 -0
- package/dist/window.js +79 -0
- package/dist/window.js.map +1 -0
- package/dist/window.mjs +76 -0
- package/dist/window.mjs.map +1 -0
- package/package.json +97 -0
- package/src/BaseTransport.test.ts +60 -0
- package/src/BaseTransport.ts +27 -0
- package/src/TransportRegistry.test.ts +345 -0
- package/src/TransportRegistry.ts +120 -0
- package/src/cefsharp.ts +3 -0
- package/src/iframe.ts +3 -0
- package/src/index.ts +26 -0
- package/src/react-native.ts +3 -0
- package/src/transports/CefSharpTransport.test.ts +187 -0
- package/src/transports/CefSharpTransport.ts +73 -0
- package/src/transports/IframeTransport.test.ts +212 -0
- package/src/transports/IframeTransport.ts +79 -0
- package/src/transports/NullTransport.test.ts +64 -0
- package/src/transports/NullTransport.ts +27 -0
- package/src/transports/PostMessageTransport.ts +50 -0
- package/src/transports/ReactNativeTransport.test.ts +196 -0
- package/src/transports/ReactNativeTransport.ts +73 -0
- package/src/transports/WindowTransport.ts +84 -0
- package/src/types.ts +69 -0
- package/src/window.ts +3 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { BaseTransport } from '../BaseTransport';
|
|
2
|
+
import type { TransportListener, TransportUnsubscribe, TransportDetector } from '../types';
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
ReactNativeWebView?: {
|
|
7
|
+
postMessage: (message: string) => void;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Transport for React Native WebView
|
|
14
|
+
* Used when web content is displayed inside a React Native app
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { ReactNativeTransport } from '@aspectly/transports/react-native';
|
|
19
|
+
*
|
|
20
|
+
* const transport = new ReactNativeTransport();
|
|
21
|
+
* if (transport.isAvailable()) {
|
|
22
|
+
* transport.send(JSON.stringify({ type: 'hello' }));
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export class ReactNativeTransport extends BaseTransport {
|
|
27
|
+
readonly name = 'react-native';
|
|
28
|
+
|
|
29
|
+
isAvailable(): boolean {
|
|
30
|
+
const win = this.getWindow();
|
|
31
|
+
return typeof win?.ReactNativeWebView?.postMessage === 'function';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
send(message: string): void {
|
|
35
|
+
const win = this.getWindow();
|
|
36
|
+
if (!win?.ReactNativeWebView?.postMessage) {
|
|
37
|
+
console.warn('[ReactNativeTransport] ReactNativeWebView.postMessage is not available');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// React Native WebView expects message wrapped in quotes (iOS quirk)
|
|
41
|
+
win.ReactNativeWebView.postMessage(`'${message}'`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
subscribe(listener: TransportListener): TransportUnsubscribe {
|
|
45
|
+
const win = this.getWindow();
|
|
46
|
+
if (!win) {
|
|
47
|
+
return () => {};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// React Native sends messages via window.postMessage
|
|
51
|
+
const handler = (event: MessageEvent): void => {
|
|
52
|
+
if (typeof event.data === 'string') {
|
|
53
|
+
listener(event.data);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
win.addEventListener('message', handler);
|
|
58
|
+
return () => win.removeEventListener('message', handler);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Detector for auto-detection registry
|
|
64
|
+
*/
|
|
65
|
+
export const reactNativeDetector: TransportDetector = {
|
|
66
|
+
name: 'react-native',
|
|
67
|
+
priority: 90, // Second priority
|
|
68
|
+
detect: () => {
|
|
69
|
+
return typeof window !== 'undefined' &&
|
|
70
|
+
typeof window.ReactNativeWebView?.postMessage === 'function';
|
|
71
|
+
},
|
|
72
|
+
createTransport: () => new ReactNativeTransport(),
|
|
73
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { BaseTransport } from '../BaseTransport';
|
|
2
|
+
import type { TransportListener, TransportUnsubscribe, TransportDetector } from '../types';
|
|
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
|
+
export class WindowTransport extends BaseTransport {
|
|
20
|
+
readonly name = 'window';
|
|
21
|
+
private readonly targetOrigin: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create a window transport
|
|
25
|
+
* @param targetOrigin Origin to send messages to (default: '*')
|
|
26
|
+
*/
|
|
27
|
+
constructor(targetOrigin: string = '*') {
|
|
28
|
+
super();
|
|
29
|
+
this.targetOrigin = targetOrigin;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
isAvailable(): boolean {
|
|
33
|
+
const win = this.getWindow();
|
|
34
|
+
if (!win) return false;
|
|
35
|
+
return win.opener !== null && !win.opener.closed;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
send(message: string): void {
|
|
39
|
+
const win = this.getWindow();
|
|
40
|
+
if (!win) {
|
|
41
|
+
console.warn('[WindowTransport] Window is not available');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (!win.opener || win.opener.closed) {
|
|
45
|
+
console.warn('[WindowTransport] Opener window is not available');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
win.opener.postMessage(message, this.targetOrigin);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
subscribe(listener: TransportListener): TransportUnsubscribe {
|
|
52
|
+
const win = this.getWindow();
|
|
53
|
+
if (!win) {
|
|
54
|
+
return () => {};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const handler = (event: MessageEvent): void => {
|
|
58
|
+
if (typeof event.data === 'string') {
|
|
59
|
+
listener(event.data);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
win.addEventListener('message', handler);
|
|
64
|
+
return () => win.removeEventListener('message', handler);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Detector for auto-detection registry
|
|
70
|
+
*/
|
|
71
|
+
export const windowDetector: TransportDetector = {
|
|
72
|
+
name: 'window',
|
|
73
|
+
priority: 70, // Below iframe (80), above postmessage (10)
|
|
74
|
+
detect: () => {
|
|
75
|
+
try {
|
|
76
|
+
return typeof window !== 'undefined' &&
|
|
77
|
+
window.opener != null &&
|
|
78
|
+
!window.opener.closed;
|
|
79
|
+
} catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
createTransport: () => new WindowTransport(),
|
|
84
|
+
};
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message listener callback type
|
|
3
|
+
*/
|
|
4
|
+
export type TransportListener = (message: string) => void;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Cleanup function returned by subscribe
|
|
8
|
+
*/
|
|
9
|
+
export type TransportUnsubscribe = () => void;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Transport interface - defines how messages are sent and received
|
|
13
|
+
* between different environments (CefSharp, React Native, iframe, etc.)
|
|
14
|
+
*/
|
|
15
|
+
export interface Transport {
|
|
16
|
+
/**
|
|
17
|
+
* Unique name of the transport (e.g., 'cefsharp', 'react-native', 'iframe')
|
|
18
|
+
*/
|
|
19
|
+
readonly name: string;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Check if this transport is available in the current environment
|
|
23
|
+
*/
|
|
24
|
+
isAvailable(): boolean;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Send a message to the parent/host context
|
|
28
|
+
* @param message Serialized message string (usually JSON)
|
|
29
|
+
*/
|
|
30
|
+
send(message: string): void;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Subscribe to incoming messages from the parent/host context
|
|
34
|
+
* @param listener Callback function for incoming messages
|
|
35
|
+
* @returns Cleanup function to unsubscribe
|
|
36
|
+
*/
|
|
37
|
+
subscribe(listener: TransportListener): TransportUnsubscribe;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Transport factory function type
|
|
42
|
+
*/
|
|
43
|
+
export type TransportFactory = () => Transport;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Transport detector - used for auto-detection
|
|
47
|
+
*/
|
|
48
|
+
export interface TransportDetector {
|
|
49
|
+
/**
|
|
50
|
+
* Name of the transport this detector is for
|
|
51
|
+
*/
|
|
52
|
+
readonly name: string;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Priority for detection order (higher = checked first)
|
|
56
|
+
* Default priorities: CefSharp=100, ReactNative=90, Iframe=80
|
|
57
|
+
*/
|
|
58
|
+
readonly priority: number;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Check if this transport is available
|
|
62
|
+
*/
|
|
63
|
+
detect(): boolean;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Create the transport instance
|
|
67
|
+
*/
|
|
68
|
+
createTransport(): Transport;
|
|
69
|
+
}
|
package/src/window.ts
ADDED