@hexclave/react 1.0.29 → 1.0.32

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 (121) hide show
  1. package/dist/clickmap/clickmap-core.js +1 -1
  2. package/dist/clickmap/index.js +2 -2
  3. package/dist/components/api-key-dialogs.js +2 -2
  4. package/dist/components/credential-sign-in.js +1 -1
  5. package/dist/components/credential-sign-up.js +1 -1
  6. package/dist/components/magic-link-sign-in.js +1 -1
  7. package/dist/components/team-switcher.js +1 -1
  8. package/dist/components-page/account-settings/active-sessions/active-sessions-page.js +1 -1
  9. package/dist/components-page/account-settings/email-and-auth/emails-section.js +1 -1
  10. package/dist/components-page/account-settings/email-and-auth/mfa-section.js +1 -1
  11. package/dist/components-page/account-settings/email-and-auth/password-section.js +1 -1
  12. package/dist/components-page/account-settings/teams/team-api-keys-section.js +1 -1
  13. package/dist/components-page/account-settings/teams/team-creation-page.js +1 -1
  14. package/dist/components-page/account-settings/teams/team-member-invitation-section.js +1 -1
  15. package/dist/components-page/auth-page.js +1 -1
  16. package/dist/components-page/cli-auth-confirm.js +1 -1
  17. package/dist/components-page/cli-auth-confirm.test.js +1 -1
  18. package/dist/components-page/forgot-password.js +1 -1
  19. package/dist/components-page/oauth-callback.d.ts.map +1 -1
  20. package/dist/components-page/oauth-callback.js +3 -1
  21. package/dist/components-page/oauth-callback.js.map +1 -1
  22. package/dist/components-page/oauth-callback.test.js +3 -1
  23. package/dist/components-page/oauth-callback.test.js.map +1 -1
  24. package/dist/components-page/onboarding.js +1 -1
  25. package/dist/components-page/password-reset.js +1 -1
  26. package/dist/components-page/team-creation.js +1 -1
  27. package/dist/dev-tool/dev-tool-core.js +1 -1
  28. package/dist/dev-tool/index.js +1 -1
  29. package/dist/esm/clickmap/clickmap-core.js +1 -1
  30. package/dist/esm/clickmap/index.js +2 -2
  31. package/dist/esm/components/api-key-dialogs.js +2 -2
  32. package/dist/esm/components/credential-sign-in.js +1 -1
  33. package/dist/esm/components/credential-sign-up.js +1 -1
  34. package/dist/esm/components/magic-link-sign-in.js +1 -1
  35. package/dist/esm/components/team-switcher.js +1 -1
  36. package/dist/esm/components-page/account-settings/active-sessions/active-sessions-page.js +1 -1
  37. package/dist/esm/components-page/account-settings/email-and-auth/emails-section.js +1 -1
  38. package/dist/esm/components-page/account-settings/email-and-auth/mfa-section.js +1 -1
  39. package/dist/esm/components-page/account-settings/email-and-auth/password-section.js +1 -1
  40. package/dist/esm/components-page/account-settings/teams/team-api-keys-section.js +1 -1
  41. package/dist/esm/components-page/account-settings/teams/team-creation-page.js +1 -1
  42. package/dist/esm/components-page/account-settings/teams/team-member-invitation-section.js +1 -1
  43. package/dist/esm/components-page/auth-page.js +1 -1
  44. package/dist/esm/components-page/cli-auth-confirm.js +1 -1
  45. package/dist/esm/components-page/cli-auth-confirm.test.js +1 -1
  46. package/dist/esm/components-page/forgot-password.js +1 -1
  47. package/dist/esm/components-page/oauth-callback.d.ts.map +1 -1
  48. package/dist/esm/components-page/oauth-callback.js +3 -1
  49. package/dist/esm/components-page/oauth-callback.js.map +1 -1
  50. package/dist/esm/components-page/oauth-callback.test.js +3 -1
  51. package/dist/esm/components-page/oauth-callback.test.js.map +1 -1
  52. package/dist/esm/components-page/onboarding.js +1 -1
  53. package/dist/esm/components-page/password-reset.js +1 -1
  54. package/dist/esm/components-page/team-creation.js +1 -1
  55. package/dist/esm/dev-tool/dev-tool-core.js +1 -1
  56. package/dist/esm/dev-tool/index.js +1 -1
  57. package/dist/esm/generated/quetzal-translations.d.ts +2 -2
  58. package/dist/esm/lib/auth.js +1 -1
  59. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +2 -1
  60. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  61. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +1 -1
  62. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  63. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +6 -10
  64. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  65. package/dist/esm/lib/hexclave-app/apps/implementations/common.js +2 -2
  66. package/dist/esm/lib/hexclave-app/apps/implementations/event-tracker.js +1 -1
  67. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +14 -0
  68. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts.map +1 -1
  69. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js +31 -16
  70. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js.map +1 -1
  71. package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.d.ts.map +1 -1
  72. package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.js +9 -2
  73. package/dist/esm/lib/hexclave-app/apps/implementations/session-replay.js.map +1 -1
  74. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.d.ts +1 -0
  75. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.d.ts.map +1 -1
  76. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -1
  77. package/dist/esm/lib/hexclave-app/apps/interfaces/server-app.d.ts +13 -0
  78. package/dist/esm/lib/hexclave-app/apps/interfaces/server-app.d.ts.map +1 -1
  79. package/dist/esm/lib/hexclave-app/apps/interfaces/server-app.js.map +1 -1
  80. package/dist/esm/lib/hexclave-app/teams/index.d.ts +4 -0
  81. package/dist/esm/lib/hexclave-app/teams/index.d.ts.map +1 -1
  82. package/dist/esm/lib/hexclave-app/teams/index.js.map +1 -1
  83. package/dist/esm/providers/theme-provider.js +1 -1
  84. package/dist/esm/pushed-config-error-overlay/index.js +1 -1
  85. package/dist/generated/quetzal-translations.d.ts +2 -2
  86. package/dist/lib/auth.js +1 -1
  87. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -0
  88. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  89. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +1 -1
  90. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  91. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +6 -10
  92. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  93. package/dist/lib/hexclave-app/apps/implementations/common.js +2 -2
  94. package/dist/lib/hexclave-app/apps/implementations/event-tracker.js +1 -1
  95. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +14 -0
  96. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts.map +1 -1
  97. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js +31 -16
  98. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js.map +1 -1
  99. package/dist/lib/hexclave-app/apps/implementations/session-replay.d.ts.map +1 -1
  100. package/dist/lib/hexclave-app/apps/implementations/session-replay.js +9 -2
  101. package/dist/lib/hexclave-app/apps/implementations/session-replay.js.map +1 -1
  102. package/dist/lib/hexclave-app/apps/interfaces/client-app.d.ts +1 -0
  103. package/dist/lib/hexclave-app/apps/interfaces/client-app.d.ts.map +1 -1
  104. package/dist/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -1
  105. package/dist/lib/hexclave-app/apps/interfaces/server-app.d.ts +13 -0
  106. package/dist/lib/hexclave-app/apps/interfaces/server-app.d.ts.map +1 -1
  107. package/dist/lib/hexclave-app/apps/interfaces/server-app.js.map +1 -1
  108. package/dist/lib/hexclave-app/teams/index.d.ts +4 -0
  109. package/dist/lib/hexclave-app/teams/index.d.ts.map +1 -1
  110. package/dist/lib/hexclave-app/teams/index.js.map +1 -1
  111. package/dist/providers/theme-provider.js +1 -1
  112. package/dist/pushed-config-error-overlay/index.js +1 -1
  113. package/package.json +3 -3
  114. package/src/components-page/oauth-callback.test.tsx +4 -0
  115. package/src/components-page/oauth-callback.tsx +6 -0
  116. package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +3 -5
  117. package/src/lib/hexclave-app/apps/implementations/server-app-impl.ts +35 -19
  118. package/src/lib/hexclave-app/apps/implementations/session-replay.ts +16 -1
  119. package/src/lib/hexclave-app/apps/interfaces/client-app.ts +1 -0
  120. package/src/lib/hexclave-app/apps/interfaces/server-app.ts +5 -0
  121. package/src/lib/hexclave-app/teams/index.ts +4 -0
@@ -2,8 +2,7 @@
2
2
  //===========================================
3
3
  // THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template
4
4
  //===========================================
5
- import { WebAuthnError, startRegistration } from "@simplewebauthn/browser";
6
- import { KnownErrors, HexclaveServerInterface } from "@hexclave/shared";
5
+ import { HexclaveServerInterface, KnownErrors } from "@hexclave/shared";
7
6
  import { ContactChannelsCrud } from "@hexclave/shared/dist/interface/crud/contact-channels";
8
7
  import { ItemCrud } from "@hexclave/shared/dist/interface/crud/items";
9
8
  import { NotificationPreferenceCrud } from "@hexclave/shared/dist/interface/crud/notification-preferences";
@@ -23,6 +22,7 @@ import { ProviderType } from "@hexclave/shared/dist/utils/oauth";
23
22
  import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
24
23
  import { suspend } from "@hexclave/shared/dist/utils/react";
25
24
  import { Result } from "@hexclave/shared/dist/utils/results";
25
+ import { WebAuthnError, startRegistration } from "@simplewebauthn/browser";
26
26
  import { useMemo } from "react"; // THIS_LINE_PLATFORM react-like
27
27
  import * as yup from "yup";
28
28
  import { constructRedirectUrl } from "../../../../utils/url";
@@ -64,14 +64,16 @@ export class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pro
64
64
  includeAnonymous?: boolean,
65
65
  onlyAnonymous?: boolean,
66
66
  teamId?: string,
67
- ], UsersCrud['Server']['List']>(async ([cursor, limit, orderBy, desc, query, includeRestricted, includeAnonymous, onlyAnonymous, teamId]) => {
67
+ excludedEmailDomains?: string,
68
+ ], UsersCrud['Server']['List']>(async ([cursor, limit, orderBy, desc, query, includeRestricted, includeAnonymous, onlyAnonymous, teamId, excludedEmailDomains]) => {
68
69
  if (onlyAnonymous && !includeAnonymous) {
69
70
  throw new HexclaveAssertionError("onlyAnonymous=true requires includeAnonymous=true");
70
71
  }
72
+ const excludedEmailDomainList = excludedEmailDomains?.split(",");
71
73
  if (onlyAnonymous) {
72
- return await this._interface.listServerUsers({ cursor, limit, orderBy, desc, query, includeRestricted, includeAnonymous: true, onlyAnonymous: true, teamId });
74
+ return await this._interface.listServerUsers({ cursor, limit, orderBy, desc, query, excludedEmailDomains: excludedEmailDomainList, includeRestricted, includeAnonymous: true, onlyAnonymous: true, teamId });
73
75
  }
74
- return await this._interface.listServerUsers({ cursor, limit, orderBy, desc, query, includeRestricted, includeAnonymous, teamId });
76
+ return await this._interface.listServerUsers({ cursor, limit, orderBy, desc, query, excludedEmailDomains: excludedEmailDomainList, includeRestricted, includeAnonymous, teamId });
75
77
  });
76
78
  private readonly _serverUserCache = createCache<string[], UsersCrud['Server']['Read'] | null>(async ([userId]) => {
77
79
  const user = await this._interface.getServerUserById(userId);
@@ -1343,14 +1345,16 @@ export class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pro
1343
1345
  }
1344
1346
 
1345
1347
  async listUsers(options?: ServerListUsersOptions): Promise<ServerUser[] & { nextCursor: string | null }> {
1346
- const crud = Result.orThrow(await this._serverUsersCache.getOrWait([options?.cursor, options?.limit, options?.orderBy, options?.desc, options?.query, options?.includeRestricted, options?.includeAnonymous, options?.onlyAnonymous, options?.teamId], "write-only"));
1348
+ const excludedEmailDomains = options?.excludedEmailDomains && options.excludedEmailDomains.length > 0 ? options.excludedEmailDomains.join(",") : undefined;
1349
+ const crud = Result.orThrow(await this._serverUsersCache.getOrWait([options?.cursor, options?.limit, options?.orderBy, options?.desc, options?.query, options?.includeRestricted, options?.includeAnonymous, options?.onlyAnonymous, options?.teamId, excludedEmailDomains], "write-only"));
1347
1350
  const result: any = crud.items.map((j) => this._serverUserFromCrud(j));
1348
1351
  result.nextCursor = crud.pagination?.next_cursor ?? null;
1349
1352
  return result as any;
1350
1353
  }
1351
1354
 
1352
1355
  useUsers(options?: ServerListUsersOptions): ServerUser[] & { nextCursor: string | null } {
1353
- const crud = useAsyncCache(this._serverUsersCache, [options?.cursor, options?.limit, options?.orderBy, options?.desc, options?.query, options?.includeRestricted, options?.includeAnonymous, options?.onlyAnonymous, options?.teamId] as const, "serverApp.useUsers()");
1356
+ const excludedEmailDomains = options?.excludedEmailDomains && options.excludedEmailDomains.length > 0 ? options.excludedEmailDomains.join(",") : undefined;
1357
+ const crud = useAsyncCache(this._serverUsersCache, [options?.cursor, options?.limit, options?.orderBy, options?.desc, options?.query, options?.includeRestricted, options?.includeAnonymous, options?.onlyAnonymous, options?.teamId, excludedEmailDomains] as const, "serverApp.useUsers()");
1354
1358
  const result: any = crud.items.map((j) => this._serverUserFromCrud(j));
1355
1359
  result.nextCursor = crud.pagination?.next_cursor ?? null;
1356
1360
  return result as any;
@@ -1426,23 +1430,24 @@ export class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pro
1426
1430
  const result = useAsyncCache(cache, cacheKey, debugLabel);
1427
1431
  return useMemo(() => this._serverItemFromCrud({ type, id }, result), [result]);
1428
1432
  }
1433
+ private _resolveCustomer(
1434
+ options: { userId: string } | { teamId: string } | { customCustomerId: string }
1435
+ ): { customerType: "user" | "team" | "custom", customerId: string } {
1436
+ if ("userId" in options) {
1437
+ return { customerType: "user", customerId: options.userId };
1438
+ }
1439
+ if ("teamId" in options) {
1440
+ return { customerType: "team", customerId: options.teamId };
1441
+ }
1442
+ return { customerType: "custom", customerId: options.customCustomerId };
1443
+ }
1444
+
1429
1445
  async grantProduct(options: (
1430
1446
  ({ userId: string } | { teamId: string } | { customCustomerId: string }) &
1431
1447
  ({ productId: string } | { product: InlineProduct }) &
1432
1448
  { quantity?: number }
1433
1449
  )): Promise<void> {
1434
- let customerType: "user" | "team" | "custom";
1435
- let customerId: string;
1436
- if ("userId" in options) {
1437
- customerType = "user";
1438
- customerId = options.userId;
1439
- } else if ("teamId" in options) {
1440
- customerType = "team";
1441
- customerId = options.teamId;
1442
- } else {
1443
- customerType = "custom";
1444
- customerId = options.customCustomerId;
1445
- }
1450
+ const { customerType, customerId } = this._resolveCustomer(options);
1446
1451
 
1447
1452
  await this._interface.grantProduct({
1448
1453
  customerType,
@@ -1460,6 +1465,17 @@ export class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pro
1460
1465
  await cache.refresh([customerId, null, null]);
1461
1466
  }
1462
1467
 
1468
+ async createCheckoutUrl(options: (
1469
+ ({ userId: string } | { teamId: string } | { customCustomerId: string }) &
1470
+ ({ productId: string } | { product: InlineProduct }) &
1471
+ { returnUrl?: string }
1472
+ )): Promise<string> {
1473
+ const { customerType, customerId } = this._resolveCustomer(options);
1474
+
1475
+ const productIdOrInline = "productId" in options ? options.productId : options.product;
1476
+ return await this._interface.createCheckoutUrl(customerType, customerId, productIdOrInline, null, options.returnUrl, "server");
1477
+ }
1478
+
1463
1479
  async createTeam(data: ServerTeamCreateOptions): Promise<ServerTeam> {
1464
1480
  const team = await this._interface.createServerTeam(serverTeamCreateOptionsToCrud(data));
1465
1481
  await this._serverTeamsCache.refreshWhere(() => true);
@@ -114,6 +114,9 @@ const MAX_APPROX_BYTES_PER_BATCH = 512_000;
114
114
  // envelope overhead (browser_session_id, timestamps, wrapper keys, etc.).
115
115
  const MAX_FLUSH_PAYLOAD_BYTES = 900_000;
116
116
 
117
+ // Reused across the emit hot path to avoid per-event allocation.
118
+ const textEncoder = new TextEncoder();
119
+
117
120
  export type StoredSession = {
118
121
  session_id: string,
119
122
  created_at_ms: number,
@@ -290,6 +293,17 @@ export class SessionRecorder {
290
293
  // When _flushInProgress blocked earlier flushes, events can accumulate
291
294
  // well past MAX_APPROX_BYTES_PER_BATCH; sending them all at once would
292
295
  // exceed the server's 1MB body limit (413).
296
+ // A single event over the limit can't be sent (rrweb events aren't splittable); drop it and move on.
297
+ const firstSize = allSizes[offset] ?? throwErr("_eventSizes out of sync with _events — this should never happen");
298
+ if (firstSize > MAX_FLUSH_PAYLOAD_BYTES) {
299
+ captureWarning(
300
+ "SessionRecorder.flush",
301
+ new Error(`Dropping oversized session replay event (${firstSize} bytes > ${MAX_FLUSH_PAYLOAD_BYTES} byte limit); it cannot be sent without a 413.`),
302
+ );
303
+ offset += 1;
304
+ continue;
305
+ }
306
+
293
307
  let batchBytes = 0;
294
308
  let batchEnd = offset;
295
309
  for (let i = offset; i < allEvents.length; i++) {
@@ -388,7 +402,8 @@ export class SessionRecorder {
388
402
  }
389
403
  }
390
404
 
391
- const eventSize = JSON.stringify(event).length;
405
+ // Measure UTF-8 byte length to match the server's byte limit (.length counts UTF-16 units, undercounting multibyte content).
406
+ const eventSize = textEncoder.encode(JSON.stringify(event)).byteLength;
392
407
  this._events.push(event);
393
408
  this._eventSizes.push(eventSize);
394
409
  this._approxBytes += eventSize;
@@ -136,6 +136,7 @@ export type StackClientApp<HasTokenStore extends boolean = boolean, ProjectId ex
136
136
  redirectToUrl(url: string | URL, options?: { replace?: boolean }): Promise<void>,
137
137
  redirectToHandler(handlerName: keyof HandlerUrls, options?: RedirectToOptions): Promise<void>,
138
138
  signInWithTokens(tokens: { accessToken: string, refreshToken: string }): Promise<void>,
139
+ awaitPendingAuthResolutions(): Promise<void>,
139
140
  },
140
141
  }
141
142
  & AsyncStoreProperty<"project", [], Project, false>
@@ -35,6 +35,11 @@ export type StackServerApp<HasTokenStore extends boolean = boolean, ProjectId ex
35
35
  ({ productId: string } | { product: InlineProduct }) &
36
36
  { quantity?: number }
37
37
  )): Promise<void>,
38
+ createCheckoutUrl(options: (
39
+ ({ userId: string } | { teamId: string } | { customCustomerId: string }) &
40
+ ({ productId: string } | { product: InlineProduct }) &
41
+ { returnUrl?: string }
42
+ )): Promise<string>,
38
43
 
39
44
  useUser(options: GetCurrentUserOptions<HasTokenStore> & { or: 'redirect' }): ProjectCurrentServerUser<ProjectId>,
40
45
  useUser(options: GetCurrentUserOptions<HasTokenStore> & { or: 'throw' }): ProjectCurrentServerUser<ProjectId>,
@@ -139,6 +139,10 @@ type ServerListUsersOptionsBase = {
139
139
  * Free-text search. Matches user ID (exact UUID), display name, and contact channels (e.g. primary email).
140
140
  */
141
141
  query?: string,
142
+ /**
143
+ * Exclude users whose primary email domain matches one of these exact domains.
144
+ */
145
+ excludedEmailDomains?: string[],
142
146
  /**
143
147
  * Only return users who are members of the given team.
144
148
  */