@buoy-gg/impersonate 2.1.16 → 3.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.
@@ -310,6 +310,32 @@ class ImpersonateStore {
310
310
  return () => this.listeners.delete(listener);
311
311
  };
312
312
 
313
+ // ===========================================================================
314
+ // REMOTE MIRROR MODE
315
+ // ===========================================================================
316
+
317
+ remoteHandler = null;
318
+
319
+ /**
320
+ * Remote mirror mode (desktop dashboard): while a handler is set, every
321
+ * mutation forwards (method, params) to the synced device instead of
322
+ * running locally — header patching, data nuking and persistence all
323
+ * happen on the device, and the resulting state comes back via
324
+ * replaceState(). Pass null to restore local behavior.
325
+ */
326
+ setRemoteHandler(handler) {
327
+ this.remoteHandler = handler;
328
+ }
329
+
330
+ /**
331
+ * Replace the mirrored state from a synced device snapshot. Does not
332
+ * persist or touch the fetch listener — the device owns both.
333
+ */
334
+ replaceState(state) {
335
+ this.state = state;
336
+ this.notify();
337
+ }
338
+
313
339
  // ===========================================================================
314
340
  // IMPERSONATION ACTIONS
315
341
  // ===========================================================================
@@ -324,6 +350,12 @@ class ImpersonateStore {
324
350
  * the visual symptom of "I clicked a user and nothing changed."
325
351
  */
326
352
  async startImpersonation(user) {
353
+ if (this.remoteHandler) {
354
+ this.remoteHandler("startImpersonation", {
355
+ user
356
+ });
357
+ return;
358
+ }
327
359
  const historyEntry = {
328
360
  user,
329
361
  lastUsedAt: new Date().toISOString()
@@ -358,6 +390,10 @@ class ImpersonateStore {
358
390
  * before nuking caches so subsequent refetches go out without the header.
359
391
  */
360
392
  async stopImpersonation() {
393
+ if (this.remoteHandler) {
394
+ this.remoteHandler("stopImpersonation");
395
+ return;
396
+ }
361
397
  // eslint-disable-next-line no-console
362
398
  console.log(`[impersonate] stopImpersonation: isActive ${this.state.isActive} -> false, listeners=${this.listeners.size}`);
363
399
  this.state = {
@@ -376,6 +412,10 @@ class ImpersonateStore {
376
412
  * Pause impersonation (temporarily stop injecting headers)
377
413
  */
378
414
  async pauseImpersonation() {
415
+ if (this.remoteHandler) {
416
+ this.remoteHandler("pauseImpersonation");
417
+ return;
418
+ }
379
419
  if (!this.state.isActive || this.state.isPaused) return;
380
420
  this.state = {
381
421
  ...this.state,
@@ -396,6 +436,10 @@ class ImpersonateStore {
396
436
  * Resume impersonation (start injecting headers again)
397
437
  */
398
438
  async resumeImpersonation() {
439
+ if (this.remoteHandler) {
440
+ this.remoteHandler("resumeImpersonation");
441
+ return;
442
+ }
399
443
  if (!this.state.isActive || !this.state.isPaused) return;
400
444
  this.state = {
401
445
  ...this.state,
@@ -427,6 +471,12 @@ class ImpersonateStore {
427
471
  * Update settings (header key, ignore patterns, data nuke settings, show banner)
428
472
  */
429
473
  async updateSettings(settings) {
474
+ if (this.remoteHandler) {
475
+ this.remoteHandler("updateSettings", {
476
+ settings
477
+ });
478
+ return;
479
+ }
430
480
  this.state = {
431
481
  ...this.state,
432
482
  headerKey: settings.headerKey ?? this.state.headerKey,
@@ -454,6 +504,12 @@ class ImpersonateStore {
454
504
  * Remove a user from history
455
505
  */
456
506
  async removeFromHistory(userId) {
507
+ if (this.remoteHandler) {
508
+ this.remoteHandler("removeFromHistory", {
509
+ userId
510
+ });
511
+ return;
512
+ }
457
513
  this.state = {
458
514
  ...this.state,
459
515
  history: this.state.history.filter(entry => entry.user.id !== userId)
@@ -466,6 +522,10 @@ class ImpersonateStore {
466
522
  * Clear all history
467
523
  */
468
524
  async clearHistory() {
525
+ if (this.remoteHandler) {
526
+ this.remoteHandler("clearHistory");
527
+ return;
528
+ }
469
529
  this.state = {
470
530
  ...this.state,
471
531
  history: []
@@ -27,6 +27,12 @@ Object.defineProperty(exports, "ImpersonateHistoryList", {
27
27
  return _ImpersonateHistoryList.ImpersonateHistoryList;
28
28
  }
29
29
  });
30
+ Object.defineProperty(exports, "ImpersonateIcon", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return _preset.ImpersonateIcon;
34
+ }
35
+ });
30
36
  Object.defineProperty(exports, "ImpersonateModal", {
31
37
  enumerable: true,
32
38
  get: function () {
@@ -51,6 +57,12 @@ Object.defineProperty(exports, "UserSearchView", {
51
57
  return _UserSearchView.UserSearchView;
52
58
  }
53
59
  });
60
+ Object.defineProperty(exports, "createImpersonateSyncAdapter", {
61
+ enumerable: true,
62
+ get: function () {
63
+ return _impersonateSyncAdapter.createImpersonateSyncAdapter;
64
+ }
65
+ });
54
66
  Object.defineProperty(exports, "createImpersonateTool", {
55
67
  enumerable: true,
56
68
  get: function () {
@@ -112,6 +124,7 @@ Object.defineProperty(exports, "useImpersonateHistory", {
112
124
  }
113
125
  });
114
126
  var _preset = require("./preset");
127
+ var _impersonateSyncAdapter = require("./sync/impersonateSyncAdapter");
115
128
  var _ImpersonateModal = require("./impersonate/components/ImpersonateModal");
116
129
  var _ImpersonateBanner = require("./impersonate/components/ImpersonateBanner");
117
130
  var _ImpersonateOverlay = require("./impersonate/components/ImpersonateOverlay");
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.ImpersonateIcon = ImpersonateIcon;
6
7
  exports.createImpersonateTool = createImpersonateTool;
7
8
  var _react = _interopRequireDefault(require("react"));
8
9
  var _reactNative = require("react-native");
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createImpersonateSyncAdapter = createImpersonateSyncAdapter;
7
+ var _impersonateStore = require("../impersonate/utils/impersonateStore");
8
+ /**
9
+ * Create a sync adapter for the impersonate tool, consumed by
10
+ * @buoy-gg/external-sync's `useExternalSync` (structurally matches its
11
+ * ToolSyncAdapter interface so this package doesn't need a dependency on it).
12
+ *
13
+ * The dashboard mirrors the impersonation state and forwards every mutation
14
+ * back as an action — header patching, data nuking and persistence all run
15
+ * on the device, so impersonating from the desktop behaves exactly like
16
+ * tapping the modal on the phone.
17
+ */
18
+ function createImpersonateSyncAdapter({
19
+ onSearchUsers
20
+ }) {
21
+ return {
22
+ version: 1,
23
+ getSnapshot: () => _impersonateStore.impersonateStore.getState(),
24
+ subscribe: onChange => _impersonateStore.impersonateStore.subscribe(onChange),
25
+ actions: {
26
+ searchUsers: params => onSearchUsers(params.query),
27
+ startImpersonation: params => _impersonateStore.impersonateStore.startImpersonation(params.user),
28
+ stopImpersonation: () => _impersonateStore.impersonateStore.stopImpersonation(),
29
+ pauseImpersonation: () => _impersonateStore.impersonateStore.pauseImpersonation(),
30
+ resumeImpersonation: () => _impersonateStore.impersonateStore.resumeImpersonation(),
31
+ updateSettings: params => _impersonateStore.impersonateStore.updateSettings(params.settings),
32
+ removeFromHistory: params => _impersonateStore.impersonateStore.removeFromHistory(params.userId),
33
+ clearHistory: () => _impersonateStore.impersonateStore.clearHistory()
34
+ }
35
+ };
36
+ }
@@ -307,6 +307,32 @@ class ImpersonateStore {
307
307
  return () => this.listeners.delete(listener);
308
308
  };
309
309
 
310
+ // ===========================================================================
311
+ // REMOTE MIRROR MODE
312
+ // ===========================================================================
313
+
314
+ remoteHandler = null;
315
+
316
+ /**
317
+ * Remote mirror mode (desktop dashboard): while a handler is set, every
318
+ * mutation forwards (method, params) to the synced device instead of
319
+ * running locally — header patching, data nuking and persistence all
320
+ * happen on the device, and the resulting state comes back via
321
+ * replaceState(). Pass null to restore local behavior.
322
+ */
323
+ setRemoteHandler(handler) {
324
+ this.remoteHandler = handler;
325
+ }
326
+
327
+ /**
328
+ * Replace the mirrored state from a synced device snapshot. Does not
329
+ * persist or touch the fetch listener — the device owns both.
330
+ */
331
+ replaceState(state) {
332
+ this.state = state;
333
+ this.notify();
334
+ }
335
+
310
336
  // ===========================================================================
311
337
  // IMPERSONATION ACTIONS
312
338
  // ===========================================================================
@@ -321,6 +347,12 @@ class ImpersonateStore {
321
347
  * the visual symptom of "I clicked a user and nothing changed."
322
348
  */
323
349
  async startImpersonation(user) {
350
+ if (this.remoteHandler) {
351
+ this.remoteHandler("startImpersonation", {
352
+ user
353
+ });
354
+ return;
355
+ }
324
356
  const historyEntry = {
325
357
  user,
326
358
  lastUsedAt: new Date().toISOString()
@@ -355,6 +387,10 @@ class ImpersonateStore {
355
387
  * before nuking caches so subsequent refetches go out without the header.
356
388
  */
357
389
  async stopImpersonation() {
390
+ if (this.remoteHandler) {
391
+ this.remoteHandler("stopImpersonation");
392
+ return;
393
+ }
358
394
  // eslint-disable-next-line no-console
359
395
  console.log(`[impersonate] stopImpersonation: isActive ${this.state.isActive} -> false, listeners=${this.listeners.size}`);
360
396
  this.state = {
@@ -373,6 +409,10 @@ class ImpersonateStore {
373
409
  * Pause impersonation (temporarily stop injecting headers)
374
410
  */
375
411
  async pauseImpersonation() {
412
+ if (this.remoteHandler) {
413
+ this.remoteHandler("pauseImpersonation");
414
+ return;
415
+ }
376
416
  if (!this.state.isActive || this.state.isPaused) return;
377
417
  this.state = {
378
418
  ...this.state,
@@ -393,6 +433,10 @@ class ImpersonateStore {
393
433
  * Resume impersonation (start injecting headers again)
394
434
  */
395
435
  async resumeImpersonation() {
436
+ if (this.remoteHandler) {
437
+ this.remoteHandler("resumeImpersonation");
438
+ return;
439
+ }
396
440
  if (!this.state.isActive || !this.state.isPaused) return;
397
441
  this.state = {
398
442
  ...this.state,
@@ -424,6 +468,12 @@ class ImpersonateStore {
424
468
  * Update settings (header key, ignore patterns, data nuke settings, show banner)
425
469
  */
426
470
  async updateSettings(settings) {
471
+ if (this.remoteHandler) {
472
+ this.remoteHandler("updateSettings", {
473
+ settings
474
+ });
475
+ return;
476
+ }
427
477
  this.state = {
428
478
  ...this.state,
429
479
  headerKey: settings.headerKey ?? this.state.headerKey,
@@ -451,6 +501,12 @@ class ImpersonateStore {
451
501
  * Remove a user from history
452
502
  */
453
503
  async removeFromHistory(userId) {
504
+ if (this.remoteHandler) {
505
+ this.remoteHandler("removeFromHistory", {
506
+ userId
507
+ });
508
+ return;
509
+ }
454
510
  this.state = {
455
511
  ...this.state,
456
512
  history: this.state.history.filter(entry => entry.user.id !== userId)
@@ -463,6 +519,10 @@ class ImpersonateStore {
463
519
  * Clear all history
464
520
  */
465
521
  async clearHistory() {
522
+ if (this.remoteHandler) {
523
+ this.remoteHandler("clearHistory");
524
+ return;
525
+ }
466
526
  this.state = {
467
527
  ...this.state,
468
528
  history: []
@@ -26,7 +26,13 @@
26
26
  // FACTORY (Primary entry point)
27
27
  // =============================================================================
28
28
 
29
- export { createImpersonateTool } from "./preset";
29
+ export { createImpersonateTool, ImpersonateIcon } from "./preset";
30
+
31
+ // =============================================================================
32
+ // EXTERNAL SYNC (Adapter for @buoy-gg/external-sync's useExternalSync)
33
+ // =============================================================================
34
+
35
+ export { createImpersonateSyncAdapter } from "./sync/impersonateSyncAdapter";
30
36
 
31
37
  // =============================================================================
32
38
  // COMPONENTS (For custom UI implementations)
@@ -79,7 +79,7 @@ async function bootstrapImpersonate() {
79
79
  /**
80
80
  * Impersonate tool icon - a mask/person symbol
81
81
  */
82
- function ImpersonateIcon({
82
+ export function ImpersonateIcon({
83
83
  size,
84
84
  color = "#F59E0B"
85
85
  }) {
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ import { impersonateStore } from "../impersonate/utils/impersonateStore";
4
+ /**
5
+ * Create a sync adapter for the impersonate tool, consumed by
6
+ * @buoy-gg/external-sync's `useExternalSync` (structurally matches its
7
+ * ToolSyncAdapter interface so this package doesn't need a dependency on it).
8
+ *
9
+ * The dashboard mirrors the impersonation state and forwards every mutation
10
+ * back as an action — header patching, data nuking and persistence all run
11
+ * on the device, so impersonating from the desktop behaves exactly like
12
+ * tapping the modal on the phone.
13
+ */
14
+ export function createImpersonateSyncAdapter({
15
+ onSearchUsers
16
+ }) {
17
+ return {
18
+ version: 1,
19
+ getSnapshot: () => impersonateStore.getState(),
20
+ subscribe: onChange => impersonateStore.subscribe(onChange),
21
+ actions: {
22
+ searchUsers: params => onSearchUsers(params.query),
23
+ startImpersonation: params => impersonateStore.startImpersonation(params.user),
24
+ stopImpersonation: () => impersonateStore.stopImpersonation(),
25
+ pauseImpersonation: () => impersonateStore.pauseImpersonation(),
26
+ resumeImpersonation: () => impersonateStore.resumeImpersonation(),
27
+ updateSettings: params => impersonateStore.updateSettings(params.settings),
28
+ removeFromHistory: params => impersonateStore.removeFromHistory(params.userId),
29
+ clearHistory: () => impersonateStore.clearHistory()
30
+ }
31
+ };
32
+ }
@@ -83,6 +83,20 @@ declare class ImpersonateStore {
83
83
  * Returns unsubscribe function
84
84
  */
85
85
  subscribe: (listener: StateListener) => (() => void);
86
+ private remoteHandler;
87
+ /**
88
+ * Remote mirror mode (desktop dashboard): while a handler is set, every
89
+ * mutation forwards (method, params) to the synced device instead of
90
+ * running locally — header patching, data nuking and persistence all
91
+ * happen on the device, and the resulting state comes back via
92
+ * replaceState(). Pass null to restore local behavior.
93
+ */
94
+ setRemoteHandler(handler: ((method: string, params?: unknown) => void) | null): void;
95
+ /**
96
+ * Replace the mirrored state from a synced device snapshot. Does not
97
+ * persist or touch the fetch listener — the device owns both.
98
+ */
99
+ replaceState(state: ImpersonationState): void;
86
100
  /**
87
101
  * Start impersonating a user.
88
102
  *
@@ -1 +1 @@
1
- {"version":3,"file":"impersonateStore.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/utils/impersonateStore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"impersonateStore.d.ts","sourceRoot":"","sources":["../../../../src/impersonate/utils/impersonateStore.ts"],"names":[],"mappings":"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"}
@@ -19,7 +19,8 @@
19
19
  * <FloatingDevTools apps={[impersonateTool]} />
20
20
  * ```
21
21
  */
22
- export { createImpersonateTool } from "./preset";
22
+ export { createImpersonateTool, ImpersonateIcon } from "./preset";
23
+ export { createImpersonateSyncAdapter } from "./sync/impersonateSyncAdapter";
23
24
  export { ImpersonateModal } from "./impersonate/components/ImpersonateModal";
24
25
  export { ImpersonateBanner, ImpersonateBannerMinimal, } from "./impersonate/components/ImpersonateBanner";
25
26
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAMH,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAMjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAC7E,OAAO,EACL,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,4CAA4C,CAAC;AACpD;;;;GAIG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,gBAAgB,IAAI,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AAC1G,OAAO,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAC;AACzF,OAAO,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;AAMrF,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,YAAY,EACV,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAClF,YAAY,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AAM7F,YAAY,EACV,IAAI,EACJ,gBAAgB,IAAI,oBAAoB,EACxC,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAM7B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,GACtB,MAAM,yCAAyC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAMH,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAMlE,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAM7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAC7E,OAAO,EACL,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,4CAA4C,CAAC;AACpD;;;;GAIG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,gBAAgB,IAAI,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AAC1G,OAAO,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAC;AACzF,OAAO,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;AAMrF,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,YAAY,EACV,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAClF,YAAY,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AAM7F,YAAY,EACV,IAAI,EACJ,gBAAgB,IAAI,oBAAoB,EACxC,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAM7B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,GACtB,MAAM,yCAAyC,CAAC"}
@@ -7,6 +7,14 @@
7
7
  import React from "react";
8
8
  import { ImpersonateBanner } from "./impersonate/components/ImpersonateBanner";
9
9
  import type { ImpersonateToolConfig } from "./impersonate/types";
10
+ interface IconProps {
11
+ size: number;
12
+ color?: string;
13
+ }
14
+ /**
15
+ * Impersonate tool icon - a mask/person symbol
16
+ */
17
+ export declare function ImpersonateIcon({ size, color }: IconProps): React.JSX.Element;
10
18
  /**
11
19
  * Create an impersonate tool with custom configuration
12
20
  *
@@ -70,4 +78,5 @@ export declare function createImpersonateTool(config: ImpersonateToolConfig): {
70
78
  };
71
79
  Banner: typeof ImpersonateBanner;
72
80
  };
81
+ export {};
73
82
  //# sourceMappingURL=preset.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../../src/preset.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAG/E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AA+GjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB;;;;;qBA6B9C;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;uBAGd;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;QAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;KAAE;;;;;EAmB3H"}
1
+ {"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../../src/preset.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAG/E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAyEjE,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,KAAiB,EAAE,EAAE,SAAS,qBAmBrE;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB;;;;;qBA6B9C;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;uBAGd;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;QAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;KAAE;;;;;EAmB3H"}
@@ -0,0 +1,35 @@
1
+ import type { User, ImpersonationState } from "../impersonate/types";
2
+ interface CreateImpersonateSyncAdapterOptions {
3
+ /**
4
+ * Same user-search callback you pass to the ImpersonateModal — the
5
+ * dashboard's search box proxies here.
6
+ */
7
+ onSearchUsers: (query: string) => Promise<User[]>;
8
+ }
9
+ /**
10
+ * Create a sync adapter for the impersonate tool, consumed by
11
+ * @buoy-gg/external-sync's `useExternalSync` (structurally matches its
12
+ * ToolSyncAdapter interface so this package doesn't need a dependency on it).
13
+ *
14
+ * The dashboard mirrors the impersonation state and forwards every mutation
15
+ * back as an action — header patching, data nuking and persistence all run
16
+ * on the device, so impersonating from the desktop behaves exactly like
17
+ * tapping the modal on the phone.
18
+ */
19
+ export declare function createImpersonateSyncAdapter({ onSearchUsers, }: CreateImpersonateSyncAdapterOptions): {
20
+ version: number;
21
+ getSnapshot: () => ImpersonationState;
22
+ subscribe: (onChange: () => void) => () => void;
23
+ actions: {
24
+ searchUsers: (params: unknown) => Promise<User[]>;
25
+ startImpersonation: (params: unknown) => Promise<void>;
26
+ stopImpersonation: () => Promise<void>;
27
+ pauseImpersonation: () => Promise<void>;
28
+ resumeImpersonation: () => Promise<void>;
29
+ updateSettings: (params: unknown) => Promise<void>;
30
+ removeFromHistory: (params: unknown) => Promise<void>;
31
+ clearHistory: () => Promise<void>;
32
+ };
33
+ };
34
+ export {};
35
+ //# sourceMappingURL=impersonateSyncAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impersonateSyncAdapter.d.ts","sourceRoot":"","sources":["../../../src/sync/impersonateSyncAdapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAErE,UAAU,mCAAmC;IAC3C;;;OAGG;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;CACnD;AAED;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,EAC3C,aAAa,GACd,EAAE,mCAAmC;;uBAGjB,kBAAkB;0BACb,MAAM,IAAI;;8BAER,OAAO;qCAEA,OAAO;;;;iCAKX,OAAO;oCAKJ,OAAO;;;EAOxC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-gg/impersonate",
3
- "version": "2.1.16",
3
+ "version": "3.0.0",
4
4
  "description": "User impersonation tool for Buoy DevTools - inject custom headers for admin testing",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -26,7 +26,7 @@
26
26
  ],
27
27
  "sideEffects": false,
28
28
  "dependencies": {
29
- "@buoy-gg/shared-ui": "2.2.0"
29
+ "@buoy-gg/shared-ui": "3.0.0"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": "*",