reflet-sdk 0.7.1 → 0.7.3

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.
@@ -16,9 +16,9 @@ function readStoredExpiry(publicKey) {
16
16
  /** Zod-free on purpose: the widget calls this eagerly in every customer bundle before lazy-loading team tools. */
17
17
  function hasTeamActivation(publicKey) {
18
18
  const expiresAt = readStoredExpiry(publicKey);
19
- return expiresAt !== null && expiresAt > Date.now() || new URL(window.location.href).searchParams.has(TEAM_ACTIVATION_PARAM);
19
+ return expiresAt !== null && expiresAt > Date.now() || new URL(window.location.href).searchParams.has("reflet-team");
20
20
  }
21
21
  //#endregion
22
- export { teamAccessStorageKey as n, hasTeamActivation as t };
22
+ export { hasTeamActivation as n, teamAccessStorageKey as r, TEAM_ACTIVATION_PARAM as t };
23
23
 
24
- //# sourceMappingURL=team-activation-DCqh71bl.js.map
24
+ //# sourceMappingURL=team-activation-Cv5U7OF1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-activation-Cv5U7OF1.js","names":[],"sources":["../src/sessions/team/team-activation.ts"],"sourcesContent":["export const TEAM_ACTIVATION_PARAM = \"reflet-team\";\nconst STORAGE_KEY_PREFIX = \"reflet-team-access:\";\n\nexport function teamAccessStorageKey(publicKey: string): string {\n return `${STORAGE_KEY_PREFIX}${publicKey}`;\n}\n\nfunction readStoredExpiry(publicKey: string): number | null {\n try {\n const stored: unknown = JSON.parse(\n localStorage.getItem(teamAccessStorageKey(publicKey)) ?? \"null\"\n );\n if (\n typeof stored === \"object\" &&\n stored !== null &&\n \"expiresAt\" in stored &&\n typeof stored.expiresAt === \"number\"\n ) {\n return stored.expiresAt;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/** Zod-free on purpose: the widget calls this eagerly in every customer bundle before lazy-loading team tools. */\nexport function hasTeamActivation(publicKey: string): boolean {\n const expiresAt = readStoredExpiry(publicKey);\n return (\n (expiresAt !== null && expiresAt > Date.now()) ||\n new URL(window.location.href).searchParams.has(TEAM_ACTIVATION_PARAM)\n );\n}\n"],"mappings":";AAAA,MAAa,wBAAwB;AACrC,MAAM,qBAAqB;AAE3B,SAAgB,qBAAqB,WAA2B;CAC9D,OAAO,GAAG,qBAAqB;AACjC;AAEA,SAAS,iBAAiB,WAAkC;CAC1D,IAAI;EACF,MAAM,SAAkB,KAAK,MAC3B,aAAa,QAAQ,qBAAqB,SAAS,CAAC,KAAK,MAC3D;EACA,IACE,OAAO,WAAW,YAClB,WAAW,QACX,eAAe,UACf,OAAO,OAAO,cAAc,UAE5B,OAAO,OAAO;EAEhB,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;AAGA,SAAgB,kBAAkB,WAA4B;CAC5D,MAAM,YAAY,iBAAiB,SAAS;CAC5C,OACG,cAAc,QAAQ,YAAY,KAAK,IAAI,KAC5C,IAAI,IAAI,OAAO,SAAS,IAAI,CAAC,CAAC,aAAa,IAAA,aAAyB;AAExE"}
@@ -1,15 +1,18 @@
1
- import { n as teamAccessStorageKey } from "./team-activation-DCqh71bl.js";
2
- import { A as Notices, M as reportFailure, _ as teamTransport, a as DevtoolsBar, d as PersonIcon, f as SessionWorkspaceProvider, h as purgeAccount, i as BarButton, k as sessionApiErrorSchema, l as SESSIONS_STYLES, m as useWorkspaceLoader, n as DEVTOOLS_STYLES, p as failureMessage, r as DevtoolsSheet, s as SessionsBarButton, t as SessionsPanel, u as RecordingLayer } from "./sessions-panel-CDrnOEwi.js";
1
+ import { r as teamAccessStorageKey, t as TEAM_ACTIVATION_PARAM } from "./team-activation-Cv5U7OF1.js";
2
+ import { A as Notices, M as reportFailure, _ as teamTransport, a as DevtoolsBar, d as PersonIcon, f as SessionWorkspaceProvider, h as purgeAccount, i as BarButton, k as sessionApiErrorSchema, l as SESSIONS_STYLES, m as useWorkspaceLoader, n as DEVTOOLS_STYLES, p as failureMessage, r as DevtoolsSheet, s as SessionsBarButton, t as SessionsPanel, u as RecordingLayer } from "./sessions-panel-BYM0UUgT.js";
3
3
  import { z } from "zod";
4
- import { useState } from "react";
4
+ import { useEffect, useState } from "react";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/sessions/team/team-auth.ts
7
- const TEAM_ACCESS_MESSAGE_TYPE = "reflet:team-access";
8
- const POPUP_NAME = "reflet-team-access";
9
- const POPUP_WIDTH_PX = 480;
10
- const POPUP_HEIGHT_PX = 680;
11
- const POPUP_CLOSED_POLL_MS = 500;
12
- const SIGN_IN_TIMEOUT_MS = 3e5;
7
+ const RETURN_CODE_PARAM = "reflet-team-code";
8
+ const RETURN_ERROR_PARAM = "reflet-team-error";
9
+ const RETURN_STATE_PARAM = "reflet-team-state";
10
+ const RETURN_PARAMS = [
11
+ RETURN_CODE_PARAM,
12
+ RETURN_ERROR_PARAM,
13
+ RETURN_STATE_PARAM
14
+ ];
15
+ const PENDING_SIGN_IN_PREFIX = "reflet-team-sign-in:";
13
16
  const PKCE_RANDOM_BYTES = 32;
14
17
  const TRAILING_SLASHES = /\/+$/;
15
18
  const BASE64_PADDING = /[=]+$/;
@@ -18,20 +21,15 @@ const teamAccessSchema = z.object({
18
21
  organizationName: z.string(),
19
22
  token: z.string().startsWith("fb_team_")
20
23
  });
21
- const teamAccessMessageSchema = z.union([z.object({
22
- code: z.string().min(1),
23
- state: z.string(),
24
- type: z.literal(TEAM_ACCESS_MESSAGE_TYPE)
25
- }), z.object({
26
- error: z.literal("cancelled"),
27
- state: z.string(),
28
- type: z.literal(TEAM_ACCESS_MESSAGE_TYPE)
29
- })]);
24
+ const pendingSignInSchema = z.object({
25
+ codeVerifier: z.string(),
26
+ state: z.string()
27
+ });
30
28
  const SIGN_IN_FAILURE_MESSAGES = {
31
29
  cancelled: "Sign-in was cancelled.",
32
30
  exchange_failed: "Couldn't finish signing in to Reflet. Try again.",
33
- popup_blocked: "Your browser blocked the Reflet sign-in window. Allow pop-ups for this site, then try again.",
34
- timeout: "Signing in took too long. Try again."
31
+ interrupted: "This sign-in was started in another tab or has expired. Sign in again.",
32
+ storage_blocked: "Your browser blocks storage for this site, so Reflet sign-in can't finish. Allow site data, then try again."
35
33
  };
36
34
  var TeamSignInError = class extends Error {
37
35
  reason;
@@ -82,36 +80,32 @@ function readTeamAccess(publicKey) {
82
80
  persistTeamAccess(publicKey, null);
83
81
  return null;
84
82
  }
85
- function centeredPopupFeatures() {
86
- const left = Math.round(window.screenX + (window.outerWidth - POPUP_WIDTH_PX) / 2);
87
- const top = Math.round(window.screenY + (window.outerHeight - POPUP_HEIGHT_PX) / 2);
88
- return `popup,width=${POPUP_WIDTH_PX},height=${POPUP_HEIGHT_PX},left=${left},top=${top}`;
83
+ function pendingSignInKey(publicKey) {
84
+ return `${PENDING_SIGN_IN_PREFIX}${publicKey}`;
89
85
  }
90
- function waitForApprovedCode(options) {
91
- return new Promise((resolve, reject) => {
92
- const listening = new AbortController();
93
- let closedOnLastPoll = false;
94
- const settle = (outcome) => {
95
- listening.abort();
96
- window.clearInterval(closedPoll);
97
- window.clearTimeout(timeout);
98
- if (outcome instanceof TeamSignInError) reject(outcome);
99
- else resolve(outcome.code);
100
- };
101
- const closedPoll = window.setInterval(() => {
102
- if (closedOnLastPoll) settle(new TeamSignInError("cancelled"));
103
- closedOnLastPoll = options.popup.closed;
104
- }, POPUP_CLOSED_POLL_MS);
105
- const timeout = window.setTimeout(() => {
106
- options.popup.close();
107
- settle(new TeamSignInError("timeout"));
108
- }, SIGN_IN_TIMEOUT_MS);
109
- window.addEventListener("message", (event) => {
110
- if (event.origin !== options.appOrigin) return;
111
- const message = teamAccessMessageSchema.safeParse(event.data);
112
- if (message.success && message.data.state === options.state) settle("code" in message.data ? { code: message.data.code } : new TeamSignInError("cancelled"));
113
- }, { signal: listening.signal });
114
- });
86
+ function takePendingSignIn(publicKey) {
87
+ try {
88
+ const key = pendingSignInKey(publicKey);
89
+ const raw = sessionStorage.getItem(key);
90
+ sessionStorage.removeItem(key);
91
+ const parsed = pendingSignInSchema.safeParse(raw === null ? null : parseStoredJson(raw));
92
+ return parsed.success ? parsed.data : null;
93
+ } catch {
94
+ return null;
95
+ }
96
+ }
97
+ function rememberPendingSignIn(publicKey, pending) {
98
+ try {
99
+ sessionStorage.setItem(pendingSignInKey(publicKey), JSON.stringify(pending));
100
+ } catch {
101
+ throw new TeamSignInError("storage_blocked");
102
+ }
103
+ }
104
+ function returnUrl() {
105
+ const url = new URL(window.location.href);
106
+ for (const param of RETURN_PARAMS) url.searchParams.delete(param);
107
+ if (!url.searchParams.has("reflet-team")) url.searchParams.set(TEAM_ACTIVATION_PARAM, "");
108
+ return url.href;
115
109
  }
116
110
  async function exchangeCode(options) {
117
111
  const response = await fetch(apiEndpoint(options.apiUrl, "/api/v1/team/token"), {
@@ -130,33 +124,52 @@ async function exchangeCode(options) {
130
124
  if (!access.success) throw new TeamSignInError("exchange_failed");
131
125
  return access.data;
132
126
  }
133
- /** Call from a click handler: the popup opens before anything is awaited so browsers don't block it. */
134
- async function signInTeam(options) {
135
- const popup = window.open("about:blank", POPUP_NAME, centeredPopupFeatures());
136
- if (!popup) throw new TeamSignInError("popup_blocked");
137
- const codeVerifier = randomBase64Url();
138
- const state = randomBase64Url();
127
+ async function prepareTeamSignIn(options) {
128
+ const pending = {
129
+ codeVerifier: randomBase64Url(),
130
+ state: randomBase64Url()
131
+ };
132
+ rememberPendingSignIn(options.publicKey, pending);
139
133
  const consentUrl = new URL("/auth/team", options.appUrl);
140
134
  consentUrl.search = new URLSearchParams({
141
- code_challenge: await pkceChallengeFor(codeVerifier),
135
+ code_challenge: await pkceChallengeFor(pending.codeVerifier),
142
136
  origin: window.location.origin,
143
137
  public_key: options.publicKey,
144
- state
138
+ return_to: returnUrl(),
139
+ state: pending.state
145
140
  }).toString();
146
- popup.location.href = consentUrl.href;
147
- const code = await waitForApprovedCode({
148
- appOrigin: consentUrl.origin,
149
- popup,
150
- state
151
- });
141
+ return consentUrl.href;
142
+ }
143
+ function hasTeamSignInReturn() {
144
+ return new URL(window.location.href).searchParams.has(RETURN_STATE_PARAM);
145
+ }
146
+ async function completeReturnedSignIn(options) {
147
+ if (options.pending?.state !== options.state) throw new TeamSignInError("interrupted");
148
+ if (options.code === null) throw new TeamSignInError("cancelled");
152
149
  const access = await exchangeCode({
153
150
  apiUrl: options.apiUrl,
154
- code,
155
- codeVerifier
151
+ code: options.code,
152
+ codeVerifier: options.pending.codeVerifier
156
153
  });
157
154
  persistTeamAccess(options.publicKey, access);
158
155
  return access;
159
156
  }
157
+ /** Strips the returned code from the address bar at once, so it is consumed by one caller only. */
158
+ function finishTeamSignIn(options) {
159
+ const url = new URL(window.location.href);
160
+ const state = url.searchParams.get(RETURN_STATE_PARAM);
161
+ if (state === null) return null;
162
+ const code = url.searchParams.get(RETURN_CODE_PARAM);
163
+ for (const param of RETURN_PARAMS) url.searchParams.delete(param);
164
+ window.history.replaceState(window.history.state, "", url.href);
165
+ return completeReturnedSignIn({
166
+ apiUrl: options.apiUrl,
167
+ code,
168
+ pending: takePendingSignIn(options.publicKey),
169
+ publicKey: options.publicKey,
170
+ state
171
+ });
172
+ }
160
173
  async function forgetTeamAccess(options) {
161
174
  const access = storedTeamAccess(options.publicKey);
162
175
  persistTeamAccess(options.publicKey, null);
@@ -168,22 +181,22 @@ async function forgetTeamAccess(options) {
168
181
  }
169
182
  //#endregion
170
183
  //#region src/sessions/team/team-sign-in-card.tsx
171
- function useTeamSignIn(connection, onSignedIn) {
172
- const [isSigningIn, setIsSigningIn] = useState(false);
184
+ function useTeamSignIn(connection) {
185
+ const [isLeaving, setIsLeaving] = useState(false);
173
186
  const [failure, setFailure] = useState(null);
174
187
  const signIn = async () => {
175
- setIsSigningIn(true);
188
+ setIsLeaving(true);
176
189
  setFailure(null);
177
190
  try {
178
- onSignedIn(await signInTeam(connection));
191
+ window.location.assign(await prepareTeamSignIn(connection));
179
192
  } catch (error) {
180
193
  setFailure(failureMessage(error));
194
+ setIsLeaving(false);
181
195
  }
182
- setIsSigningIn(false);
183
196
  };
184
197
  return {
185
198
  failure,
186
- isSigningIn,
199
+ isLeaving,
187
200
  signIn
188
201
  };
189
202
  }
@@ -205,9 +218,9 @@ function SignInActions({ isSigningIn, onHide, onSignIn }) {
205
218
  })]
206
219
  });
207
220
  }
208
- function TeamSignInCard({ connection, notice, onSignedIn }) {
221
+ function TeamSignInCard({ connection, isFinishing, notice }) {
209
222
  const [isHidden, setIsHidden] = useState(false);
210
- const { failure, isSigningIn, signIn } = useTeamSignIn(connection, onSignedIn);
223
+ const { failure, isLeaving, signIn } = useTeamSignIn(connection);
211
224
  if (isHidden) return null;
212
225
  return /* @__PURE__ */ jsxs("section", {
213
226
  "aria-labelledby": "rf-team-title",
@@ -226,8 +239,14 @@ function TeamSignInCard({ connection, notice, onSignedIn }) {
226
239
  className: "dt-meta",
227
240
  children: "Only members of the app's Reflet organization can sign in."
228
241
  }),
242
+ isFinishing && /* @__PURE__ */ jsx("p", {
243
+ className: "dt-meta",
244
+ role: "status",
245
+ children: "Finishing sign-in…"
246
+ }),
229
247
  notice && /* @__PURE__ */ jsx("p", {
230
248
  className: "dt-meta",
249
+ role: "status",
231
250
  children: notice
232
251
  }),
233
252
  failure && /* @__PURE__ */ jsx("p", {
@@ -236,7 +255,7 @@ function TeamSignInCard({ connection, notice, onSignedIn }) {
236
255
  children: failure
237
256
  }),
238
257
  /* @__PURE__ */ jsx(SignInActions, {
239
- isSigningIn,
258
+ isSigningIn: isLeaving || isFinishing,
240
259
  onHide: () => setIsHidden(true),
241
260
  onSignIn: signIn
242
261
  })
@@ -379,6 +398,16 @@ function TeamLayer({ connection, position }) {
379
398
  const { apiUrl, publicKey } = connection;
380
399
  const [access, setAccess] = useState(() => readTeamAccess(publicKey));
381
400
  const [notice, setNotice] = useState(null);
401
+ const [isFinishing, setIsFinishing] = useState(hasTeamSignInReturn);
402
+ useEffect(() => {
403
+ finishTeamSignIn({
404
+ apiUrl,
405
+ publicKey
406
+ })?.then((signedIn) => {
407
+ setAccess(signedIn);
408
+ setNotice(null);
409
+ }, (error) => setNotice(failureMessage(error))).finally(() => setIsFinishing(false));
410
+ }, [apiUrl, publicKey]);
382
411
  const signOut = (reason) => {
383
412
  setAccess(null);
384
413
  setNotice(reason);
@@ -405,11 +434,8 @@ function TeamLayer({ connection, position }) {
405
434
  "data-side": placement.side,
406
435
  children: /* @__PURE__ */ jsx(TeamSignInCard, {
407
436
  connection,
408
- notice,
409
- onSignedIn: (signedIn) => {
410
- setAccess(signedIn);
411
- setNotice(null);
412
- }
437
+ isFinishing,
438
+ notice
413
439
  })
414
440
  }),
415
441
  /* @__PURE__ */ jsx(Notices, {})
@@ -419,4 +445,4 @@ function TeamLayer({ connection, position }) {
419
445
  //#endregion
420
446
  export { TeamLayer };
421
447
 
422
- //# sourceMappingURL=team-layer-D-6Il66z.js.map
448
+ //# sourceMappingURL=team-layer-Dvjkh-_y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-layer-Dvjkh-_y.js","names":[],"sources":["../src/sessions/team/team-auth.ts","../src/sessions/team/team-sign-in-card.tsx","../src/sessions/team/team-layer.tsx"],"sourcesContent":["import { z } from \"zod\";\nimport { sessionApiErrorSchema } from \"../protocol\";\nimport { TEAM_ACTIVATION_PARAM, teamAccessStorageKey } from \"./team-activation\";\n\nconst RETURN_CODE_PARAM = \"reflet-team-code\";\nconst RETURN_ERROR_PARAM = \"reflet-team-error\";\nconst RETURN_STATE_PARAM = \"reflet-team-state\";\nconst RETURN_PARAMS = [\n RETURN_CODE_PARAM,\n RETURN_ERROR_PARAM,\n RETURN_STATE_PARAM,\n];\nconst PENDING_SIGN_IN_PREFIX = \"reflet-team-sign-in:\";\nconst PKCE_RANDOM_BYTES = 32;\nconst TRAILING_SLASHES = /\\/+$/;\nconst BASE64_PADDING = /[=]+$/;\n\nconst teamAccessSchema = z.object({\n expiresAt: z.number(),\n organizationName: z.string(),\n token: z.string().startsWith(\"fb_team_\"),\n});\n\nexport type TeamAccess = z.infer<typeof teamAccessSchema>;\n\nconst pendingSignInSchema = z.object({\n codeVerifier: z.string(),\n state: z.string(),\n});\n\ntype PendingSignIn = z.infer<typeof pendingSignInSchema>;\n\nconst SIGN_IN_FAILURE_MESSAGES = {\n cancelled: \"Sign-in was cancelled.\",\n exchange_failed: \"Couldn't finish signing in to Reflet. Try again.\",\n interrupted:\n \"This sign-in was started in another tab or has expired. Sign in again.\",\n storage_blocked:\n \"Your browser blocks storage for this site, so Reflet sign-in can't finish. Allow site data, then try again.\",\n} as const;\n\nexport type TeamSignInFailure = keyof typeof SIGN_IN_FAILURE_MESSAGES;\n\nexport class TeamSignInError extends Error {\n readonly reason: TeamSignInFailure;\n\n constructor(reason: TeamSignInFailure, message?: string) {\n super(message ?? SIGN_IN_FAILURE_MESSAGES[reason]);\n this.name = \"TeamSignInError\";\n this.reason = reason;\n }\n}\n\nfunction base64Url(bytes: Uint8Array): string {\n return btoa(String.fromCharCode(...bytes))\n .replaceAll(\"+\", \"-\")\n .replaceAll(\"/\", \"_\")\n .replace(BASE64_PADDING, \"\");\n}\n\nfunction randomBase64Url(): string {\n return base64Url(crypto.getRandomValues(new Uint8Array(PKCE_RANDOM_BYTES)));\n}\n\nasync function pkceChallengeFor(codeVerifier: string): Promise<string> {\n const digest = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(codeVerifier)\n );\n return base64Url(new Uint8Array(digest));\n}\n\nfunction apiEndpoint(apiUrl: string, path: string): string {\n return `${apiUrl.replace(TRAILING_SLASHES, \"\")}${path}`;\n}\n\nfunction parseStoredJson(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n\nfunction storedTeamAccess(publicKey: string): TeamAccess | null {\n try {\n const raw = localStorage.getItem(teamAccessStorageKey(publicKey));\n const parsed = teamAccessSchema.safeParse(\n raw === null ? null : parseStoredJson(raw)\n );\n return parsed.success ? parsed.data : null;\n } catch {\n return null;\n }\n}\n\nfunction persistTeamAccess(publicKey: string, access: TeamAccess | null): void {\n try {\n if (access) {\n localStorage.setItem(\n teamAccessStorageKey(publicKey),\n JSON.stringify(access)\n );\n } else {\n localStorage.removeItem(teamAccessStorageKey(publicKey));\n }\n } catch {\n // Storage disabled by browser policy: access then only lasts for this page.\n }\n}\n\nexport function readTeamAccess(publicKey: string): TeamAccess | null {\n const access = storedTeamAccess(publicKey);\n if (access && access.expiresAt > Date.now()) {\n return access;\n }\n persistTeamAccess(publicKey, null);\n return null;\n}\n\nfunction pendingSignInKey(publicKey: string): string {\n return `${PENDING_SIGN_IN_PREFIX}${publicKey}`;\n}\n\nfunction takePendingSignIn(publicKey: string): PendingSignIn | null {\n try {\n const key = pendingSignInKey(publicKey);\n const raw = sessionStorage.getItem(key);\n sessionStorage.removeItem(key);\n const parsed = pendingSignInSchema.safeParse(\n raw === null ? null : parseStoredJson(raw)\n );\n return parsed.success ? parsed.data : null;\n } catch {\n return null;\n }\n}\n\nfunction rememberPendingSignIn(publicKey: string, pending: PendingSignIn) {\n try {\n sessionStorage.setItem(\n pendingSignInKey(publicKey),\n JSON.stringify(pending)\n );\n } catch {\n throw new TeamSignInError(\"storage_blocked\");\n }\n}\n\nfunction returnUrl(): string {\n const url = new URL(window.location.href);\n for (const param of RETURN_PARAMS) {\n url.searchParams.delete(param);\n }\n if (!url.searchParams.has(TEAM_ACTIVATION_PARAM)) {\n url.searchParams.set(TEAM_ACTIVATION_PARAM, \"\");\n }\n return url.href;\n}\n\nasync function exchangeCode(options: {\n apiUrl: string;\n code: string;\n codeVerifier: string;\n}): Promise<TeamAccess> {\n const response = await fetch(\n apiEndpoint(options.apiUrl, \"/api/v1/team/token\"),\n {\n body: JSON.stringify({\n code: options.code,\n codeVerifier: options.codeVerifier,\n }),\n headers: { \"Content-Type\": \"application/json\" },\n method: \"POST\",\n }\n );\n if (!response.ok) {\n const failure = sessionApiErrorSchema.safeParse(\n await response.json().catch(() => null)\n );\n throw new TeamSignInError(\n \"exchange_failed\",\n failure.success ? failure.data.error : undefined\n );\n }\n const access = teamAccessSchema.safeParse(\n await response.json().catch(() => null)\n );\n if (!access.success) {\n throw new TeamSignInError(\"exchange_failed\");\n }\n return access.data;\n}\n\nexport async function prepareTeamSignIn(options: {\n appUrl: string;\n publicKey: string;\n}): Promise<string> {\n const pending = { codeVerifier: randomBase64Url(), state: randomBase64Url() };\n rememberPendingSignIn(options.publicKey, pending);\n const consentUrl = new URL(\"/auth/team\", options.appUrl);\n consentUrl.search = new URLSearchParams({\n code_challenge: await pkceChallengeFor(pending.codeVerifier),\n origin: window.location.origin,\n public_key: options.publicKey,\n return_to: returnUrl(),\n state: pending.state,\n }).toString();\n return consentUrl.href;\n}\n\nexport function hasTeamSignInReturn(): boolean {\n return new URL(window.location.href).searchParams.has(RETURN_STATE_PARAM);\n}\n\nasync function completeReturnedSignIn(options: {\n apiUrl: string;\n code: string | null;\n pending: PendingSignIn | null;\n publicKey: string;\n state: string;\n}): Promise<TeamAccess> {\n if (options.pending?.state !== options.state) {\n throw new TeamSignInError(\"interrupted\");\n }\n if (options.code === null) {\n throw new TeamSignInError(\"cancelled\");\n }\n const access = await exchangeCode({\n apiUrl: options.apiUrl,\n code: options.code,\n codeVerifier: options.pending.codeVerifier,\n });\n persistTeamAccess(options.publicKey, access);\n return access;\n}\n\n/** Strips the returned code from the address bar at once, so it is consumed by one caller only. */\nexport function finishTeamSignIn(options: {\n apiUrl: string;\n publicKey: string;\n}): Promise<TeamAccess> | null {\n const url = new URL(window.location.href);\n const state = url.searchParams.get(RETURN_STATE_PARAM);\n if (state === null) {\n return null;\n }\n const code = url.searchParams.get(RETURN_CODE_PARAM);\n for (const param of RETURN_PARAMS) {\n url.searchParams.delete(param);\n }\n window.history.replaceState(window.history.state, \"\", url.href);\n return completeReturnedSignIn({\n apiUrl: options.apiUrl,\n code,\n pending: takePendingSignIn(options.publicKey),\n publicKey: options.publicKey,\n state,\n });\n}\n\nexport async function forgetTeamAccess(options: {\n apiUrl: string;\n publicKey: string;\n}): Promise<void> {\n const access = storedTeamAccess(options.publicKey);\n persistTeamAccess(options.publicKey, null);\n if (!access) {\n return;\n }\n await fetch(apiEndpoint(options.apiUrl, \"/api/v1/team/revoke\"), {\n headers: { Authorization: `Bearer ${access.token}` },\n method: \"POST\",\n });\n}\n","import { useState } from \"react\";\nimport { failureMessage } from \"../ui/session-workspace\";\nimport { prepareTeamSignIn } from \"./team-auth\";\n\nexport interface TeamConnection {\n apiUrl: string;\n appUrl: string;\n publicKey: string;\n}\n\nfunction useTeamSignIn(connection: TeamConnection) {\n const [isLeaving, setIsLeaving] = useState(false);\n const [failure, setFailure] = useState<string | null>(null);\n\n const signIn = async () => {\n setIsLeaving(true);\n setFailure(null);\n try {\n window.location.assign(await prepareTeamSignIn(connection));\n } catch (error) {\n setFailure(failureMessage(error));\n setIsLeaving(false);\n }\n };\n\n return { failure, isLeaving, signIn };\n}\n\nfunction SignInActions({\n isSigningIn,\n onHide,\n onSignIn,\n}: {\n isSigningIn: boolean;\n onHide: () => void;\n onSignIn: () => void;\n}) {\n return (\n <div className=\"dt-actions\">\n <button\n className=\"dt-btn\"\n data-variant=\"primary\"\n disabled={isSigningIn}\n onClick={onSignIn}\n type=\"button\"\n >\n Sign in with Reflet\n </button>\n <button className=\"dt-btn\" onClick={onHide} type=\"button\">\n Hide\n </button>\n </div>\n );\n}\n\nexport function TeamSignInCard({\n connection,\n isFinishing,\n notice,\n}: {\n connection: TeamConnection;\n isFinishing: boolean;\n notice: string | null;\n}) {\n const [isHidden, setIsHidden] = useState(false);\n const { failure, isLeaving, signIn } = useTeamSignIn(connection);\n\n if (isHidden) {\n return null;\n }\n return (\n <section aria-labelledby=\"rf-team-title\" className=\"dt-team-card glass\">\n <h2 className=\"dt-ses-subhead\" id=\"rf-team-title\">\n Reflet team tools\n </h2>\n <p className=\"dt-meta\">\n Sign in with your Reflet account to record a session on this app.\n </p>\n <p className=\"dt-meta\">\n Only members of the app's Reflet organization can sign in.\n </p>\n {isFinishing && (\n <p className=\"dt-meta\" role=\"status\">\n Finishing sign-in…\n </p>\n )}\n {notice && (\n <p className=\"dt-meta\" role=\"status\">\n {notice}\n </p>\n )}\n {failure && (\n <p className=\"dt-error\" role=\"alert\">\n {failure}\n </p>\n )}\n <SignInActions\n isSigningIn={isLeaving || isFinishing}\n onHide={() => setIsHidden(true)}\n onSignIn={signIn}\n />\n </section>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport {\n BarButton,\n DevtoolsBar,\n SessionsBarButton,\n} from \"../../devtools/client/devtools-bar\";\nimport { DevtoolsSheet } from \"../../devtools/client/devtools-sheet\";\nimport { DEVTOOLS_STYLES } from \"../../devtools/client/devtools-styles\";\nimport { Notices, reportFailure } from \"../../devtools/client/notices\";\nimport type { RefletFeedbackProps } from \"../../feedback/types\";\nimport { teamTransport } from \"../api/session-transports\";\nimport { purgeAccount } from \"../local/local-sessions\";\nimport { RecordingLayer } from \"../ui/recording/recording-layer\";\nimport { PersonIcon } from \"../ui/session-icons\";\nimport {\n failureMessage,\n type SessionWorkspace,\n SessionWorkspaceProvider,\n useWorkspaceLoader,\n type WorkspaceState,\n} from \"../ui/session-workspace\";\nimport { type SessionNavigation, SessionsPanel } from \"../ui/sessions-panel\";\nimport { SESSIONS_STYLES } from \"../ui/sessions-styles\";\nimport type { SessionTarget } from \"../ui/start/session-list\";\nimport {\n finishTeamSignIn,\n forgetTeamAccess,\n hasTeamSignInReturn,\n readTeamAccess,\n type TeamAccess,\n} from \"./team-auth\";\nimport { type TeamConnection, TeamSignInCard } from \"./team-sign-in-card\";\n\nconst TEAM_TOOLS_LABEL = \"Reflet team tools\";\nconst REFUSED_SIGN_IN_COPY =\n \"Reflet no longer accepts this sign-in. Sign in again to record.\";\n\ninterface TeamPlacement {\n edge: \"bottom\" | \"top\";\n side: \"left\" | \"right\";\n}\n\nfunction AccountControls({\n access,\n onSignOut,\n workspace,\n}: {\n access: TeamAccess;\n onSignOut: () => void;\n workspace: SessionWorkspace | null;\n}) {\n const [isOpen, setIsOpen] = useState(false);\n const user = workspace?.account.userName ?? workspace?.account.userEmail;\n const label = user\n ? `Signed in as ${user} · ${access.organizationName}`\n : `Signed in · ${access.organizationName}`;\n return (\n <>\n <BarButton\n label={label}\n onClick={() => setIsOpen(!isOpen)}\n pressed={isOpen}\n >\n <PersonIcon />\n </BarButton>\n {isOpen && (\n <button className=\"dt-btn\" onClick={onSignOut} type=\"button\">\n Sign out\n </button>\n )}\n </>\n );\n}\n\nfunction SessionsBody({\n navigation,\n onStarted,\n state,\n}: {\n navigation: SessionNavigation;\n onStarted: () => void;\n state: WorkspaceState;\n}) {\n if (state.kind === \"ready\") {\n return <SessionsPanel navigation={navigation} onStarted={onStarted} />;\n }\n if (state.kind === \"failed\") {\n return (\n <div className=\"dt-empty\" role=\"alert\">\n <p>Sessions did not open: {state.message}</p>\n <button className=\"dt-btn\" onClick={state.retry} type=\"button\">\n Try again\n </button>\n </div>\n );\n }\n return <p className=\"dt-status\">Opening your sessions…</p>;\n}\n\nfunction TeamSheet({\n navigation,\n onOpenChange,\n side,\n state,\n}: {\n navigation: SessionNavigation;\n onOpenChange: (isOpen: boolean) => void;\n side: TeamPlacement[\"side\"];\n state: WorkspaceState;\n}) {\n return (\n <DevtoolsSheet\n label={TEAM_TOOLS_LABEL}\n onClose={() => onOpenChange(false)}\n onSelectTab={() => onOpenChange(true)}\n side={side}\n tab=\"sessions\"\n tabs={[\"sessions\"]}\n >\n <SessionsBody\n navigation={navigation}\n onStarted={() => onOpenChange(false)}\n state={state}\n />\n </DevtoolsSheet>\n );\n}\n\ninterface TeamSession {\n access: TeamAccess;\n apiUrl: string;\n onSignOut: (reason: string | null) => void;\n}\n\nfunction useTeamTransport(team: TeamSession) {\n const createTransport = () => ({\n apiUrl: team.apiUrl,\n transport: teamTransport({ apiUrl: team.apiUrl, token: team.access.token }),\n });\n const [current, setCurrent] = useState(createTransport);\n if (current.apiUrl !== team.apiUrl) {\n const next = createTransport();\n setCurrent(next);\n return next.transport;\n }\n return current.transport;\n}\n\nfunction useTeamWorkspace(team: TeamSession) {\n const { onSignOut } = team;\n const transport = useTeamTransport(team);\n const state = useWorkspaceLoader({\n onUnauthorized: () => onSignOut(REFUSED_SIGN_IN_COPY),\n surface: \"app\",\n transport,\n });\n const workspace = state.kind === \"ready\" ? state.workspace : null;\n\n const signOut = async () => {\n if (workspace) {\n await purgeAccount(workspace.account.key).catch((error: unknown) =>\n reportFailure(\"This device's session data was not removed\", error)\n );\n }\n onSignOut(null);\n };\n\n return { signOut, state, workspace };\n}\n\nfunction TeamTools({\n team,\n placement,\n}: {\n placement: TeamPlacement;\n team: TeamSession;\n}) {\n const { signOut, state, workspace } = useTeamWorkspace(team);\n const [isSheetOpen, setIsSheetOpen] = useState(false);\n const [open, setOpen] = useState<SessionTarget | null>(null);\n\n return (\n <SessionWorkspaceProvider workspace={workspace}>\n {isSheetOpen && (\n <TeamSheet\n navigation={{ onOpen: setOpen, open }}\n onOpenChange={setIsSheetOpen}\n side={placement.side}\n state={state}\n />\n )}\n <DevtoolsBar\n edge={placement.edge}\n label={TEAM_TOOLS_LABEL}\n side={placement.side}\n >\n <SessionsBarButton\n isOpen={isSheetOpen}\n onToggle={() => setIsSheetOpen(!isSheetOpen)}\n />\n <AccountControls\n access={team.access}\n onSignOut={signOut}\n workspace={workspace}\n />\n </DevtoolsBar>\n {workspace && (\n <RecordingLayer\n onFinished={(target) => {\n setOpen(target);\n setIsSheetOpen(true);\n }}\n />\n )}\n </SessionWorkspaceProvider>\n );\n}\n\nfunction placementFor(\n position: NonNullable<RefletFeedbackProps[\"position\"]>\n): TeamPlacement {\n return {\n edge: position.startsWith(\"top\") ? \"top\" : \"bottom\",\n side: position.endsWith(\"right\") ? \"right\" : \"left\",\n };\n}\n\nexport function TeamLayer({\n connection,\n position,\n}: {\n connection: TeamConnection;\n position: NonNullable<RefletFeedbackProps[\"position\"]>;\n}) {\n const { apiUrl, publicKey } = connection;\n const [access, setAccess] = useState(() => readTeamAccess(publicKey));\n const [notice, setNotice] = useState<string | null>(null);\n const [isFinishing, setIsFinishing] = useState(hasTeamSignInReturn);\n useEffect(() => {\n finishTeamSignIn({ apiUrl, publicKey })\n ?.then(\n (signedIn) => {\n setAccess(signedIn);\n setNotice(null);\n },\n (error: unknown) => setNotice(failureMessage(error))\n )\n .finally(() => setIsFinishing(false));\n }, [apiUrl, publicKey]);\n const signOut = (reason: string | null) => {\n setAccess(null);\n setNotice(reason);\n forgetTeamAccess({ apiUrl, publicKey }).catch((error: unknown) =>\n reportFailure(\"Signing out of Reflet did not finish\", error)\n );\n };\n const placement = placementFor(position);\n\n return (\n <div className=\"dt\">\n <style>{`${DEVTOOLS_STYLES}${SESSIONS_STYLES}`}</style>\n {access ? (\n <TeamTools\n placement={placement}\n team={{ access, apiUrl, onSignOut: signOut }}\n />\n ) : (\n <div\n className=\"dt-team-anchor\"\n data-edge={placement.edge}\n data-side={placement.side}\n >\n <TeamSignInCard\n connection={connection}\n isFinishing={isFinishing}\n notice={notice}\n />\n </div>\n )}\n <Notices />\n </div>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reflet-sdk",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "Official Reflet SDK - Collect user feedback, feature requests, and bug reports from your app",
5
5
  "keywords": [
6
6
  "feedback",