@weave-apps/sdk 0.10.0 → 0.12.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 (32) hide show
  1. package/dist/WeaveDOMAPI.d.ts +66 -0
  2. package/dist/WeaveDOMAPI.d.ts.map +1 -1
  3. package/dist/WeaveDOMAPI.js +51 -0
  4. package/dist/apis/api-mono/services/interfaces/WorkflowsTriggersWorkflowCompanyIdPostPost.d.ts +224 -0
  5. package/dist/apis/api-mono/services/interfaces/WorkflowsTriggersWorkflowCompanyIdPostPost.d.ts.map +1 -0
  6. package/dist/apis/api-mono/services/interfaces/WorkflowsTriggersWorkflowCompanyIdPostPost.js +66 -0
  7. package/dist/app-sdk/src/WeaveAPIClient.d.ts +373 -0
  8. package/dist/app-sdk/src/WeaveAPIClient.d.ts.map +1 -0
  9. package/dist/app-sdk/src/WeaveAPIClient.js +361 -0
  10. package/dist/app-sdk/src/WeaveAppInstanceAPI.d.ts +237 -0
  11. package/dist/app-sdk/src/WeaveAppInstanceAPI.d.ts.map +1 -0
  12. package/dist/app-sdk/src/WeaveAppInstanceAPI.js +395 -0
  13. package/dist/app-sdk/src/WeaveBackgroundAPI.d.ts +81 -0
  14. package/dist/app-sdk/src/WeaveBackgroundAPI.d.ts.map +1 -0
  15. package/dist/app-sdk/src/WeaveBackgroundAPI.js +165 -0
  16. package/dist/app-sdk/src/WeaveBaseApp.d.ts +318 -0
  17. package/dist/app-sdk/src/WeaveBaseApp.d.ts.map +1 -0
  18. package/dist/app-sdk/src/WeaveBaseApp.js +434 -0
  19. package/dist/app-sdk/src/WeaveCronAPI.d.ts +68 -0
  20. package/dist/app-sdk/src/WeaveCronAPI.d.ts.map +1 -0
  21. package/dist/app-sdk/src/WeaveCronAPI.js +172 -0
  22. package/dist/app-sdk/src/WeaveDOMAPI.d.ts +593 -0
  23. package/dist/app-sdk/src/WeaveDOMAPI.d.ts.map +1 -0
  24. package/dist/app-sdk/src/WeaveDOMAPI.js +774 -0
  25. package/dist/app-sdk/src/global.d.ts +25 -0
  26. package/dist/app-sdk/src/global.d.ts.map +1 -0
  27. package/dist/app-sdk/src/global.js +23 -0
  28. package/dist/app-sdk/src/index.d.ts +14 -0
  29. package/dist/app-sdk/src/index.d.ts.map +1 -0
  30. package/dist/app-sdk/src/index.js +14 -0
  31. package/package.json +3 -3
  32. package/templates/WEAVE_SPEC.md +459 -2
@@ -0,0 +1,395 @@
1
+ /**
2
+ * WeaveAppInstanceAPI
3
+ *
4
+ * Client-side API for Weave apps to discover and communicate with
5
+ * other instances of themselves across browser tabs.
6
+ *
7
+ * Use cases:
8
+ * - Prevent duplicate automation runs across tabs
9
+ * - Coordinate which tab is "controlling" vs "observing"
10
+ * - Send messages between app instances
11
+ *
12
+ * Usage:
13
+ * ```typescript
14
+ * // Register this instance
15
+ * const instances = await this.instances.register({ url: window.location.href });
16
+ *
17
+ * // Claim controller status (for automation)
18
+ * const claimed = await this.instances.claimController();
19
+ *
20
+ * // Listen for messages from other instances
21
+ * this.instances.onMessage((msg, sender) => {
22
+ * if (msg.type === 'YIELD_CONTROL') {
23
+ * // Another tab wants control
24
+ * }
25
+ * });
26
+ *
27
+ * // Broadcast to all other instances
28
+ * await this.instances.broadcast({ type: 'YIELD_CONTROL' });
29
+ * ```
30
+ */
31
+ // Request timeout in ms
32
+ const REQUEST_TIMEOUT = 5000;
33
+ // Counter for unique request IDs
34
+ let requestIdCounter = 0;
35
+ // Pending requests waiting for response
36
+ const pendingRequests = new Map();
37
+ // Flag to track if listener is set up
38
+ let listenerInitialized = false;
39
+ // Global callbacks for instance messages (keyed by appId)
40
+ const messageCallbacks = new Map();
41
+ // Global callbacks for instance changes (keyed by appId)
42
+ const changeCallbacks = new Map();
43
+ /**
44
+ * Initialize the response listener (called once)
45
+ */
46
+ function initializeListener() {
47
+ if (listenerInitialized)
48
+ return;
49
+ listenerInitialized = true;
50
+ window.addEventListener('message', (event) => {
51
+ const message = event.data;
52
+ // Handle app instance responses
53
+ if (message?.type === 'APP_INSTANCE_RESPONSE') {
54
+ const response = message;
55
+ const pending = pendingRequests.get(response.requestId);
56
+ if (!pending)
57
+ return;
58
+ // Clear timeout and remove from pending
59
+ clearTimeout(pending.timeout);
60
+ pendingRequests.delete(response.requestId);
61
+ if (response.success) {
62
+ pending.resolve(response);
63
+ }
64
+ else {
65
+ pending.reject(new Error(response.error || 'Unknown error'));
66
+ }
67
+ return;
68
+ }
69
+ // Handle incoming instance messages from other tabs
70
+ if (message?.type === 'APP_INSTANCE_MESSAGE') {
71
+ const { appId, message: instanceMessage } = message.payload;
72
+ const callbacks = messageCallbacks.get(appId);
73
+ if (callbacks) {
74
+ for (const callback of callbacks) {
75
+ try {
76
+ callback(instanceMessage);
77
+ }
78
+ catch (error) {
79
+ console.error('[WeaveAppInstanceAPI] Error in message callback:', error);
80
+ }
81
+ }
82
+ }
83
+ return;
84
+ }
85
+ // Handle instance change notifications
86
+ if (message?.type === 'APP_INSTANCE_CHANGE') {
87
+ const { appId, instances } = message.payload;
88
+ const callbacks = changeCallbacks.get(appId);
89
+ if (callbacks) {
90
+ for (const callback of callbacks) {
91
+ try {
92
+ callback(instances);
93
+ }
94
+ catch (error) {
95
+ console.error('[WeaveAppInstanceAPI] Error in change callback:', error);
96
+ }
97
+ }
98
+ }
99
+ return;
100
+ }
101
+ });
102
+ }
103
+ /**
104
+ * Send a message to the background service via content script
105
+ */
106
+ async function sendMessage(type, payload) {
107
+ // Initialize listener on first use
108
+ initializeListener();
109
+ const requestId = `app-${++requestIdCounter}-${Date.now()}`;
110
+ return new Promise((resolve, reject) => {
111
+ // Set up timeout
112
+ const timeout = setTimeout(() => {
113
+ pendingRequests.delete(requestId);
114
+ reject(new Error(`App instance request timed out: ${type}`));
115
+ }, REQUEST_TIMEOUT);
116
+ // Store pending request
117
+ pendingRequests.set(requestId, { resolve, reject, timeout });
118
+ // Send message to content script (which forwards to background)
119
+ window.parent.postMessage({
120
+ type,
121
+ requestId,
122
+ payload,
123
+ }, '*');
124
+ });
125
+ }
126
+ /**
127
+ * WeaveAppInstanceAPI class
128
+ *
129
+ * Provides methods for apps to discover and communicate with
130
+ * other instances of themselves across browser tabs.
131
+ */
132
+ export class WeaveAppInstanceAPI {
133
+ constructor(appId) {
134
+ this._tabId = null;
135
+ this.appId = appId;
136
+ }
137
+ /**
138
+ * Get this instance's tab ID (available after register)
139
+ */
140
+ get tabId() {
141
+ return this._tabId;
142
+ }
143
+ /**
144
+ * Register this app instance
145
+ * Call this when your app starts to make it discoverable by other instances.
146
+ *
147
+ * @param metadata - Optional metadata to associate with this instance
148
+ * @returns All current instances of this app (including this one)
149
+ *
150
+ * @example
151
+ * const instances = await this.instances.register({
152
+ * url: window.location.href,
153
+ * startedAt: Date.now()
154
+ * });
155
+ * console.log(`There are ${instances.length} instances of this app`);
156
+ */
157
+ async register(metadata) {
158
+ const response = await sendMessage('APP_REGISTER_INSTANCE', {
159
+ appId: this.appId,
160
+ url: window.location.href,
161
+ metadata,
162
+ });
163
+ // Store our tab ID
164
+ if (response.tabId) {
165
+ this._tabId = response.tabId;
166
+ }
167
+ return response.instances || [];
168
+ }
169
+ /**
170
+ * Unregister this app instance
171
+ * Call this when your app is being destroyed.
172
+ *
173
+ * @example
174
+ * await this.instances.unregister();
175
+ */
176
+ async unregister() {
177
+ await sendMessage('APP_UNREGISTER_INSTANCE', {
178
+ appId: this.appId,
179
+ });
180
+ this._tabId = null;
181
+ }
182
+ /**
183
+ * Get all instances of this app
184
+ *
185
+ * @returns All current instances
186
+ *
187
+ * @example
188
+ * const instances = await this.instances.getInstances();
189
+ * const otherInstances = instances.filter(i => i.tabId !== this.instances.tabId);
190
+ */
191
+ async getInstances() {
192
+ const response = await sendMessage('APP_GET_INSTANCES', {
193
+ appId: this.appId,
194
+ });
195
+ return response.instances || [];
196
+ }
197
+ /**
198
+ * Claim controller status for this instance
199
+ * Only one instance can be controller at a time.
200
+ *
201
+ * @param force - If true, forcibly take control from current controller
202
+ * @returns true if successfully claimed, false if another instance is controller
203
+ *
204
+ * @example
205
+ * const claimed = await this.instances.claimController();
206
+ * if (claimed) {
207
+ * // This instance is now the controller
208
+ * this.startAutomation();
209
+ * } else {
210
+ * // Another instance is already controlling
211
+ * this.showObserverUI();
212
+ * }
213
+ */
214
+ async claimController(force = false) {
215
+ const response = await sendMessage('APP_CLAIM_CONTROLLER', {
216
+ appId: this.appId,
217
+ force,
218
+ });
219
+ return response.claimed ?? false;
220
+ }
221
+ /**
222
+ * Release controller status
223
+ * Call this when you want to give up control.
224
+ *
225
+ * @example
226
+ * await this.instances.releaseController();
227
+ */
228
+ async releaseController() {
229
+ await sendMessage('APP_RELEASE_CONTROLLER', {
230
+ appId: this.appId,
231
+ });
232
+ }
233
+ /**
234
+ * Check if this instance is the controller
235
+ *
236
+ * @returns true if this instance is the controller
237
+ *
238
+ * @example
239
+ * if (await this.instances.isController()) {
240
+ * // We're in control
241
+ * }
242
+ */
243
+ async isController() {
244
+ const response = await sendMessage('APP_IS_CONTROLLER', {
245
+ appId: this.appId,
246
+ });
247
+ return response.isController ?? false;
248
+ }
249
+ /**
250
+ * Get the current controller instance
251
+ *
252
+ * @returns The controller instance, or null if none
253
+ *
254
+ * @example
255
+ * const controller = await this.instances.getController();
256
+ * if (controller) {
257
+ * console.log(`Controller is in tab ${controller.tabId}`);
258
+ * }
259
+ */
260
+ async getController() {
261
+ const response = await sendMessage('APP_GET_CONTROLLER', {
262
+ appId: this.appId,
263
+ });
264
+ return response.controller ?? null;
265
+ }
266
+ /**
267
+ * Broadcast a message to all other instances
268
+ *
269
+ * @param message - Message to send (type and optional data)
270
+ * @returns Array of tab IDs that received the message
271
+ *
272
+ * @example
273
+ * await this.instances.broadcast({
274
+ * type: 'YIELD_CONTROL',
275
+ * data: { reason: 'User requested control' }
276
+ * });
277
+ */
278
+ async broadcast(message) {
279
+ const response = await sendMessage('APP_BROADCAST', {
280
+ appId: this.appId,
281
+ instanceMessage: message,
282
+ });
283
+ return response.recipientTabIds || [];
284
+ }
285
+ /**
286
+ * Send a message to the controller instance
287
+ *
288
+ * @param message - Message to send
289
+ * @returns Tab ID of the controller, or null if no controller
290
+ *
291
+ * @example
292
+ * await this.instances.sendToController({
293
+ * type: 'REQUEST_STATUS',
294
+ * });
295
+ */
296
+ async sendToController(message) {
297
+ const response = await sendMessage('APP_SEND_TO_CONTROLLER', {
298
+ appId: this.appId,
299
+ instanceMessage: message,
300
+ });
301
+ return response.controllerTabId ?? null;
302
+ }
303
+ /**
304
+ * Send a message to a specific tab
305
+ *
306
+ * @param targetTabId - Tab ID to send to
307
+ * @param message - Message to send
308
+ * @returns true if sent successfully
309
+ *
310
+ * @example
311
+ * await this.instances.sendToTab(123, {
312
+ * type: 'PING',
313
+ * });
314
+ */
315
+ async sendToTab(targetTabId, message) {
316
+ const response = await sendMessage('APP_SEND_TO_TAB', {
317
+ appId: this.appId,
318
+ targetTabId,
319
+ instanceMessage: message,
320
+ });
321
+ return response.sent ?? false;
322
+ }
323
+ /**
324
+ * Listen for messages from other instances
325
+ *
326
+ * @param callback - Function to call when a message is received
327
+ * @returns Unsubscribe function
328
+ *
329
+ * @example
330
+ * const unsubscribe = this.instances.onMessage((msg) => {
331
+ * if (msg.type === 'YIELD_CONTROL') {
332
+ * this.releaseController();
333
+ * this.showObserverUI();
334
+ * }
335
+ * });
336
+ *
337
+ * // Later, to stop listening:
338
+ * unsubscribe();
339
+ */
340
+ onMessage(callback) {
341
+ // Initialize listener
342
+ initializeListener();
343
+ // Get or create callback set for this app
344
+ let callbacks = messageCallbacks.get(this.appId);
345
+ if (!callbacks) {
346
+ callbacks = new Set();
347
+ messageCallbacks.set(this.appId, callbacks);
348
+ }
349
+ callbacks.add(callback);
350
+ // Return unsubscribe function
351
+ return () => {
352
+ callbacks?.delete(callback);
353
+ if (callbacks?.size === 0) {
354
+ messageCallbacks.delete(this.appId);
355
+ }
356
+ };
357
+ }
358
+ /**
359
+ * Listen for instance changes (new instances, removed instances)
360
+ *
361
+ * @param callback - Function to call when instances change
362
+ * @returns Unsubscribe function
363
+ *
364
+ * @example
365
+ * const unsubscribe = this.instances.onInstanceChange((instances) => {
366
+ * console.log(`Now ${instances.length} instances`);
367
+ * const controller = instances.find(i => i.isController);
368
+ * if (controller) {
369
+ * console.log(`Controller is tab ${controller.tabId}`);
370
+ * }
371
+ * });
372
+ */
373
+ onInstanceChange(callback) {
374
+ // Initialize listener
375
+ initializeListener();
376
+ // Get or create callback set for this app
377
+ let callbacks = changeCallbacks.get(this.appId);
378
+ if (!callbacks) {
379
+ callbacks = new Set();
380
+ changeCallbacks.set(this.appId, callbacks);
381
+ }
382
+ callbacks.add(callback);
383
+ // Return unsubscribe function
384
+ return () => {
385
+ callbacks?.delete(callback);
386
+ if (callbacks?.size === 0) {
387
+ changeCallbacks.delete(this.appId);
388
+ }
389
+ };
390
+ }
391
+ }
392
+ // Export for global usage
393
+ if (typeof window !== 'undefined') {
394
+ window.WeaveAppInstanceAPI = WeaveAppInstanceAPI;
395
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * WeaveBackgroundAPI
3
+ *
4
+ * Client-side API for Weave apps to interact with the background state service.
5
+ * Allows apps to persist state across page reloads and manage multi-page operations.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * // Save state (survives page reload)
10
+ * await weaveAPI.background.saveState({ count: 5, items: [...] });
11
+ *
12
+ * // Load state after page reload
13
+ * const state = await weaveAPI.background.loadState();
14
+ *
15
+ * // Set pending operation before navigation
16
+ * await weaveAPI.background.setPendingOperation({
17
+ * type: 'fill-form',
18
+ * data: { content: '...' },
19
+ * targetUrl: 'https://example.com/form'
20
+ * });
21
+ *
22
+ * // Check for pending operation after navigation
23
+ * const pending = await weaveAPI.background.getPendingOperation();
24
+ * ```
25
+ */
26
+ /**
27
+ * Pending operation for multi-page flows
28
+ */
29
+ export interface PendingOperation {
30
+ type: string;
31
+ data: any;
32
+ targetUrl?: string;
33
+ }
34
+ /**
35
+ * WeaveBackgroundAPI class
36
+ *
37
+ * Provides methods for apps to interact with background state service.
38
+ * Each app instance gets its own API instance with its appId.
39
+ */
40
+ export declare class WeaveBackgroundAPI {
41
+ private appId;
42
+ constructor(appId: string);
43
+ /**
44
+ * Save app state to background service
45
+ * State survives page reloads within the browser session
46
+ *
47
+ * @param state - The state object to save
48
+ */
49
+ saveState(state: any): Promise<void>;
50
+ /**
51
+ * Load app state from background service
52
+ * Returns null if no state exists or if it has expired
53
+ *
54
+ * @returns The saved state or null
55
+ */
56
+ loadState<T = any>(): Promise<T | null>;
57
+ /**
58
+ * Clear app state from background service
59
+ */
60
+ clearState(): Promise<void>;
61
+ /**
62
+ * Set a pending operation for multi-page flows
63
+ * Use this before triggering navigation to save context
64
+ *
65
+ * @param operation - The operation to save
66
+ */
67
+ setPendingOperation(operation: PendingOperation): Promise<void>;
68
+ /**
69
+ * Get pending operation after navigation
70
+ * Returns null if no pending operation exists
71
+ *
72
+ * @returns The pending operation or null
73
+ */
74
+ getPendingOperation(): Promise<PendingOperation | null>;
75
+ /**
76
+ * Clear pending operation
77
+ * Call this after successfully handling the pending operation
78
+ */
79
+ clearPendingOperation(): Promise<void>;
80
+ }
81
+ //# sourceMappingURL=WeaveBackgroundAPI.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WeaveBackgroundAPI.d.ts","sourceRoot":"","sources":["../../../src/WeaveBackgroundAPI.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAWH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,GAAG,CAAC;IACV,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA4FD;;;;;GAKG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,EAAE,MAAM;IAIzB;;;;;OAKG;IACG,SAAS,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAO1C;;;;;OAKG;IACG,SAAS,CAAC,CAAC,GAAG,GAAG,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAO7C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC;;;;;OAKG;IACG,mBAAmB,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrE;;;;;OAKG;IACG,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAO7D;;;OAGG;IACG,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7C"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * WeaveBackgroundAPI
3
+ *
4
+ * Client-side API for Weave apps to interact with the background state service.
5
+ * Allows apps to persist state across page reloads and manage multi-page operations.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * // Save state (survives page reload)
10
+ * await weaveAPI.background.saveState({ count: 5, items: [...] });
11
+ *
12
+ * // Load state after page reload
13
+ * const state = await weaveAPI.background.loadState();
14
+ *
15
+ * // Set pending operation before navigation
16
+ * await weaveAPI.background.setPendingOperation({
17
+ * type: 'fill-form',
18
+ * data: { content: '...' },
19
+ * targetUrl: 'https://example.com/form'
20
+ * });
21
+ *
22
+ * // Check for pending operation after navigation
23
+ * const pending = await weaveAPI.background.getPendingOperation();
24
+ * ```
25
+ */
26
+ // Request timeout in ms
27
+ const REQUEST_TIMEOUT = 5000;
28
+ // Counter for unique request IDs
29
+ let requestIdCounter = 0;
30
+ // Pending requests waiting for response
31
+ const pendingRequests = new Map();
32
+ // Flag to track if listener is set up
33
+ let listenerInitialized = false;
34
+ /**
35
+ * Initialize the response listener (called once)
36
+ */
37
+ function initializeListener() {
38
+ if (listenerInitialized)
39
+ return;
40
+ listenerInitialized = true;
41
+ window.addEventListener('message', (event) => {
42
+ const message = event.data;
43
+ // Only handle background state responses
44
+ if (message?.type !== 'BG_STATE_RESPONSE')
45
+ return;
46
+ const pending = pendingRequests.get(message.requestId);
47
+ if (!pending)
48
+ return;
49
+ // Clear timeout and remove from pending
50
+ clearTimeout(pending.timeout);
51
+ pendingRequests.delete(message.requestId);
52
+ if (message.success) {
53
+ pending.resolve({
54
+ state: message.state,
55
+ operation: message.operation,
56
+ });
57
+ }
58
+ else {
59
+ pending.reject(new Error(message.error || 'Unknown error'));
60
+ }
61
+ });
62
+ }
63
+ /**
64
+ * Send a message to the background state service via content script
65
+ */
66
+ async function sendMessage(type, payload) {
67
+ // Initialize listener on first use
68
+ initializeListener();
69
+ const requestId = `bg-${++requestIdCounter}-${Date.now()}`;
70
+ return new Promise((resolve, reject) => {
71
+ // Set up timeout
72
+ const timeout = setTimeout(() => {
73
+ pendingRequests.delete(requestId);
74
+ reject(new Error(`Background state request timed out: ${type}`));
75
+ }, REQUEST_TIMEOUT);
76
+ // Store pending request
77
+ pendingRequests.set(requestId, { resolve, reject, timeout });
78
+ // Send message to content script (which forwards to background)
79
+ window.parent.postMessage({
80
+ type,
81
+ requestId,
82
+ payload,
83
+ }, '*');
84
+ });
85
+ }
86
+ /**
87
+ * WeaveBackgroundAPI class
88
+ *
89
+ * Provides methods for apps to interact with background state service.
90
+ * Each app instance gets its own API instance with its appId.
91
+ */
92
+ export class WeaveBackgroundAPI {
93
+ constructor(appId) {
94
+ this.appId = appId;
95
+ }
96
+ /**
97
+ * Save app state to background service
98
+ * State survives page reloads within the browser session
99
+ *
100
+ * @param state - The state object to save
101
+ */
102
+ async saveState(state) {
103
+ await sendMessage('BG_SAVE_STATE', {
104
+ appId: this.appId,
105
+ state,
106
+ });
107
+ }
108
+ /**
109
+ * Load app state from background service
110
+ * Returns null if no state exists or if it has expired
111
+ *
112
+ * @returns The saved state or null
113
+ */
114
+ async loadState() {
115
+ const response = await sendMessage('BG_LOAD_STATE', {
116
+ appId: this.appId,
117
+ });
118
+ return response.state;
119
+ }
120
+ /**
121
+ * Clear app state from background service
122
+ */
123
+ async clearState() {
124
+ await sendMessage('BG_CLEAR_STATE', {
125
+ appId: this.appId,
126
+ });
127
+ }
128
+ /**
129
+ * Set a pending operation for multi-page flows
130
+ * Use this before triggering navigation to save context
131
+ *
132
+ * @param operation - The operation to save
133
+ */
134
+ async setPendingOperation(operation) {
135
+ await sendMessage('BG_SET_PENDING_OP', {
136
+ appId: this.appId,
137
+ operation,
138
+ });
139
+ }
140
+ /**
141
+ * Get pending operation after navigation
142
+ * Returns null if no pending operation exists
143
+ *
144
+ * @returns The pending operation or null
145
+ */
146
+ async getPendingOperation() {
147
+ const response = await sendMessage('BG_GET_PENDING_OP', {
148
+ appId: this.appId,
149
+ });
150
+ return response.operation;
151
+ }
152
+ /**
153
+ * Clear pending operation
154
+ * Call this after successfully handling the pending operation
155
+ */
156
+ async clearPendingOperation() {
157
+ await sendMessage('BG_CLEAR_PENDING_OP', {
158
+ appId: this.appId,
159
+ });
160
+ }
161
+ }
162
+ // Export for global usage
163
+ if (typeof window !== 'undefined') {
164
+ window.WeaveBackgroundAPI = WeaveBackgroundAPI;
165
+ }