@kookapp/web-bridge 0.0.1

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 (50) hide show
  1. package/README.md +144 -0
  2. package/dist/child/ChildBridge.d.ts +40 -0
  3. package/dist/child/ChildBridge.d.ts.map +1 -0
  4. package/dist/child/ChildBridge.js +124 -0
  5. package/dist/child/index.d.ts +4 -0
  6. package/dist/child/index.d.ts.map +1 -0
  7. package/dist/child/index.js +2 -0
  8. package/dist/child/utils.d.ts +7 -0
  9. package/dist/child/utils.d.ts.map +1 -0
  10. package/dist/child/utils.js +22 -0
  11. package/dist/constants.d.ts +29 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/constants.js +28 -0
  14. package/dist/errors/BridgeError.d.ts +21 -0
  15. package/dist/errors/BridgeError.d.ts.map +1 -0
  16. package/dist/errors/BridgeError.js +35 -0
  17. package/dist/errors/errorFactory.d.ts +14 -0
  18. package/dist/errors/errorFactory.d.ts.map +1 -0
  19. package/dist/errors/errorFactory.js +13 -0
  20. package/dist/index.d.ts +17 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +17 -0
  23. package/dist/parent/IframeChannel.d.ts +44 -0
  24. package/dist/parent/IframeChannel.d.ts.map +1 -0
  25. package/dist/parent/IframeChannel.js +96 -0
  26. package/dist/parent/ParentBridge.d.ts +41 -0
  27. package/dist/parent/ParentBridge.d.ts.map +1 -0
  28. package/dist/parent/ParentBridge.js +101 -0
  29. package/dist/parent/index.d.ts +6 -0
  30. package/dist/parent/index.d.ts.map +1 -0
  31. package/dist/parent/index.js +3 -0
  32. package/dist/parent/utils.d.ts +6 -0
  33. package/dist/parent/utils.d.ts.map +1 -0
  34. package/dist/parent/utils.js +23 -0
  35. package/dist/shared/EventEmitter.d.ts +13 -0
  36. package/dist/shared/EventEmitter.d.ts.map +1 -0
  37. package/dist/shared/EventEmitter.js +47 -0
  38. package/dist/shared/IdGenerator.d.ts +11 -0
  39. package/dist/shared/IdGenerator.d.ts.map +1 -0
  40. package/dist/shared/IdGenerator.js +16 -0
  41. package/dist/shared/MessageHandler.d.ts +75 -0
  42. package/dist/shared/MessageHandler.d.ts.map +1 -0
  43. package/dist/shared/MessageHandler.js +197 -0
  44. package/dist/shared/OriginValidator.d.ts +14 -0
  45. package/dist/shared/OriginValidator.d.ts.map +1 -0
  46. package/dist/shared/OriginValidator.js +53 -0
  47. package/dist/types.d.ts +73 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +4 -0
  50. package/package.json +31 -0
package/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # WebBridge
2
+
3
+ A PostMessage-based bridge for iframe communication, providing symmetric callHandler and registerHandler APIs similar to jsbridge but for web environments.
4
+
5
+ ## Features
6
+
7
+ - **Symmetric API**: Both parent and iframe can call handlers and register responders
8
+ - **PostMessage-based**: Uses native Web APIs for cross-origin communication
9
+ - **Origin Validation**: Strict domain whitelist verification
10
+ - **Type-Safe**: Full TypeScript support with comprehensive type definitions
11
+ - **Promise & Callback**: Supports both async/await and callback patterns
12
+ - **Error Handling**: Comprehensive error codes and timeout management
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @kookapp/web-bridge
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Parent Side (iframe外部)
23
+
24
+ ```typescript
25
+ import { ParentBridge } from '@kookapp/web-bridge'
26
+
27
+ // Initialize the bridge
28
+ const bridge = new ParentBridge({
29
+ allowedOrigins: ['https://iframe.example.com']
30
+ })
31
+
32
+ // Register a handler that can be called from iframe
33
+ bridge.registerHandler('getUserInfo', (data, callback) => {
34
+ const userInfo = { id: 1, name: 'John' }
35
+ callback(userInfo)
36
+ })
37
+
38
+ // Create a communication channel with an iframe
39
+ const iframeElement = document.getElementById('myIframe') as HTMLIFrameElement
40
+ const channel = bridge.createChannel(iframeElement)
41
+
42
+ // Call a handler inside iframe
43
+ channel.callHandler('getIframeData', { type: 'user' })
44
+ .then(result => console.log('Result:', result))
45
+ .catch(error => console.error('Error:', error))
46
+
47
+ // Clean up
48
+ // bridge.destroy()
49
+ ```
50
+
51
+ ### Child Side (iframe内部)
52
+
53
+ ```typescript
54
+ import { ChildBridge } from '@kookapp/web-bridge'
55
+
56
+ // Initialize the bridge
57
+ const bridge = new ChildBridge({
58
+ allowedOrigins: ['https://parent.example.com']
59
+ })
60
+
61
+ // Register a handler that can be called from parent
62
+ bridge.registerHandler('getIframeData', (data, callback) => {
63
+ const response = { data: 'from iframe', type: data.type }
64
+ callback(response)
65
+ })
66
+
67
+ // Call a handler on parent
68
+ bridge.callHandler('getUserInfo', {})
69
+ .then(userInfo => console.log('User:', userInfo))
70
+ .catch(error => console.error('Error:', error))
71
+ ```
72
+
73
+ ## API Reference
74
+
75
+ ### ParentBridge
76
+
77
+ ```typescript
78
+ class ParentBridge {
79
+ constructor(config: BridgeConfig)
80
+ registerHandler(handlerName: string, handler: Handler): void
81
+ createChannel(iframe: HTMLIFrameElement, options?: { origin: string }): IframeChannel
82
+ unregisterHandler(handlerName: string): void
83
+ destroy(): void
84
+ }
85
+ ```
86
+
87
+ ### IframeChannel
88
+
89
+ ```typescript
90
+ interface IframeChannel {
91
+ callHandler(handlerName: string, data?: any, callback?: (result: any) => void): Promise<any>
92
+ getIframe(): HTMLIFrameElement
93
+ isConnected(): boolean
94
+ destroy(): void
95
+ }
96
+ ```
97
+
98
+ ### ChildBridge
99
+
100
+ ```typescript
101
+ class ChildBridge {
102
+ constructor(config: BridgeConfig)
103
+ callHandler(handlerName: string, data?: any, callback?: (result: any) => void): Promise<any>
104
+ registerHandler(handlerName: string, handler: Handler): void
105
+ unregisterHandler(handlerName: string): void
106
+ destroy(): void
107
+ isConnected(): boolean
108
+ }
109
+ ```
110
+
111
+ ### BridgeConfig
112
+
113
+ ```typescript
114
+ interface BridgeConfig {
115
+ allowedOrigins: string[] // Domain whitelist (supports exact match, regex, and wildcard)
116
+ timeout?: number // Message timeout in ms (default: 5000)
117
+ debug?: boolean // Enable debug logging
118
+ maxRetries?: number // Maximum retry attempts (default: 0)
119
+ }
120
+ ```
121
+
122
+ ## Error Handling
123
+
124
+ The bridge throws `BridgeError` with specific error codes:
125
+
126
+ - `HANDLER_NOT_FOUND`: Handler not found on the other side
127
+ - `ORIGIN_NOT_ALLOWED`: Message origin not in whitelist
128
+ - `TIMEOUT`: Request exceeded timeout
129
+ - `INVALID_MESSAGE`: Malformed message received
130
+ - `CONNECTION_LOST`: Connection to other side lost
131
+
132
+ ## Security
133
+
134
+ ### Origin Validation
135
+
136
+ - Exact match: `'https://example.com'`
137
+ - Regex pattern: `'^https://.*\\.example\\.com$'`
138
+ - Wildcard (dev only): `'*'`
139
+
140
+ Origins are validated for both incoming and outgoing messages.
141
+
142
+ ## License
143
+
144
+ MIT
@@ -0,0 +1,40 @@
1
+ /**
2
+ * ChildBridge for communication from inside an iframe
3
+ */
4
+ import { ChildBridgeConfig, BridgeMessage } from '@/types';
5
+ import { MessageHandler } from '@/shared/MessageHandler';
6
+ export declare class ChildBridge extends MessageHandler {
7
+ private parentWindow;
8
+ private parentOrigin;
9
+ private connected;
10
+ constructor(config: ChildBridgeConfig);
11
+ /**
12
+ * Get parent origin
13
+ */
14
+ private getParentOrigin;
15
+ /**
16
+ * Notify parent that child is ready
17
+ */
18
+ private notifyReady;
19
+ /**
20
+ * Call a handler on parent
21
+ */
22
+ callHandler(handlerName: string, data?: any, callback?: (result: any) => void): Promise<any>;
23
+ /**
24
+ * Send message to parent
25
+ */
26
+ protected sendMessage(targetOrigin: string, message: BridgeMessage): void;
27
+ /**
28
+ * Get target origin
29
+ */
30
+ protected getTargetOrigin(): string;
31
+ /**
32
+ * Check if connected to parent
33
+ */
34
+ isConnected(): boolean;
35
+ /**
36
+ * Destroy the bridge
37
+ */
38
+ destroy(): void;
39
+ }
40
+ //# sourceMappingURL=ChildBridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChildBridge.d.ts","sourceRoot":"","sources":["../../src/child/ChildBridge.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAGxD,qBAAa,WAAY,SAAQ,cAAc;IAC7C,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAiB;gBAEtB,MAAM,EAAE,iBAAiB;IA+BrC;;OAEG;IACH,OAAO,CAAC,eAAe;IAyBvB;;OAEG;IACH,OAAO,CAAC,WAAW;IAgBnB;;OAEG;IACG,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,GAAG,EACV,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,GAC/B,OAAO,CAAC,GAAG,CAAC;IAUf;;OAEG;IACH,SAAS,CAAC,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI;IAezE;;OAEG;IACH,SAAS,CAAC,eAAe,IAAI,MAAM;IAInC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,OAAO,IAAI,IAAI;CAQhB"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * ChildBridge for communication from inside an iframe
3
+ */
4
+ import { MessageHandler } from '@/shared/MessageHandler';
5
+ import { DEFAULT_TIMEOUT } from '@/constants';
6
+ export class ChildBridge extends MessageHandler {
7
+ constructor(config) {
8
+ const timeout = config.timeout || DEFAULT_TIMEOUT;
9
+ super(config.allowedOrigins, timeout, config.debug);
10
+ this.connected = false;
11
+ // Get parent window and origin
12
+ this.parentWindow = window.parent;
13
+ this.parentOrigin = this.getParentOrigin(config.allowedOrigins);
14
+ // Setup message listener
15
+ this.setupMessageListener((event) => {
16
+ // Only accept messages from parent
17
+ if (event.source === this.parentWindow) {
18
+ this.handleMessage(event.data, event.origin);
19
+ if (!this.connected) {
20
+ this.connected = true;
21
+ this.eventEmitter.emit('ready');
22
+ }
23
+ }
24
+ });
25
+ // Notify parent that we're ready
26
+ this.notifyReady();
27
+ if (this.debug) {
28
+ console.log('[WebBridge] ChildBridge initialized', {
29
+ parentOrigin: this.parentOrigin,
30
+ allowedOrigins: config.allowedOrigins
31
+ });
32
+ }
33
+ }
34
+ /**
35
+ * Get parent origin
36
+ */
37
+ getParentOrigin(allowedOrigins) {
38
+ // If wildcard is allowed, use it
39
+ if (allowedOrigins.includes('*')) {
40
+ return '*';
41
+ }
42
+ // Try to get document.referrer as parent origin
43
+ if (document.referrer) {
44
+ try {
45
+ return new URL(document.referrer).origin;
46
+ }
47
+ catch {
48
+ // If referrer is not a valid URL, fall back to *
49
+ }
50
+ }
51
+ // Fall back to the first allowed origin if it's specific
52
+ const specificOrigins = allowedOrigins.filter(o => o !== '*');
53
+ if (specificOrigins.length > 0) {
54
+ return specificOrigins[0];
55
+ }
56
+ // Last resort: use wildcard
57
+ return '*';
58
+ }
59
+ /**
60
+ * Notify parent that child is ready
61
+ */
62
+ notifyReady() {
63
+ try {
64
+ this.parentWindow.postMessage({
65
+ type: 'ready',
66
+ _version: '1.0.0'
67
+ }, this.parentOrigin);
68
+ }
69
+ catch (error) {
70
+ if (this.debug) {
71
+ console.warn('[WebBridge] Failed to notify parent:', error);
72
+ }
73
+ }
74
+ }
75
+ /**
76
+ * Call a handler on parent
77
+ */
78
+ async callHandler(handlerName, data, callback) {
79
+ const promise = this.callHandlerWithTimeout(this.parentOrigin, handlerName, data);
80
+ if (callback) {
81
+ promise.then(callback).catch(error => console.error(error));
82
+ }
83
+ return promise;
84
+ }
85
+ /**
86
+ * Send message to parent
87
+ */
88
+ sendMessage(targetOrigin, message) {
89
+ try {
90
+ message._version = '1.0.0';
91
+ this.parentWindow.postMessage(message, targetOrigin);
92
+ if (this.debug) {
93
+ console.log('[WebBridge] Sent message to parent:', message);
94
+ }
95
+ }
96
+ catch (error) {
97
+ if (this.debug) {
98
+ console.error('[WebBridge] Failed to send message to parent:', error);
99
+ }
100
+ }
101
+ }
102
+ /**
103
+ * Get target origin
104
+ */
105
+ getTargetOrigin() {
106
+ return this.parentOrigin;
107
+ }
108
+ /**
109
+ * Check if connected to parent
110
+ */
111
+ isConnected() {
112
+ return this.connected;
113
+ }
114
+ /**
115
+ * Destroy the bridge
116
+ */
117
+ destroy() {
118
+ this.connected = false;
119
+ super.destroy();
120
+ if (this.debug) {
121
+ console.log('[WebBridge] ChildBridge destroyed');
122
+ }
123
+ }
124
+ }
@@ -0,0 +1,4 @@
1
+ export { ChildBridge } from '@/child/ChildBridge';
2
+ export type { ChildBridgeConfig } from '@/types';
3
+ export * from '@/child/utils';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/child/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAChD,cAAc,eAAe,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { ChildBridge } from '@/child/ChildBridge';
2
+ export * from '@/child/utils';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Utility functions for child bridge
3
+ */
4
+ export declare function isInIframe(): boolean;
5
+ export declare function getParentWindow(): Window;
6
+ export declare function getTopWindow(): Window;
7
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/child/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,UAAU,IAAI,OAAO,CAMpC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAMrC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Utility functions for child bridge
3
+ */
4
+ export function isInIframe() {
5
+ try {
6
+ return window.self !== window.top;
7
+ }
8
+ catch {
9
+ return true;
10
+ }
11
+ }
12
+ export function getParentWindow() {
13
+ return window.parent;
14
+ }
15
+ export function getTopWindow() {
16
+ try {
17
+ return window.top || window;
18
+ }
19
+ catch {
20
+ return window;
21
+ }
22
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Constants for WebBridge
3
+ */
4
+ export declare const BRIDGE_VERSION = "1.0.0";
5
+ export declare const DEFAULT_TIMEOUT = 5000;
6
+ export declare const DEFAULT_MAX_RETRIES = 0;
7
+ export declare const MESSAGE_TYPE: {
8
+ CALL: "call";
9
+ RESPONSE: "response";
10
+ REGISTER: "register";
11
+ READY: "ready";
12
+ };
13
+ export declare const ERROR_CODE: {
14
+ readonly HANDLER_NOT_FOUND: "HANDLER_NOT_FOUND";
15
+ readonly ORIGIN_NOT_ALLOWED: "ORIGIN_NOT_ALLOWED";
16
+ readonly TIMEOUT: "TIMEOUT";
17
+ readonly INVALID_MESSAGE: "INVALID_MESSAGE";
18
+ readonly CONNECTION_LOST: "CONNECTION_LOST";
19
+ readonly INVALID_CONFIG: "INVALID_CONFIG";
20
+ };
21
+ export declare const ERROR_MESSAGE: {
22
+ readonly HANDLER_NOT_FOUND: "Handler not found";
23
+ readonly ORIGIN_NOT_ALLOWED: "Origin not allowed";
24
+ readonly TIMEOUT: "Request timeout";
25
+ readonly INVALID_MESSAGE: "Invalid message format";
26
+ readonly CONNECTION_LOST: "Connection lost";
27
+ readonly INVALID_CONFIG: "Invalid configuration";
28
+ };
29
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,cAAc,UAAU,CAAA;AAErC,eAAO,MAAM,eAAe,OAAO,CAAA;AAEnC,eAAO,MAAM,mBAAmB,IAAI,CAAA;AAEpC,eAAO,MAAM,YAAY;;;;;CAKxB,CAAA;AAED,eAAO,MAAM,UAAU;;;;;;;CAOb,CAAA;AAEV,eAAO,MAAM,aAAa;;;;;;;CAOhB,CAAA"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Constants for WebBridge
3
+ */
4
+ export const BRIDGE_VERSION = '1.0.0';
5
+ export const DEFAULT_TIMEOUT = 5000; // 5 seconds
6
+ export const DEFAULT_MAX_RETRIES = 0;
7
+ export const MESSAGE_TYPE = {
8
+ CALL: 'call',
9
+ RESPONSE: 'response',
10
+ REGISTER: 'register',
11
+ READY: 'ready'
12
+ };
13
+ export const ERROR_CODE = {
14
+ HANDLER_NOT_FOUND: 'HANDLER_NOT_FOUND',
15
+ ORIGIN_NOT_ALLOWED: 'ORIGIN_NOT_ALLOWED',
16
+ TIMEOUT: 'TIMEOUT',
17
+ INVALID_MESSAGE: 'INVALID_MESSAGE',
18
+ CONNECTION_LOST: 'CONNECTION_LOST',
19
+ INVALID_CONFIG: 'INVALID_CONFIG'
20
+ };
21
+ export const ERROR_MESSAGE = {
22
+ [ERROR_CODE.HANDLER_NOT_FOUND]: 'Handler not found',
23
+ [ERROR_CODE.ORIGIN_NOT_ALLOWED]: 'Origin not allowed',
24
+ [ERROR_CODE.TIMEOUT]: 'Request timeout',
25
+ [ERROR_CODE.INVALID_MESSAGE]: 'Invalid message format',
26
+ [ERROR_CODE.CONNECTION_LOST]: 'Connection lost',
27
+ [ERROR_CODE.INVALID_CONFIG]: 'Invalid configuration'
28
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Custom error class for WebBridge
3
+ */
4
+ import { ERROR_CODE } from '@/constants';
5
+ export type BridgeErrorCode = keyof typeof ERROR_CODE;
6
+ export declare class BridgeError extends Error {
7
+ code: BridgeErrorCode;
8
+ originalError?: Error;
9
+ constructor(code: BridgeErrorCode, message?: string, originalError?: Error);
10
+ static create(code: BridgeErrorCode, message?: string, originalError?: Error): BridgeError;
11
+ static isHandlerNotFound(error: any): boolean;
12
+ static isOriginNotAllowed(error: any): boolean;
13
+ static isTimeout(error: any): boolean;
14
+ toJSON(): {
15
+ name: string;
16
+ code: "HANDLER_NOT_FOUND" | "ORIGIN_NOT_ALLOWED" | "TIMEOUT" | "INVALID_MESSAGE" | "CONNECTION_LOST" | "INVALID_CONFIG";
17
+ message: string;
18
+ originalError: string;
19
+ };
20
+ }
21
+ //# sourceMappingURL=BridgeError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BridgeError.d.ts","sourceRoot":"","sources":["../../src/errors/BridgeError.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAiB,MAAM,aAAa,CAAA;AAEvD,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,UAAU,CAAA;AAErD,qBAAa,WAAY,SAAQ,KAAK;IACpC,IAAI,EAAE,eAAe,CAAA;IACrB,aAAa,CAAC,EAAE,KAAK,CAAA;gBAET,IAAI,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,KAAK;IAW1E,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,KAAK,GAAG,WAAW;IAI1F,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO;IAI7C,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO;IAI9C,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO;IAIrC,MAAM;;;;;;CAQP"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Custom error class for WebBridge
3
+ */
4
+ import { ERROR_MESSAGE } from '@/constants';
5
+ export class BridgeError extends Error {
6
+ constructor(code, message, originalError) {
7
+ const errorMessage = message || ERROR_MESSAGE[code] || 'Unknown error';
8
+ super(errorMessage);
9
+ this.name = 'BridgeError';
10
+ this.code = code;
11
+ this.originalError = originalError;
12
+ // Maintain proper prototype chain for instanceof checks
13
+ Object.setPrototypeOf(this, BridgeError.prototype);
14
+ }
15
+ static create(code, message, originalError) {
16
+ return new BridgeError(code, message, originalError);
17
+ }
18
+ static isHandlerNotFound(error) {
19
+ return error instanceof BridgeError && error.code === 'HANDLER_NOT_FOUND';
20
+ }
21
+ static isOriginNotAllowed(error) {
22
+ return error instanceof BridgeError && error.code === 'ORIGIN_NOT_ALLOWED';
23
+ }
24
+ static isTimeout(error) {
25
+ return error instanceof BridgeError && error.code === 'TIMEOUT';
26
+ }
27
+ toJSON() {
28
+ return {
29
+ name: this.name,
30
+ code: this.code,
31
+ message: this.message,
32
+ originalError: this.originalError?.message
33
+ };
34
+ }
35
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Error factory functions
3
+ */
4
+ import { BridgeError, BridgeErrorCode } from '@/errors/BridgeError';
5
+ export declare const errorFactory: {
6
+ handlerNotFound: (handlerName: string) => BridgeError;
7
+ originNotAllowed: (origin: string) => BridgeError;
8
+ timeout: (timeout: number) => BridgeError;
9
+ invalidMessage: (message: string) => BridgeError;
10
+ connectionLost: () => BridgeError;
11
+ invalidConfig: (message: string) => BridgeError;
12
+ wrap: (code: BridgeErrorCode, originalError: Error, message?: string) => BridgeError;
13
+ };
14
+ //# sourceMappingURL=errorFactory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorFactory.d.ts","sourceRoot":"","sources":["../../src/errors/errorFactory.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEnE,eAAO,MAAM,YAAY;mCACQ,MAAM;+BAGV,MAAM;uBAGd,MAAM;8BAGC,MAAM;;6BAMP,MAAM;iBAGlB,eAAe,iBAAiB,KAAK,YAAY,MAAM;CAErE,CAAA"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Error factory functions
3
+ */
4
+ import { BridgeError } from '@/errors/BridgeError';
5
+ export const errorFactory = {
6
+ handlerNotFound: (handlerName) => BridgeError.create('HANDLER_NOT_FOUND', `Handler "${handlerName}" not found`),
7
+ originNotAllowed: (origin) => BridgeError.create('ORIGIN_NOT_ALLOWED', `Origin "${origin}" not allowed`),
8
+ timeout: (timeout) => BridgeError.create('TIMEOUT', `Request timeout after ${timeout}ms`),
9
+ invalidMessage: (message) => BridgeError.create('INVALID_MESSAGE', `Invalid message: ${message}`),
10
+ connectionLost: () => BridgeError.create('CONNECTION_LOST', 'Connection to the other side was lost'),
11
+ invalidConfig: (message) => BridgeError.create('INVALID_CONFIG', `Invalid configuration: ${message}`),
12
+ wrap: (code, originalError, message) => BridgeError.create(code, message || originalError.message, originalError)
13
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Main entry point for WebBridge
3
+ */
4
+ export { ParentBridge } from '@/parent/index';
5
+ export type { ParentBridgeConfig, IframeChannelInterface } from '@/parent/index';
6
+ export { IframeChannel } from '@/parent/IframeChannel';
7
+ export { ChildBridge } from '@/child/index';
8
+ export type { ChildBridgeConfig } from '@/child/index';
9
+ export type { BridgeConfig, BridgeMessage, Handler, HandlerRegistry, MessageType } from '@/types';
10
+ export { BridgeError } from '@/errors/BridgeError';
11
+ export type { BridgeErrorCode } from '@/errors/BridgeError';
12
+ export { errorFactory } from '@/errors/errorFactory';
13
+ export { BRIDGE_VERSION, DEFAULT_TIMEOUT, ERROR_CODE, MESSAGE_TYPE } from '@/constants';
14
+ export { EventEmitter } from '@/shared/EventEmitter';
15
+ export { OriginValidator } from '@/shared/OriginValidator';
16
+ export { IdGenerator } from '@/shared/IdGenerator';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAGtD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAGtD,YAAY,EACV,YAAY,EACZ,aAAa,EACb,OAAO,EACP,eAAe,EACf,WAAW,EACZ,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAGpD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAGvF,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Main entry point for WebBridge
3
+ */
4
+ // Export parent bridge
5
+ export { ParentBridge } from '@/parent/index';
6
+ export { IframeChannel } from '@/parent/IframeChannel';
7
+ // Export child bridge
8
+ export { ChildBridge } from '@/child/index';
9
+ // Export error handling
10
+ export { BridgeError } from '@/errors/BridgeError';
11
+ export { errorFactory } from '@/errors/errorFactory';
12
+ // Export constants
13
+ export { BRIDGE_VERSION, DEFAULT_TIMEOUT, ERROR_CODE, MESSAGE_TYPE } from '@/constants';
14
+ // Export utilities
15
+ export { EventEmitter } from '@/shared/EventEmitter';
16
+ export { OriginValidator } from '@/shared/OriginValidator';
17
+ export { IdGenerator } from '@/shared/IdGenerator';
@@ -0,0 +1,44 @@
1
+ /**
2
+ * IframeChannel for managing communication with a specific iframe
3
+ */
4
+ import { BridgeMessage, IframeChannelInterface } from '@/types';
5
+ import { MessageHandler } from '@/shared/MessageHandler';
6
+ export declare class IframeChannel extends MessageHandler implements IframeChannelInterface {
7
+ private iframe;
8
+ private iframeOrigin;
9
+ private connected;
10
+ constructor(iframe: HTMLIFrameElement, allowedOrigins: string[], timeout?: number, debug?: boolean);
11
+ /**
12
+ * Extract origin from URL
13
+ */
14
+ private extractOrigin;
15
+ /**
16
+ * Call a handler in the iframe
17
+ */
18
+ callHandler(handlerName: string, data?: any, callback?: (result: any) => void): Promise<any>;
19
+ /**
20
+ * Send message to iframe
21
+ */
22
+ protected sendMessage(targetOrigin: string, message: BridgeMessage): void;
23
+ /**
24
+ * Get target origin (for this channel, it's the iframe origin)
25
+ */
26
+ protected getTargetOrigin(): string;
27
+ /**
28
+ * Get the iframe element
29
+ */
30
+ getIframe(): HTMLIFrameElement;
31
+ /**
32
+ * Check if connected
33
+ */
34
+ isConnected(): boolean;
35
+ /**
36
+ * Set connected status
37
+ */
38
+ setConnected(connected: boolean): void;
39
+ /**
40
+ * Destroy the channel
41
+ */
42
+ destroy(): void;
43
+ }
44
+ //# sourceMappingURL=IframeChannel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IframeChannel.d.ts","sourceRoot":"","sources":["../../src/parent/IframeChannel.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAExD,qBAAa,aAAc,SAAQ,cAAe,YAAW,sBAAsB;IACjF,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAiB;gBAGhC,MAAM,EAAE,iBAAiB,EACzB,cAAc,EAAE,MAAM,EAAE,EACxB,OAAO,GAAE,MAAa,EACtB,KAAK,GAAE,OAAe;IAmBxB;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB;;OAEG;IACG,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,GAAG,EACV,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,GAC/B,OAAO,CAAC,GAAG,CAAC;IAcf;;OAEG;IACH,SAAS,CAAC,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI;IAkBzE;;OAEG;IACH,SAAS,CAAC,eAAe,IAAI,MAAM;IAInC;;OAEG;IACH,SAAS,IAAI,iBAAiB;IAI9B;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAItC;;OAEG;IACH,OAAO,IAAI,IAAI;CAIhB"}