@hexclave/react 1.0.51 → 1.0.53
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.
- package/dist/{admin-app-impl-DAQHCcD9.d.ts → admin-app-impl-CObFu26f.d.ts} +11 -8
- package/dist/{admin-app-impl-DAQHCcD9.d.ts.map → admin-app-impl-CObFu26f.d.ts.map} +1 -1
- package/dist/clickmap/clickmap-core.d.ts +1 -1
- package/dist/clickmap/index.d.ts +1 -1
- package/dist/{client-app-O21Ylb76.d.ts → client-app-DhFlsws7.d.ts} +2 -1
- package/dist/{client-app-O21Ylb76.d.ts.map → client-app-DhFlsws7.d.ts.map} +1 -1
- package/dist/common-BijZ0ocq.d.ts.map +1 -1
- package/dist/components/selected-team-switcher.d.ts +1 -1
- package/dist/components/team-icon.d.ts +1 -1
- package/dist/components/team-switcher.d.ts +1 -1
- package/dist/components-page/account-settings/payments/payments-page.d.ts +1 -1
- package/dist/components-page/account-settings/teams/leave-team-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-api-keys-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-display-name-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-member-invitation-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-member-list-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-page.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-profile-image-section.d.ts +1 -1
- package/dist/components-page/account-settings/teams/team-profile-user-section.d.ts +1 -1
- package/dist/components-page/hexclave-handler-client.d.ts +1 -1
- package/dist/components-page/hexclave-handler.d.ts +1 -1
- package/dist/components-page/sign-out.js +11 -2
- package/dist/components-page/sign-out.js.map +1 -1
- package/dist/components-page/sign-out.test.d.ts +1 -0
- package/dist/components-page/sign-out.test.js +157 -0
- package/dist/components-page/sign-out.test.js.map +1 -0
- package/dist/dev-tool/dev-tool-core.d.ts +1 -1
- package/dist/dev-tool/dev-tool-core.d.ts.map +1 -1
- package/dist/dev-tool/dev-tool-core.js +58 -28
- package/dist/dev-tool/dev-tool-core.js.map +1 -1
- package/dist/dev-tool/dev-tool-styles.js +35 -0
- package/dist/dev-tool/dev-tool-styles.js.map +1 -1
- package/dist/dev-tool/index.d.ts +1 -1
- package/dist/esm/components-page/sign-out.d.ts.map +1 -1
- package/dist/esm/components-page/sign-out.js +12 -3
- package/dist/esm/components-page/sign-out.js.map +1 -1
- package/dist/esm/components-page/sign-out.test.d.ts +1 -0
- package/dist/esm/components-page/sign-out.test.js +156 -0
- package/dist/esm/components-page/sign-out.test.js.map +1 -0
- package/dist/esm/dev-tool/dev-tool-core.d.ts.map +1 -1
- package/dist/esm/dev-tool/dev-tool-core.js +58 -28
- package/dist/esm/dev-tool/dev-tool-core.js.map +1 -1
- package/dist/esm/dev-tool/dev-tool-styles.js +35 -0
- package/dist/esm/dev-tool/dev-tool-styles.js.map +1 -1
- package/dist/esm/generated/global-css.d.ts +1 -1
- package/dist/esm/generated/global-css.js +1 -1
- package/dist/esm/generated/global-css.js.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +5 -4
- package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +97 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +3 -2
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +26 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/common.d.ts.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/common.js +21 -4
- package/dist/esm/lib/hexclave-app/apps/implementations/common.js.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.d.ts +37 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.d.ts.map +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.js +89 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.js.map +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.test.d.ts +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.test.js +134 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-back-state.test.js.map +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.d.ts +8 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.d.ts.map +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.js +73 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.js.map +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.d.ts +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.js +92 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.js.map +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js +27 -6
- package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.d.ts +1 -0
- package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.d.ts.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -1
- package/dist/esm/pushed-config-error-overlay/index.js +1 -1
- package/dist/esm/pushed-config-error-overlay/index.js.map +1 -1
- package/dist/esm/utils/session-storage.d.ts +12 -0
- package/dist/esm/utils/session-storage.d.ts.map +1 -0
- package/dist/esm/utils/session-storage.js +30 -0
- package/dist/esm/utils/session-storage.js.map +1 -0
- package/dist/generated/global-css.d.ts +1 -1
- package/dist/generated/global-css.js +1 -1
- package/dist/generated/global-css.js.map +1 -1
- package/dist/{hexclave-provider-DMSXFNp-.d.ts → hexclave-provider-C7c7GEpb.d.ts} +2 -2
- package/dist/{hexclave-provider-DMSXFNp-.d.ts.map → hexclave-provider-C7c7GEpb.d.ts.map} +1 -1
- package/dist/{hooks-UtbmjOdS.d.ts → hooks-BZQw1aT7.d.ts} +2 -2
- package/dist/{hooks-UtbmjOdS.d.ts.map → hooks-BZQw1aT7.d.ts.map} +1 -1
- package/dist/{index-C8Roh_o-.d.ts → index-6eQ0iUUE.d.ts} +2 -2
- package/dist/{index-C8Roh_o-.d.ts.map → index-6eQ0iUUE.d.ts.map} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -1
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +97 -0
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +1 -1
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +26 -1
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/lib/hexclave-app/apps/implementations/common.js +21 -4
- package/dist/lib/hexclave-app/apps/implementations/common.js.map +1 -1
- package/dist/lib/hexclave-app/apps/implementations/index.d.ts +1 -1
- package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.d.ts +37 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.d.ts.map +1 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.js +92 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.js.map +1 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.test.d.ts +1 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.test.js +133 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-back-state.test.js.map +1 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.d.ts +8 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.d.ts.map +1 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.js +74 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.js.map +1 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.d.ts +1 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.js +91 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.js.map +1 -0
- package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
- package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js +27 -6
- package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/lib/hexclave-app/apps/index.d.ts +1 -1
- package/dist/lib/hexclave-app/apps/interfaces/admin-app.d.ts +1 -1
- package/dist/lib/hexclave-app/apps/interfaces/client-app.d.ts +1 -1
- package/dist/lib/hexclave-app/apps/interfaces/client-app.js.map +1 -1
- package/dist/lib/hexclave-app/apps/interfaces/server-app.d.ts +1 -1
- package/dist/lib/hexclave-app/index.d.ts +1 -1
- package/dist/lib/hexclave-app/projects/index.d.ts +1 -1
- package/dist/lib/hexclave-app/teams/index.d.ts +1 -1
- package/dist/lib/hexclave-app/users/index.d.ts +1 -1
- package/dist/lib/hooks.d.ts +1 -1
- package/dist/providers/hexclave-context.d.ts +1 -1
- package/dist/providers/hexclave-provider-client.d.ts +1 -1
- package/dist/providers/hexclave-provider.d.ts +1 -1
- package/dist/pushed-config-error-overlay/index.d.ts +1 -1
- package/dist/pushed-config-error-overlay/index.js +1 -1
- package/dist/pushed-config-error-overlay/index.js.map +1 -1
- package/dist/sign-out-DBnSkfDz.d.ts.map +1 -1
- package/dist/utils/session-storage.d.ts +12 -0
- package/dist/utils/session-storage.d.ts.map +1 -0
- package/dist/utils/session-storage.js +33 -0
- package/dist/utils/session-storage.js.map +1 -0
- package/package.json +3 -3
- package/src/components-page/sign-out.test.tsx +190 -0
- package/src/components-page/sign-out.tsx +22 -3
- package/src/dev-tool/dev-tool-core.ts +100 -35
- package/src/dev-tool/dev-tool-styles.ts +35 -0
- package/src/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.ts +127 -0
- package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +34 -1
- package/src/lib/hexclave-app/apps/implementations/common.ts +18 -1
- package/src/lib/hexclave-app/apps/implementations/redirect-back-state.test.ts +134 -0
- package/src/lib/hexclave-app/apps/implementations/redirect-back-state.ts +140 -0
- package/src/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.ts +127 -0
- package/src/lib/hexclave-app/apps/implementations/redirect-loop-breaker.ts +117 -0
- package/src/lib/hexclave-app/apps/implementations/server-app-impl.ts +31 -5
- package/src/lib/hexclave-app/apps/interfaces/client-app.ts +1 -0
- package/src/pushed-config-error-overlay/index.ts +1 -1
- package/src/utils/session-storage.ts +45 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { recordRedirectAndThrowIfLoopDetected } from "./redirect-loop-breaker.js";
|
|
3
|
+
//#region src/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.ts
|
|
4
|
+
function createMockSessionStorage() {
|
|
5
|
+
const map = /* @__PURE__ */ new Map();
|
|
6
|
+
return {
|
|
7
|
+
getItem: (key) => map.get(key) ?? null,
|
|
8
|
+
setItem: (key, value) => {
|
|
9
|
+
map.set(key, value);
|
|
10
|
+
},
|
|
11
|
+
removeItem: (key) => {
|
|
12
|
+
map.delete(key);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const previousWindow = Reflect.get(globalThis, "window");
|
|
17
|
+
const hadPreviousWindow = Reflect.has(globalThis, "window");
|
|
18
|
+
function record(from, to) {
|
|
19
|
+
recordRedirectAndThrowIfLoopDetected({
|
|
20
|
+
currentUrl: new URL(from),
|
|
21
|
+
targetUrl: new URL(to)
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
describe("recordRedirectAndThrowIfLoopDetected", () => {
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
Reflect.set(globalThis, "window", { sessionStorage: createMockSessionStorage() });
|
|
27
|
+
vi.useFakeTimers();
|
|
28
|
+
vi.setSystemTime(/* @__PURE__ */ new Date("2026-01-01T00:00:00Z"));
|
|
29
|
+
});
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
vi.useRealTimers();
|
|
32
|
+
if (hadPreviousWindow) Reflect.set(globalThis, "window", previousWindow);
|
|
33
|
+
else Reflect.deleteProperty(globalThis, "window");
|
|
34
|
+
});
|
|
35
|
+
it("allows distinct redirects in quick succession", () => {
|
|
36
|
+
for (let i = 0; i < 20; i++) record(`https://app.example.test/page-${i}`, `https://app.example.test/page-${i + 1}`);
|
|
37
|
+
});
|
|
38
|
+
it("throws once the same redirect repeats 5 times within the window", () => {
|
|
39
|
+
for (let i = 0; i < 4; i++) {
|
|
40
|
+
record("https://app.example.test/dashboard", "https://hosted.example.test/handler/sign-in");
|
|
41
|
+
vi.advanceTimersByTime(1e3);
|
|
42
|
+
}
|
|
43
|
+
expect(() => {
|
|
44
|
+
record("https://app.example.test/dashboard", "https://hosted.example.test/handler/sign-in");
|
|
45
|
+
}).toThrowError(/Redirect loop detected/);
|
|
46
|
+
});
|
|
47
|
+
it("treats redirects that differ only in query params or hash as identical", () => {
|
|
48
|
+
for (let i = 0; i < 4; i++) record(`https://app.example.test/dashboard?code=code-${i}`, `https://hosted.example.test/handler/sign-in?state=state-${i}#frag-${i}`);
|
|
49
|
+
expect(() => {
|
|
50
|
+
record("https://app.example.test/dashboard?code=final", "https://hosted.example.test/handler/sign-in?state=final");
|
|
51
|
+
}).toThrowError(/Redirect loop detected/);
|
|
52
|
+
});
|
|
53
|
+
it("does not throw when the identical redirects are spread out beyond the window", () => {
|
|
54
|
+
for (let i = 0; i < 20; i++) {
|
|
55
|
+
record("https://app.example.test/dashboard", "https://hosted.example.test/handler/sign-in");
|
|
56
|
+
vi.advanceTimersByTime(31e3);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
it("allows the same redirect again after a loop was broken", () => {
|
|
60
|
+
for (let i = 0; i < 4; i++) record("https://app.example.test/dashboard", "https://hosted.example.test/handler/sign-in");
|
|
61
|
+
expect(() => {
|
|
62
|
+
record("https://app.example.test/dashboard", "https://hosted.example.test/handler/sign-in");
|
|
63
|
+
}).toThrowError(/Redirect loop detected/);
|
|
64
|
+
record("https://app.example.test/dashboard", "https://hosted.example.test/handler/sign-in");
|
|
65
|
+
});
|
|
66
|
+
it("counts self-redirects (same origin and path) towards loops", () => {
|
|
67
|
+
for (let i = 0; i < 4; i++) record(`https://hosted.example.test/handler/sign-in?attempt=${i}`, "https://hosted.example.test/handler/sign-in");
|
|
68
|
+
expect(() => {
|
|
69
|
+
record("https://hosted.example.test/handler/sign-in?attempt=final", "https://hosted.example.test/handler/sign-in");
|
|
70
|
+
}).toThrowError(/Redirect loop detected/);
|
|
71
|
+
});
|
|
72
|
+
it("degrades to a no-op when sessionStorage is unavailable", () => {
|
|
73
|
+
Reflect.set(globalThis, "window", { get sessionStorage() {
|
|
74
|
+
throw new Error("Storage is disabled");
|
|
75
|
+
} });
|
|
76
|
+
for (let i = 0; i < 20; i++) record("https://app.example.test/dashboard", "https://hosted.example.test/handler/sign-in");
|
|
77
|
+
});
|
|
78
|
+
it("recovers from corrupted breadcrumb storage", () => {
|
|
79
|
+
const storage = createMockSessionStorage();
|
|
80
|
+
storage.setItem("hexclave-redirect-loop-breadcrumbs", "{not json");
|
|
81
|
+
Reflect.set(globalThis, "window", { sessionStorage: storage });
|
|
82
|
+
record("https://app.example.test/dashboard", "https://hosted.example.test/handler/sign-in");
|
|
83
|
+
for (let i = 0; i < 3; i++) record("https://app.example.test/dashboard", "https://hosted.example.test/handler/sign-in");
|
|
84
|
+
expect(() => {
|
|
85
|
+
record("https://app.example.test/dashboard", "https://hosted.example.test/handler/sign-in");
|
|
86
|
+
}).toThrowError(/Redirect loop detected/);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
//#endregion
|
|
90
|
+
export {};
|
|
91
|
+
|
|
92
|
+
//# sourceMappingURL=redirect-loop-breaker.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect-loop-breaker.test.js","names":[],"sources":["../../../../../../src/lib/hexclave-app/apps/implementations/redirect-loop-breaker.test.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { recordRedirectAndThrowIfLoopDetected } from \"./redirect-loop-breaker\";\n\nfunction createMockSessionStorage() {\n const map = new Map<string, string>();\n return {\n getItem: (key: string) => map.get(key) ?? null,\n setItem: (key: string, value: string) => {\n map.set(key, value);\n },\n removeItem: (key: string) => {\n map.delete(key);\n },\n };\n}\n\nconst previousWindow = Reflect.get(globalThis, \"window\");\nconst hadPreviousWindow = Reflect.has(globalThis, \"window\");\n\nfunction record(from: string, to: string) {\n recordRedirectAndThrowIfLoopDetected({\n currentUrl: new URL(from),\n targetUrl: new URL(to),\n });\n}\n\ndescribe(\"recordRedirectAndThrowIfLoopDetected\", () => {\n beforeEach(() => {\n Reflect.set(globalThis, \"window\", { sessionStorage: createMockSessionStorage() });\n vi.useFakeTimers();\n vi.setSystemTime(new Date(\"2026-01-01T00:00:00Z\"));\n });\n\n afterEach(() => {\n vi.useRealTimers();\n if (hadPreviousWindow) {\n Reflect.set(globalThis, \"window\", previousWindow);\n } else {\n Reflect.deleteProperty(globalThis, \"window\");\n }\n });\n\n it(\"allows distinct redirects in quick succession\", () => {\n for (let i = 0; i < 20; i++) {\n record(`https://app.example.test/page-${i}`, `https://app.example.test/page-${i + 1}`);\n }\n });\n\n it(\"throws once the same redirect repeats 5 times within the window\", () => {\n for (let i = 0; i < 4; i++) {\n record(\"https://app.example.test/dashboard\", \"https://hosted.example.test/handler/sign-in\");\n vi.advanceTimersByTime(1000);\n }\n expect(() => {\n record(\"https://app.example.test/dashboard\", \"https://hosted.example.test/handler/sign-in\");\n }).toThrowError(/Redirect loop detected/);\n });\n\n it(\"treats redirects that differ only in query params or hash as identical\", () => {\n // Real loops usually rotate nonce-style params (code, state, after_auth_return_to) each cycle.\n for (let i = 0; i < 4; i++) {\n record(\n `https://app.example.test/dashboard?code=code-${i}`,\n `https://hosted.example.test/handler/sign-in?state=state-${i}#frag-${i}`,\n );\n }\n expect(() => {\n record(\"https://app.example.test/dashboard?code=final\", \"https://hosted.example.test/handler/sign-in?state=final\");\n }).toThrowError(/Redirect loop detected/);\n });\n\n it(\"does not throw when the identical redirects are spread out beyond the window\", () => {\n for (let i = 0; i < 20; i++) {\n record(\"https://app.example.test/dashboard\", \"https://hosted.example.test/handler/sign-in\");\n vi.advanceTimersByTime(31_000);\n }\n });\n\n it(\"allows the same redirect again after a loop was broken\", () => {\n for (let i = 0; i < 4; i++) {\n record(\"https://app.example.test/dashboard\", \"https://hosted.example.test/handler/sign-in\");\n }\n expect(() => {\n record(\"https://app.example.test/dashboard\", \"https://hosted.example.test/handler/sign-in\");\n }).toThrowError(/Redirect loop detected/);\n // The breadcrumbs for the broken loop are dropped, so a manual retry isn't instantly blocked.\n record(\"https://app.example.test/dashboard\", \"https://hosted.example.test/handler/sign-in\");\n });\n\n it(\"counts self-redirects (same origin and path) towards loops\", () => {\n for (let i = 0; i < 4; i++) {\n record(`https://hosted.example.test/handler/sign-in?attempt=${i}`, \"https://hosted.example.test/handler/sign-in\");\n }\n expect(() => {\n record(\"https://hosted.example.test/handler/sign-in?attempt=final\", \"https://hosted.example.test/handler/sign-in\");\n }).toThrowError(/Redirect loop detected/);\n });\n\n it(\"degrades to a no-op when sessionStorage is unavailable\", () => {\n Reflect.set(globalThis, \"window\", {\n get sessionStorage(): Storage {\n throw new Error(\"Storage is disabled\");\n },\n });\n for (let i = 0; i < 20; i++) {\n record(\"https://app.example.test/dashboard\", \"https://hosted.example.test/handler/sign-in\");\n }\n });\n\n it(\"recovers from corrupted breadcrumb storage\", () => {\n const storage = createMockSessionStorage();\n storage.setItem(\"hexclave-redirect-loop-breadcrumbs\", \"{not json\");\n Reflect.set(globalThis, \"window\", { sessionStorage: storage });\n record(\"https://app.example.test/dashboard\", \"https://hosted.example.test/handler/sign-in\");\n // After recovery, loop detection works again.\n for (let i = 0; i < 3; i++) {\n record(\"https://app.example.test/dashboard\", \"https://hosted.example.test/handler/sign-in\");\n }\n expect(() => {\n record(\"https://app.example.test/dashboard\", \"https://hosted.example.test/handler/sign-in\");\n }).toThrowError(/Redirect loop detected/);\n });\n});\n"],"mappings":"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"}
|
|
@@ -35,6 +35,7 @@ declare class _HexclaveServerAppImplIncomplete<HasTokenStore extends boolean, Pr
|
|
|
35
35
|
private readonly _serverUsersCache;
|
|
36
36
|
private readonly _serverUserCache;
|
|
37
37
|
private readonly _serverTeamsCache;
|
|
38
|
+
private readonly _serverTeamCache;
|
|
38
39
|
protected _refreshTeamMembership(teamId: string, userId: string): Promise<void>;
|
|
39
40
|
private readonly _serverUserTeamInvitationsCache;
|
|
40
41
|
private readonly _serverTeamUserPermissionsCache;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-app-impl.d.ts","names":[],"sources":["../../../../../../src/lib/hexclave-app/apps/implementations/server-app-impl.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"server-app-impl.d.ts","names":[],"sources":["../../../../../../src/lib/hexclave-app/apps/implementations/server-app-impl.ts"],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import { suspend } from "@hexclave/shared/dist/utils/react";
|
|
|
6
6
|
import { Result } from "@hexclave/shared/dist/utils/results";
|
|
7
7
|
import { clientVersion, createCache, createCacheBySession, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getDefaultSecretServerKey, resolveApiUrls, resolveConstructorOptions, useAsyncCache } from "./common.js";
|
|
8
8
|
import { InternalSession } from "@hexclave/shared/dist/sessions";
|
|
9
|
+
import { isUuid } from "@hexclave/shared/dist/utils/uuids";
|
|
9
10
|
import { WebAuthnError, startRegistration } from "@simplewebauthn/browser";
|
|
10
11
|
import { constructRedirectUrl } from "../../../../utils/url.js";
|
|
11
12
|
import { apiKeyCreationOptionsToCrud, apiKeyUpdateOptionsToCrud } from "../../api-keys/index.js";
|
|
@@ -225,6 +226,15 @@ var _HexclaveServerAppImplIncomplete = class extends _HexclaveClientAppImplIncom
|
|
|
225
226
|
query
|
|
226
227
|
});
|
|
227
228
|
});
|
|
229
|
+
this._serverTeamCache = createCache(async ([teamId]) => {
|
|
230
|
+
if (!isUuid(teamId)) return null;
|
|
231
|
+
try {
|
|
232
|
+
return await this._interface.getServerTeam(teamId);
|
|
233
|
+
} catch (error) {
|
|
234
|
+
if (KnownErrors.TeamNotFound.isInstance(error)) return null;
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
});
|
|
228
238
|
this._serverUserTeamInvitationsCache = createCache(async ([userId]) => {
|
|
229
239
|
return await this._interface.listServerUserTeamInvitations(userId);
|
|
230
240
|
});
|
|
@@ -831,11 +841,19 @@ var _HexclaveServerAppImplIncomplete = class extends _HexclaveClientAppImplIncom
|
|
|
831
841
|
serverMetadata: crud.server_metadata,
|
|
832
842
|
async update(update) {
|
|
833
843
|
await app._interface.updateServerTeam(crud.id, serverTeamUpdateOptionsToCrud(update));
|
|
834
|
-
await Promise.all([
|
|
844
|
+
await Promise.all([
|
|
845
|
+
app._serverTeamCache.refresh([crud.id]),
|
|
846
|
+
app._serverTeamsCache.refreshWhere(() => true),
|
|
847
|
+
app._serverUsersCache.refreshWhere(() => true)
|
|
848
|
+
]);
|
|
835
849
|
},
|
|
836
850
|
async delete() {
|
|
837
851
|
await app._interface.deleteServerTeam(crud.id);
|
|
838
|
-
await Promise.all([
|
|
852
|
+
await Promise.all([
|
|
853
|
+
app._serverTeamCache.refresh([crud.id]),
|
|
854
|
+
app._serverTeamsCache.refreshWhere(() => true),
|
|
855
|
+
app._serverUsersCache.refreshWhere(() => true)
|
|
856
|
+
]);
|
|
839
857
|
},
|
|
840
858
|
async listUsers() {
|
|
841
859
|
return Result.orThrow(await app._serverTeamMemberProfilesCache.getOrWait([crud.id], "write-only")).map((u) => app._serverTeamUserFromCrud(u));
|
|
@@ -1254,6 +1272,7 @@ var _HexclaveServerAppImplIncomplete = class extends _HexclaveClientAppImplIncom
|
|
|
1254
1272
|
}
|
|
1255
1273
|
async createTeam(data) {
|
|
1256
1274
|
const team = await this._interface.createServerTeam(serverTeamCreateOptionsToCrud(data));
|
|
1275
|
+
await this._serverTeamCache.refresh([team.id]);
|
|
1257
1276
|
await this._serverTeamsCache.refreshWhere(() => true);
|
|
1258
1277
|
return this._serverTeamFromCrud(team);
|
|
1259
1278
|
}
|
|
@@ -1304,17 +1323,19 @@ var _HexclaveServerAppImplIncomplete = class extends _HexclaveClientAppImplIncom
|
|
|
1304
1323
|
if (typeof options === "object" && "apiKey" in options) return await this._getTeamByApiKey(options.apiKey);
|
|
1305
1324
|
else {
|
|
1306
1325
|
const teamId = options;
|
|
1307
|
-
|
|
1326
|
+
if (teamId == null) return null;
|
|
1327
|
+
const team = Result.orThrow(await this._serverTeamCache.getOrWait([teamId], "write-only"));
|
|
1328
|
+
return team == null ? null : this._serverTeamFromCrud(team);
|
|
1308
1329
|
}
|
|
1309
1330
|
}
|
|
1310
1331
|
useTeam(options) {
|
|
1311
1332
|
if (typeof options === "object" && "apiKey" in options) return this._useTeamByApiKey(options.apiKey);
|
|
1312
1333
|
else {
|
|
1313
1334
|
const teamId = options;
|
|
1314
|
-
const
|
|
1335
|
+
const team = useAsyncCache(this._serverTeamCache, [teamId ?? ""], "serverApp.useTeam()");
|
|
1315
1336
|
return useMemo(() => {
|
|
1316
|
-
return
|
|
1317
|
-
}, [
|
|
1337
|
+
return team == null ? null : this._serverTeamFromCrud(team);
|
|
1338
|
+
}, [team]);
|
|
1318
1339
|
}
|
|
1319
1340
|
}
|
|
1320
1341
|
_createServerDataVaultStore(id) {
|