@schoolpalm/message-bridge 0.1.0 → 1.2.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/dist/bridgeBase.d.ts +6 -52
- package/dist/bridgeBase.d.ts.map +1 -1
- package/dist/bridgeBase.js +40 -47
- package/dist/bridgeBase.js.map +1 -1
- package/dist/hostBridge.d.ts +9 -41
- package/dist/hostBridge.d.ts.map +1 -1
- package/dist/hostBridge.js +39 -40
- package/dist/hostBridge.js.map +1 -1
- package/dist/messageTypes.d.ts +2 -1
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js +1 -0
- package/dist/messageTypes.js.map +1 -1
- package/dist/moduleBridge.d.ts +7 -47
- package/dist/moduleBridge.d.ts.map +1 -1
- package/dist/moduleBridge.js +27 -49
- package/dist/moduleBridge.js.map +1 -1
- package/dist/payloadSchemas.d.ts +40 -61
- package/dist/payloadSchemas.d.ts.map +1 -1
- package/dist/payloadSchemas.js +0 -4
- package/dist/payloadSchemas.js.map +1 -1
- package/package.json +21 -4
- package/TODO.md +0 -13
- package/dist/__tests__/bridge.test.d.ts +0 -6
- package/dist/__tests__/bridge.test.d.ts.map +0 -1
- package/dist/__tests__/bridge.test.js +0 -84
- package/dist/__tests__/bridge.test.js.map +0 -1
- package/src/__tests__/bridge.test.ts +0 -100
- package/src/bridgeBase.ts +0 -93
- package/src/hostBridge.ts +0 -63
- package/src/index.ts +0 -20
- package/src/messageTypes.ts +0 -40
- package/src/moduleBridge.ts +0 -79
- package/src/payloadSchemas.ts +0 -115
- package/tsconfig.json +0 -18
- package/vitest.config.ts +0 -8
package/dist/payloadSchemas.d.ts
CHANGED
|
@@ -1,97 +1,76 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Payload schema definitions for message-based communication.
|
|
3
|
-
* @module @schoolpalm/message-bridge/payloadSchemas
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Payload interfaces for each message type in the bridge communication protocol.
|
|
7
|
-
*
|
|
8
|
-
* These interfaces define the structure of data exchanged between host applications
|
|
9
|
-
* and embedded modules. Each payload corresponds to a specific message type and
|
|
10
|
-
* contains the necessary information for that communication scenario.
|
|
11
|
-
*/
|
|
12
1
|
/**
|
|
13
2
|
* Payload for handshake ready message.
|
|
14
|
-
*
|
|
3
|
+
* Module → Host
|
|
15
4
|
*/
|
|
16
5
|
export interface HandshakeReadyPayload {
|
|
17
|
-
/** Version of the module or SDK */
|
|
18
6
|
version: string;
|
|
19
|
-
/** Timestamp when the handshake was initiated */
|
|
20
7
|
timestamp: number;
|
|
21
8
|
}
|
|
22
9
|
/**
|
|
23
|
-
* Payload for
|
|
24
|
-
*
|
|
10
|
+
* Payload for starting a module.
|
|
11
|
+
* Host → Module
|
|
25
12
|
*/
|
|
26
13
|
export interface ModuleStartPayload {
|
|
27
|
-
|
|
14
|
+
moduleId: string;
|
|
28
15
|
route: string;
|
|
29
|
-
/** Context data passed to the module (user info, permissions, etc.) */
|
|
30
16
|
context: Record<string, any>;
|
|
31
|
-
/** Timestamp when the module start was requested */
|
|
32
17
|
timestamp: number;
|
|
33
18
|
}
|
|
34
19
|
/**
|
|
35
|
-
* Payload for
|
|
36
|
-
*
|
|
20
|
+
* Payload for module exit
|
|
21
|
+
* Host → Module
|
|
22
|
+
*/
|
|
23
|
+
export interface ModuleExitPayload {
|
|
24
|
+
reason?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Payload for UI updates from module
|
|
28
|
+
* Module → Host
|
|
37
29
|
*/
|
|
38
30
|
export interface UIUpdatePayload {
|
|
39
|
-
/** Title to display in the host UI */
|
|
40
31
|
title: string;
|
|
41
|
-
/** Breadcrumb navigation path */
|
|
42
32
|
breadcrumb: string[];
|
|
43
|
-
/** Optional theme to apply to the host UI */
|
|
44
33
|
theme?: string;
|
|
45
34
|
}
|
|
46
35
|
/**
|
|
47
|
-
* Payload for
|
|
48
|
-
*
|
|
36
|
+
* Payload for errors
|
|
37
|
+
* Module → Host
|
|
49
38
|
*/
|
|
50
|
-
export interface
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
action: string;
|
|
55
|
-
/** Optional payload data for the request */
|
|
56
|
-
payload?: Record<string, any>;
|
|
39
|
+
export interface ErrorPayload {
|
|
40
|
+
code: string;
|
|
41
|
+
message: string;
|
|
42
|
+
details?: any;
|
|
57
43
|
}
|
|
58
44
|
/**
|
|
59
|
-
* Payload for
|
|
60
|
-
*
|
|
45
|
+
* Payload for context updates
|
|
46
|
+
* Host → Module
|
|
61
47
|
*/
|
|
62
|
-
export interface
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
/** Response data (present on success) */
|
|
68
|
-
payload?: any;
|
|
48
|
+
export interface ModuleContextPayload {
|
|
49
|
+
user?: Record<string, any>;
|
|
50
|
+
tenant?: Record<string, any>;
|
|
51
|
+
permissions?: string[];
|
|
52
|
+
theme?: string;
|
|
69
53
|
}
|
|
70
54
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
55
|
+
* Request payload (sent by requester)
|
|
56
|
+
* Can be Module → Host or Host → Module
|
|
73
57
|
*/
|
|
74
|
-
export interface
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
message: string;
|
|
79
|
-
/** Optional additional error details */
|
|
80
|
-
details?: any;
|
|
58
|
+
export interface RequestPayload {
|
|
59
|
+
requestId: string;
|
|
60
|
+
type: string;
|
|
61
|
+
payload?: Record<string, any>;
|
|
81
62
|
}
|
|
82
63
|
/**
|
|
83
|
-
*
|
|
84
|
-
* Sent by host to signal module termination.
|
|
64
|
+
* Response payload (sent by responder)
|
|
85
65
|
*/
|
|
86
|
-
export interface
|
|
87
|
-
|
|
88
|
-
|
|
66
|
+
export interface ResponsePayload {
|
|
67
|
+
requestId: string;
|
|
68
|
+
status: 'success' | 'error';
|
|
69
|
+
payload?: any;
|
|
70
|
+
error?: string;
|
|
89
71
|
}
|
|
90
72
|
/**
|
|
91
|
-
* Union type representing all
|
|
92
|
-
*
|
|
93
|
-
* This type is used internally for type safety when handling messages
|
|
94
|
-
* of any type in the bridge classes.
|
|
73
|
+
* Union type representing all payloads
|
|
95
74
|
*/
|
|
96
|
-
export type MessagePayload = HandshakeReadyPayload | ModuleStartPayload | UIUpdatePayload |
|
|
75
|
+
export type MessagePayload = HandshakeReadyPayload | ModuleStartPayload | ModuleExitPayload | UIUpdatePayload | ErrorPayload | ModuleContextPayload | RequestPayload | ResponsePayload;
|
|
97
76
|
//# sourceMappingURL=payloadSchemas.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payloadSchemas.d.ts","sourceRoot":"","sources":["../src/payloadSchemas.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"payloadSchemas.d.ts","sourceRoot":"","sources":["../src/payloadSchemas.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,GAAG,CAAA;CACd;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,SAAS,GAAG,OAAO,CAAA;IAC3B,OAAO,CAAC,EAAE,GAAG,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,qBAAqB,GACrB,kBAAkB,GAClB,iBAAiB,GACjB,eAAe,GACf,YAAY,GACZ,oBAAoB,GACpB,cAAc,GACd,eAAe,CAAA"}
|
package/dist/payloadSchemas.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payloadSchemas.js","sourceRoot":"","sources":["../src/payloadSchemas.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"payloadSchemas.js","sourceRoot":"","sources":["../src/payloadSchemas.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schoolpalm/message-bridge",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "TypeScript SDK for message-based communication between SchoolPalm host and vendor modules.",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"AUTHORS"
|
|
21
|
+
],
|
|
22
|
+
|
|
7
23
|
"scripts": {
|
|
8
24
|
"build": "tsc",
|
|
9
25
|
"watch": "tsc -w",
|
|
10
26
|
"lint": "eslint 'src/**/*.{ts,tsx}' --fix",
|
|
11
27
|
"prepublishOnly": "npm run build",
|
|
12
|
-
|
|
13
|
-
|
|
28
|
+
"test": "vitest",
|
|
29
|
+
"test:watch": "vitest --watch"
|
|
14
30
|
},
|
|
31
|
+
|
|
15
32
|
"keywords": [
|
|
16
33
|
"schoolpalm",
|
|
17
34
|
"vue",
|
|
@@ -19,11 +36,11 @@
|
|
|
19
36
|
"module",
|
|
20
37
|
"iframe",
|
|
21
38
|
"postMessage",
|
|
22
|
-
"Unnovate Brains",
|
|
23
39
|
"typescript"
|
|
24
40
|
],
|
|
25
41
|
"author": "Hassan Mugabo",
|
|
26
42
|
"license": "MIT",
|
|
43
|
+
|
|
27
44
|
"devDependencies": {
|
|
28
45
|
"@types/jsdom": "^27.0.0",
|
|
29
46
|
"@typescript-eslint/eslint-plugin": "^6.5.1",
|
package/TODO.md
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# TODO: Project Documentation and Enhancement
|
|
2
|
-
|
|
3
|
-
## Tasks
|
|
4
|
-
- [x] Enhance README.md with detailed documentation
|
|
5
|
-
- [x] Add doc comments to src/index.ts
|
|
6
|
-
- [x] Add doc comments to src/bridgeBase.ts
|
|
7
|
-
- [x] Add doc comments to src/hostBridge.ts
|
|
8
|
-
- [x] Add doc comments to src/moduleBridge.ts
|
|
9
|
-
- [x] Add doc comments to src/messageTypes.ts
|
|
10
|
-
- [x] Add doc comments to src/payloadSchemas.ts
|
|
11
|
-
- [x] Add doc comments to src/__tests__/bridge.test.ts
|
|
12
|
-
- [x] Create AUTHORS file for npm package
|
|
13
|
-
- [x] Verify LICENSE and package.json setup
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/bridge.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Test suite for the MessageBridge SDK.
|
|
3
|
-
* @module @schoolpalm/message-bridge/__tests__/bridge.test
|
|
4
|
-
*/
|
|
5
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
6
|
-
import { HostBridge, ModuleBridge, MessageType } from '../index';
|
|
7
|
-
/**
|
|
8
|
-
* Test suite for the MessageBridge SDK.
|
|
9
|
-
*
|
|
10
|
-
* This suite tests the core functionality of both HostBridge and ModuleBridge
|
|
11
|
-
* classes, including message sending, receiving, and event handling.
|
|
12
|
-
*/
|
|
13
|
-
describe('MessageBridge SDK', () => {
|
|
14
|
-
let iframeMock;
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
// Simulate an iframe with contentWindow
|
|
17
|
-
iframeMock = {
|
|
18
|
-
contentWindow: {
|
|
19
|
-
postMessage: vi.fn()
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
// Mock parent window for ModuleBridge
|
|
23
|
-
vi.stubGlobal('parent', {
|
|
24
|
-
postMessage: vi.fn()
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
// -----------------------
|
|
28
|
-
// HostBridge Tests
|
|
29
|
-
// -----------------------
|
|
30
|
-
/**
|
|
31
|
-
* Test that HostBridge sends module-start messages correctly.
|
|
32
|
-
*/
|
|
33
|
-
it('HostBridge sends module-start correctly', () => {
|
|
34
|
-
const hostBridge = new HostBridge(iframeMock);
|
|
35
|
-
hostBridge.sendModuleStart({ route: '/users', context: {}, timestamp: Date.now() });
|
|
36
|
-
expect(iframeMock.contentWindow.postMessage).toHaveBeenCalledTimes(1);
|
|
37
|
-
const callArg = iframeMock.contentWindow.postMessage.mock.calls[0][0];
|
|
38
|
-
expect(callArg.type).toBe(MessageType.MODULE_START);
|
|
39
|
-
expect(callArg.payload.route).toBe('/users');
|
|
40
|
-
});
|
|
41
|
-
/**
|
|
42
|
-
* Test that HostBridge can register listeners and receive messages.
|
|
43
|
-
*/
|
|
44
|
-
it('HostBridge can register and receive messages', () => {
|
|
45
|
-
const hostBridge = new HostBridge(iframeMock);
|
|
46
|
-
const callback = vi.fn();
|
|
47
|
-
hostBridge.on(MessageType.UI_UPDATE, callback);
|
|
48
|
-
// Simulate incoming postMessage from iframe
|
|
49
|
-
const event = new MessageEvent('message', {
|
|
50
|
-
data: {
|
|
51
|
-
type: MessageType.UI_UPDATE,
|
|
52
|
-
payload: { title: 'Test', breadcrumb: ['Home'] }
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
window.dispatchEvent(event);
|
|
56
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
57
|
-
expect(callback.mock.calls[0][0].title).toBe('Test');
|
|
58
|
-
});
|
|
59
|
-
// -----------------------
|
|
60
|
-
// ModuleBridge Tests
|
|
61
|
-
// -----------------------
|
|
62
|
-
/**
|
|
63
|
-
* Test that ModuleBridge sends handshake messages correctly.
|
|
64
|
-
*/
|
|
65
|
-
it('ModuleBridge sends handshake correctly', () => {
|
|
66
|
-
const moduleBridge = new ModuleBridge();
|
|
67
|
-
moduleBridge.sendHandshake({ version: '0.1.0', timestamp: Date.now() });
|
|
68
|
-
expect(window.parent.postMessage).toHaveBeenCalledTimes(1);
|
|
69
|
-
const callArg = window.parent.postMessage.mock.calls[0][0];
|
|
70
|
-
expect(callArg.type).toBe(MessageType.HANDSHAKE_READY);
|
|
71
|
-
expect(callArg.payload.version).toBe('0.1.0');
|
|
72
|
-
});
|
|
73
|
-
/**
|
|
74
|
-
* Test that ModuleBridge sends UI update messages.
|
|
75
|
-
*/
|
|
76
|
-
it('ModuleBridge sends UI update', () => {
|
|
77
|
-
const moduleBridge = new ModuleBridge();
|
|
78
|
-
moduleBridge.sendUIUpdate({ title: 'Users', breadcrumb: ['Home', 'Users'] });
|
|
79
|
-
const callArg = window.parent.postMessage.mock.calls[0][0];
|
|
80
|
-
expect(callArg.type).toBe(MessageType.UI_UPDATE);
|
|
81
|
-
expect(callArg.payload.breadcrumb.length).toBe(2);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
//# sourceMappingURL=bridge.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.test.js","sourceRoot":"","sources":["../../src/__tests__/bridge.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Test suite for the MessageBridge SDK.
|
|
3
|
-
* @module @schoolpalm/message-bridge/__tests__/bridge.test
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
7
|
-
import { HostBridge, ModuleBridge, MessageType } from '../index';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Test suite for the MessageBridge SDK.
|
|
11
|
-
*
|
|
12
|
-
* This suite tests the core functionality of both HostBridge and ModuleBridge
|
|
13
|
-
* classes, including message sending, receiving, and event handling.
|
|
14
|
-
*/
|
|
15
|
-
describe('MessageBridge SDK', () => {
|
|
16
|
-
let iframeMock: any;
|
|
17
|
-
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
// Simulate an iframe with contentWindow
|
|
20
|
-
iframeMock = {
|
|
21
|
-
contentWindow: {
|
|
22
|
-
postMessage: vi.fn()
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// Mock parent window for ModuleBridge
|
|
27
|
-
vi.stubGlobal('parent', {
|
|
28
|
-
postMessage: vi.fn()
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
// -----------------------
|
|
33
|
-
// HostBridge Tests
|
|
34
|
-
// -----------------------
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Test that HostBridge sends module-start messages correctly.
|
|
38
|
-
*/
|
|
39
|
-
it('HostBridge sends module-start correctly', () => {
|
|
40
|
-
const hostBridge = new HostBridge(iframeMock);
|
|
41
|
-
hostBridge.sendModuleStart({ route: '/users', context: {}, timestamp: Date.now() });
|
|
42
|
-
|
|
43
|
-
expect(iframeMock.contentWindow.postMessage).toHaveBeenCalledTimes(1);
|
|
44
|
-
const callArg = iframeMock.contentWindow.postMessage.mock.calls[0][0];
|
|
45
|
-
expect(callArg.type).toBe(MessageType.MODULE_START);
|
|
46
|
-
expect(callArg.payload.route).toBe('/users');
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Test that HostBridge can register listeners and receive messages.
|
|
51
|
-
*/
|
|
52
|
-
it('HostBridge can register and receive messages', () => {
|
|
53
|
-
const hostBridge = new HostBridge(iframeMock);
|
|
54
|
-
|
|
55
|
-
const callback = vi.fn();
|
|
56
|
-
hostBridge.on(MessageType.UI_UPDATE, callback);
|
|
57
|
-
|
|
58
|
-
// Simulate incoming postMessage from iframe
|
|
59
|
-
const event = new MessageEvent('message', {
|
|
60
|
-
data: {
|
|
61
|
-
type: MessageType.UI_UPDATE,
|
|
62
|
-
payload: { title: 'Test', breadcrumb: ['Home'] }
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
window.dispatchEvent(event);
|
|
67
|
-
|
|
68
|
-
expect(callback).toHaveBeenCalledTimes(1);
|
|
69
|
-
expect(callback.mock.calls[0][0].title).toBe('Test');
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
// -----------------------
|
|
73
|
-
// ModuleBridge Tests
|
|
74
|
-
// -----------------------
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Test that ModuleBridge sends handshake messages correctly.
|
|
78
|
-
*/
|
|
79
|
-
it('ModuleBridge sends handshake correctly', () => {
|
|
80
|
-
const moduleBridge = new ModuleBridge();
|
|
81
|
-
moduleBridge.sendHandshake({ version: '0.1.0', timestamp: Date.now() });
|
|
82
|
-
|
|
83
|
-
expect(window.parent.postMessage).toHaveBeenCalledTimes(1);
|
|
84
|
-
const callArg = (window.parent.postMessage as any).mock.calls[0][0];
|
|
85
|
-
expect(callArg.type).toBe(MessageType.HANDSHAKE_READY);
|
|
86
|
-
expect(callArg.payload.version).toBe('0.1.0');
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Test that ModuleBridge sends UI update messages.
|
|
91
|
-
*/
|
|
92
|
-
it('ModuleBridge sends UI update', () => {
|
|
93
|
-
const moduleBridge = new ModuleBridge();
|
|
94
|
-
moduleBridge.sendUIUpdate({ title: 'Users', breadcrumb: ['Home', 'Users'] });
|
|
95
|
-
|
|
96
|
-
const callArg = (window.parent.postMessage as any).mock.calls[0][0];
|
|
97
|
-
expect(callArg.type).toBe(MessageType.UI_UPDATE);
|
|
98
|
-
expect(callArg.payload.breadcrumb.length).toBe(2);
|
|
99
|
-
});
|
|
100
|
-
});
|
package/src/bridgeBase.ts
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Base bridge class for message-based communication.
|
|
3
|
-
* @module @schoolpalm/message-bridge/bridgeBase
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// src/bridgeBase.ts
|
|
7
|
-
import { MessageType } from './messageTypes';
|
|
8
|
-
import { MessagePayload } from './payloadSchemas';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Type definition for message handler functions.
|
|
12
|
-
* @template T - The type of message payload this handler accepts.
|
|
13
|
-
*/
|
|
14
|
-
type MessageHandler<T extends MessagePayload> = (payload: T) => void;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Base class for Host and Module bridges.
|
|
18
|
-
*
|
|
19
|
-
* This abstract base class provides the core functionality for message-based
|
|
20
|
-
* communication between windows using the postMessage API. It handles sending
|
|
21
|
-
* messages, registering listeners, and managing event listeners.
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```typescript
|
|
25
|
-
* class CustomBridge extends BridgeBase {
|
|
26
|
-
* constructor(targetWindow: Window) {
|
|
27
|
-
* super(targetWindow, 'https://example.com');
|
|
28
|
-
* }
|
|
29
|
-
*
|
|
30
|
-
* // Add custom methods here
|
|
31
|
-
* }
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
export class BridgeBase {
|
|
35
|
-
/** The target window to send messages to. */
|
|
36
|
-
protected targetWindow: Window;
|
|
37
|
-
/** The origin to restrict messages to. */
|
|
38
|
-
protected targetOrigin: string;
|
|
39
|
-
/** Map of message type to array of handler functions. */
|
|
40
|
-
private listeners: Map<MessageType, MessageHandler<any>[]> = new Map();
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Creates a new BridgeBase instance.
|
|
44
|
-
* @param targetWindow - The window to send messages to.
|
|
45
|
-
* @param targetOrigin - The origin to restrict messages to (default: '*').
|
|
46
|
-
*/
|
|
47
|
-
constructor(targetWindow: Window, targetOrigin: string = '*') {
|
|
48
|
-
this.targetWindow = targetWindow;
|
|
49
|
-
this.targetOrigin = targetOrigin;
|
|
50
|
-
window.addEventListener('message', this._handleMessage.bind(this));
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Sends a message to the target window.
|
|
55
|
-
* @template T - The type of the message payload.
|
|
56
|
-
* @param type - The message type to send.
|
|
57
|
-
* @param payload - The payload data to send.
|
|
58
|
-
*/
|
|
59
|
-
send<T extends MessagePayload>(type: MessageType, payload: T) {
|
|
60
|
-
this.targetWindow.postMessage({ type, payload }, this.targetOrigin);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Registers a listener for a specific message type.
|
|
65
|
-
* @template T - The type of the message payload.
|
|
66
|
-
* @param type - The message type to listen for.
|
|
67
|
-
* @param callback - The function to call when a message of this type is received.
|
|
68
|
-
*/
|
|
69
|
-
on<T extends MessagePayload>(type: MessageType, callback: MessageHandler<T>) {
|
|
70
|
-
if (!this.listeners.has(type)) this.listeners.set(type, []);
|
|
71
|
-
this.listeners.get(type)?.push(callback);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Internal message handler for incoming postMessage events.
|
|
76
|
-
* @private
|
|
77
|
-
* @param event - The message event received.
|
|
78
|
-
*/
|
|
79
|
-
private _handleMessage(event: MessageEvent) {
|
|
80
|
-
const { type, payload } = event.data || {};
|
|
81
|
-
if (!type || !this.listeners.has(type)) return;
|
|
82
|
-
this.listeners.get(type)?.forEach(cb => cb(payload));
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Cleans up event listeners and resources.
|
|
87
|
-
* Call this method when the bridge is no longer needed.
|
|
88
|
-
*/
|
|
89
|
-
destroy() {
|
|
90
|
-
window.removeEventListener('message', this._handleMessage.bind(this));
|
|
91
|
-
this.listeners.clear();
|
|
92
|
-
}
|
|
93
|
-
}
|
package/src/hostBridge.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Host-side bridge for communication with embedded modules.
|
|
3
|
-
* @module @schoolpalm/message-bridge/hostBridge
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// src/hostBridge.ts
|
|
7
|
-
import { BridgeBase } from './bridgeBase';
|
|
8
|
-
import { MessageType } from './messageTypes';
|
|
9
|
-
import { ModuleStartPayload } from './payloadSchemas';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Host-side bridge for communication with embedded modules.
|
|
13
|
-
*
|
|
14
|
-
* This class extends BridgeBase to provide host-specific functionality for
|
|
15
|
-
* communicating with modules embedded in iframes. It handles initialization
|
|
16
|
-
* and termination of modules.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* const iframe = document.getElementById('module-iframe') as HTMLIFrameElement;
|
|
21
|
-
* const hostBridge = new HostBridge(iframe, 'https://module.example.com');
|
|
22
|
-
*
|
|
23
|
-
* // Start a module
|
|
24
|
-
* hostBridge.sendModuleStart({
|
|
25
|
-
* route: '/dashboard',
|
|
26
|
-
* context: { userId: 123 },
|
|
27
|
-
* timestamp: Date.now()
|
|
28
|
-
* });
|
|
29
|
-
*
|
|
30
|
-
* // Listen for UI updates from the module
|
|
31
|
-
* hostBridge.on(MessageType.UI_UPDATE, (payload) => {
|
|
32
|
-
* console.log('UI Update:', payload);
|
|
33
|
-
* });
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
|
-
export class HostBridge extends BridgeBase {
|
|
37
|
-
/**
|
|
38
|
-
* Creates a new HostBridge instance.
|
|
39
|
-
* @param iframe - The iframe element containing the module.
|
|
40
|
-
* @param targetOrigin - The origin to restrict messages to (default: '*').
|
|
41
|
-
*/
|
|
42
|
-
constructor(iframe: HTMLIFrameElement, targetOrigin: string = '*') {
|
|
43
|
-
super(iframe.contentWindow!, targetOrigin);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Sends a module-start message to the embedded module.
|
|
48
|
-
* This initializes the module with the provided route and context.
|
|
49
|
-
* @param payload - The module start payload containing route, context, and timestamp.
|
|
50
|
-
*/
|
|
51
|
-
sendModuleStart(payload: ModuleStartPayload) {
|
|
52
|
-
this.send(MessageType.MODULE_START, payload);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Sends a module-exit message to the embedded module.
|
|
57
|
-
* This signals the module to clean up and terminate.
|
|
58
|
-
* @param reason - Optional reason for the module exit.
|
|
59
|
-
*/
|
|
60
|
-
sendModuleExit(reason?: string) {
|
|
61
|
-
this.send(MessageType.MODULE_EXIT, { reason });
|
|
62
|
-
}
|
|
63
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @packageDocumentation
|
|
3
|
-
* @module @schoolpalm/message-bridge
|
|
4
|
-
*
|
|
5
|
-
* TypeScript SDK for message-based communication between SchoolPalm host and vendor modules.
|
|
6
|
-
*
|
|
7
|
-
* This module exports the main classes and types for establishing communication
|
|
8
|
-
* between a host application and embedded modules using the postMessage API.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```typescript
|
|
12
|
-
* import { HostBridge, ModuleBridge, MessageType } from '@schoolpalm/message-bridge';
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
export { BridgeBase } from './bridgeBase';
|
|
17
|
-
export { HostBridge } from './hostBridge';
|
|
18
|
-
export { ModuleBridge } from './moduleBridge';
|
|
19
|
-
export { MessageType } from './messageTypes';
|
|
20
|
-
export * from './payloadSchemas';
|
package/src/messageTypes.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Message type definitions for bridge communication.
|
|
3
|
-
* @module @schoolpalm/message-bridge/messageTypes
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// src/messageTypes.ts
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Enumeration of all allowed message types for Host ↔ Module communication.
|
|
10
|
-
*
|
|
11
|
-
* These message types define the protocol for communication between the host
|
|
12
|
-
* application and embedded modules. Each type indicates the direction and
|
|
13
|
-
* purpose of the message.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* import { MessageType } from '@schoolpalm/message-bridge';
|
|
18
|
-
*
|
|
19
|
-
* // Listen for UI updates from modules
|
|
20
|
-
* bridge.on(MessageType.UI_UPDATE, (payload) => {
|
|
21
|
-
* console.log('UI updated:', payload);
|
|
22
|
-
* });
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
export enum MessageType {
|
|
26
|
-
/** Module → Host: Indicates the module is ready for communication. */
|
|
27
|
-
HANDSHAKE_READY = 'handshake:ready',
|
|
28
|
-
/** Host → Module: Signals the module to start with provided context. */
|
|
29
|
-
MODULE_START = 'module:start',
|
|
30
|
-
/** Module → Host: Updates the host UI (title, breadcrumb, theme). */
|
|
31
|
-
UI_UPDATE = 'ui:update',
|
|
32
|
-
/** Module → Host: Requests data from the host. */
|
|
33
|
-
DATA_REQUEST = 'data:request',
|
|
34
|
-
/** Host → Module: Responds to a data request. */
|
|
35
|
-
DATA_RESPONSE = 'data:response',
|
|
36
|
-
/** Module → Host: Reports an error to the host. */
|
|
37
|
-
ERROR = 'error',
|
|
38
|
-
/** Host → Module: Signals the module to exit and clean up. */
|
|
39
|
-
MODULE_EXIT = 'module:exit'
|
|
40
|
-
}
|