@hexclave/js 1.0.49 → 1.0.52

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 (116) hide show
  1. package/dist/{admin-app-impl-Du4dsPO9.d.ts → admin-app-impl-DHs4il4z.d.ts} +5 -2
  2. package/dist/{admin-app-impl-Du4dsPO9.d.ts.map → admin-app-impl-DHs4il4z.d.ts.map} +1 -1
  3. package/dist/clickmap/clickmap-core.d.ts +1 -1
  4. package/dist/clickmap/index.d.ts +1 -1
  5. package/dist/{client-app-BgdvwktS.d.ts → client-app-BoOM8rxo.d.ts} +2 -1
  6. package/dist/{client-app-BgdvwktS.d.ts.map → client-app-BoOM8rxo.d.ts.map} +1 -1
  7. package/dist/common-CRu2FsO9.d.ts.map +1 -1
  8. package/dist/dev-tool/dev-tool-core.d.ts +1 -1
  9. package/dist/dev-tool/dev-tool-core.d.ts.map +1 -1
  10. package/dist/dev-tool/dev-tool-core.js +58 -28
  11. package/dist/dev-tool/dev-tool-core.js.map +1 -1
  12. package/dist/dev-tool/dev-tool-styles.js +35 -0
  13. package/dist/dev-tool/dev-tool-styles.js.map +1 -1
  14. package/dist/dev-tool/index.d.ts +1 -1
  15. package/dist/esm/dev-tool/dev-tool-core.d.ts.map +1 -1
  16. package/dist/esm/dev-tool/dev-tool-core.js +58 -28
  17. package/dist/esm/dev-tool/dev-tool-core.js.map +1 -1
  18. package/dist/esm/dev-tool/dev-tool-styles.js +35 -0
  19. package/dist/esm/dev-tool/dev-tool-styles.js.map +1 -1
  20. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -0
  21. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  22. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +97 -0
  23. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
  24. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +1 -0
  25. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  26. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +26 -1
  27. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  28. package/dist/esm/lib/hexclave-app/apps/implementations/common.d.ts.map +1 -1
  29. package/dist/esm/lib/hexclave-app/apps/implementations/common.js +21 -4
  30. package/dist/esm/lib/hexclave-app/apps/implementations/common.js.map +1 -1
  31. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.d.ts +37 -0
  32. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.d.ts.map +1 -0
  33. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.js +89 -0
  34. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.js.map +1 -0
  35. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.test.d.ts +1 -0
  36. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.test.js +134 -0
  37. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.test.js.map +1 -0
  38. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.d.ts +8 -0
  39. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.d.ts.map +1 -0
  40. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.js +73 -0
  41. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.js.map +1 -0
  42. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.d.ts +1 -0
  43. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.js +92 -0
  44. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.js.map +1 -0
  45. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -0
  46. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts.map +1 -1
  47. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js +24 -3
  48. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js.map +1 -1
  49. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.d.ts +1 -0
  50. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.d.ts.map +1 -1
  51. package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -1
  52. package/dist/esm/pushed-config-error-overlay/index.js +1 -1
  53. package/dist/esm/pushed-config-error-overlay/index.js.map +1 -1
  54. package/dist/esm/pushed-config-error-overlay/index.test.js +1 -1
  55. package/dist/esm/utils/session-storage.d.ts +12 -0
  56. package/dist/esm/utils/session-storage.d.ts.map +1 -0
  57. package/dist/esm/utils/session-storage.js +30 -0
  58. package/dist/esm/utils/session-storage.js.map +1 -0
  59. package/dist/index.d.ts +1 -1
  60. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -1
  61. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +97 -0
  62. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
  63. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +1 -1
  64. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +26 -1
  65. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  66. package/dist/lib/hexclave-app/apps/implementations/common.js +21 -4
  67. package/dist/lib/hexclave-app/apps/implementations/common.js.map +1 -1
  68. package/dist/lib/hexclave-app/apps/implementations/index.d.ts +1 -1
  69. package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.d.ts +37 -0
  70. package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.d.ts.map +1 -0
  71. package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.js +92 -0
  72. package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.js.map +1 -0
  73. package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.test.d.ts +1 -0
  74. package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.test.js +133 -0
  75. package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.test.js.map +1 -0
  76. package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.d.ts +8 -0
  77. package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.d.ts.map +1 -0
  78. package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.js +74 -0
  79. package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.js.map +1 -0
  80. package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.d.ts +1 -0
  81. package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.js +91 -0
  82. package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.js.map +1 -0
  83. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
  84. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js +24 -3
  85. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js.map +1 -1
  86. package/dist/lib/hexclave-app/apps/index.d.ts +1 -1
  87. package/dist/lib/hexclave-app/apps/interfaces/admin-app.d.ts +1 -1
  88. package/dist/lib/hexclave-app/apps/interfaces/client-app.d.ts +1 -1
  89. package/dist/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -1
  90. package/dist/lib/hexclave-app/apps/interfaces/server-app.d.ts +1 -1
  91. package/dist/lib/hexclave-app/index.d.ts +1 -1
  92. package/dist/lib/hexclave-app/projects/index.d.ts +1 -1
  93. package/dist/lib/hexclave-app/teams/index.d.ts +1 -1
  94. package/dist/lib/hexclave-app/users/index.d.ts +1 -1
  95. package/dist/pushed-config-error-overlay/index.d.ts +1 -1
  96. package/dist/pushed-config-error-overlay/index.js +1 -1
  97. package/dist/pushed-config-error-overlay/index.js.map +1 -1
  98. package/dist/pushed-config-error-overlay/index.test.js +1 -1
  99. package/dist/utils/session-storage.d.ts +12 -0
  100. package/dist/utils/session-storage.d.ts.map +1 -0
  101. package/dist/utils/session-storage.js +33 -0
  102. package/dist/utils/session-storage.js.map +1 -0
  103. package/package.json +2 -2
  104. package/src/dev-tool/dev-tool-core.ts +100 -35
  105. package/src/dev-tool/dev-tool-styles.ts +35 -0
  106. package/src/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.ts +127 -0
  107. package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +34 -1
  108. package/src/lib/hexclave-app/apps/implementations/common.ts +18 -1
  109. package/src/lib/hexclave-app/apps/implementations/redirect-back-state.test.ts +134 -0
  110. package/src/lib/hexclave-app/apps/implementations/redirect-back-state.ts +140 -0
  111. package/src/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.ts +127 -0
  112. package/src/lib/hexclave-app/apps/implementations/redirect-loop-breaker.ts +117 -0
  113. package/src/lib/hexclave-app/apps/implementations/server-app-impl.ts +27 -2
  114. package/src/lib/hexclave-app/apps/interfaces/client-app.ts +1 -0
  115. package/src/pushed-config-error-overlay/index.ts +1 -1
  116. package/src/utils/session-storage.ts +45 -0
@@ -23,6 +23,7 @@ import { ProviderType } from "@hexclave/shared/dist/utils/oauth";
23
23
  import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
24
24
  import { suspend } from "@hexclave/shared/dist/utils/react";
25
25
  import { Result } from "@hexclave/shared/dist/utils/results";
26
+ import { isUuid } from "@hexclave/shared/dist/utils/uuids";
26
27
  import { WebAuthnError, startRegistration } from "@simplewebauthn/browser";
27
28
  import * as yup from "yup";
28
29
  import { constructRedirectUrl } from "../../../../utils/url";
@@ -88,6 +89,20 @@ export class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pro
88
89
  ], TeamsCrud['Server']['List']>(async ([userId, orderBy, desc, cursor, limit, query]) => {
89
90
  return await this._interface.listServerTeamsPaginated({ userId, orderBy, desc, cursor, limit, query });
90
91
  });
92
+ private readonly _serverTeamCache = createCache<string[], TeamsCrud['Server']['Read'] | null>(async ([teamId]) => {
93
+ // The previous list-and-find implementation treated unknown or malformed IDs as null; preserve that behavior without making an invalid request.
94
+ if (!isUuid(teamId)) {
95
+ return null;
96
+ }
97
+ try {
98
+ return await this._interface.getServerTeam(teamId);
99
+ } catch (error) {
100
+ if (KnownErrors.TeamNotFound.isInstance(error)) {
101
+ return null;
102
+ }
103
+ throw error;
104
+ }
105
+ });
91
106
 
92
107
  protected async _refreshTeamMembership(teamId: string, userId: string) {
93
108
  await Promise.all([
@@ -650,6 +665,10 @@ export class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pro
650
665
  throw new HexclaveAssertionError("getOrLinkConnectedAccount is not available for server users. OAuth flows must be initiated on the client side.");
651
666
  },
652
667
  selectedTeam: crud.selected_team ? app._serverTeamFromCrud(crud.selected_team) : null,
668
+ // Unlike the app-level getTeam/useTeam (which fetch any team by id),
669
+ // the user-scoped variants search the user's own team list on purpose:
670
+ // they must return null for teams the user is not a member of, and some
671
+ // callers rely on that as a membership check.
653
672
  async getTeam(teamId: string) {
654
673
  const teams = await this.listTeams();
655
674
  return teams.find((t) => t.id === teamId) ?? null;
@@ -892,6 +911,7 @@ export class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pro
892
911
  async update(update: Partial<ServerTeamUpdateOptions>) {
893
912
  await app._interface.updateServerTeam(crud.id, serverTeamUpdateOptionsToCrud(update));
894
913
  await Promise.all([
914
+ app._serverTeamCache.refresh([crud.id]),
895
915
  app._serverTeamsCache.refreshWhere(() => true),
896
916
  app._serverUsersCache.refreshWhere(() => true),
897
917
  ]);
@@ -899,6 +919,7 @@ export class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pro
899
919
  async delete() {
900
920
  await app._interface.deleteServerTeam(crud.id);
901
921
  await Promise.all([
922
+ app._serverTeamCache.refresh([crud.id]),
902
923
  app._serverTeamsCache.refreshWhere(() => true),
903
924
  app._serverUsersCache.refreshWhere(() => true),
904
925
  ]);
@@ -1227,6 +1248,7 @@ export class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pro
1227
1248
 
1228
1249
  async createTeam(data: ServerTeamCreateOptions): Promise<ServerTeam> {
1229
1250
  const team = await this._interface.createServerTeam(serverTeamCreateOptionsToCrud(data));
1251
+ await this._serverTeamCache.refresh([team.id]);
1230
1252
  await this._serverTeamsCache.refreshWhere(() => true);
1231
1253
  return this._serverTeamFromCrud(team);
1232
1254
  }
@@ -1253,8 +1275,11 @@ export class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pro
1253
1275
  return await this._getTeamByApiKey(options.apiKey);
1254
1276
  } else {
1255
1277
  const teamId = options;
1256
- const teams = await this.listTeams();
1257
- return teams.find((t) => t.id === teamId) ?? null;
1278
+ if (teamId == null) {
1279
+ return null;
1280
+ }
1281
+ const team = Result.orThrow(await this._serverTeamCache.getOrWait([teamId], "write-only"));
1282
+ return team == null ? null : this._serverTeamFromCrud(team);
1258
1283
  }
1259
1284
  }
1260
1285
 
@@ -130,6 +130,7 @@ export type StackClientApp<HasTokenStore extends boolean = boolean, ProjectId ex
130
130
  redirectToHandler(handlerName: keyof HandlerUrls, options?: RedirectToOptions): Promise<void>,
131
131
  signInWithTokens(tokens: { accessToken: string, refreshToken: string }): Promise<void>,
132
132
  awaitPendingAuthResolutions(): Promise<void>,
133
+ isTrustedRedirectUrl(url: string): Promise<boolean>,
133
134
  },
134
135
  }
135
136
  & AsyncStoreProperty<"project", [], Project, false>
@@ -372,7 +372,7 @@ export function mountPushedConfigErrorOverlay(app: StackClientApp<true>): () =>
372
372
  return;
373
373
  }
374
374
 
375
- const issueMessage = issue.messages.join("\n");
375
+ const issueMessage = "Hexclave config " + issue.kind + ": " + issue.messages.join("\n");
376
376
  const issueKey = `${app.projectId}:${issue.kind}:${issueMessage}`;
377
377
  const issueLabel = issue.kind === "error" ? "error" : "warning";
378
378
  const issueTitle = issue.kind === "error"
@@ -0,0 +1,45 @@
1
+
2
+ //===========================================
3
+ // THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template
4
+ //===========================================
5
+ /**
6
+ * Guarded sessionStorage access for resilience layers (redirect loop breaking, redirect-back state
7
+ * mirroring). These layers must degrade to "no stored value" when storage is unavailable, instead
8
+ * of breaking the auth flow they are trying to protect.
9
+ */
10
+
11
+ export function readSessionStorageItem(key: string): string | null {
12
+ if (typeof window === "undefined") {
13
+ return null;
14
+ }
15
+ try {
16
+ return window.sessionStorage.getItem(key);
17
+ } catch {
18
+ // Storage can be blocked entirely (private browsing, sandboxed iframes, disabled cookies), in
19
+ // which case accessing window.sessionStorage throws. Treat that as "nothing stored".
20
+ return null;
21
+ }
22
+ }
23
+
24
+ export function writeSessionStorageItem(key: string, value: string): void {
25
+ if (typeof window === "undefined") {
26
+ return;
27
+ }
28
+ try {
29
+ window.sessionStorage.setItem(key, value);
30
+ } catch {
31
+ // Storage can be blocked or full; see readSessionStorageItem. Values written here are only
32
+ // used as a fallback, so failing to persist must not fail the caller.
33
+ }
34
+ }
35
+
36
+ export function removeSessionStorageItem(key: string): void {
37
+ if (typeof window === "undefined") {
38
+ return;
39
+ }
40
+ try {
41
+ window.sessionStorage.removeItem(key);
42
+ } catch {
43
+ // See readSessionStorageItem.
44
+ }
45
+ }