@flow-industries/id 0.24.5 → 0.26.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.
@@ -32,8 +32,12 @@ const installBodySchema = z.object({
32
32
  refreshToken: z.string().min(1).optional(),
33
33
  jwt: z.string().min(1).optional(),
34
34
  mint: z.array(z.string()).optional(),
35
- action: z.enum(["login", "account", "guest"]).optional(),
35
+ action: z
36
+ .enum(["login", "account", "switch", "guest", "accounts"])
37
+ .optional(),
38
+ intent: z.enum(["login", "manage", "switch", "add"]).optional(),
36
39
  returnTo: z.string().optional(),
40
+ userId: z.string().max(256).optional(),
37
41
  signUp: z.boolean().optional(),
38
42
  accessKeyHash: z
39
43
  .string()
@@ -95,7 +99,11 @@ export async function handleSessionRequest(request, opts = {}) {
95
99
  case "GET": {
96
100
  if (callback.searchParams.get("action") === "account") {
97
101
  try {
98
- return await startBrowserSession(request, audience, issuerUrl, { action: "account", redirect: true }, apiUrl);
102
+ return await startBrowserSession(request, audience, issuerUrl, {
103
+ action: "account",
104
+ redirect: true,
105
+ returnTo: callback.searchParams.get("returnTo") ?? "/",
106
+ }, apiUrl);
99
107
  }
100
108
  catch {
101
109
  return json({ state: null }, 502);
@@ -134,7 +142,46 @@ export async function handleSessionRequest(request, opts = {}) {
134
142
  case "POST": {
135
143
  const parsed = installBodySchema.safeParse(await request.json().catch(() => null));
136
144
  const body = parsed.success ? parsed.data : null;
137
- if (body?.action === "login" || body?.action === "account") {
145
+ if (body?.action === "accounts") {
146
+ const cookies = parseCookieHeader(request.headers.get("Cookie"));
147
+ const refreshName = cookieNamesFor(audience).refresh;
148
+ const grant = cookies[`${refreshName}.accounts`];
149
+ const refresh = cookies[refreshName];
150
+ function emptyAccountList() {
151
+ return new Response(JSON.stringify({ accounts: [], activeUserId: null }), {
152
+ headers: {
153
+ "Content-Type": "application/json",
154
+ "Cache-Control": "no-store",
155
+ },
156
+ });
157
+ }
158
+ if (!grant || !refresh)
159
+ return emptyAccountList();
160
+ try {
161
+ const result = await fetchIssuerApi(`${apiUrl}/api/auth/browser/app-accounts`, {
162
+ method: "POST",
163
+ headers: {
164
+ "Content-Type": "application/json",
165
+ Authorization: `Bearer ${refresh}`,
166
+ },
167
+ body: JSON.stringify({ audience, grant }),
168
+ });
169
+ if (!result.ok)
170
+ return emptyAccountList();
171
+ return new Response(await result.text(), {
172
+ headers: {
173
+ "Content-Type": "application/json",
174
+ "Cache-Control": "no-store",
175
+ },
176
+ });
177
+ }
178
+ catch {
179
+ return emptyAccountList();
180
+ }
181
+ }
182
+ if (body?.action === "login" ||
183
+ body?.action === "account" ||
184
+ body?.action === "switch") {
138
185
  try {
139
186
  return await startBrowserSession(request, audience, issuerUrl, {
140
187
  ...body,
@@ -176,6 +176,8 @@ export type AccountRegistration = {
176
176
  credential: FlowCredential | null;
177
177
  };
178
178
  export type AuthorizationTransaction = {
179
+ selectedAccount?: boolean;
180
+ intent: "login" | "manage" | "switch" | "add";
179
181
  expiresAt: number;
180
182
  accessKeyHash?: string;
181
183
  credentialId?: string;
@@ -0,0 +1,9 @@
1
+ export interface BrowserAccount {
2
+ id: string;
3
+ username: string;
4
+ image: string | null;
5
+ }
6
+ export interface BrowserAccounts {
7
+ accounts: BrowserAccount[];
8
+ activeUserId: string | null;
9
+ }
File without changes
@@ -2,6 +2,7 @@ export type { AccountDeleteRequest, AccountDeleteResponse, AccountErasureCounts,
2
2
  export type { ActionCurve, ActionEventRequest, ActionEventResponse, ActionsApi, ActiveActionState, FinishActionRequest, ListStudySessionsOptions, ListStudySubjectsOptions, StartActionInput, StartActionResult, StudyApi, StudySubjectResponse, UseActiveActionOptions, XpEstimateContext, } from "./actions";
3
3
  export type { AtprotoCompletion, AtprotoStartRequest, AtprotoStatus, } from "./atproto";
4
4
  export type { AccountRegistration, AccountSession, AccountSessionsResponse, AdditionalSession, AuthConfig, AuthorizationTransaction, AuthPageBootstrap, AuthResponse, AuthResponseWithWebAuthn, BioNormalization, BioRejection, BioWriteRefusal, BioWriteResult, FlowCredential, FlowUser, PasskeyEnrollment, PasskeyPluginOptions, RevokeAllSessionsResponse, RevokeSessionResponse, SecurityActivityEntry, SecurityActivityResponse, SessionUser, VerifiedFlowJWT, VerifyOptions, WebAuthnSignature, } from "./auth";
5
+ export type { BrowserAccount, BrowserAccounts } from "./browser-accounts";
5
6
  export type { BodyRegion, CosmeticItem, CosmeticMaterial, CosmeticPaint, CosmeticSlot, EquipConflict, EquippedCosmetic, EquippedCosmetics, EquipRegion, PaintSlot, SettingsConflict, } from "./cosmetics";
6
7
  export { BODY_REGIONS, COSMETIC_MATERIALS } from "./cosmetics";
7
8
  export type { AccountDataDownload, AccountDataIdentity, BoundaryError, DialogCustomFeatures, DialogCustomLabels, DialogError, DialogReferrer, DialogState, Loadable, ProfileData, ProfileIdentity, SignInWithEmailProps, SignUpProps, } from "./dialog";
@@ -18,7 +19,7 @@ export { isPersonalSignParams, isSendCallsParams, isSendTransactionParams, } fro
18
19
  export type { ReportOperation, ReportRequest, ReportResponse, ReportsApi, ReportTransport, } from "./reports";
19
20
  export type { CreateRoomEventInput, RoomEventArchive, RoomEventAttendance, RoomEventFrequency, RoomEventInstance, RoomEventInterest, RoomEventInterestState, RoomEventList, RoomEventOccurrence, RoomEventRecurrence, RoomEventRoomRef, RoomEventRun, RoomEventSeries, RoomEventStatus, SetInterestInput, UpdateRoomEventInput, } from "./room-events";
20
21
  export type { CreateRoomInput, GlobalRole, ModerationSubject, MyRooms, PlayerPositionReport, RoleChangeVerdict, RoomCapabilities, RoomCapability, RoomChannel, RoomDetail, RoomList, RoomMemberEntry, RoomMembers, RoomOccupancy, RoomOwner, RoomPlayerPosition, RoomPresenceEntry, RoomPresenceSnapshot, RoomRestrictionKind, RoomRole, RoomSummary, RoomSurfaceSettings, RoomsApi, RoomVisibility, StaffEntry, UpdateRoomInput, VerifyRoomContext, Viewer, VoiceDecisionReason, VoiceDecisionSubject, VoiceRoomDecision, } from "./rooms";
21
- export type { AccessKeyOptions, AccessKeyPreparation, Address, ColorScheme, CreateDialogHostOptions, CreateFlowOptions, DialogHost, DialogOpenOptions, FinalizeAccessKeyParams, Flow, FlowConnectorParameters, FlowCookieNames, FlowIdProviderProps, FlowSessionState, FlowState, FlowWidgetHandle, FlowWidgetName, FlowWidgetProps, Listener, LoginOptions, MountFlowWidgetOptions, MountProfileOptions, OpenProfileOptions, PrepareArgsWithAuth, PrepareTransactionRequestPhase, ProfileButtonHandle, ProfileButtonProps, ProfilePosition, ResolveAccountParams, ResolvedAccessKeyOptions, RootCredential, SendCallsArgs, SendTransactionArgs, Session, SigningContext, SignMessageArgs, SignTypedDataArgs, Store, StoredAccessKey, UseOpenProfileOptions, WagmiConnectCapabilities, WagmiConnectParams, } from "./sdk";
22
+ export type { AccessKeyOptions, AccessKeyPreparation, AccountMenuProps, Address, ColorScheme, CreateDialogHostOptions, CreateFlowOptions, DialogHost, DialogOpenOptions, FinalizeAccessKeyParams, Flow, FlowConnectorParameters, FlowCookieNames, FlowIdProviderProps, FlowProfileButtonProps, FlowSessionState, FlowState, FlowWidgetHandle, FlowWidgetName, FlowWidgetProps, Listener, LoginOptions, MountFlowWidgetOptions, MountProfileOptions, OpenProfileOptions, PrepareArgsWithAuth, PrepareTransactionRequestPhase, ProfileButtonHandle, ProfileButtonProps, ProfileMenuMountOptions, ProfilePosition, ResolveAccountParams, ResolvedAccessKeyOptions, RootCredential, SendCallsArgs, SendTransactionArgs, Session, SigningContext, SignMessageArgs, SignTypedDataArgs, Store, StoredAccessKey, SwitchAccountOptions, UseOpenProfileOptions, WagmiConnectCapabilities, WagmiConnectParams, } from "./sdk";
22
23
  export type { GracefulShutdownCleanup, GracefulShutdownOptions, GracefulShutdownServer, GracefulShutdownSignal, ResolvedFlowSession, ResolveSessionOptions, SessionRouteOptions, SessionRouteResponse, SessionRouteSession, } from "./server";
23
24
  export type { CosmeticOffer, PaintDescriptor, SettingDescriptor, Settings, SettingsMigration, StoredSettings, SurfaceRegistry, } from "./settings";
24
25
  export type { CreateStudySubjectInput, ListStudySessionsInput, StudyCatalog, StudyCategory, StudyCategoryTotals, StudyField, StudyRange, StudySessionEntry, StudySessionPage, StudySessionsResult, StudySubject, StudySubjectCreation, StudySubjectList, StudySubjectRefusal, StudySubjectRemoval, StudySubjectRemovalResponse, StudySubjectTotals, StudySubjectUpdate, StudySummary, UpdateStudySubjectInput, } from "./study";
@@ -3,6 +3,7 @@ import type { Chain, Hex, PrepareTransactionRequestParameters, SendTransactionPa
3
3
  import type { SendCallsParameters } from "viem/actions";
4
4
  import type { RawValue } from "../json";
5
5
  import type { AdditionalSession, FlowCredential, FlowUser, WebAuthnSignature } from "./auth";
6
+ import type { BrowserAccount, BrowserAccounts } from "./browser-accounts";
6
7
  import type { ConnectCapabilities } from "./protocol";
7
8
  import type { RoomsApi } from "./rooms";
8
9
  export type Address = `0x${string}`;
@@ -318,6 +319,9 @@ export type DialogHost = {
318
319
  requestSilent: <T = unknown>(method: string, params?: readonly unknown[]) => Promise<T>;
319
320
  messenger: import("./messenger").Messenger;
320
321
  };
322
+ export type SwitchAccountOptions = Pick<LoginOptions, "returnTo"> & {
323
+ userId?: string;
324
+ };
321
325
  export type Flow = {
322
326
  readonly user: FlowState["user"];
323
327
  readonly jwt: FlowState["jwt"];
@@ -332,6 +336,9 @@ export type Flow = {
332
336
  readonly isGuest: boolean;
333
337
  login(options?: LoginOptions): Promise<never>;
334
338
  openAccount(): boolean;
339
+ switchAccounts(options?: SwitchAccountOptions): Promise<never>;
340
+ addAccount(options?: Pick<LoginOptions, "returnTo">): Promise<never>;
341
+ listAccounts(): Promise<BrowserAccounts>;
335
342
  logout(): Promise<void>;
336
343
  restore(): Promise<boolean>;
337
344
  /**
@@ -405,7 +412,7 @@ export type FlowIdProviderProps = {
405
412
  children: ReactNode;
406
413
  };
407
414
  export type ProfileButtonProps = {
408
- /** Class applied to the host element the pill iframe mounts into. */
415
+ /** Class applied to the profile menu host element. */
409
416
  className?: string;
410
417
  /** Override the Flow ID origin; defaults to the resolved Flow's `host`. */
411
418
  host?: string;
@@ -424,3 +431,20 @@ export type ResolveAccountParams = {
424
431
  rpId?: string;
425
432
  strict?: boolean;
426
433
  };
434
+ export type AccountMenuProps = {
435
+ account: BrowserAccount | null;
436
+ guest?: boolean;
437
+ disabled?: boolean;
438
+ theme?: ColorScheme;
439
+ loadAccounts: () => Promise<BrowserAccounts>;
440
+ onSelect: (userId: string) => Promise<void> | void;
441
+ onAdd: () => Promise<void> | void;
442
+ onSignOut: () => Promise<void> | void;
443
+ onSignIn?: () => Promise<void> | void;
444
+ onManage?: () => Promise<void> | void;
445
+ onSwitch?: () => Promise<void> | void;
446
+ };
447
+ export type FlowProfileButtonProps = ProfileButtonProps & {
448
+ flow: Flow;
449
+ };
450
+ export type ProfileMenuMountOptions = Omit<FlowProfileButtonProps, "className">;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flow-industries/id",
3
- "version": "0.24.5",
3
+ "version": "0.26.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -10,7 +10,9 @@
10
10
  "module": "./dist/sdk/client/index.js",
11
11
  "types": "./dist/sdk/client/index.d.ts",
12
12
  "type": "module",
13
- "sideEffects": false,
13
+ "sideEffects": [
14
+ "**/*.css"
15
+ ],
14
16
  "publishConfig": {
15
17
  "access": "public"
16
18
  },
@@ -57,7 +59,8 @@
57
59
  },
58
60
  "./contracts/v1/reports.json": "./contracts/v1/reports.json",
59
61
  "./contracts/v1/openapi.json": "./contracts/v1/openapi.json",
60
- "./contracts/v1/sdk-exports.json": "./contracts/v1/sdk-exports.json"
62
+ "./contracts/v1/sdk-exports.json": "./contracts/v1/sdk-exports.json",
63
+ "./profile.css": "./dist/sdk/profile.css"
61
64
  },
62
65
  "files": [
63
66
  "dist/sdk",
@@ -69,7 +72,7 @@
69
72
  "build:playground": "bunx vite build --config vite.playground.config.ts",
70
73
  "build:landing": "bunx vite build --config vite.landing.config.ts",
71
74
  "build": "bunx vite build && bunx vite build --config vite.playground.config.ts && bunx vite build --config vite.landing.config.ts",
72
- "build:sdk": "tsc --project tsconfig.sdk.json",
75
+ "build:sdk": "tsc --project tsconfig.sdk.json && tailwindcss -i src/react/profile-menu.css -o dist/sdk/profile.css --minify",
73
76
  "prepublishOnly": "bun run build:sdk",
74
77
  "start": "bun run src/index.ts",
75
78
  "worker": "bun run src/worker.ts",
@@ -95,7 +98,8 @@
95
98
  "ox": ">=0.14.0",
96
99
  "react": ">=18",
97
100
  "@wagmi/core": ">=3.0.0",
98
- "@tanstack/react-start": ">=1.168.0"
101
+ "@tanstack/react-start": ">=1.168.0",
102
+ "react-dom": ">=18"
99
103
  },
100
104
  "peerDependenciesMeta": {
101
105
  "react": {
@@ -106,6 +110,9 @@
106
110
  },
107
111
  "@tanstack/react-start": {
108
112
  "optional": true
113
+ },
114
+ "react-dom": {
115
+ "optional": true
109
116
  }
110
117
  },
111
118
  "devDependencies": {
@@ -132,7 +139,9 @@
132
139
  "typescript": "^5",
133
140
  "vite": "^7.3.1",
134
141
  "react": "^19.2.4",
135
- "react-dom": "^19.2.4"
142
+ "react-dom": "^19.2.4",
143
+ "@tailwindcss/cli": "4.1.18",
144
+ "happy-dom": "^20.0.0"
136
145
  },
137
146
  "trustedDependencies": [
138
147
  "esbuild",