@w3streamdev/plugin-core 1.0.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.
@@ -0,0 +1,217 @@
1
+ interface PluginInfraConfig {
2
+ /** Base URL of your @w3stream/plugin-server deployment */
3
+ serverURL: string;
4
+ /** Org-scoped API key for the plugin server */
5
+ apiKey: string;
6
+ /** Your RTK organization ID */
7
+ orgId: string;
8
+ /** Set to true in development — enables devURL override from server */
9
+ devMode?: boolean;
10
+ }
11
+ /** Shape returned by GET /v2/plugins/user */
12
+ interface ServerPluginRecord {
13
+ id: string;
14
+ name: string;
15
+ description: string;
16
+ picture: string;
17
+ /** The custom self-hosted URL — this is the whole point */
18
+ baseURL: string;
19
+ organizationId: string;
20
+ published: boolean;
21
+ private: boolean;
22
+ staggered: boolean;
23
+ tags: string[];
24
+ type: string;
25
+ createdAt: string;
26
+ updatedAt: string;
27
+ }
28
+
29
+ /**
30
+ * @w3stream/plugin-core — StoreSyncManager
31
+ *
32
+ * Maintains in-memory store state per plugin and synchronizes updates
33
+ * across local iframes and remote peers via RTK data channel.
34
+ *
35
+ * Reference: PRD Section 4.7
36
+ */
37
+
38
+ declare class StoreSyncManager {
39
+ private meeting;
40
+ /** pluginId → storeName → key → value */
41
+ private stores;
42
+ /** pluginId → viewId → W3PostMessageBridge */
43
+ private bridges;
44
+ constructor(meeting: unknown);
45
+ /**
46
+ * Register a bridge so store updates can be forwarded to its iframe.
47
+ */
48
+ registerBridge(pluginId: string, viewId: string, bridge: W3PostMessageBridge): void;
49
+ /**
50
+ * Unregister a bridge when the plugin view is removed.
51
+ */
52
+ unregisterBridge(pluginId: string, viewId: string): void;
53
+ /**
54
+ * Returns the current snapshot of a named store for a plugin.
55
+ */
56
+ getStoreSnapshot(pluginId: string, storeName: string): Record<string, unknown>;
57
+ /**
58
+ * Apply a store update from a local iframe:
59
+ * 1. Update the in-memory store
60
+ * 2. Forward to all other local iframes for this plugin (excluding origin)
61
+ * 3. Broadcast to all remote peers via RTK data channel
62
+ */
63
+ applyUpdate(pluginId: string, storeName: string, key: string, value: unknown, fromPeerId: string, originViewId?: string): void;
64
+ /**
65
+ * Apply a store update received from a remote peer:
66
+ * 1. Update the in-memory store
67
+ * 2. Forward to all local iframes for this plugin
68
+ * (No re-broadcast — the sender already broadcast to all peers)
69
+ */
70
+ applyRemoteUpdate(pluginId: string, storeName: string, key: string, value: unknown, fromPeerId: string): void;
71
+ /**
72
+ * Listen for incoming store updates from remote peers via RTK data channel.
73
+ * Call this once after constructing the StoreSyncManager.
74
+ */
75
+ listenForRemoteUpdates(): void;
76
+ }
77
+
78
+ /**
79
+ * @w3stream/plugin-core — W3PostMessageBridge (host side)
80
+ *
81
+ * Host-side mirror of the PostMessageTransport in @w3stream/plugin-sdk.
82
+ * Manages the full handshake lifecycle between the host page and plugin iframe.
83
+ *
84
+ * Sequence (per PRD Section 2.2 and 4.6):
85
+ * 1. new W3PostMessageBridge(plugin, iframe, viewId, meeting) — on addPluginView()
86
+ * 2. connect() — attach window.addEventListener('message', handleMessage)
87
+ * 3. Wait for 'PLUGIN_READY' from iframe
88
+ * 4. Send 'PLUGIN_INIT' with full meeting context
89
+ * 5. Plugin SDK resolves init() → fires 'ready' event
90
+ *
91
+ * Reference: PRD Section 4.6
92
+ */
93
+
94
+ declare class W3PostMessageBridge {
95
+ private iframe;
96
+ private viewId;
97
+ private pluginId;
98
+ private plugin;
99
+ private meeting;
100
+ private storeSync;
101
+ private messageHandler;
102
+ private connected;
103
+ constructor(plugin: unknown, iframe: HTMLIFrameElement, viewId: string, meeting: unknown, storeSync?: StoreSyncManager);
104
+ connect(): void;
105
+ destroy(): void;
106
+ /** Send PLUGIN_DATA to the iframe */
107
+ send(eventName: string, data?: unknown): void;
108
+ /** Send PLUGIN_CLOSE to the iframe */
109
+ sendClose(): void;
110
+ /** Send a STORE_UPDATE to this iframe */
111
+ sendStoreUpdate(storeName: string, key: string, value: unknown, fromPeerId: string): void;
112
+ private handleMessage;
113
+ private sendInit;
114
+ }
115
+
116
+ /**
117
+ * @w3stream/plugin-core — W3PluginObject
118
+ *
119
+ * Factory function returning an RTKPlugin-compatible object that
120
+ * <rtk-plugins>, <rtk-plugin-main>, and <rtk-plugins-toggle> can use
121
+ * without modification.
122
+ *
123
+ * Reference: PRD Section 4.5
124
+ */
125
+
126
+ interface W3PluginObject {
127
+ id: string;
128
+ name: string;
129
+ description: string;
130
+ picture: string;
131
+ baseURL: string;
132
+ organizationId: string;
133
+ published: boolean;
134
+ private: boolean;
135
+ staggered: boolean;
136
+ tags: string[];
137
+ type: string;
138
+ createdAt: Date;
139
+ updatedAt: Date;
140
+ config: unknown;
141
+ active: boolean;
142
+ enabledBy: string;
143
+ iframes: Map<string, HTMLIFrameElement>;
144
+ _bridges: Map<string, W3PostMessageBridge>;
145
+ activate: () => Promise<void>;
146
+ deactivate: () => Promise<void>;
147
+ activateForSelf: () => Promise<void>;
148
+ deactivateForSelf: () => void;
149
+ enable: () => Promise<void>;
150
+ disable: () => void;
151
+ addPluginView: (iframe: HTMLIFrameElement, viewId?: string) => void;
152
+ removePluginView: (viewId?: string) => void;
153
+ sendData: (payload: {
154
+ eventName: string;
155
+ data?: unknown;
156
+ }) => void;
157
+ sendIframeEvent: (message: unknown) => void;
158
+ on: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
159
+ off: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
160
+ once: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
161
+ emit: (event: string, ...args: unknown[]) => boolean;
162
+ addListener: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
163
+ removeListener: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
164
+ removeAllListeners: (event?: string) => W3PluginObject;
165
+ listeners: (event: string) => ((...args: unknown[]) => void)[];
166
+ listenerCount: (event: string) => number;
167
+ eventNames: () => (string | symbol)[];
168
+ setMaxListeners: (n: number) => W3PluginObject;
169
+ getMaxListeners: () => number;
170
+ rawListeners: (event: string) => ((...args: unknown[]) => void)[];
171
+ prependListener: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
172
+ prependOnceListener: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
173
+ telemetry: Record<string, unknown>;
174
+ logger: typeof console;
175
+ }
176
+ declare function createW3PluginObject(serverPlugin: ServerPluginRecord, meeting: unknown, _config: PluginInfraConfig, storeSync?: StoreSyncManager): W3PluginObject;
177
+
178
+ /**
179
+ * @w3stream/plugin-core — PluginManager
180
+ *
181
+ * Fetches plugins from your plugin server, builds RTKPlugin-compatible objects,
182
+ * and patches the meeting object so <rtk-plugins>, <rtk-plugin-main>, and
183
+ * <rtk-plugins-toggle> work against your own infrastructure.
184
+ *
185
+ * Reference: PRD Section 4 — Package 3: @w3stream/plugin-core
186
+ */
187
+
188
+ declare class PluginList {
189
+ private items;
190
+ private listeners;
191
+ toArray(): W3PluginObject[];
192
+ addListener(event: string, callback: (...args: unknown[]) => void): void;
193
+ removeListener(event: string, callback: (...args: unknown[]) => void): void;
194
+ _setItems(items: W3PluginObject[]): void;
195
+ _addItem(item: W3PluginObject): void;
196
+ _removeItem(id: string): void;
197
+ }
198
+ /**
199
+ * Patches meeting.plugins with a W3PluginManager backed by your plugin server.
200
+ *
201
+ * Steps:
202
+ * 1. Fetch plugin records from your server
203
+ * 2. Create RTKPlugin-compatible objects for each
204
+ * 3. Set up store sync manager for cross-peer store propagation
205
+ * 4. Replace meeting.plugins.all and meeting.plugins.active
206
+ * 5. Listen for activation/deactivation broadcasts from peers
207
+ */
208
+ declare function patchMeeting(meeting: unknown, config: PluginInfraConfig): Promise<void>;
209
+ /**
210
+ * Convenience wrapper: init the meeting AND patch it in one call.
211
+ *
212
+ * Usage:
213
+ * const meeting = await initWithPlugins(rtkInitOptions, pluginConfig)
214
+ */
215
+ declare function initWithPlugins(rtkInitOptions: Record<string, unknown>, pluginConfig: PluginInfraConfig): Promise<unknown>;
216
+
217
+ export { type PluginInfraConfig, PluginList, type ServerPluginRecord, StoreSyncManager, type W3PluginObject, W3PostMessageBridge, createW3PluginObject, initWithPlugins, patchMeeting };
@@ -0,0 +1,217 @@
1
+ interface PluginInfraConfig {
2
+ /** Base URL of your @w3stream/plugin-server deployment */
3
+ serverURL: string;
4
+ /** Org-scoped API key for the plugin server */
5
+ apiKey: string;
6
+ /** Your RTK organization ID */
7
+ orgId: string;
8
+ /** Set to true in development — enables devURL override from server */
9
+ devMode?: boolean;
10
+ }
11
+ /** Shape returned by GET /v2/plugins/user */
12
+ interface ServerPluginRecord {
13
+ id: string;
14
+ name: string;
15
+ description: string;
16
+ picture: string;
17
+ /** The custom self-hosted URL — this is the whole point */
18
+ baseURL: string;
19
+ organizationId: string;
20
+ published: boolean;
21
+ private: boolean;
22
+ staggered: boolean;
23
+ tags: string[];
24
+ type: string;
25
+ createdAt: string;
26
+ updatedAt: string;
27
+ }
28
+
29
+ /**
30
+ * @w3stream/plugin-core — StoreSyncManager
31
+ *
32
+ * Maintains in-memory store state per plugin and synchronizes updates
33
+ * across local iframes and remote peers via RTK data channel.
34
+ *
35
+ * Reference: PRD Section 4.7
36
+ */
37
+
38
+ declare class StoreSyncManager {
39
+ private meeting;
40
+ /** pluginId → storeName → key → value */
41
+ private stores;
42
+ /** pluginId → viewId → W3PostMessageBridge */
43
+ private bridges;
44
+ constructor(meeting: unknown);
45
+ /**
46
+ * Register a bridge so store updates can be forwarded to its iframe.
47
+ */
48
+ registerBridge(pluginId: string, viewId: string, bridge: W3PostMessageBridge): void;
49
+ /**
50
+ * Unregister a bridge when the plugin view is removed.
51
+ */
52
+ unregisterBridge(pluginId: string, viewId: string): void;
53
+ /**
54
+ * Returns the current snapshot of a named store for a plugin.
55
+ */
56
+ getStoreSnapshot(pluginId: string, storeName: string): Record<string, unknown>;
57
+ /**
58
+ * Apply a store update from a local iframe:
59
+ * 1. Update the in-memory store
60
+ * 2. Forward to all other local iframes for this plugin (excluding origin)
61
+ * 3. Broadcast to all remote peers via RTK data channel
62
+ */
63
+ applyUpdate(pluginId: string, storeName: string, key: string, value: unknown, fromPeerId: string, originViewId?: string): void;
64
+ /**
65
+ * Apply a store update received from a remote peer:
66
+ * 1. Update the in-memory store
67
+ * 2. Forward to all local iframes for this plugin
68
+ * (No re-broadcast — the sender already broadcast to all peers)
69
+ */
70
+ applyRemoteUpdate(pluginId: string, storeName: string, key: string, value: unknown, fromPeerId: string): void;
71
+ /**
72
+ * Listen for incoming store updates from remote peers via RTK data channel.
73
+ * Call this once after constructing the StoreSyncManager.
74
+ */
75
+ listenForRemoteUpdates(): void;
76
+ }
77
+
78
+ /**
79
+ * @w3stream/plugin-core — W3PostMessageBridge (host side)
80
+ *
81
+ * Host-side mirror of the PostMessageTransport in @w3stream/plugin-sdk.
82
+ * Manages the full handshake lifecycle between the host page and plugin iframe.
83
+ *
84
+ * Sequence (per PRD Section 2.2 and 4.6):
85
+ * 1. new W3PostMessageBridge(plugin, iframe, viewId, meeting) — on addPluginView()
86
+ * 2. connect() — attach window.addEventListener('message', handleMessage)
87
+ * 3. Wait for 'PLUGIN_READY' from iframe
88
+ * 4. Send 'PLUGIN_INIT' with full meeting context
89
+ * 5. Plugin SDK resolves init() → fires 'ready' event
90
+ *
91
+ * Reference: PRD Section 4.6
92
+ */
93
+
94
+ declare class W3PostMessageBridge {
95
+ private iframe;
96
+ private viewId;
97
+ private pluginId;
98
+ private plugin;
99
+ private meeting;
100
+ private storeSync;
101
+ private messageHandler;
102
+ private connected;
103
+ constructor(plugin: unknown, iframe: HTMLIFrameElement, viewId: string, meeting: unknown, storeSync?: StoreSyncManager);
104
+ connect(): void;
105
+ destroy(): void;
106
+ /** Send PLUGIN_DATA to the iframe */
107
+ send(eventName: string, data?: unknown): void;
108
+ /** Send PLUGIN_CLOSE to the iframe */
109
+ sendClose(): void;
110
+ /** Send a STORE_UPDATE to this iframe */
111
+ sendStoreUpdate(storeName: string, key: string, value: unknown, fromPeerId: string): void;
112
+ private handleMessage;
113
+ private sendInit;
114
+ }
115
+
116
+ /**
117
+ * @w3stream/plugin-core — W3PluginObject
118
+ *
119
+ * Factory function returning an RTKPlugin-compatible object that
120
+ * <rtk-plugins>, <rtk-plugin-main>, and <rtk-plugins-toggle> can use
121
+ * without modification.
122
+ *
123
+ * Reference: PRD Section 4.5
124
+ */
125
+
126
+ interface W3PluginObject {
127
+ id: string;
128
+ name: string;
129
+ description: string;
130
+ picture: string;
131
+ baseURL: string;
132
+ organizationId: string;
133
+ published: boolean;
134
+ private: boolean;
135
+ staggered: boolean;
136
+ tags: string[];
137
+ type: string;
138
+ createdAt: Date;
139
+ updatedAt: Date;
140
+ config: unknown;
141
+ active: boolean;
142
+ enabledBy: string;
143
+ iframes: Map<string, HTMLIFrameElement>;
144
+ _bridges: Map<string, W3PostMessageBridge>;
145
+ activate: () => Promise<void>;
146
+ deactivate: () => Promise<void>;
147
+ activateForSelf: () => Promise<void>;
148
+ deactivateForSelf: () => void;
149
+ enable: () => Promise<void>;
150
+ disable: () => void;
151
+ addPluginView: (iframe: HTMLIFrameElement, viewId?: string) => void;
152
+ removePluginView: (viewId?: string) => void;
153
+ sendData: (payload: {
154
+ eventName: string;
155
+ data?: unknown;
156
+ }) => void;
157
+ sendIframeEvent: (message: unknown) => void;
158
+ on: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
159
+ off: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
160
+ once: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
161
+ emit: (event: string, ...args: unknown[]) => boolean;
162
+ addListener: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
163
+ removeListener: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
164
+ removeAllListeners: (event?: string) => W3PluginObject;
165
+ listeners: (event: string) => ((...args: unknown[]) => void)[];
166
+ listenerCount: (event: string) => number;
167
+ eventNames: () => (string | symbol)[];
168
+ setMaxListeners: (n: number) => W3PluginObject;
169
+ getMaxListeners: () => number;
170
+ rawListeners: (event: string) => ((...args: unknown[]) => void)[];
171
+ prependListener: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
172
+ prependOnceListener: (event: string, cb: (...args: unknown[]) => void) => W3PluginObject;
173
+ telemetry: Record<string, unknown>;
174
+ logger: typeof console;
175
+ }
176
+ declare function createW3PluginObject(serverPlugin: ServerPluginRecord, meeting: unknown, _config: PluginInfraConfig, storeSync?: StoreSyncManager): W3PluginObject;
177
+
178
+ /**
179
+ * @w3stream/plugin-core — PluginManager
180
+ *
181
+ * Fetches plugins from your plugin server, builds RTKPlugin-compatible objects,
182
+ * and patches the meeting object so <rtk-plugins>, <rtk-plugin-main>, and
183
+ * <rtk-plugins-toggle> work against your own infrastructure.
184
+ *
185
+ * Reference: PRD Section 4 — Package 3: @w3stream/plugin-core
186
+ */
187
+
188
+ declare class PluginList {
189
+ private items;
190
+ private listeners;
191
+ toArray(): W3PluginObject[];
192
+ addListener(event: string, callback: (...args: unknown[]) => void): void;
193
+ removeListener(event: string, callback: (...args: unknown[]) => void): void;
194
+ _setItems(items: W3PluginObject[]): void;
195
+ _addItem(item: W3PluginObject): void;
196
+ _removeItem(id: string): void;
197
+ }
198
+ /**
199
+ * Patches meeting.plugins with a W3PluginManager backed by your plugin server.
200
+ *
201
+ * Steps:
202
+ * 1. Fetch plugin records from your server
203
+ * 2. Create RTKPlugin-compatible objects for each
204
+ * 3. Set up store sync manager for cross-peer store propagation
205
+ * 4. Replace meeting.plugins.all and meeting.plugins.active
206
+ * 5. Listen for activation/deactivation broadcasts from peers
207
+ */
208
+ declare function patchMeeting(meeting: unknown, config: PluginInfraConfig): Promise<void>;
209
+ /**
210
+ * Convenience wrapper: init the meeting AND patch it in one call.
211
+ *
212
+ * Usage:
213
+ * const meeting = await initWithPlugins(rtkInitOptions, pluginConfig)
214
+ */
215
+ declare function initWithPlugins(rtkInitOptions: Record<string, unknown>, pluginConfig: PluginInfraConfig): Promise<unknown>;
216
+
217
+ export { type PluginInfraConfig, PluginList, type ServerPluginRecord, StoreSyncManager, type W3PluginObject, W3PostMessageBridge, createW3PluginObject, initWithPlugins, patchMeeting };