@andco/sdk 0.0.2 → 0.0.4

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 (83) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +96 -54
  3. package/dist/auth.d.ts +8 -3
  4. package/dist/auth.d.ts.map +1 -1
  5. package/dist/auth.js +32 -23
  6. package/dist/browser/controller.d.ts +55 -1
  7. package/dist/browser/controller.d.ts.map +1 -1
  8. package/dist/browser/controller.js +166 -9
  9. package/dist/browser/frame.d.ts +4 -3
  10. package/dist/browser/frame.d.ts.map +1 -1
  11. package/dist/browser/frame.js +12 -20
  12. package/dist/browser/index.d.ts +18 -6
  13. package/dist/browser/index.d.ts.map +1 -1
  14. package/dist/browser/index.js +64 -29
  15. package/dist/browser/popup.d.ts +6 -1
  16. package/dist/browser/popup.d.ts.map +1 -1
  17. package/dist/browser/popup.js +37 -8
  18. package/dist/cli/index.d.ts +4 -2
  19. package/dist/cli/index.d.ts.map +1 -1
  20. package/dist/cli/index.js +10 -3
  21. package/dist/cli/server.d.ts +5 -0
  22. package/dist/cli/server.d.ts.map +1 -1
  23. package/dist/cli/server.js +5 -0
  24. package/dist/client.d.ts +66 -19
  25. package/dist/client.d.ts.map +1 -1
  26. package/dist/client.js +125 -74
  27. package/dist/config.d.ts +2 -1
  28. package/dist/config.d.ts.map +1 -1
  29. package/dist/config.js +1 -0
  30. package/dist/credentials.d.ts +58 -4
  31. package/dist/credentials.d.ts.map +1 -1
  32. package/dist/credentials.js +0 -0
  33. package/dist/errors.d.ts +23 -21
  34. package/dist/errors.d.ts.map +1 -1
  35. package/dist/errors.js +18 -20
  36. package/dist/globals.d.ts +25 -0
  37. package/dist/globals.d.ts.map +1 -0
  38. package/dist/globals.js +15 -0
  39. package/dist/grants-api.d.ts +34 -0
  40. package/dist/grants-api.d.ts.map +1 -0
  41. package/dist/grants-api.js +48 -0
  42. package/dist/grants.d.ts +16 -0
  43. package/dist/grants.d.ts.map +1 -0
  44. package/dist/grants.js +13 -0
  45. package/dist/index.d.ts +12 -6
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +8 -2
  48. package/dist/inflight.d.ts +31 -0
  49. package/dist/inflight.d.ts.map +1 -0
  50. package/dist/inflight.js +26 -0
  51. package/dist/intents.d.ts +386 -40
  52. package/dist/intents.d.ts.map +1 -1
  53. package/dist/intents.js +712 -53
  54. package/dist/oauth.d.ts +55 -6
  55. package/dist/oauth.d.ts.map +1 -1
  56. package/dist/oauth.js +86 -57
  57. package/dist/presenter.d.ts +59 -11
  58. package/dist/presenter.d.ts.map +1 -1
  59. package/dist/presenter.js +40 -1
  60. package/dist/resource.d.ts +109 -0
  61. package/dist/resource.d.ts.map +1 -0
  62. package/dist/resource.js +151 -0
  63. package/dist/rest.d.ts +23 -4
  64. package/dist/rest.d.ts.map +1 -1
  65. package/dist/rest.js +46 -5
  66. package/dist/server/index.d.ts +3 -0
  67. package/dist/server/index.d.ts.map +1 -1
  68. package/dist/server/index.js +1 -0
  69. package/dist/server-metadata.generated.d.ts.map +1 -1
  70. package/dist/server-metadata.generated.js +8 -4
  71. package/dist/service.d.ts +109 -0
  72. package/dist/service.d.ts.map +1 -0
  73. package/dist/service.js +241 -0
  74. package/dist/session-store.d.ts +12 -4
  75. package/dist/session-store.d.ts.map +1 -1
  76. package/dist/session-store.js +64 -14
  77. package/dist/storage.d.ts +16 -23
  78. package/dist/storage.d.ts.map +1 -1
  79. package/dist/storage.js +27 -25
  80. package/dist/tokens.d.ts +46 -0
  81. package/dist/tokens.d.ts.map +1 -0
  82. package/dist/tokens.js +148 -0
  83. package/package.json +13 -3
@@ -1,6 +1,34 @@
1
1
  import { ANDCO_ERROR_CODES as ANDCO_PROTOCOL_ERROR_CODES, ANDCO_RELEASE, callbackStateCreate } from "@andco/protocol";
2
2
  import { ANDCO_ERROR_CODES, AndcoError } from "../errors.js";
3
3
  import { AndcoButtonBridge } from "./frame.js";
4
+ /**
5
+ * Sandbox restrictions the hosted iframe grants: scripts to run, same-origin to reach its own
6
+ * storage, and a popup that may escape the sandbox because it is a separate top-level browsing
7
+ * context the sandbox does not otherwise constrain.
8
+ *
9
+ * This is a containment boundary, not a per-binding style choice, so it is declared exactly once
10
+ * here rather than copied into every framework binding.
11
+ */
12
+ const IFRAME_SANDBOX = "allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox";
13
+ /** Keeps the Project's own URL out of the request the hosted iframe makes. */
14
+ const IFRAME_REFERRER_POLICY = "no-referrer";
15
+ /** The part of the default iframe style every binding shares regardless of size. */
16
+ const IFRAME_BASE_STYLE = { border: "0", display: "block" };
17
+ /**
18
+ * The hosted control's default box.
19
+ *
20
+ * A bare iframe is 300x150 with a border, and the hosted control fills whatever box it is given, so
21
+ * without a default an application sees a bordered grey slab. React, Vue, and Svelte apply this
22
+ * directly to the `<iframe>` they render.
23
+ */
24
+ const DEFAULT_SIZE = { height: "3rem", width: "18rem" };
25
+ const IFRAME_DEFAULT_STYLE = { ...IFRAME_BASE_STYLE, ...DEFAULT_SIZE };
26
+ /** Renders a style record — property names only, no camelCase — as inline CSS text. */
27
+ function frameStyleText(style) {
28
+ return Object.entries(style)
29
+ .map(([property, value]) => `${property}:${value}`)
30
+ .join(";");
31
+ }
4
32
  /**
5
33
  * Coordinates one hosted Andco iframe without owning how a framework renders it.
6
34
  *
@@ -11,6 +39,15 @@ import { AndcoButtonBridge } from "./frame.js";
11
39
  * Render `snapshot.iframeURL` in your platform's own iframe element, then hand that element to
12
40
  * `connect()` once it mounts.
13
41
  *
42
+ * The frame's fixed attributes and default sizing are published as static data —
43
+ * {@link AndcoButtonController.IFRAME_SANDBOX}, {@link AndcoButtonController.IFRAME_REFERRER_POLICY},
44
+ * {@link AndcoButtonController.IFRAME_DEFAULT_STYLE}, and {@link AndcoButtonController.frameProps} for
45
+ * the snapshot-derived `src`/`hidden` pair — so every binding applies the same contract to its own
46
+ * element instead of redeclaring it. `sdk-script`'s custom element is the one exception on sizing: it
47
+ * sizes itself through a stylesheet layer (using {@link AndcoButtonController.DEFAULT_SIZE}, so the
48
+ * visible default stays the same) and stretches its internal iframe to fill it, so that an author's
49
+ * own CSS on `andco-button` wins without touching the iframe's inline style.
50
+ *
14
51
  * @example
15
52
  * ```ts
16
53
  * const controller = new AndcoButtonController({ client: andco, onComplete: reload });
@@ -19,6 +56,31 @@ import { AndcoButtonBridge } from "./frame.js";
19
56
  * ```
20
57
  */
21
58
  export class AndcoButtonController {
59
+ /** @see {@link IFRAME_SANDBOX} */
60
+ static IFRAME_SANDBOX = IFRAME_SANDBOX;
61
+ /** @see {@link IFRAME_REFERRER_POLICY} */
62
+ static IFRAME_REFERRER_POLICY = IFRAME_REFERRER_POLICY;
63
+ /** @see {@link IFRAME_BASE_STYLE} */
64
+ static IFRAME_BASE_STYLE = IFRAME_BASE_STYLE;
65
+ /** @see {@link DEFAULT_SIZE} */
66
+ static DEFAULT_SIZE = DEFAULT_SIZE;
67
+ /** @see {@link IFRAME_DEFAULT_STYLE} */
68
+ static IFRAME_DEFAULT_STYLE = IFRAME_DEFAULT_STYLE;
69
+ /**
70
+ * Renders a style record as inline CSS text, for a binding that needs a string rather than an
71
+ * object — Svelte's `style` attribute and `sdk-script`'s `HTMLElement.style.cssText`.
72
+ */
73
+ static frameStyleText = frameStyleText;
74
+ /**
75
+ * The two iframe attributes a snapshot drives, mapped from protocol terms to DOM ones.
76
+ *
77
+ * Every binding applies this on top of {@link AndcoButtonController.IFRAME_SANDBOX} and
78
+ * {@link AndcoButtonController.IFRAME_REFERRER_POLICY}: those two are fixed, this pair changes
79
+ * with the connection.
80
+ */
81
+ static frameProps(snapshot) {
82
+ return { src: snapshot.iframeURL, hidden: !snapshot.ready };
83
+ }
22
84
  #options;
23
85
  #listeners = new Set();
24
86
  #bridge;
@@ -26,6 +88,7 @@ export class AndcoButtonController {
26
88
  #snapshot;
27
89
  #pending;
28
90
  #presentationId;
91
+ #intentId;
29
92
  #generation = 0;
30
93
  /** One automatic reconnect per `connect()` call, so a single slow network blip self-heals without
31
94
  * bothering the app — but a persistently broken endpoint still surfaces as a visible `"error"`
@@ -50,7 +113,7 @@ export class AndcoButtonController {
50
113
  connect(iframe) {
51
114
  this.disconnect();
52
115
  this.#iframe = iframe;
53
- console.debug("[AndcoButtonController] connecting: %o", { iframeURL: this.#snapshot.iframeURL });
116
+ console.debug("[AndcoButtonController] connecting: %s", this.#snapshot.iframeURL);
54
117
  this.#publish({ status: "connecting", ready: false, error: null });
55
118
  try {
56
119
  this.#bridge = new AndcoButtonBridge(iframe, {
@@ -80,7 +143,7 @@ export class AndcoButtonController {
80
143
  const timedOut = event.error.code === ANDCO_PROTOCOL_ERROR_CODES.HANDSHAKE_TIMEOUT;
81
144
  if (timedOut && !this.#timedOutOnce && this.#iframe) {
82
145
  this.#timedOutOnce = true;
83
- console.debug("[AndcoButtonController] handshake timed out", { action: "reconnect", retry: 1 });
146
+ console.debug("[AndcoButtonController] handshake timed out; reconnecting once");
84
147
  this.connect(this.#iframe);
85
148
  return;
86
149
  }
@@ -93,6 +156,7 @@ export class AndcoButtonController {
93
156
  }
94
157
  return () => this.disconnect();
95
158
  }
159
+ /** Detaches the iframe bridge while retaining listeners and the last iframe for reuse. */
96
160
  disconnect() {
97
161
  this.#bridge?.destroy();
98
162
  this.#bridge = undefined;
@@ -108,25 +172,25 @@ export class AndcoButtonController {
108
172
  restart() {
109
173
  this.#generation += 1;
110
174
  this.#pending = undefined;
175
+ this.#intentId = undefined;
111
176
  if (this.#snapshot.status === "error" && this.#iframe) {
112
177
  // A deliberate retry (the app calling this after showing the error) earns its own one-shot
113
178
  // auto-reconnect on a future timeout, same as the very first connect did.
114
179
  this.#timedOutOnce = false;
115
- console.debug("[AndcoButtonController] restarting after an error, reconnecting: %o", {
116
- code: this.#snapshot.error?.code,
117
- });
180
+ console.debug("[AndcoButtonController] restarting after an error, reconnecting: %O", this.#snapshot.error);
118
181
  this.connect(this.#iframe);
119
182
  return;
120
183
  }
121
184
  this.#publish({ status: this.#bridge ? "ready" : "idle", error: null });
122
185
  }
186
+ /** Releases the bridge, iframe reference, and all snapshot listeners. */
123
187
  destroy() {
124
188
  this.disconnect();
125
189
  this.#iframe = undefined;
126
190
  this.#listeners.clear();
127
191
  }
128
192
  /**
129
- * Prepares an authorization once the user has activated the hosted control.
193
+ * Prepares a presentation once the user has activated the hosted control.
130
194
  *
131
195
  * Deferred on purpose: the iframe holds the user activation and opens the popup synchronously,
132
196
  * then asks for the URL. Preparing it earlier would waste a transaction on every render and,
@@ -135,19 +199,101 @@ export class AndcoButtonController {
135
199
  async #authorize() {
136
200
  const generation = ++this.#generation;
137
201
  this.#publish({ status: "authorizing", error: null });
202
+ const presentationId = this.#presentationId;
138
203
  // The hosted surface opens the popup, so the callback has to know to deliver its result there.
139
204
  // Encoding that in the state is the protocol's own mechanism and the only one available: the
140
205
  // callback document cannot read a cross-origin opener's location.
206
+ const state = callbackStateCreate(this.#options.client.config.endpoints.widget.origin, presentationId);
207
+ if (this.#options.flow === "intent")
208
+ return this.#presentIntent(generation, presentationId, state);
209
+ if (this.#options.presentation === "redirect")
210
+ return this.#presentRedirect(generation, presentationId);
141
211
  const prepared = await this.#options.client.oauth.createAuthorizationRequest({
142
212
  ...(this.#options.authorization ?? {}),
143
- state: callbackStateCreate(this.#options.client.config.endpoints.widget.origin, this.#presentationId),
213
+ state,
144
214
  });
145
215
  if (generation !== this.#generation)
146
216
  return;
147
217
  if (prepared.error)
148
218
  return this.#fail(prepared.error);
149
219
  this.#pending = prepared.data;
150
- this.#bridge?.resolveAuthorization(this.#presentationId, prepared.data.authorizationUrl.href);
220
+ this.#bridge?.resolvePresentation(presentationId, prepared.data.authorizationUrl.href);
221
+ }
222
+ /**
223
+ * Presents the authorization by replacing this document.
224
+ *
225
+ * The hosted surface cannot do it: its sandbox grants no top navigation, so a URL resolved back to
226
+ * the iframe would only reach a popup that was never opened. The instance's own sign-in already
227
+ * knows how to redirect — it prepares the request, persists the transaction for the next load, and
228
+ * assigns the location — so the control delegates to it rather than repeating those steps. Nothing
229
+ * settles here on success: the document is gone, and the session arrives through Callback
230
+ * Consumption on the next load.
231
+ */
232
+ async #presentRedirect(generation, presentationId) {
233
+ console.debug("[AndcoButtonController] presenting by redirect: presentationId=%s", presentationId);
234
+ const signedIn = await this.#options.client.auth.signIn({
235
+ ...(this.#options.authorization ?? {}),
236
+ presentation: "redirect",
237
+ });
238
+ if (generation !== this.#generation)
239
+ return;
240
+ if (signedIn.error) {
241
+ // Tell the surface the presentation is over so it leaves its busy state; there is no popup to close.
242
+ this.#bridge?.resolvePresentation(presentationId);
243
+ return this.#fail(signedIn.error);
244
+ }
245
+ }
246
+ /**
247
+ * Resolves the Intent this control presents, reusing the instance's own URL construction.
248
+ *
249
+ * It does not build the URL itself. Two constructions of one presentation URL is exactly how the
250
+ * direct and hosted paths drifted before, which is why `intents.presentationURLFor` is published.
251
+ */
252
+ async #presentIntent(generation, presentationId, state) {
253
+ const client = this.#options.client;
254
+ const intentId = this.#options.intentId;
255
+ if (!intentId) {
256
+ return this.#fail(new AndcoError(ANDCO_ERROR_CODES.INVALID_CONFIGURATION, {
257
+ message: 'a control with flow="intent" requires an intentId',
258
+ }));
259
+ }
260
+ // Out of scope for now, and refused rather than silently resolving to nothing: an Intent result
261
+ // that comes back by redirect has no consumer yet, so the presentation would never settle.
262
+ if (this.#options.presentation === "redirect") {
263
+ return this.#fail(new AndcoError(ANDCO_ERROR_CODES.PRESENTATION_UNSUPPORTED, {
264
+ message: 'an Intent cannot be presented with presentation="redirect" yet',
265
+ }));
266
+ }
267
+ const returnTo = client.config.redirectTo;
268
+ if (!returnTo) {
269
+ return this.#fail(new AndcoError(ANDCO_ERROR_CODES.INVALID_CONFIGURATION, {
270
+ message: "an Intent Presentation needs the instance's redirectTo",
271
+ }));
272
+ }
273
+ let resolvedId;
274
+ try {
275
+ resolvedId = typeof intentId === "string" ? intentId : await intentId();
276
+ }
277
+ catch (cause) {
278
+ return this.#fail(AndcoError.from(cause, ANDCO_ERROR_CODES.INVALID_CONFIGURATION));
279
+ }
280
+ if (generation !== this.#generation) {
281
+ return;
282
+ }
283
+ const url = await client.intents.presentationURLFor(resolvedId, {
284
+ presentation: "popup",
285
+ returnTo,
286
+ errorReturnTo: returnTo,
287
+ state,
288
+ });
289
+ if (generation !== this.#generation) {
290
+ return;
291
+ }
292
+ else if (url.error) {
293
+ return this.#fail(url.error);
294
+ }
295
+ this.#intentId = resolvedId;
296
+ this.#bridge?.resolvePresentation(presentationId, url.data.href);
151
297
  }
152
298
  async #settle(event) {
153
299
  const generation = this.#generation;
@@ -170,13 +316,24 @@ export class AndcoButtonController {
170
316
  }
171
317
  if (generation !== this.#generation)
172
318
  return;
319
+ // An Intent completion is a lifecycle fact. What it means financially is read, not relayed.
320
+ if (event.type === "intent.complete" && this.#intentId) {
321
+ const intent = await this.#options.client.intents.get(this.#intentId);
322
+ if (generation !== this.#generation)
323
+ return;
324
+ if (intent.error)
325
+ return this.#fail(intent.error);
326
+ this.#publish({ status: "complete", error: null });
327
+ this.#options.onComplete?.({ outcome: "complete", intent: intent.data });
328
+ return;
329
+ }
173
330
  this.#publish({ status: "complete", error: null });
174
331
  this.#options.onComplete?.();
175
332
  }
176
333
  #fail(error, event) {
177
334
  // An app that never wired `onError` must not lose the failure entirely — a button that just sits
178
335
  // there disabled, with nothing in the console, is what made the last one of these hard to find.
179
- console.error("[AndcoButtonController] %s: %o", error.code, { message: error.message, details: error.details });
336
+ console.error("[AndcoButtonController] %O", error);
180
337
  this.#publish({ status: "error", error });
181
338
  this.#options.onError?.(error, event);
182
339
  }
@@ -40,15 +40,16 @@ export declare class AndcoButtonBridge {
40
40
  /** Sends a validated protocol message to the hosted iframe. */
41
41
  private post;
42
42
  /**
43
- * Resolves a deferred authorization request from the hosted button.
43
+ * Resolves a deferred presentation the hosted button asked this side to prepare — an
44
+ * authorization or an Intent, which is why it is not named after either.
44
45
  * Omit the URL to close the pending popup after resolution fails.
45
46
  *
46
47
  * @example
47
48
  * ```ts
48
- * bridge.resolveAuthorization(presentationId, "https://app.example.com/oauth/start");
49
+ * bridge.resolvePresentation(presentationId, "https://app.example.com/oauth/start");
49
50
  * ```
50
51
  */
51
- resolveAuthorization(presentationId: string, authorizationUrl?: string | URL): void;
52
+ resolvePresentation(presentationId: string, url?: string | URL): void;
52
53
  /**
53
54
  * Forwards a validated same-origin host callback to the iframe that owns the popup.
54
55
  *
@@ -1 +1 @@
1
- {"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../src/browser/frame.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,eAAe,EAEpB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,gCAAgC,EACrC,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAEhC,MAAM,iBAAiB,CAAC;AAGzB,iEAAiE;AACjE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3C,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,GAAG,uBAAuB,GAAG,wBAAwB,KAAK,IAAI,CAAC;IACpH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,GAAG,uBAAuB,KAAK,IAAI,CAAC;IAC9E,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC7D,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,iBAAiB;IAY1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZ1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,SAAS,CAAS;gBAGP,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,iBAAiB;IAkB7C,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,OAAO;IAkDf,OAAO,CAAC,QAAQ,CAAC,aAAa,CAM5B;IAEF,OAAO,CAAC,QAAQ,CAAC,UAAU,CA8BzB;IAEF,OAAO,CAAC,QAAQ,CAAC,cAAc,CA0B7B;IAEF,+DAA+D;IAC/D,OAAO,CAAC,IAAI;IASZ;;;;;;;;OAQG;IACI,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,GAAG;IAWnF;;;;;;OAMG;IACI,0BAA0B,CAAC,OAAO,EAAE,gBAAgB;IAI3D,oEAAoE;IAC7D,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,0BAA0B,EAAE,QAAQ,GAAG,WAAW,CAAC;IAU3F,0EAA0E;IACnE,OAAO;CASf"}
1
+ {"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../src/browser/frame.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,eAAe,EAEpB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,gCAAgC,EACrC,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EAErB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAEhC,MAAM,iBAAiB,CAAC;AAGzB,iEAAiE;AACjE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3C,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,GAAG,uBAAuB,GAAG,wBAAwB,KAAK,IAAI,CAAC;IACpH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,GAAG,uBAAuB,KAAK,IAAI,CAAC;IAC9E,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC7D,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,iBAAiB;IAY1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZ1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,SAAS,CAAS;gBAGP,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,iBAAiB;IAkB7C,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,OAAO;IAmDf,OAAO,CAAC,QAAQ,CAAC,aAAa,CAM5B;IAEF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAgCzB;IAEF,OAAO,CAAC,QAAQ,CAAC,cAAc,CA2B7B;IAEF,+DAA+D;IAC/D,OAAO,CAAC,IAAI;IASZ;;;;;;;;;OASG;IACI,mBAAmB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG;IAWrE;;;;;;OAMG;IACI,0BAA0B,CAAC,OAAO,EAAE,gBAAgB;IAI3D,oEAAoE;IAC7D,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,0BAA0B,EAAE,QAAQ,GAAG,WAAW,CAAC;IAU3F,0EAA0E;IACnE,OAAO;CASf"}
@@ -34,7 +34,7 @@ export class AndcoButtonBridge {
34
34
  if (this.url.origin === window.location.origin) {
35
35
  throw new AndcoError(ANDCO_ERROR_CODES.SAME_ORIGIN_ENDPOINT, { details: { endpointButton: this.url.href } });
36
36
  }
37
- console.debug("[AndcoButtonBridge] created: %o", { endpointButton: this.url.href });
37
+ console.debug("[AndcoButtonBridge] created: %s", this.url.href);
38
38
  iframe.addEventListener("load", this.startHandshake);
39
39
  this.startHandshake();
40
40
  }
@@ -62,11 +62,7 @@ export class AndcoButtonBridge {
62
62
  return;
63
63
  this.settled = true;
64
64
  this.stopHandshake();
65
- console.debug("[AndcoButtonBridge] handshake settled: %o", {
66
- attempts: this.handshakeAttempts,
67
- transport: this.transport,
68
- elapsedMs: Date.now() - this.handshakeStartedAt,
69
- });
65
+ console.debug("[AndcoButtonBridge] handshake settled: attempts=%d transport=%s elapsedMs=%d", this.handshakeAttempts, this.transport, Date.now() - this.handshakeStartedAt);
70
66
  this.options.onReady?.(message);
71
67
  return;
72
68
  }
@@ -75,7 +71,7 @@ export class AndcoButtonBridge {
75
71
  this.settled = true;
76
72
  this.stopHandshake();
77
73
  }
78
- console.warn("[AndcoButtonBridge] hosted surface reported an error: %o", message.error);
74
+ console.warn("[AndcoButtonBridge] hosted surface reported an error: %O", message.error);
79
75
  this.options.onError?.(message);
80
76
  return;
81
77
  }
@@ -142,9 +138,7 @@ export class AndcoButtonBridge {
142
138
  // makes the very first attempt throw a targetOrigin mismatch; the 250ms retry loop recovers
143
139
  // once the iframe has actually navigated, so a transient failure here is not fatal — but it is
144
140
  // worth a log line, since a run that never recovers looks identical to this from the outside.
145
- console.debug("[AndcoButtonBridge] init attempt %d could not post yet, retrying: %o", this.handshakeAttempts, {
146
- cause,
147
- });
141
+ console.debug("[AndcoButtonBridge] init attempt %d could not post yet, retrying: %O", this.handshakeAttempts, cause);
148
142
  }
149
143
  };
150
144
  startHandshake = () => {
@@ -160,10 +154,7 @@ export class AndcoButtonBridge {
160
154
  this.settled = true;
161
155
  this.stopHandshake();
162
156
  this.closePort();
163
- console.error("[AndcoButtonBridge] handshake timed out: %o", {
164
- attempts: this.handshakeAttempts,
165
- endpointButton: this.url.href,
166
- });
157
+ console.error("[AndcoButtonBridge] handshake timed out: attempts=%d endpointButton=%s", this.handshakeAttempts, this.url.href);
167
158
  const message = {
168
159
  protocol: ANDCO_SDK_PROTOCOL,
169
160
  version: ANDCO_PROTOCOL_VERSION,
@@ -185,21 +176,22 @@ export class AndcoButtonBridge {
185
176
  this.iframe.contentWindow?.postMessage(message, this.url.origin);
186
177
  }
187
178
  /**
188
- * Resolves a deferred authorization request from the hosted button.
179
+ * Resolves a deferred presentation the hosted button asked this side to prepare — an
180
+ * authorization or an Intent, which is why it is not named after either.
189
181
  * Omit the URL to close the pending popup after resolution fails.
190
182
  *
191
183
  * @example
192
184
  * ```ts
193
- * bridge.resolveAuthorization(presentationId, "https://app.example.com/oauth/start");
185
+ * bridge.resolvePresentation(presentationId, "https://app.example.com/oauth/start");
194
186
  * ```
195
187
  */
196
- resolveAuthorization(presentationId, authorizationUrl) {
188
+ resolvePresentation(presentationId, url) {
197
189
  const message = {
198
190
  protocol: ANDCO_SDK_PROTOCOL,
199
191
  version: ANDCO_PROTOCOL_VERSION,
200
- type: "authorization-response",
192
+ type: "presentation-response",
201
193
  presentationId,
202
- authorizationUrl: authorizationUrl?.toString(),
194
+ url: url?.toString(),
203
195
  };
204
196
  this.post(message);
205
197
  }
@@ -227,7 +219,7 @@ export class AndcoButtonBridge {
227
219
  destroy() {
228
220
  if (this.destroyed)
229
221
  return;
230
- console.debug("[AndcoButtonBridge] destroyed: %o", { settled: this.settled, attempts: this.handshakeAttempts });
222
+ console.debug("[AndcoButtonBridge] destroyed: settled=%s attempts=%d", this.settled, this.handshakeAttempts);
231
223
  this.destroyed = true;
232
224
  window.removeEventListener("message", this.receiveWindow);
233
225
  this.iframe.removeEventListener("load", this.startHandshake);
@@ -1,17 +1,29 @@
1
1
  import { AndcoClient, type AndcoClientOptions } from "../client.js";
2
+ import { Result } from "../errors.js";
2
3
  import type { AndcoAuthorizationRequest } from "../oauth.js";
3
- import type { AndcoPresenter } from "../presenter.js";
4
+ import { AndcoPresenter, type AndcoPresentOptions } from "../presenter.js";
4
5
  export { AndcoButtonController, type AndcoButtonControllerOptions, type AndcoButtonFlow, type AndcoButtonSnapshot, type AndcoButtonStatus, } from "./controller.js";
5
6
  export { AndcoButtonBridge, type AndcoFrameOptions } from "./frame.js";
6
7
  export { type AndcoPopupMessage, type AndcoPopupWindow, type AndcoRelayOutcome, andcoPopupPresentationId, isAndcoNativeHost, openAndcoPopup, openAndcoPopupWindow, relayAndcoPopupCallback, } from "./popup.js";
7
8
  /**
8
- * Presents an authorization in a browser.
9
+ * Presents an authorization or an Intent in a browser.
9
10
  *
10
- * It detects the first-party Andco Host and routes over the native bridge instead of opening a
11
- * window, so a Miniapp runs the same build in a browser tab and inside the Host without branching
12
- * on the platform. That is why there is no mobile presenter and no mobile builder.
11
+ * A browser treats both alike — one window, one callback — so it reads `kind` only to refuse what
12
+ * it cannot do. It detects the first-party Andco Host and routes over the native bridge instead of
13
+ * opening a window, so a Miniapp runs the same build in a browser tab and inside the Host without
14
+ * branching on the platform. That is why there is no mobile presenter and no mobile builder.
15
+ *
16
+ * The window opens *before* the destination is resolved. A browser grants `window.open` only during
17
+ * a user activation, and both flows need a server round trip to learn where the window should go:
18
+ * an authorization may be pushed, and an Intent is created on demand. Resolving first is what got
19
+ * the window blocked.
13
20
  */
14
- export declare function browserPresenter(): AndcoPresenter;
21
+ export declare class AndcoPresenterBrowser extends AndcoPresenter {
22
+ #private;
23
+ focus(presentationId: string): void;
24
+ present(options: AndcoPresentOptions): Promise<Result<URL | null>>;
25
+ }
26
+ /** Public-client options for browser sign-in, callback relay, and transaction recovery. */
15
27
  export type AndcoBrowserOptions = Omit<AndcoClientOptions, "presenter" | "source" | "clientSecret"> & {
16
28
  /** Rejected by type: a confidential credential must never reach a browser. */
17
29
  clientSecret?: never;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAIpE,OAAO,KAAK,EAAE,yBAAyB,EAAc,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAItD,OAAO,EACL,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,cAAc,CAyBjD;AAED,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,kBAAkB,EAAE,WAAW,GAAG,QAAQ,GAAG,cAAc,CAAC,GAAG;IACpG,8EAA8E;IAC9E,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,iGAAiG;IACjG,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,uGAAuG;IACvG,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,uEAAuE;IACvE,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,+FAA+F;IAC/F,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,mBAAmB,GAAG,WAAW,CAmBvF;AA0CD,6FAA6F;AAC7F,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAMnH"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGpE,OAAO,EAAqB,MAAM,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,yBAAyB,EAAc,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAI3E,OAAO,EACL,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,SAAQ,cAAc;;IAI9C,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAKtC,OAAO,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;CA8CzE;AAED,2FAA2F;AAC3F,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,kBAAkB,EAAE,WAAW,GAAG,QAAQ,GAAG,cAAc,CAAC,GAAG;IACpG,8EAA8E;IAC9E,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,iGAAiG;IACjG,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,uGAAuG;IACvG,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,uEAAuE;IACvE,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAChC,+FAA+F;IAC/F,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,mBAAmB,GAAG,WAAW,CAkBvF;AA0CD,6FAA6F;AAC7F,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAMnH"}
@@ -1,40 +1,75 @@
1
1
  import { AndcoClient } from "../client.js";
2
2
  import { ANDCO_ERROR_CODES, Result } from "../errors.js";
3
- import { WebStorage } from "../storage.js";
4
- import { andcoPopupPresentationId, isAndcoNativeHost, openAndcoPopup, relayAndcoPopupCallback } from "./popup.js";
3
+ import { AndcoPresenter } from "../presenter.js";
4
+ import { LocalStorage } from "../storage.js";
5
+ import { andcoPopupPresentationId, isAndcoNativeHost, openAndcoPopupWindow, relayAndcoPopupCallback } from "./popup.js";
5
6
  export { AndcoButtonController, } from "./controller.js";
6
7
  export { AndcoButtonBridge } from "./frame.js";
7
8
  export { andcoPopupPresentationId, isAndcoNativeHost, openAndcoPopup, openAndcoPopupWindow, relayAndcoPopupCallback, } from "./popup.js";
8
9
  /**
9
- * Presents an authorization in a browser.
10
+ * Presents an authorization or an Intent in a browser.
10
11
  *
11
- * It detects the first-party Andco Host and routes over the native bridge instead of opening a
12
- * window, so a Miniapp runs the same build in a browser tab and inside the Host without branching
13
- * on the platform. That is why there is no mobile presenter and no mobile builder.
12
+ * A browser treats both alike — one window, one callback — so it reads `kind` only to refuse what
13
+ * it cannot do. It detects the first-party Andco Host and routes over the native bridge instead of
14
+ * opening a window, so a Miniapp runs the same build in a browser tab and inside the Host without
15
+ * branching on the platform. That is why there is no mobile presenter and no mobile builder.
16
+ *
17
+ * The window opens *before* the destination is resolved. A browser grants `window.open` only during
18
+ * a user activation, and both flows need a server round trip to learn where the window should go:
19
+ * an authorization may be pushed, and an Intent is created on demand. Resolving first is what got
20
+ * the window blocked.
14
21
  */
15
- export function browserPresenter() {
16
- return {
17
- async present(options) {
18
- if (typeof window === "undefined")
19
- return Result.fail(ANDCO_ERROR_CODES.BROWSER_REQUIRED);
20
- if (options.presentation === "redirect") {
21
- window.location.assign(options.url.href);
22
- // The document is being replaced. The result arrives on the next load, not here.
23
- return Result.ok(null);
24
- }
25
- if (isAndcoNativeHost() && window.__ANDCO_NATIVE_POPUP_HANDLER__ !== true) {
26
- return Result.fail(ANDCO_ERROR_CODES.PRESENTATION_UNSUPPORTED, {
27
- message: "the native Host cannot present a popup without navigating the Miniapp",
28
- });
22
+ export class AndcoPresenterBrowser extends AndcoPresenter {
23
+ /** Windows still open, by Presentation ID, so {@link AndcoPresenterBrowser.focus} can find them. */
24
+ #open = new Map();
25
+ focus(presentationId) {
26
+ console.debug("[AndcoPresenterBrowser.focus] %s open=%s", presentationId, this.#open.has(presentationId));
27
+ this.#open.get(presentationId)?.focus();
28
+ }
29
+ async present(options) {
30
+ if (typeof window === "undefined")
31
+ return Result.fail(ANDCO_ERROR_CODES.BROWSER_REQUIRED);
32
+ if (options.presentation === "redirect") {
33
+ const resolved = await AndcoPresenter.present(options.url);
34
+ if (resolved.error) {
35
+ console.error("[AndcoPresenterBrowser] for options %O got error: %O", options, resolved.error);
36
+ return Result.fail(resolved.error);
29
37
  }
30
- return openAndcoPopup({
31
- url: options.url,
32
- presentationId: options.presentationId,
33
- expectedOrigin: options.returnTo.origin,
34
- signal: options.signal,
38
+ console.debug("[AndcoPresenterBrowser] will window location assign: %s", resolved.data.href);
39
+ window.location.assign(resolved.data.href);
40
+ // The document is being replaced. The result arrives on the next load, not here.
41
+ return Result.ok(null);
42
+ }
43
+ if (isAndcoNativeHost() && window["__ANDCO_NATIVE_POPUP_HANDLER__"] !== true) {
44
+ return Result.fail(ANDCO_ERROR_CODES.PRESENTATION_UNSUPPORTED, {
45
+ message: "the native Host cannot present a popup without navigating the Miniapp",
35
46
  });
36
- },
37
- };
47
+ }
48
+ const popup = openAndcoPopupWindow({
49
+ presentationId: options.presentationId,
50
+ expectedOrigin: options.returnTo.origin,
51
+ signal: options.signal,
52
+ target: options.kind === "intent" && options.presentation === "newtab" ? "newtab" : "popup",
53
+ });
54
+ // Abandon before the server work: a blocked window that still started an authorization or
55
+ // created an Intent would leave a transaction nobody can complete.
56
+ if (popup.blocked) {
57
+ return Result.fail(ANDCO_ERROR_CODES.POPUP_BLOCKED);
58
+ }
59
+ this.#open.set(options.presentationId, popup);
60
+ try {
61
+ const resolved = await AndcoPresenter.present(options.url);
62
+ if (resolved.error) {
63
+ popup.close();
64
+ return Result.fail(resolved.error);
65
+ }
66
+ popup.navigate(resolved.data);
67
+ return await popup.result;
68
+ }
69
+ finally {
70
+ this.#open.delete(options.presentationId);
71
+ }
72
+ }
38
73
  }
39
74
  const TRANSACTION_KEY = "andco.transaction";
40
75
  /**
@@ -59,8 +94,8 @@ const TRANSACTION_KEY = "andco.transaction";
59
94
  * ```
60
95
  */
61
96
  export function createAndcoInstanceForBrowser(options) {
62
- const presenter = options.presenter ?? browserPresenter();
63
- const storage = options.storage ?? (typeof window === "undefined" ? undefined : new WebStorage(window.sessionStorage));
97
+ const presenter = options.presenter ?? new AndcoPresenterBrowser();
98
+ const storage = options.storage ?? (typeof window === "undefined" ? undefined : new LocalStorage());
64
99
  // Annotated because `source` closes over `client`; the closure only runs on the first read.
65
100
  const client = new AndcoClient({
66
101
  ...options,
@@ -41,7 +41,8 @@ export declare function isAndcoNativeHost(): boolean;
41
41
  */
42
42
  export declare function andcoPopupPresentationId(): string | null;
43
43
  /**
44
- * Hands this document's callback to the window that opened it, then closes.
44
+ * Hands this document's callback — an authorization or an Intent outcome — to the window that
45
+ * opened it, then closes.
45
46
  *
46
47
  * The popup cannot complete the exchange itself: the PKCE verifier was generated by the opener and
47
48
  * never left it. So this is a courier, not a consumer — it carries the callback URL back and dies.
@@ -73,6 +74,8 @@ export type AndcoPopupWindow = {
73
74
  navigate(url: URL): void;
74
75
  /** Settles with the relayed callback, `null` on dismissal, or an error. */
75
76
  readonly result: Promise<Result<URL | null>>;
77
+ /** Brings the window to the front; a browser may decline when no user activation is current. */
78
+ focus(): void;
76
79
  close(): void;
77
80
  };
78
81
  /**
@@ -94,6 +97,8 @@ export declare function openAndcoPopupWindow(options: {
94
97
  expectedOrigin: string;
95
98
  url?: URL;
96
99
  signal?: AbortSignal;
100
+ /** `"newtab"` opens a tab instead of a sized window; the relay back is the same. Default `"popup"`. */
101
+ target?: "popup" | "newtab";
97
102
  }): AndcoPopupWindow;
98
103
  /** Opens a popup straight to its destination and waits for the relayed callback. */
99
104
  export declare function openAndcoPopup(options: {
@@ -1 +1 @@
1
- {"version":3,"file":"popup.d.ts","sourceRoot":"","sources":["../../src/browser/popup.ts"],"names":[],"mappings":"AAOA,OAAO,EAAqB,UAAU,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAMrE,mGAAmG;AACnG,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,CAAC,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,mEAAmE;AACnE,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,cAAc,CAAA;CAAE,GAC1B;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC;AAE9C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,uEAAuE;QACvE,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,sFAAsF;QACtF,8BAA8B,CAAC,EAAE,OAAO,CAAC;QACzC,kBAAkB,CAAC,EAAE;YAAE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,CAAC;KAC7D;CACF;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,IAAI,OAAO,CAM3C;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,IAAI,CAMxD;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,EACnC,OAAO,GAAE;IACP;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;CACvB,GACL,iBAAiB,CAkCnB;AAsBD,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,6DAA6D;IAC7D,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC;IAC7C,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,gBAAgB,CA+DnB;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,OAAO,EAAE;IACtC,GAAG,EAAE,GAAG,CAAC;IACT,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAE9B"}
1
+ {"version":3,"file":"popup.d.ts","sourceRoot":"","sources":["../../src/browser/popup.ts"],"names":[],"mappings":"AAOA,OAAO,EAAqB,UAAU,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAMrE,mGAAmG;AACnG,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,CAAC,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,mEAAmE;AACnE,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,cAAc,CAAA;CAAE,GAC1B;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC;AAE9C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,uEAAuE;QACvE,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,sFAAsF;QACtF,8BAA8B,CAAC,EAAE,OAAO,CAAC;QACzC,kBAAkB,CAAC,EAAE;YAAE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,CAAC;KAC7D;CACF;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,IAAI,OAAO,CAM3C;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,IAAI,CAMxD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,EACnC,OAAO,GAAE;IACP;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;CACvB,GACL,iBAAiB,CAyCnB;AAoCD,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,6DAA6D;IAC7D,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC;IAC7C,gGAAgG;IAChG,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,uGAAuG;IACvG,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B,GAAG,gBAAgB,CAsEnB;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,OAAO,EAAE;IACtC,GAAG,EAAE,GAAG,CAAC;IACT,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAE9B"}