@hexclave/js 1.0.76 → 1.0.78

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 (84) hide show
  1. package/dist/{admin-app-impl-B86v7B0O.d.ts → admin-app-impl-DOGMiOUL.d.ts} +7 -5
  2. package/dist/admin-app-impl-DOGMiOUL.d.ts.map +1 -0
  3. package/dist/clickmap/clickmap-core.d.ts +1 -1
  4. package/dist/clickmap/index.d.ts +1 -1
  5. package/dist/{client-app-WOX3pOo1.d.ts → client-app-Dj2NuO6C.d.ts} +5 -2
  6. package/dist/client-app-Dj2NuO6C.d.ts.map +1 -0
  7. package/dist/dev-tool/dev-tool-core.d.ts +1 -1
  8. package/dist/dev-tool/index.d.ts +1 -1
  9. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -1
  10. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  11. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.js +2 -0
  12. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -1
  13. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.automatic-side-effects.test.js +30 -1
  14. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.automatic-side-effects.test.js.map +1 -1
  15. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
  16. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +3 -1
  17. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  18. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +90 -20
  19. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  20. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.sign-out.test.d.ts +1 -0
  21. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.sign-out.test.js +83 -0
  22. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.sign-out.test.js.map +1 -0
  23. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.untrusted-redirect-card.test.d.ts +1 -0
  24. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.untrusted-redirect-card.test.js +120 -0
  25. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.untrusted-redirect-card.test.js.map +1 -0
  26. package/dist/esm/lib/hexclave-app/apps/implementations/common.js +2 -2
  27. package/dist/esm/lib/hexclave-app/apps/implementations/common.js.map +1 -1
  28. package/dist/esm/lib/hexclave-app/apps/implementations/index.d.ts +1 -1
  29. package/dist/esm/lib/hexclave-app/apps/implementations/index.js +1 -1
  30. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
  31. package/dist/esm/lib/hexclave-app/apps/implementations/server-app-impl.js +1 -1
  32. package/dist/esm/lib/hexclave-app/session-replays/index.d.ts +2 -1
  33. package/dist/esm/lib/hexclave-app/session-replays/index.d.ts.map +1 -1
  34. package/dist/esm/lib/hexclave-app/teams/index.d.ts +3 -0
  35. package/dist/esm/lib/hexclave-app/teams/index.d.ts.map +1 -1
  36. package/dist/esm/lib/hexclave-app/teams/index.js.map +1 -1
  37. package/dist/{index-hYjsGKNc.d.ts → index-Cf1wOohp.d.ts} +3 -2
  38. package/dist/index-Cf1wOohp.d.ts.map +1 -0
  39. package/dist/index.d.ts +1 -1
  40. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -1
  41. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.js +2 -0
  42. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.js.map +1 -1
  43. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.automatic-side-effects.test.js +29 -0
  44. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.automatic-side-effects.test.js.map +1 -1
  45. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
  46. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +2 -2
  47. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +89 -18
  48. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  49. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.sign-out.test.d.ts +1 -0
  50. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.sign-out.test.js +82 -0
  51. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.sign-out.test.js.map +1 -0
  52. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.untrusted-redirect-card.test.d.ts +1 -0
  53. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.untrusted-redirect-card.test.js +119 -0
  54. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.untrusted-redirect-card.test.js.map +1 -0
  55. package/dist/lib/hexclave-app/apps/implementations/common.js +2 -2
  56. package/dist/lib/hexclave-app/apps/implementations/common.js.map +1 -1
  57. package/dist/lib/hexclave-app/apps/implementations/index.d.ts +1 -1
  58. package/dist/lib/hexclave-app/apps/implementations/index.js +1 -1
  59. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
  60. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.js +1 -1
  61. package/dist/lib/hexclave-app/apps/index.d.ts +1 -1
  62. package/dist/lib/hexclave-app/apps/interfaces/admin-app.d.ts +2 -2
  63. package/dist/lib/hexclave-app/apps/interfaces/client-app.d.ts +1 -1
  64. package/dist/lib/hexclave-app/apps/interfaces/server-app.d.ts +1 -1
  65. package/dist/lib/hexclave-app/index.d.ts +1 -1
  66. package/dist/lib/hexclave-app/projects/index.d.ts +1 -1
  67. package/dist/lib/hexclave-app/session-replays/index.d.ts +1 -1
  68. package/dist/lib/hexclave-app/teams/index.d.ts +1 -1
  69. package/dist/lib/hexclave-app/teams/index.js.map +1 -1
  70. package/dist/lib/hexclave-app/users/index.d.ts +1 -1
  71. package/dist/pushed-config-error-overlay/index.d.ts +1 -1
  72. package/package.json +2 -2
  73. package/src/lib/hexclave-app/apps/implementations/admin-app-impl.ts +2 -0
  74. package/src/lib/hexclave-app/apps/implementations/client-app-impl.automatic-side-effects.test.ts +38 -1
  75. package/src/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.ts +2 -3
  76. package/src/lib/hexclave-app/apps/implementations/client-app-impl.sign-out.test.ts +96 -0
  77. package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +126 -24
  78. package/src/lib/hexclave-app/apps/implementations/client-app-impl.untrusted-redirect-card.test.ts +146 -0
  79. package/src/lib/hexclave-app/apps/implementations/common.ts +1 -1
  80. package/src/lib/hexclave-app/session-replays/index.ts +2 -0
  81. package/src/lib/hexclave-app/teams/index.ts +3 -0
  82. package/dist/admin-app-impl-B86v7B0O.d.ts.map +0 -1
  83. package/dist/client-app-WOX3pOo1.d.ts.map +0 -1
  84. package/dist/index-hYjsGKNc.d.ts.map +0 -1
@@ -0,0 +1,82 @@
1
+ let vitest = require("vitest");
2
+ let ___interfaces_client_app_js = require("../interfaces/client-app.js");
3
+ let _hexclave_shared_dist_utils_stores = require("@hexclave/shared/dist/utils/stores");
4
+ //#region src/lib/hexclave-app/apps/implementations/client-app-impl.sign-out.test.ts
5
+ function createAccessTokenString(refreshTokenId) {
6
+ const encode = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
7
+ const nowSeconds = Math.floor(Date.now() / 1e3);
8
+ return [
9
+ encode({
10
+ alg: "none",
11
+ typ: "JWT"
12
+ }),
13
+ encode({
14
+ sub: "user-id",
15
+ exp: nowSeconds + 60,
16
+ iat: nowSeconds,
17
+ refresh_token_id: refreshTokenId
18
+ }),
19
+ ""
20
+ ].join(".");
21
+ }
22
+ var Deferred = class {
23
+ constructor() {
24
+ this._resolve = () => {
25
+ throw new Error("Deferred promise was resolved before initialization");
26
+ };
27
+ this.promise = new Promise((resolve) => {
28
+ this._resolve = resolve;
29
+ });
30
+ }
31
+ resolve() {
32
+ this._resolve();
33
+ }
34
+ };
35
+ (0, vitest.describe)("StackClientApp sign-out", () => {
36
+ (0, vitest.it)("delays current-user reads until redirect dispatch without blocking unrelated stores", async () => {
37
+ const clientApp = new ___interfaces_client_app_js.StackClientApp({
38
+ baseUrl: "http://localhost:12345",
39
+ projectId: "00000000-0000-4000-8000-000000000000",
40
+ publishableClientKey: "stack-pk-test",
41
+ tokenStore: "memory",
42
+ redirectMethod: "none",
43
+ noAutomaticPrefetch: true,
44
+ devTool: false
45
+ });
46
+ const clientInterface = Reflect.get(clientApp, "_interface");
47
+ Reflect.set(clientInterface, "getClientUserByToken", async () => ({
48
+ id: "user-id",
49
+ is_anonymous: false,
50
+ is_restricted: false
51
+ }));
52
+ await Reflect.get(clientApp, "_signInToAccountWithTokens").call(clientApp, {
53
+ accessToken: createAccessTokenString("refresh-token-id"),
54
+ refreshToken: "refresh-token"
55
+ });
56
+ const createCookieHelper = Reflect.get(clientApp, "_createCookieHelper");
57
+ const getOrCreateTokenStore = Reflect.get(clientApp, "_getOrCreateTokenStore");
58
+ const getSessionFromTokenStore = Reflect.get(clientApp, "_getSessionFromTokenStore");
59
+ const tokenStore = getOrCreateTokenStore.call(clientApp, await createCookieHelper.call(clientApp));
60
+ const session = getSessionFromTokenStore.call(clientApp, tokenStore);
61
+ Reflect.set(clientInterface, "signOut", async () => {
62
+ session.markInvalid();
63
+ });
64
+ const redirectStarted = new Deferred();
65
+ const redirectFinished = new Deferred();
66
+ Reflect.set(clientApp, "_redirectToDefaultAfterSignOut", async () => {
67
+ redirectStarted.resolve();
68
+ await redirectFinished.promise;
69
+ });
70
+ (0, vitest.expect)(new _hexclave_shared_dist_utils_stores.AsyncStore().setAsync(new Promise(() => {}))).toBeInstanceOf(Promise);
71
+ const signOutPromise = Reflect.get(clientApp, "_signOut").call(clientApp, session);
72
+ await redirectStarted.promise;
73
+ const getUserDuringSignOut = clientApp.getUser();
74
+ (0, vitest.expect)(await Promise.race([getUserDuringSignOut.then(() => "resolved"), Promise.resolve("pending")])).toBe("pending");
75
+ redirectFinished.resolve();
76
+ await signOutPromise;
77
+ await (0, vitest.expect)(getUserDuringSignOut).resolves.toBeNull();
78
+ });
79
+ });
80
+ //#endregion
81
+
82
+ //# sourceMappingURL=client-app-impl.sign-out.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-app-impl.sign-out.test.js","names":["StackClientApp","AsyncStore"],"sources":["../../../../../src/lib/hexclave-app/apps/implementations/client-app-impl.sign-out.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 { AsyncStore } from \"@hexclave/shared/dist/utils/stores\";\nimport { describe, expect, it } from \"vitest\";\nimport { StackClientApp } from \"../interfaces/client-app\";\n\nfunction createAccessTokenString(refreshTokenId: string): string {\n const encode = (value: unknown) => Buffer.from(JSON.stringify(value)).toString(\"base64url\");\n const nowSeconds = Math.floor(Date.now() / 1000);\n return [\n encode({ alg: \"none\", typ: \"JWT\" }),\n encode({ sub: \"user-id\", exp: nowSeconds + 60, iat: nowSeconds, refresh_token_id: refreshTokenId }),\n \"\",\n ].join(\".\");\n}\n\nclass Deferred {\n readonly promise: Promise<void>;\n private _resolve: () => void = () => {\n throw new Error(\"Deferred promise was resolved before initialization\");\n };\n\n constructor() {\n this.promise = new Promise<void>((resolve) => {\n this._resolve = resolve;\n });\n }\n\n resolve(): void {\n this._resolve();\n }\n}\n\ndescribe(\"StackClientApp sign-out\", () => {\n it(\"delays current-user reads until redirect dispatch without blocking unrelated stores\", async () => {\n const clientApp = new StackClientApp({\n baseUrl: \"http://localhost:12345\",\n projectId: \"00000000-0000-4000-8000-000000000000\",\n publishableClientKey: \"stack-pk-test\",\n tokenStore: \"memory\",\n redirectMethod: \"none\",\n noAutomaticPrefetch: true,\n devTool: false,\n });\n const clientInterface = Reflect.get(clientApp, \"_interface\");\n Reflect.set(clientInterface, \"getClientUserByToken\", async () => ({\n id: \"user-id\",\n is_anonymous: false,\n is_restricted: false,\n }));\n\n const signInToAccountWithTokens = Reflect.get(clientApp, \"_signInToAccountWithTokens\");\n await signInToAccountWithTokens.call(clientApp, {\n accessToken: createAccessTokenString(\"refresh-token-id\"),\n refreshToken: \"refresh-token\",\n });\n\n const createCookieHelper = Reflect.get(clientApp, \"_createCookieHelper\");\n const getOrCreateTokenStore = Reflect.get(clientApp, \"_getOrCreateTokenStore\");\n const getSessionFromTokenStore = Reflect.get(clientApp, \"_getSessionFromTokenStore\");\n const tokenStore = getOrCreateTokenStore.call(clientApp, await createCookieHelper.call(clientApp));\n const session = getSessionFromTokenStore.call(clientApp, tokenStore);\n\n Reflect.set(clientInterface, \"signOut\", async () => {\n session.markInvalid();\n });\n\n const redirectStarted = new Deferred();\n const redirectFinished = new Deferred();\n Reflect.set(clientApp, \"_redirectToDefaultAfterSignOut\", async () => {\n redirectStarted.resolve();\n await redirectFinished.promise;\n });\n\n const unrelatedStore = new AsyncStore<void>();\n expect(unrelatedStore.setAsync(new Promise<void>(() => {}))).toBeInstanceOf(Promise);\n\n const signOut = Reflect.get(clientApp, \"_signOut\");\n const signOutPromise = signOut.call(clientApp, session);\n await redirectStarted.promise;\n\n const getUserDuringSignOut = clientApp.getUser();\n const stateBeforeRedirectFinished = await Promise.race([\n getUserDuringSignOut.then(() => \"resolved\"),\n Promise.resolve(\"pending\"),\n ]);\n expect(stateBeforeRedirectFinished).toBe(\"pending\");\n\n redirectFinished.resolve();\n await signOutPromise;\n\n await expect(getUserDuringSignOut).resolves.toBeNull();\n });\n});\n"],"mappings":";;;;AAQA,SAAS,wBAAwB,gBAAgC;CAC/D,MAAM,UAAU,UAAmB,OAAO,KAAK,KAAK,UAAU,KAAK,CAAC,CAAC,CAAC,SAAS,WAAW;CAC1F,MAAM,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;CAC/C,OAAO;EACL,OAAO;GAAE,KAAK;GAAQ,KAAK;EAAM,CAAC;EAClC,OAAO;GAAE,KAAK;GAAW,KAAK,aAAa;GAAI,KAAK;GAAY,kBAAkB;EAAe,CAAC;EAClG;CACF,CAAC,CAAC,KAAK,GAAG;AACZ;AAEA,IAAM,WAAN,MAAe;CAMb,cAAc;wBAJuB;GACnC,MAAM,IAAI,MAAM,qDAAqD;EACvE;EAGE,KAAK,UAAU,IAAI,SAAe,YAAY;GAC5C,KAAK,WAAW;EAClB,CAAC;CACH;CAEA,UAAgB;EACd,KAAK,SAAS;CAChB;AACF;qBAES,iCAAiC;CACxC,CAAA,GAAA,OAAA,GAAA,CAAG,uFAAuF,YAAY;EACpG,MAAM,YAAY,IAAIA,4BAAAA,eAAe;GACnC,SAAS;GACT,WAAW;GACX,sBAAsB;GACtB,YAAY;GACZ,gBAAgB;GAChB,qBAAqB;GACrB,SAAS;EACX,CAAC;EACD,MAAM,kBAAkB,QAAQ,IAAI,WAAW,YAAY;EAC3D,QAAQ,IAAI,iBAAiB,wBAAwB,aAAa;GAChE,IAAI;GACJ,cAAc;GACd,eAAe;EACjB,EAAE;EAGF,MADkC,QAAQ,IAAI,WAAW,4BAC3B,CAAC,CAAC,KAAK,WAAW;GAC9C,aAAa,wBAAwB,kBAAkB;GACvD,cAAc;EAChB,CAAC;EAED,MAAM,qBAAqB,QAAQ,IAAI,WAAW,qBAAqB;EACvE,MAAM,wBAAwB,QAAQ,IAAI,WAAW,wBAAwB;EAC7E,MAAM,2BAA2B,QAAQ,IAAI,WAAW,2BAA2B;EACnF,MAAM,aAAa,sBAAsB,KAAK,WAAW,MAAM,mBAAmB,KAAK,SAAS,CAAC;EACjG,MAAM,UAAU,yBAAyB,KAAK,WAAW,UAAU;EAEnE,QAAQ,IAAI,iBAAiB,WAAW,YAAY;GAClD,QAAQ,YAAY;EACtB,CAAC;EAED,MAAM,kBAAkB,IAAI,SAAS;EACrC,MAAM,mBAAmB,IAAI,SAAS;EACtC,QAAQ,IAAI,WAAW,kCAAkC,YAAY;GACnE,gBAAgB,QAAQ;GACxB,MAAM,iBAAiB;EACzB,CAAC;EAGD,CAAA,GAAA,OAAA,OAAA,CAAO,IADoBC,mCAAAA,WACP,CAAC,CAAC,SAAS,IAAI,cAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,OAAO;EAGnF,MAAM,iBADU,QAAQ,IAAI,WAAW,UACV,CAAC,CAAC,KAAK,WAAW,OAAO;EACtD,MAAM,gBAAgB;EAEtB,MAAM,uBAAuB,UAAU,QAAQ;EAK/C,CAAA,GAAA,OAAA,OAAA,CAAO,MAJmC,QAAQ,KAAK,CACrD,qBAAqB,WAAW,UAAU,GAC1C,QAAQ,QAAQ,SAAS,CAC3B,CAAC,CACiC,CAAC,CAAC,KAAK,SAAS;EAElD,iBAAiB,QAAQ;EACzB,MAAM;EAEN,OAAA,GAAA,OAAA,OAAA,CAAa,oBAAoB,CAAC,CAAC,SAAS,SAAS;CACvD,CAAC;AACH,CAAC"}
@@ -0,0 +1,119 @@
1
+ let _hexclave_shared_dist_utils_errors = require("@hexclave/shared/dist/utils/errors");
2
+ let vitest = require("vitest");
3
+ let _hexclave_shared = require("@hexclave/shared");
4
+ let ___interfaces_client_app_js = require("../interfaces/client-app.js");
5
+ let _hexclave_shared_dist_sessions = require("@hexclave/shared/dist/sessions");
6
+ let ____________setup_error_overlay_index_js = require("../../../../setup-error-overlay/index.js");
7
+ let ____________in_page_ui_dom_js = require("../../../../in-page-ui/dom.js");
8
+ //#region src/lib/hexclave-app/apps/implementations/client-app-impl.untrusted-redirect-card.test.ts
9
+ // @vitest-environment jsdom
10
+ function createAccessTokenString(refreshTokenId) {
11
+ const encode = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
12
+ const nowSeconds = Math.floor(Date.now() / 1e3);
13
+ return [
14
+ encode({
15
+ alg: "none",
16
+ typ: "JWT"
17
+ }),
18
+ encode({
19
+ sub: "user-id",
20
+ exp: nowSeconds + 60,
21
+ iat: nowSeconds,
22
+ iss: "https://api.example.test",
23
+ aud: "project-id",
24
+ project_id: "project-id",
25
+ branch_id: "main",
26
+ refresh_token_id: refreshTokenId,
27
+ role: "authenticated",
28
+ name: null,
29
+ email: null,
30
+ email_verified: false,
31
+ selected_team_id: null,
32
+ signed_up_at: nowSeconds,
33
+ is_anonymous: false,
34
+ is_restricted: false,
35
+ restricted_reason: null,
36
+ requires_totp_mfa: false
37
+ }),
38
+ ""
39
+ ].join(".");
40
+ }
41
+ function overlayRoots() {
42
+ return document.querySelectorAll(".hexclave-setup-error-overlay");
43
+ }
44
+ function createAppWithFailingHandoff(options) {
45
+ const app = new ___interfaces_client_app_js.StackClientApp({
46
+ baseUrl: "http://localhost:12345",
47
+ projectId: options.projectId,
48
+ publishableClientKey: "stack-pk-test",
49
+ tokenStore: "memory",
50
+ redirectMethod: "none",
51
+ noAutomaticPrefetch: true,
52
+ devTool: false
53
+ });
54
+ const accessToken = createAccessTokenString("source-refresh-token-id");
55
+ const clientInterface = Reflect.get(app, "_interface");
56
+ Reflect.set(clientInterface, "fetchNewAccessToken", async () => {
57
+ return _hexclave_shared_dist_sessions.AccessToken.createIfValid(accessToken) ?? (() => {
58
+ throw new Error("Expected the test access token to be valid.");
59
+ })();
60
+ });
61
+ Reflect.set(clientInterface, "sendClientRequest", options.sendClientRequest);
62
+ return app;
63
+ }
64
+ function createCrossDomainAuthRedirectUrl(app, redirectUri) {
65
+ const method = Reflect.get(app, "_createCrossDomainAuthRedirectUrl");
66
+ if (typeof method !== "function") throw new Error("Expected StackClientApp to expose _createCrossDomainAuthRedirectUrl in tests.");
67
+ return method.call(app, {
68
+ redirectUri,
69
+ state: "handoff-state",
70
+ codeChallenge: "abcdefghijklmnopqrstuvwxyzABCDEFG_0123456789-._~",
71
+ afterCallbackRedirectUrl: redirectUri,
72
+ overrideTokenStoreInit: {
73
+ accessToken: createAccessTokenString("source-refresh-token-id"),
74
+ refreshToken: "source-refresh-token"
75
+ }
76
+ });
77
+ }
78
+ (0, vitest.describe)("cross-domain handoff rejected by the server", () => {
79
+ (0, vitest.afterEach)(() => {
80
+ (0, ____________in_page_ui_dom_js.getGlobalUiInstance)(____________setup_error_overlay_index_js.SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY)?.cleanup();
81
+ (0, ____________in_page_ui_dom_js.setGlobalUiInstance)(____________setup_error_overlay_index_js.SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY, null);
82
+ for (const root of overlayRoots()) root.remove();
83
+ });
84
+ (0, vitest.it)("shows a setup error card even when the caller swallows the redirect failure", async () => {
85
+ const untrustedUrl = "https://demo.example.test/?hexclave_cross_domain_auth=1";
86
+ const app = createAppWithFailingHandoff({
87
+ projectId: "00000000-0000-4000-8000-000000000101",
88
+ sendClientRequest: async () => {
89
+ throw new _hexclave_shared.KnownErrors.RedirectUrlNotWhitelisted(untrustedUrl);
90
+ }
91
+ });
92
+ let caught = null;
93
+ try {
94
+ await createCrossDomainAuthRedirectUrl(app, untrustedUrl);
95
+ } catch (error) {
96
+ caught = error;
97
+ }
98
+ if (!_hexclave_shared_dist_utils_errors.HexclaveSetupError.isSetupError(caught)) throw new Error(`Expected the rejected handoff to throw a setup error, got: ${caught}`);
99
+ (0, vitest.expect)(caught.message).toBe("Cross-domain auth redirect URL https://demo.example.test/ is not trusted.");
100
+ (0, vitest.expect)(Reflect.get(caught, "customCaptureExtraArgs")).toMatchObject([{ url: untrustedUrl }]);
101
+ (0, vitest.expect)(caught.cause).toBeInstanceOf(_hexclave_shared.KnownErrors.RedirectUrlNotWhitelisted);
102
+ (0, vitest.expect)(overlayRoots()).toHaveLength(1);
103
+ const cardText = document.body.textContent;
104
+ (0, vitest.expect)(cardText).toContain("A domain in your authentication flow is not one of your project's trusted domains");
105
+ (0, vitest.expect)(cardText).toContain("add it to your project's trusted domains in the Hexclave dashboard, under Domains.");
106
+ });
107
+ (0, vitest.it)("leaves other handoff failures to captureError", async () => {
108
+ await (0, vitest.expect)(createCrossDomainAuthRedirectUrl(createAppWithFailingHandoff({
109
+ projectId: "00000000-0000-4000-8000-000000000102",
110
+ sendClientRequest: async () => {
111
+ throw new _hexclave_shared.KnownErrors.UserAuthenticationRequired();
112
+ }
113
+ }), "https://demo.example.test/")).rejects.toSatisfy((error) => _hexclave_shared.KnownErrors.UserAuthenticationRequired.isInstance(error));
114
+ (0, vitest.expect)(overlayRoots()).toHaveLength(0);
115
+ });
116
+ });
117
+ //#endregion
118
+
119
+ //# sourceMappingURL=client-app-impl.untrusted-redirect-card.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-app-impl.untrusted-redirect-card.test.js","names":["StackClientApp","AccessToken","SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY","KnownErrors","HexclaveSetupError"],"sources":["../../../../../src/lib/hexclave-app/apps/implementations/client-app-impl.untrusted-redirect-card.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//===========================================\n// @vitest-environment jsdom\n\nimport { KnownErrors } from \"@hexclave/shared\";\nimport { AccessToken } from \"@hexclave/shared/dist/sessions\";\nimport { HexclaveSetupError } from \"@hexclave/shared/dist/utils/errors\";\nimport { afterEach, describe, expect, it } from \"vitest\";\nimport { getGlobalUiInstance, setGlobalUiInstance } from \"../../../../in-page-ui/dom\";\nimport { SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY } from \"../../../../setup-error-overlay\";\nimport { StackClientApp } from \"../interfaces/client-app\";\n\nfunction createAccessTokenString(refreshTokenId: string): string {\n const encode = (value: unknown) => Buffer.from(JSON.stringify(value)).toString(\"base64url\");\n const nowSeconds = Math.floor(Date.now() / 1000);\n return [\n encode({ alg: \"none\", typ: \"JWT\" }),\n encode({\n sub: \"user-id\",\n exp: nowSeconds + 60,\n iat: nowSeconds,\n iss: \"https://api.example.test\",\n aud: \"project-id\",\n project_id: \"project-id\",\n branch_id: \"main\",\n refresh_token_id: refreshTokenId,\n role: \"authenticated\",\n name: null,\n email: null,\n email_verified: false,\n selected_team_id: null,\n signed_up_at: nowSeconds,\n is_anonymous: false,\n is_restricted: false,\n restricted_reason: null,\n requires_totp_mfa: false,\n }),\n \"\",\n ].join(\".\");\n}\n\nfunction overlayRoots(): NodeListOf<Element> {\n return document.querySelectorAll(\".hexclave-setup-error-overlay\");\n}\n\nfunction createAppWithFailingHandoff(options: {\n projectId: string,\n sendClientRequest: () => Promise<never>,\n}): StackClientApp<true> {\n const app = new StackClientApp({\n baseUrl: \"http://localhost:12345\",\n projectId: options.projectId,\n publishableClientKey: \"stack-pk-test\",\n tokenStore: \"memory\",\n redirectMethod: \"none\",\n noAutomaticPrefetch: true,\n devTool: false,\n });\n const accessToken = createAccessTokenString(\"source-refresh-token-id\");\n const clientInterface = Reflect.get(app, \"_interface\");\n Reflect.set(clientInterface, \"fetchNewAccessToken\", async () => {\n return AccessToken.createIfValid(accessToken) ?? (() => {\n throw new Error(\"Expected the test access token to be valid.\");\n })();\n });\n Reflect.set(clientInterface, \"sendClientRequest\", options.sendClientRequest);\n return app;\n}\n\nfunction createCrossDomainAuthRedirectUrl(app: StackClientApp<true>, redirectUri: string): Promise<unknown> {\n const method = Reflect.get(app, \"_createCrossDomainAuthRedirectUrl\");\n if (typeof method !== \"function\") {\n throw new Error(\"Expected StackClientApp to expose _createCrossDomainAuthRedirectUrl in tests.\");\n }\n return method.call(app, {\n redirectUri,\n state: \"handoff-state\",\n codeChallenge: \"abcdefghijklmnopqrstuvwxyzABCDEFG_0123456789-._~\",\n afterCallbackRedirectUrl: redirectUri,\n overrideTokenStoreInit: {\n accessToken: createAccessTokenString(\"source-refresh-token-id\"),\n refreshToken: \"source-refresh-token\",\n },\n });\n}\n\ndescribe(\"cross-domain handoff rejected by the server\", () => {\n afterEach(() => {\n // The card's own cleanup, so that the focus trap it installed is released too and does not follow the next test.\n getGlobalUiInstance(SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY)?.cleanup();\n setGlobalUiInstance(SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY, null);\n for (const root of overlayRoots()) {\n root.remove();\n }\n });\n\n it(\"shows a setup error card even when the caller swallows the redirect failure\", async () => {\n const untrustedUrl = \"https://demo.example.test/?hexclave_cross_domain_auth=1\";\n const app = createAppWithFailingHandoff({\n projectId: \"00000000-0000-4000-8000-000000000101\",\n sendClientRequest: async () => {\n throw new KnownErrors.RedirectUrlNotWhitelisted(untrustedUrl);\n },\n });\n\n // The hosted auth pages catch a failing post-auth redirect and render their own \"we could not continue\n // automatically, please try again\" screen, which is exactly how this error used to disappear: nothing on the page\n // said that the flow is dead until a domain is added to the project's trusted domains.\n let caught: unknown = null;\n try {\n await createCrossDomainAuthRedirectUrl(app, untrustedUrl);\n } catch (error) {\n caught = error;\n }\n\n if (!HexclaveSetupError.isSetupError(caught)) {\n throw new Error(`Expected the rejected handoff to throw a setup error, got: ${caught}`);\n }\n // The handoff query parameters have nothing to do with the rejection, so the message keeps only the checked part.\n expect(caught.message).toBe(\"Cross-domain auth redirect URL https://demo.example.test/ is not trusted.\");\n // The full URL is still handed to the error sinks, which is where `customCaptureExtraArgs` ends up.\n expect(Reflect.get(caught, \"customCaptureExtraArgs\")).toMatchObject([{ url: untrustedUrl }]);\n expect(caught.cause).toBeInstanceOf(KnownErrors.RedirectUrlNotWhitelisted);\n\n expect(overlayRoots()).toHaveLength(1);\n const cardText = document.body.textContent;\n expect(cardText).toContain(\"A domain in your authentication flow is not one of your project's trusted domains\");\n expect(cardText).toContain(\"add it to your project's trusted domains in the Hexclave dashboard, under Domains.\");\n });\n\n it(\"leaves other handoff failures to captureError\", async () => {\n const app = createAppWithFailingHandoff({\n projectId: \"00000000-0000-4000-8000-000000000102\",\n sendClientRequest: async () => {\n throw new KnownErrors.UserAuthenticationRequired();\n },\n });\n\n await expect(createCrossDomainAuthRedirectUrl(app, \"https://demo.example.test/\")).rejects.toSatisfy(\n (error: unknown) => KnownErrors.UserAuthenticationRequired.isInstance(error),\n );\n expect(overlayRoots()).toHaveLength(0);\n });\n});\n"],"mappings":"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"}
@@ -13,8 +13,8 @@ let ______url_targets_js = require("../../url-targets.js");
13
13
  let _hexclave_shared_dist_utils_caches = require("@hexclave/shared/dist/utils/caches");
14
14
  let _hexclave_shared_dist_utils_globals = require("@hexclave/shared/dist/utils/globals");
15
15
  //#region src/lib/hexclave-app/apps/implementations/common.ts
16
- const clientVersion = "js @hexclave/js@1.0.76";
17
- if ("js @hexclave/js@1.0.76".startsWith("STACK_COMPILE_TIME"));
16
+ const clientVersion = "js @hexclave/js@1.0.78";
17
+ if ("js @hexclave/js@1.0.78".startsWith("STACK_COMPILE_TIME"));
18
18
  const replaceHexclavePortPrefix = (input) => {
19
19
  if (!input) return input;
20
20
  const prefix = ____________generated_env_js.envVars.HEXCLAVE_PORT_PREFIX;
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","names":["HexclaveAssertionError","envVars","AsyncCache","Result","hexclaveAppInternalsSymbol","Store"],"sources":["../../../../../src/lib/hexclave-app/apps/implementations/common.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 { InternalSession } from \"@hexclave/shared/dist/sessions\";\nimport { AsyncCache } from \"@hexclave/shared/dist/utils/caches\";\nimport { isBrowserLike } from \"@hexclave/shared/dist/utils/env\";\nimport { HexclaveAssertionError, captureError, concatStacktraces, throwErr } from \"@hexclave/shared/dist/utils/errors\";\nimport { createGlobal, getGlobal } from \"@hexclave/shared/dist/utils/globals\";\nimport { filterUndefined, omit } from \"@hexclave/shared/dist/utils/objects\";\nimport { ReactPromise, runAsynchronously } from \"@hexclave/shared/dist/utils/promises\";\nimport { suspendIfSsr, use } from \"@hexclave/shared/dist/utils/react\";\nimport { Result } from \"@hexclave/shared/dist/utils/results\";\nimport { Store } from \"@hexclave/shared/dist/utils/stores\";\nimport { deindent } from \"@hexclave/shared/dist/utils/strings\";\nimport { getDefaultApiUrls } from \"@hexclave/shared/dist/utils/urls\";\nimport { envVars } from \"../../../../generated/env\";\nimport { HandlerUrlOptions, ResolvedHandlerUrls, hexclaveAppInternalsSymbol } from \"../../common\";\nimport { resolveHandlerUrls } from \"../../url-targets\";\n\nexport const clientVersion = \"STACK_COMPILE_TIME_CLIENT_PACKAGE_VERSION_SENTINEL\";\nif (clientVersion.startsWith(\"STACK_COMPILE_TIME\")) {\n throw new HexclaveAssertionError(\"Client version was not replaced. Something went wrong during build!\");\n}\n\nconst replaceHexclavePortPrefix = <T extends string | undefined>(input: T): T => {\n if (!input) return input;\n const prefix = envVars.HEXCLAVE_PORT_PREFIX;\n return prefix ? input.replace(/\\$\\{NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81\\}/g, prefix) as T : input;\n};\n\nconst showMissingConfigAlertInBrowser = (message: string) => {\n if (!isBrowserLike()) return;\n\n const global = globalThis as any;\n const alertAlreadyShownKey = \"__hexclave_missing_config_alert_already_shown\";\n if (global[alertAlreadyShownKey]) return;\n global[alertAlreadyShownKey] = true;\n\n const alertFn = global.alert;\n if (typeof alertFn === \"function\") {\n alertFn(message);\n }\n};\n\nconst throwMissingProjectIdError = (): never => {\n const message = deindent`\n Welcome to Hexclave!\n \n It seems that you haven't provided a project ID.\n\n ${envVars.NODE_ENV?.includes(\"dev\") ? deindent`\n You are running this app in development mode. Make sure that your start command is wrapped in a call to the Hexclave CLI: \\`npx @hexclave/cli dev --config-file <file> -- <command>\\`\n\n Alternatively, you can also connect to a Cloud project's environment variables instead by creating a project on the Hexclave dashboard at https://app.hexclave.com and put its information in the HEXCLAVE_PROJECT_ID environment variable.\n ` : envVars.NODE_ENV?.includes(\"prod\") ? deindent`\n It seems you are running a project in production. Please create a project on the Hexclave dashboard at https://app.hexclave.com and put it in the HEXCLAVE_PROJECT_ID environment variable.\n ` : deindent`\n - If you are running a development project and would like to connect the local Hexclave dashboard, wrap your start command in: \\`npx @hexclave/cli dev --config-file <file> -- <command>\\`\n\n - If you are running a project in production and would like to connect to Hexclave Cloud, create a project on the Hexclave dashboard at https://app.hexclave.com and put its information in the HEXCLAVE_PROJECT_ID environment variable.\n `}\n `;\n showMissingConfigAlertInBrowser(message);\n return throwErr(new Error(message));\n};\n\n\nexport const createCache = <D extends any[], T>(fetcher: (dependencies: D) => Promise<T>) => {\n return new AsyncCache<D, Result<T>>(\n async (dependencies) => await Result.fromThrowingAsync(async () => await fetcher(dependencies)),\n {},\n );\n};\n\nexport const createCacheBySession = <D extends any[], T>(fetcher: (session: InternalSession, extraDependencies: D) => Promise<T> ) => {\n return new AsyncCache<[InternalSession, ...D], Result<T>>(\n async ([session, ...extraDependencies]) => await Result.fromThrowingAsync(async () => await fetcher(session, extraDependencies)),\n {\n onSubscribe: ([session], refresh) => {\n const handler = session.onInvalidate(() => refresh());\n return () => handler.unsubscribe();\n },\n },\n );\n};\n\n\ntype AppLike = { [hexclaveAppInternalsSymbol]: { getConstructorOptions: () => any } };\nexport function resolveConstructorOptions<T extends { inheritsFrom?: AppLike }>(options: T): T & { inheritsFrom?: undefined } {\n return {\n ...options.inheritsFrom?.[hexclaveAppInternalsSymbol].getConstructorOptions() ?? {},\n ...filterUndefined(omit(options, [\"inheritsFrom\"])),\n };\n}\n\nexport function getUrls(partial: HandlerUrlOptions, options: { projectId: string }): ResolvedHandlerUrls {\n return resolveHandlerUrls({\n urls: partial,\n projectId: options.projectId,\n });\n}\n\nexport function getDefaultProjectId() {\n return envVars.HEXCLAVE_PROJECT_ID || throwMissingProjectIdError();\n}\n\nexport function getDefaultPublishableClientKey() {\n return envVars.HEXCLAVE_PUBLISHABLE_CLIENT_KEY;\n}\n\nexport function getDefaultSecretServerKey() {\n return envVars.HEXCLAVE_SECRET_SERVER_KEY || throwErr(new Error(\"No secret server key provided. Please copy your key from the Hexclave dashboard and put it in the HEXCLAVE_SECRET_SERVER_KEY environment variable.\"));\n}\n\nexport function getDefaultSuperSecretAdminKey() {\n return envVars.HEXCLAVE_SUPER_SECRET_ADMIN_KEY || throwErr(new Error(\"No super secret admin key provided. Please copy your key from the Hexclave dashboard and put it in the HEXCLAVE_SUPER_SECRET_ADMIN_KEY environment variable.\"));\n}\n\nexport function getDefaultExtraRequestHeaders() {\n return JSON.parse(envVars.HEXCLAVE_EXTRA_REQUEST_HEADERS || '{}');\n}\n\n/**\n * Returns the base URL for the Stack API.\n *\n * The URL can be specified in several ways, in order of precedence:\n * 1. Directly through userSpecifiedBaseUrl parameter as string or browser/server object\n * 2. Through environment variables:\n * - Browser: NEXT_PUBLIC_HEXCLAVE_API_URL_BROWSER/VITE_HEXCLAVE_API_URL_BROWSER\n * - Server: HEXCLAVE_API_URL_SERVER\n * - Default: HEXCLAVE_API_URL\n * 3. Default base URL if none of the above are specified\n *\n * The function also ensures the URL doesn't end with a trailing slash\n * by removing it if present.\n *\n * @param userSpecifiedBaseUrl - Optional URL override as string or {browser, server} object\n * @returns The configured base URL without trailing slash\n\n */\nexport function getBaseUrl(userSpecifiedBaseUrl: string | { browser: string, server: string } | undefined) {\n let url;\n if (userSpecifiedBaseUrl) {\n if (typeof userSpecifiedBaseUrl === \"string\") {\n url = userSpecifiedBaseUrl;\n } else {\n if (isBrowserLike()) {\n url = userSpecifiedBaseUrl.browser;\n } else {\n url = userSpecifiedBaseUrl.server;\n }\n }\n } else {\n if (isBrowserLike()) {\n url = envVars.HEXCLAVE_API_URL_BROWSER;\n } else {\n url = envVars.HEXCLAVE_API_URL_SERVER;\n }\n url = url || envVars.HEXCLAVE_API_URL || defaultBaseUrl;\n }\n\n return replaceHexclavePortPrefix(url.endsWith('/') ? url.slice(0, -1) : url);\n}\n\nexport const defaultBaseUrl = \"https://api.hexclave.com\";\nexport const defaultAnalyticsBaseUrl = \"https://r.hexclave.com\";\n\nconst analyticsBaseUrlsByApiBaseUrl = new Map<string, string>([\n [defaultBaseUrl, defaultAnalyticsBaseUrl],\n [\"https://api.stack-auth.com\", \"https://r.stack-auth.com\"],\n]);\n\nexport function getAnalyticsBaseUrl(regularBaseUrl: string): string {\n return analyticsBaseUrlsByApiBaseUrl.get(regularBaseUrl) ?? regularBaseUrl;\n}\n\n\nfunction fetchBackendUrlsInBackground(primaryBaseUrl: string): void {\n createGlobal('__stack-fetch-backend-urls-started', () => {\n runAsynchronously(async () => {\n try {\n const res = await fetch(`${primaryBaseUrl}/api/v1/internal/backend-urls`);\n if (!res.ok) {\n return;\n }\n const data = await res.json();\n if (!Array.isArray(data.urls) || !data.urls.every((u: unknown) => typeof u === 'string')) {\n return;\n }\n createGlobal('__stack-fetched-backend-urls', () => data.urls as string[]);\n } catch (e) {\n captureError('fetch-backend-urls-in-background', e);\n }\n });\n return true;\n });\n}\n\nexport function resolveApiUrls(userExplicitBaseUrl: string | { browser: string, server: string } | undefined): () => string[] {\n return () => {\n if (userExplicitBaseUrl != null) {\n return [getBaseUrl(userExplicitBaseUrl)];\n }\n const primary = getBaseUrl(undefined);\n // Always try to fetch server-configured URLs (supports custom domains via\n // STACK_BACKEND_URLS_CONFIG). Hardcoded fallbacks are used as a default\n // until the background fetch completes.\n fetchBackendUrlsInBackground(primary);\n return getGlobal('__stack-fetched-backend-urls') ?? getDefaultApiUrls(primary);\n };\n}\n\nexport type TokenObject = {\n accessToken: string | null,\n refreshToken: string | null,\n};\n\nexport function createEmptyTokenStore() {\n return new Store<TokenObject>({\n refreshToken: null,\n accessToken: null,\n });\n}\n\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"common.js","names":["HexclaveAssertionError","envVars","AsyncCache","Result","hexclaveAppInternalsSymbol","Store"],"sources":["../../../../../src/lib/hexclave-app/apps/implementations/common.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 { InternalSession } from \"@hexclave/shared/dist/sessions\";\nimport { AsyncCache } from \"@hexclave/shared/dist/utils/caches\";\nimport { isBrowserLike } from \"@hexclave/shared/dist/utils/env\";\nimport { HexclaveAssertionError, captureError, concatStacktraces, throwErr } from \"@hexclave/shared/dist/utils/errors\";\nimport { createGlobal, getGlobal } from \"@hexclave/shared/dist/utils/globals\";\nimport { filterUndefined, omit } from \"@hexclave/shared/dist/utils/objects\";\nimport { ReactPromise, runAsynchronously } from \"@hexclave/shared/dist/utils/promises\";\nimport { use } from \"@hexclave/shared/dist/utils/react\";\nimport { Result } from \"@hexclave/shared/dist/utils/results\";\nimport { Store } from \"@hexclave/shared/dist/utils/stores\";\nimport { deindent } from \"@hexclave/shared/dist/utils/strings\";\nimport { getDefaultApiUrls } from \"@hexclave/shared/dist/utils/urls\";\nimport { envVars } from \"../../../../generated/env\";\nimport { HandlerUrlOptions, ResolvedHandlerUrls, hexclaveAppInternalsSymbol } from \"../../common\";\nimport { resolveHandlerUrls } from \"../../url-targets\";\n\nexport const clientVersion = \"STACK_COMPILE_TIME_CLIENT_PACKAGE_VERSION_SENTINEL\";\nif (clientVersion.startsWith(\"STACK_COMPILE_TIME\")) {\n throw new HexclaveAssertionError(\"Client version was not replaced. Something went wrong during build!\");\n}\n\nconst replaceHexclavePortPrefix = <T extends string | undefined>(input: T): T => {\n if (!input) return input;\n const prefix = envVars.HEXCLAVE_PORT_PREFIX;\n return prefix ? input.replace(/\\$\\{NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81\\}/g, prefix) as T : input;\n};\n\nconst showMissingConfigAlertInBrowser = (message: string) => {\n if (!isBrowserLike()) return;\n\n const global = globalThis as any;\n const alertAlreadyShownKey = \"__hexclave_missing_config_alert_already_shown\";\n if (global[alertAlreadyShownKey]) return;\n global[alertAlreadyShownKey] = true;\n\n const alertFn = global.alert;\n if (typeof alertFn === \"function\") {\n alertFn(message);\n }\n};\n\nconst throwMissingProjectIdError = (): never => {\n const message = deindent`\n Welcome to Hexclave!\n \n It seems that you haven't provided a project ID.\n\n ${envVars.NODE_ENV?.includes(\"dev\") ? deindent`\n You are running this app in development mode. Make sure that your start command is wrapped in a call to the Hexclave CLI: \\`npx @hexclave/cli dev --config-file <file> -- <command>\\`\n\n Alternatively, you can also connect to a Cloud project's environment variables instead by creating a project on the Hexclave dashboard at https://app.hexclave.com and put its information in the HEXCLAVE_PROJECT_ID environment variable.\n ` : envVars.NODE_ENV?.includes(\"prod\") ? deindent`\n It seems you are running a project in production. Please create a project on the Hexclave dashboard at https://app.hexclave.com and put it in the HEXCLAVE_PROJECT_ID environment variable.\n ` : deindent`\n - If you are running a development project and would like to connect the local Hexclave dashboard, wrap your start command in: \\`npx @hexclave/cli dev --config-file <file> -- <command>\\`\n\n - If you are running a project in production and would like to connect to Hexclave Cloud, create a project on the Hexclave dashboard at https://app.hexclave.com and put its information in the HEXCLAVE_PROJECT_ID environment variable.\n `}\n `;\n showMissingConfigAlertInBrowser(message);\n return throwErr(new Error(message));\n};\n\n\nexport const createCache = <D extends any[], T>(fetcher: (dependencies: D) => Promise<T>) => {\n return new AsyncCache<D, Result<T>>(\n async (dependencies) => await Result.fromThrowingAsync(async () => await fetcher(dependencies)),\n {},\n );\n};\n\nexport const createCacheBySession = <D extends any[], T>(fetcher: (session: InternalSession, extraDependencies: D) => Promise<T> ) => {\n return new AsyncCache<[InternalSession, ...D], Result<T>>(\n async ([session, ...extraDependencies]) => await Result.fromThrowingAsync(async () => await fetcher(session, extraDependencies)),\n {\n onSubscribe: ([session], refresh) => {\n const handler = session.onInvalidate(() => refresh());\n return () => handler.unsubscribe();\n },\n },\n );\n};\n\n\ntype AppLike = { [hexclaveAppInternalsSymbol]: { getConstructorOptions: () => any } };\nexport function resolveConstructorOptions<T extends { inheritsFrom?: AppLike }>(options: T): T & { inheritsFrom?: undefined } {\n return {\n ...options.inheritsFrom?.[hexclaveAppInternalsSymbol].getConstructorOptions() ?? {},\n ...filterUndefined(omit(options, [\"inheritsFrom\"])),\n };\n}\n\nexport function getUrls(partial: HandlerUrlOptions, options: { projectId: string }): ResolvedHandlerUrls {\n return resolveHandlerUrls({\n urls: partial,\n projectId: options.projectId,\n });\n}\n\nexport function getDefaultProjectId() {\n return envVars.HEXCLAVE_PROJECT_ID || throwMissingProjectIdError();\n}\n\nexport function getDefaultPublishableClientKey() {\n return envVars.HEXCLAVE_PUBLISHABLE_CLIENT_KEY;\n}\n\nexport function getDefaultSecretServerKey() {\n return envVars.HEXCLAVE_SECRET_SERVER_KEY || throwErr(new Error(\"No secret server key provided. Please copy your key from the Hexclave dashboard and put it in the HEXCLAVE_SECRET_SERVER_KEY environment variable.\"));\n}\n\nexport function getDefaultSuperSecretAdminKey() {\n return envVars.HEXCLAVE_SUPER_SECRET_ADMIN_KEY || throwErr(new Error(\"No super secret admin key provided. Please copy your key from the Hexclave dashboard and put it in the HEXCLAVE_SUPER_SECRET_ADMIN_KEY environment variable.\"));\n}\n\nexport function getDefaultExtraRequestHeaders() {\n return JSON.parse(envVars.HEXCLAVE_EXTRA_REQUEST_HEADERS || '{}');\n}\n\n/**\n * Returns the base URL for the Stack API.\n *\n * The URL can be specified in several ways, in order of precedence:\n * 1. Directly through userSpecifiedBaseUrl parameter as string or browser/server object\n * 2. Through environment variables:\n * - Browser: NEXT_PUBLIC_HEXCLAVE_API_URL_BROWSER/VITE_HEXCLAVE_API_URL_BROWSER\n * - Server: HEXCLAVE_API_URL_SERVER\n * - Default: HEXCLAVE_API_URL\n * 3. Default base URL if none of the above are specified\n *\n * The function also ensures the URL doesn't end with a trailing slash\n * by removing it if present.\n *\n * @param userSpecifiedBaseUrl - Optional URL override as string or {browser, server} object\n * @returns The configured base URL without trailing slash\n\n */\nexport function getBaseUrl(userSpecifiedBaseUrl: string | { browser: string, server: string } | undefined) {\n let url;\n if (userSpecifiedBaseUrl) {\n if (typeof userSpecifiedBaseUrl === \"string\") {\n url = userSpecifiedBaseUrl;\n } else {\n if (isBrowserLike()) {\n url = userSpecifiedBaseUrl.browser;\n } else {\n url = userSpecifiedBaseUrl.server;\n }\n }\n } else {\n if (isBrowserLike()) {\n url = envVars.HEXCLAVE_API_URL_BROWSER;\n } else {\n url = envVars.HEXCLAVE_API_URL_SERVER;\n }\n url = url || envVars.HEXCLAVE_API_URL || defaultBaseUrl;\n }\n\n return replaceHexclavePortPrefix(url.endsWith('/') ? url.slice(0, -1) : url);\n}\n\nexport const defaultBaseUrl = \"https://api.hexclave.com\";\nexport const defaultAnalyticsBaseUrl = \"https://r.hexclave.com\";\n\nconst analyticsBaseUrlsByApiBaseUrl = new Map<string, string>([\n [defaultBaseUrl, defaultAnalyticsBaseUrl],\n [\"https://api.stack-auth.com\", \"https://r.stack-auth.com\"],\n]);\n\nexport function getAnalyticsBaseUrl(regularBaseUrl: string): string {\n return analyticsBaseUrlsByApiBaseUrl.get(regularBaseUrl) ?? regularBaseUrl;\n}\n\n\nfunction fetchBackendUrlsInBackground(primaryBaseUrl: string): void {\n createGlobal('__stack-fetch-backend-urls-started', () => {\n runAsynchronously(async () => {\n try {\n const res = await fetch(`${primaryBaseUrl}/api/v1/internal/backend-urls`);\n if (!res.ok) {\n return;\n }\n const data = await res.json();\n if (!Array.isArray(data.urls) || !data.urls.every((u: unknown) => typeof u === 'string')) {\n return;\n }\n createGlobal('__stack-fetched-backend-urls', () => data.urls as string[]);\n } catch (e) {\n captureError('fetch-backend-urls-in-background', e);\n }\n });\n return true;\n });\n}\n\nexport function resolveApiUrls(userExplicitBaseUrl: string | { browser: string, server: string } | undefined): () => string[] {\n return () => {\n if (userExplicitBaseUrl != null) {\n return [getBaseUrl(userExplicitBaseUrl)];\n }\n const primary = getBaseUrl(undefined);\n // Always try to fetch server-configured URLs (supports custom domains via\n // STACK_BACKEND_URLS_CONFIG). Hardcoded fallbacks are used as a default\n // until the background fetch completes.\n fetchBackendUrlsInBackground(primary);\n return getGlobal('__stack-fetched-backend-urls') ?? getDefaultApiUrls(primary);\n };\n}\n\nexport type TokenObject = {\n accessToken: string | null,\n refreshToken: string | null,\n};\n\nexport function createEmptyTokenStore() {\n return new Store<TokenObject>({\n refreshToken: null,\n accessToken: null,\n });\n}\n\n\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { n as _HexclaveServerAppImplIncomplete, r as _HexclaveClientAppImplIncomplete, t as _HexclaveAdminAppImplIncomplete } from "../../../../admin-app-impl-B86v7B0O.js";
1
+ import { n as _HexclaveServerAppImplIncomplete, r as _HexclaveClientAppImplIncomplete, t as _HexclaveAdminAppImplIncomplete } from "../../../../admin-app-impl-DOGMiOUL.js";
2
2
 
3
3
  //#region src/lib/hexclave-app/apps/implementations/index.d.ts
4
4
  declare const _HexclaveAdminAppImpl: typeof _HexclaveAdminAppImplIncomplete, _HexclaveClientAppImpl: typeof _HexclaveClientAppImplIncomplete, _HexclaveServerAppImpl: typeof _HexclaveServerAppImplIncomplete;
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let __server_app_impl_js = require("./server-app-impl.js");
3
+ let __client_app_impl_js = require("./client-app-impl.js");
3
4
  let _hexclave_shared_dist_utils_compile_time = require("@hexclave/shared/dist/utils/compile-time");
4
5
  let __admin_app_impl_js = require("./admin-app-impl.js");
5
- let __client_app_impl_js = require("./client-app-impl.js");
6
6
  //#region src/lib/hexclave-app/apps/implementations/index.ts
7
7
  /**
8
8
  * Prevents a circular dependency between the client and admin apps. For more information, see the documentation comment
@@ -1,2 +1,2 @@
1
- import { n as _HexclaveServerAppImplIncomplete } from "../../../../admin-app-impl-B86v7B0O.js";
1
+ import { n as _HexclaveServerAppImplIncomplete } from "../../../../admin-app-impl-DOGMiOUL.js";
2
2
  export { _HexclaveServerAppImplIncomplete };
@@ -3,6 +3,7 @@ let _hexclave_shared_dist_utils_errors = require("@hexclave/shared/dist/utils/er
3
3
  let _hexclave_shared = require("@hexclave/shared");
4
4
  let _hexclave_shared_dist_utils_results = require("@hexclave/shared/dist/utils/results");
5
5
  let __common_js = require("./common.js");
6
+ let __client_app_impl_js = require("./client-app-impl.js");
6
7
  let _hexclave_shared_dist_sessions = require("@hexclave/shared/dist/sessions");
7
8
  let _hexclave_shared_dist_utils_uuids = require("@hexclave/shared/dist/utils/uuids");
8
9
  let _simplewebauthn_browser = require("@simplewebauthn/browser");
@@ -12,7 +13,6 @@ let ______contact_channels_index_js = require("../../contact-channels/index.js")
12
13
  let ______teams_index_js = require("../../teams/index.js");
13
14
  let ______passkey_rp_id_js = require("../../passkey-rp-id.js");
14
15
  let ______users_index_js = require("../../users/index.js");
15
- let __client_app_impl_js = require("./client-app-impl.js");
16
16
  //#region src/lib/hexclave-app/apps/implementations/server-app-impl.ts
17
17
  var _HexclaveServerAppImplIncomplete = class extends __client_app_impl_js._HexclaveClientAppImplIncomplete {
18
18
  async _refreshTeamMembership(teamId, userId) {
@@ -1,2 +1,2 @@
1
- import { B as StackServerAppConstructor, D as HexclaveAdminApp, F as StackAdminAppConstructorOptions, I as HexclaveServerApp, L as HexclaveServerAppConstructor, N as StackAdminApp, O as HexclaveAdminAppConstructor, P as StackAdminAppConstructor, R as HexclaveServerAppConstructorOptions, V as StackServerAppConstructorOptions, a as StackClientApp, c as StackClientAppJson, i as HexclaveClientAppJson, k as HexclaveAdminAppConstructorOptions, n as HexclaveClientAppConstructor, o as StackClientAppConstructor, r as HexclaveClientAppConstructorOptions, s as StackClientAppConstructorOptions, t as HexclaveClientApp, z as StackServerApp } from "../../../client-app-WOX3pOo1.js";
1
+ import { B as StackServerAppConstructor, D as HexclaveAdminApp, F as StackAdminAppConstructorOptions, I as HexclaveServerApp, L as HexclaveServerAppConstructor, N as StackAdminApp, O as HexclaveAdminAppConstructor, P as StackAdminAppConstructor, R as HexclaveServerAppConstructorOptions, V as StackServerAppConstructorOptions, a as StackClientApp, c as StackClientAppJson, i as HexclaveClientAppJson, k as HexclaveAdminAppConstructorOptions, n as HexclaveClientAppConstructor, o as StackClientAppConstructor, r as HexclaveClientAppConstructorOptions, s as StackClientAppConstructorOptions, t as HexclaveClientApp, z as StackServerApp } from "../../../client-app-Dj2NuO6C.js";
2
2
  export { HexclaveAdminApp, type HexclaveAdminAppConstructor, type HexclaveAdminAppConstructorOptions, HexclaveClientApp, type HexclaveClientAppConstructor, type HexclaveClientAppConstructorOptions, type HexclaveClientAppJson, HexclaveServerApp, type HexclaveServerAppConstructor, type HexclaveServerAppConstructorOptions, StackAdminApp, type StackAdminAppConstructor, type StackAdminAppConstructorOptions, StackClientApp, type StackClientAppConstructor, type StackClientAppConstructorOptions, type StackClientAppJson, StackServerApp, type StackServerAppConstructor, type StackServerAppConstructorOptions };
@@ -1,4 +1,4 @@
1
1
  import { a as AdminWorkflowRunState, c as AdminWorkflowStepAttempt, d as AdminWorkflowUpgradeResult, f as AdminWorkflowVersion, i as AdminWorkflowRunDetails, l as AdminWorkflowSyncResult, n as AdminWorkflowDivergenceDiagnostic, o as AdminWorkflowRunsFilter, r as AdminWorkflowRun, s as AdminWorkflowStep, t as AdminWorkflow, u as AdminWorkflowTrigger } from "../../../../workflows-DEb7pIuQ.js";
2
- import { A as ManagedEmailProviderListItem, D as HexclaveAdminApp, E as EmailOutboxUpdateOptions, F as StackAdminAppConstructorOptions, M as ManagedEmailProviderStatus, N as StackAdminApp, O as HexclaveAdminAppConstructor, P as StackAdminAppConstructor, T as EmailOutboxListResult, j as ManagedEmailProviderSetupResult, k as HexclaveAdminAppConstructorOptions, w as EmailOutboxListOptions } from "../../../../client-app-WOX3pOo1.js";
3
- import { a as ListSessionReplaysOptions, i as ListSessionReplayChunksResult, n as AdminSessionReplayChunk, o as ListSessionReplaysResult, r as ListSessionReplayChunksOptions, s as SessionReplayAllEventsResult, t as AdminSessionReplay } from "../../../../index-hYjsGKNc.js";
2
+ import { A as ManagedEmailProviderListItem, D as HexclaveAdminApp, E as EmailOutboxUpdateOptions, F as StackAdminAppConstructorOptions, M as ManagedEmailProviderStatus, N as StackAdminApp, O as HexclaveAdminAppConstructor, P as StackAdminAppConstructor, T as EmailOutboxListResult, j as ManagedEmailProviderSetupResult, k as HexclaveAdminAppConstructorOptions, w as EmailOutboxListOptions } from "../../../../client-app-Dj2NuO6C.js";
3
+ import { a as ListSessionReplaysOptions, i as ListSessionReplayChunksResult, n as AdminSessionReplayChunk, o as ListSessionReplaysResult, r as ListSessionReplayChunksOptions, s as SessionReplayAllEventsResult, t as AdminSessionReplay } from "../../../../index-Cf1wOohp.js";
4
4
  export { type AdminSessionReplay, type AdminSessionReplayChunk, type AdminWorkflow, type AdminWorkflowDivergenceDiagnostic, type AdminWorkflowRun, type AdminWorkflowRunDetails, type AdminWorkflowRunState, type AdminWorkflowRunsFilter, type AdminWorkflowStep, type AdminWorkflowStepAttempt, type AdminWorkflowSyncResult, type AdminWorkflowTrigger, type AdminWorkflowUpgradeResult, type AdminWorkflowVersion, EmailOutboxListOptions, EmailOutboxListResult, EmailOutboxUpdateOptions, HexclaveAdminApp, HexclaveAdminAppConstructor, HexclaveAdminAppConstructorOptions, type ListSessionReplayChunksOptions, type ListSessionReplayChunksResult, type ListSessionReplaysOptions, type ListSessionReplaysResult, ManagedEmailProviderListItem, ManagedEmailProviderSetupResult, ManagedEmailProviderStatus, type SessionReplayAllEventsResult, StackAdminApp, StackAdminAppConstructor, StackAdminAppConstructorOptions };
@@ -1,2 +1,2 @@
1
- import { a as StackClientApp, c as StackClientAppJson, i as HexclaveClientAppJson, n as HexclaveClientAppConstructor, o as StackClientAppConstructor, r as HexclaveClientAppConstructorOptions, s as StackClientAppConstructorOptions, t as HexclaveClientApp } from "../../../../client-app-WOX3pOo1.js";
1
+ import { a as StackClientApp, c as StackClientAppJson, i as HexclaveClientAppJson, n as HexclaveClientAppConstructor, o as StackClientAppConstructor, r as HexclaveClientAppConstructorOptions, s as StackClientAppConstructorOptions, t as HexclaveClientApp } from "../../../../client-app-Dj2NuO6C.js";
2
2
  export { HexclaveClientApp, HexclaveClientAppConstructor, HexclaveClientAppConstructorOptions, HexclaveClientAppJson, StackClientApp, StackClientAppConstructor, StackClientAppConstructorOptions, StackClientAppJson };
@@ -1,2 +1,2 @@
1
- import { B as StackServerAppConstructor, I as HexclaveServerApp, L as HexclaveServerAppConstructor, R as HexclaveServerAppConstructorOptions, V as StackServerAppConstructorOptions, z as StackServerApp } from "../../../../client-app-WOX3pOo1.js";
1
+ import { B as StackServerAppConstructor, I as HexclaveServerApp, L as HexclaveServerAppConstructor, R as HexclaveServerAppConstructorOptions, V as StackServerAppConstructorOptions, z as StackServerApp } from "../../../../client-app-Dj2NuO6C.js";
2
2
  export { HexclaveServerApp, HexclaveServerAppConstructor, HexclaveServerAppConstructorOptions, StackServerApp, StackServerAppConstructor, StackServerAppConstructorOptions };
@@ -6,7 +6,7 @@ import { a as PlanUsageRow, i as PlanUsagePlanId, n as PlanUsageKind, r as PlanU
6
6
  import { a as AdminWorkflowRunState, c as AdminWorkflowStepAttempt, d as AdminWorkflowUpgradeResult, f as AdminWorkflowVersion, i as AdminWorkflowRunDetails, l as AdminWorkflowSyncResult, n as AdminWorkflowDivergenceDiagnostic, o as AdminWorkflowRunsFilter, r as AdminWorkflowRun, s as AdminWorkflowStep, t as AdminWorkflow, u as AdminWorkflowTrigger } from "../../workflows-DEb7pIuQ.js";
7
7
  import { r as OAuthConnection, t as Connection } from "../../index-ClBTM-St.js";
8
8
  import { i as ServerContactChannel, t as ContactChannel } from "../../index-DN04TjLM.js";
9
- import { $ as TeamCreateOptions, B as StackServerAppConstructor, D as HexclaveAdminApp, E as EmailOutboxUpdateOptions, F as StackAdminAppConstructorOptions, H as EditableTeamMemberProfile, I as HexclaveServerApp, J as ServerTeamCreateOptions, K as ServerListUsersOptions, L as HexclaveServerAppConstructor, N as StackAdminApp, O as HexclaveAdminAppConstructor, Ot as User, P as StackAdminAppConstructor, Q as Team, R as HexclaveServerAppConstructorOptions, St as ServerUser, T as EmailOutboxListResult, U as ReceivedTeamInvitation, V as StackServerAppConstructorOptions, W as SentTeamInvitation, X as ServerTeamUpdateOptions, Y as ServerTeamMemberProfile, Z as ServerTeamUser, _ as AdminProjectCreateOptions, _t as OAuthProvider, a as StackClientApp, c as StackClientAppJson, d as AdminDeploymentEnvVarOptions, et as TeamInvitation, f as AdminDeploymentRunJson, ft as CurrentInternalServerUser, g as AdminProject, h as AdminOwnedProject, ht as CurrentUser, i as HexclaveClientAppJson, it as TeamUser, k as HexclaveAdminAppConstructorOptions, l as AdminDeploymentDomainJson, m as AdminDeploymentServiceJson, mt as CurrentServerUser, n as HexclaveClientAppConstructor, o as StackClientAppConstructor, p as AdminDeploymentServiceBuildOptions, pt as CurrentInternalUser, q as ServerTeam, r as HexclaveClientAppConstructorOptions, rt as TeamUpdateOptions, s as StackClientAppConstructorOptions, t as HexclaveClientApp, tt as TeamMemberProfile, u as AdminDeploymentEnvVarJson, ut as Auth, v as AdminProjectUpdateOptions, w as EmailOutboxListOptions, x as PushedConfigSource, xt as ServerOAuthProvider, y as Project, z as StackServerApp } from "../../client-app-WOX3pOo1.js";
9
+ import { $ as TeamCreateOptions, B as StackServerAppConstructor, D as HexclaveAdminApp, E as EmailOutboxUpdateOptions, F as StackAdminAppConstructorOptions, H as EditableTeamMemberProfile, I as HexclaveServerApp, J as ServerTeamCreateOptions, K as ServerListUsersOptions, L as HexclaveServerAppConstructor, N as StackAdminApp, O as HexclaveAdminAppConstructor, Ot as User, P as StackAdminAppConstructor, Q as Team, R as HexclaveServerAppConstructorOptions, St as ServerUser, T as EmailOutboxListResult, U as ReceivedTeamInvitation, V as StackServerAppConstructorOptions, W as SentTeamInvitation, X as ServerTeamUpdateOptions, Y as ServerTeamMemberProfile, Z as ServerTeamUser, _ as AdminProjectCreateOptions, _t as OAuthProvider, a as StackClientApp, c as StackClientAppJson, d as AdminDeploymentEnvVarOptions, et as TeamInvitation, f as AdminDeploymentRunJson, ft as CurrentInternalServerUser, g as AdminProject, h as AdminOwnedProject, ht as CurrentUser, i as HexclaveClientAppJson, it as TeamUser, k as HexclaveAdminAppConstructorOptions, l as AdminDeploymentDomainJson, m as AdminDeploymentServiceJson, mt as CurrentServerUser, n as HexclaveClientAppConstructor, o as StackClientAppConstructor, p as AdminDeploymentServiceBuildOptions, pt as CurrentInternalUser, q as ServerTeam, r as HexclaveClientAppConstructorOptions, rt as TeamUpdateOptions, s as StackClientAppConstructorOptions, t as HexclaveClientApp, tt as TeamMemberProfile, u as AdminDeploymentEnvVarJson, ut as Auth, v as AdminProjectUpdateOptions, w as EmailOutboxListOptions, x as PushedConfigSource, xt as ServerOAuthProvider, y as Project, z as StackServerApp } from "../../client-app-Dj2NuO6C.js";
10
10
  import { a as AdminProjectConfigUpdateOptions, i as AdminProjectConfig, n as AdminEmailConfig, o as OAuthProviderConfig, r as AdminOAuthProviderConfig, s as ProjectConfig, t as AdminDomainConfig } from "../../index-B-MazpM_.js";
11
11
  import { r as getPagePrompt } from "../../url-targets-BJgkwPGW.js";
12
12
  export { type AdminDeploymentDomainJson, type AdminDeploymentEnvVarJson, type AdminDeploymentEnvVarOptions, type AdminDeploymentRunJson, type AdminDeploymentServiceBuildOptions, type AdminDeploymentServiceJson, type AdminDomainConfig, type AdminEmailConfig, type AdminEmailOutbox, type AdminEmailOutboxRecipient, type AdminEmailOutboxSimpleStatus, type AdminEmailOutboxStatus, type AdminOAuthProviderConfig, type AdminOwnedProject, type AdminProject, type AdminProjectConfig, type AdminProjectConfigUpdateOptions, type AdminProjectCreateOptions, type AdminProjectPermission, type AdminProjectPermissionDefinition, type AdminProjectPermissionDefinitionCreateOptions, type AdminProjectPermissionDefinitionUpdateOptions, type AdminProjectUpdateOptions, type AdminSendAttemptError, type AdminSentEmail, type AdminTeamPermission, type AdminTeamPermissionDefinition, type AdminTeamPermissionDefinitionCreateOptions, type AdminTeamPermissionDefinitionUpdateOptions, type AdminWorkflow, type AdminWorkflowDivergenceDiagnostic, type AdminWorkflowRun, type AdminWorkflowRunDetails, type AdminWorkflowRunState, type AdminWorkflowRunsFilter, type AdminWorkflowStep, type AdminWorkflowStepAttempt, type AdminWorkflowSyncResult, type AdminWorkflowTrigger, type AdminWorkflowUpgradeResult, type AdminWorkflowVersion, type Auth, type Connection, type ContactChannel, type CurrentInternalServerUser, type CurrentInternalUser, type CurrentServerUser, type CurrentUser, type EditableTeamMemberProfile, type EmailOutboxListOptions, type EmailOutboxListResult, type EmailOutboxUpdateOptions, type GetCurrentUserOptions, type GetCurrentUserOptions as GetUserOptions, type HandlerUrlOptions, type HandlerUrls, HexclaveAdminApp, type HexclaveAdminAppConstructor, type HexclaveAdminAppConstructorOptions, HexclaveClientApp, type HexclaveClientAppConstructor, type HexclaveClientAppConstructorOptions, type HexclaveClientAppJson, HexclaveServerApp, type HexclaveServerAppConstructor, type HexclaveServerAppConstructorOptions, type InternalApiKey, type InternalApiKeyBase, type InternalApiKeyBaseCrudRead, type InternalApiKeyCreateOptions, type InternalApiKeyFirstView, type OAuthConnection, type OAuthProvider, type OAuthProviderConfig, type OAuthScopesOnSignIn, type PlanUsage, type PlanUsageKind, type PlanUsageNextPlanId, type PlanUsagePlanId, type PlanUsageRow, type Project, type ProjectConfig, type PushedConfigSource, type ReceivedTeamInvitation, type ResolvedHandlerUrls, type SentTeamInvitation, type ServerContactChannel, type ServerListUsersOptions, type ServerOAuthProvider, type ServerTeam, type ServerTeamCreateOptions, type ServerTeamMemberProfile, type ServerTeamUpdateOptions, type ServerTeamUser, type ServerUser, StackAdminApp, type StackAdminAppConstructor, type StackAdminAppConstructorOptions, StackClientApp, type StackClientAppConstructor, type StackClientAppConstructorOptions, type StackClientAppJson, StackServerApp, type StackServerAppConstructor, type StackServerAppConstructorOptions, type Team, type TeamCreateOptions, type TeamInvitation, type TeamMemberProfile, type TeamUpdateOptions, type TeamUser, type User, getPagePrompt, hexclaveAppInternalsSymbol };
@@ -1,2 +1,2 @@
1
- import { C as adminProjectUpdateOptionsToCrud, S as adminProjectCreateOptionsToCrud, _ as AdminProjectCreateOptions, b as PushConfigOptions, d as AdminDeploymentEnvVarOptions, f as AdminDeploymentRunJson, g as AdminProject, h as AdminOwnedProject, l as AdminDeploymentDomainJson, m as AdminDeploymentServiceJson, p as AdminDeploymentServiceBuildOptions, u as AdminDeploymentEnvVarJson, v as AdminProjectUpdateOptions, x as PushedConfigSource, y as Project } from "../../../client-app-WOX3pOo1.js";
1
+ import { C as adminProjectUpdateOptionsToCrud, S as adminProjectCreateOptionsToCrud, _ as AdminProjectCreateOptions, b as PushConfigOptions, d as AdminDeploymentEnvVarOptions, f as AdminDeploymentRunJson, g as AdminProject, h as AdminOwnedProject, l as AdminDeploymentDomainJson, m as AdminDeploymentServiceJson, p as AdminDeploymentServiceBuildOptions, u as AdminDeploymentEnvVarJson, v as AdminProjectUpdateOptions, x as PushedConfigSource, y as Project } from "../../../client-app-Dj2NuO6C.js";
2
2
  export { type AdminDeploymentDomainJson, type AdminDeploymentEnvVarJson, type AdminDeploymentEnvVarOptions, type AdminDeploymentRunJson, type AdminDeploymentServiceBuildOptions, type AdminDeploymentServiceJson, AdminOwnedProject, AdminProject, AdminProjectCreateOptions, AdminProjectUpdateOptions, Project, PushConfigOptions, PushedConfigSource, adminProjectCreateOptionsToCrud, adminProjectUpdateOptionsToCrud };
@@ -1,2 +1,2 @@
1
- import { a as ListSessionReplaysOptions, i as ListSessionReplayChunksResult, n as AdminSessionReplayChunk, o as ListSessionReplaysResult, r as ListSessionReplayChunksOptions, s as SessionReplayAllEventsResult, t as AdminSessionReplay } from "../../../index-hYjsGKNc.js";
1
+ import { a as ListSessionReplaysOptions, i as ListSessionReplayChunksResult, n as AdminSessionReplayChunk, o as ListSessionReplaysResult, r as ListSessionReplayChunksOptions, s as SessionReplayAllEventsResult, t as AdminSessionReplay } from "../../../index-Cf1wOohp.js";
2
2
  export { AdminSessionReplay, AdminSessionReplayChunk, ListSessionReplayChunksOptions, ListSessionReplayChunksResult, ListSessionReplaysOptions, ListSessionReplaysResult, SessionReplayAllEventsResult };
@@ -1,2 +1,2 @@
1
- import { $ as TeamCreateOptions, G as ServerListTeamsOptions, H as EditableTeamMemberProfile, J as ServerTeamCreateOptions, K as ServerListUsersOptions, Q as Team, U as ReceivedTeamInvitation, W as SentTeamInvitation, X as ServerTeamUpdateOptions, Y as ServerTeamMemberProfile, Z as ServerTeamUser, at as serverTeamCreateOptionsToCrud, ct as teamUpdateOptionsToCrud, et as TeamInvitation, it as TeamUser, nt as TeamMemberProfileUpdateOptions, ot as serverTeamUpdateOptionsToCrud, q as ServerTeam, rt as TeamUpdateOptions, st as teamCreateOptionsToCrud, tt as TeamMemberProfile } from "../../../client-app-WOX3pOo1.js";
1
+ import { $ as TeamCreateOptions, G as ServerListTeamsOptions, H as EditableTeamMemberProfile, J as ServerTeamCreateOptions, K as ServerListUsersOptions, Q as Team, U as ReceivedTeamInvitation, W as SentTeamInvitation, X as ServerTeamUpdateOptions, Y as ServerTeamMemberProfile, Z as ServerTeamUser, at as serverTeamCreateOptionsToCrud, ct as teamUpdateOptionsToCrud, et as TeamInvitation, it as TeamUser, nt as TeamMemberProfileUpdateOptions, ot as serverTeamUpdateOptionsToCrud, q as ServerTeam, rt as TeamUpdateOptions, st as teamCreateOptionsToCrud, tt as TeamMemberProfile } from "../../../client-app-Dj2NuO6C.js";
2
2
  export { EditableTeamMemberProfile, ReceivedTeamInvitation, SentTeamInvitation, ServerListTeamsOptions, ServerListUsersOptions, ServerTeam, ServerTeamCreateOptions, ServerTeamMemberProfile, ServerTeamUpdateOptions, ServerTeamUser, Team, TeamCreateOptions, TeamInvitation, TeamMemberProfile, TeamMemberProfileUpdateOptions, TeamUpdateOptions, TeamUser, serverTeamCreateOptionsToCrud, serverTeamUpdateOptionsToCrud, teamCreateOptionsToCrud, teamUpdateOptionsToCrud };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/lib/hexclave-app/teams/index.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 { TeamsCrud } from \"@hexclave/shared/dist/interface/crud/teams\";\nimport { ReadonlyJson } from \"@hexclave/shared/dist/utils/json\";\n\nimport { ApiKeyCreationOptions, TeamApiKey, TeamApiKeyFirstView } from \"../api-keys\";\nimport { AsyncStoreProperty } from \"../common\";\nimport { Customer } from \"../customers\";\nimport { ServerUser } from \"../users\";\n\n\nexport type TeamMemberProfile = {\n displayName: string | null,\n profileImageUrl: string | null,\n}\n\nexport type TeamMemberProfileUpdateOptions = {\n displayName?: string,\n profileImageUrl?: string | null,\n};\n\nexport type EditableTeamMemberProfile = TeamMemberProfile & {\n update(update: TeamMemberProfileUpdateOptions): Promise<void>,\n}\n\nexport type TeamUser = {\n id: string,\n teamProfile: TeamMemberProfile,\n}\n\n/**\n * A team invitation as seen from the team's perspective (ie. the sender).\n *\n * Returned by `team.listInvitations()`. Contains the recipient email and allows\n * revoking the invitation.\n */\nexport type SentTeamInvitation = {\n id: string,\n recipientEmail: string | null,\n expiresAt: Date,\n revoke(): Promise<void>,\n}\n\n/**\n * @deprecated Use `SentTeamInvitation` instead.\n */\nexport type TeamInvitation = SentTeamInvitation;\n\n/**\n * A team invitation as seen from the invited user's perspective (ie. the receiver).\n *\n * Returned by `user.listTeamInvitations()`. Contains information about teams that have\n * sent invitations to any of the user's verified email addresses, and allows accepting\n * the invitation to join the team.\n */\nexport type ReceivedTeamInvitation = {\n id: string,\n teamId: string,\n teamDisplayName: string,\n recipientEmail: string,\n expiresAt: Date,\n\n /**\n * Accepts the invitation, adding the current user to the team.\n *\n * The user must have a verified email address matching the invitation's recipient email.\n */\n accept(): Promise<void>,\n}\n\nexport type Team = {\n id: string,\n displayName: string,\n profileImageUrl: string | null,\n clientMetadata: any,\n clientReadOnlyMetadata: any,\n inviteUser(options: { email: string, callbackUrl?: string }): Promise<void>,\n listUsers(): Promise<TeamUser[]>,\n removeUser(userId: string): Promise<void>,\n listInvitations(): Promise<SentTeamInvitation[]>,\n update(update: TeamUpdateOptions): Promise<void>,\n delete(): Promise<void>,\n createApiKey(options: ApiKeyCreationOptions<\"team\">): Promise<TeamApiKeyFirstView>,\n} & AsyncStoreProperty<\"apiKeys\", [], TeamApiKey[], true> & Customer;\n\nexport type TeamUpdateOptions = {\n displayName?: string,\n profileImageUrl?: string | null,\n clientMetadata?: ReadonlyJson,\n};\nexport function teamUpdateOptionsToCrud(options: TeamUpdateOptions): TeamsCrud[\"Client\"][\"Update\"] {\n return {\n display_name: options.displayName,\n profile_image_url: options.profileImageUrl,\n client_metadata: options.clientMetadata,\n };\n}\n\nexport type TeamCreateOptions = {\n displayName: string,\n profileImageUrl?: string,\n}\nexport function teamCreateOptionsToCrud(options: TeamCreateOptions, creatorUserId: string): TeamsCrud[\"Client\"][\"Create\"] {\n return {\n display_name: options.displayName,\n profile_image_url: options.profileImageUrl,\n creator_user_id: creatorUserId,\n };\n}\n\n\nexport type ServerTeamMemberProfile = TeamMemberProfile;\n\nexport type ServerTeamUser = ServerUser & {\n teamProfile: ServerTeamMemberProfile,\n}\n\nexport type ServerTeam = {\n createdAt: Date,\n serverMetadata: any,\n listUsers(): Promise<ServerTeamUser[]>,\n update(update: ServerTeamUpdateOptions): Promise<void>,\n delete(): Promise<void>,\n addUser(userId: string): Promise<void>,\n inviteUser(options: { email: string, callbackUrl?: string }): Promise<void>,\n removeUser(userId: string): Promise<void>,\n} & Team;\n\ntype ServerListUsersOptionsBase = {\n cursor?: string,\n limit?: number,\n orderBy?: 'signedUpAt' | 'lastActiveAt',\n desc?: boolean,\n /**\n * Free-text search. Matches user ID (exact UUID), display name, and contact channels (e.g. primary email).\n */\n query?: string,\n /**\n * Exclude users whose primary email domain matches one of these exact domains.\n */\n excludedEmailDomains?: string[],\n /**\n * Only return users who are members of the given team.\n */\n teamId?: string,\n /**\n * Whether to include restricted users (users who haven't completed onboarding requirements).\n * Defaults to false.\n */\n includeRestricted?: boolean,\n /**\n * Whether to include anonymous users (and restricted users).\n * Defaults to false.\n */\n includeAnonymous?: boolean,\n};\n\nexport type ServerListUsersOptions = ServerListUsersOptionsBase & (\n {\n onlyAnonymous?: false,\n } | {\n /**\n * Whether to return only anonymous users.\n * Requires includeAnonymous=true.\n * Defaults to false.\n */\n onlyAnonymous: true,\n includeAnonymous: true,\n }\n);\n\nexport type ServerListTeamsOptions = {\n orderBy?: 'createdAt',\n desc?: boolean,\n cursor?: string,\n limit?: number,\n /**\n * Free-text search. Matches team ID (exact UUID) and display name.\n */\n query?: string,\n};\n\nexport type ServerTeamCreateOptions = TeamCreateOptions & {\n creatorUserId?: string,\n};\nexport function serverTeamCreateOptionsToCrud(options: ServerTeamCreateOptions): TeamsCrud[\"Server\"][\"Create\"] {\n return {\n display_name: options.displayName,\n profile_image_url: options.profileImageUrl,\n creator_user_id: options.creatorUserId,\n };\n}\n\nexport type ServerTeamUpdateOptions = TeamUpdateOptions & {\n clientReadOnlyMetadata?: ReadonlyJson,\n serverMetadata?: ReadonlyJson,\n};\nexport function serverTeamUpdateOptionsToCrud(options: ServerTeamUpdateOptions): TeamsCrud[\"Server\"][\"Update\"] {\n return {\n display_name: options.displayName,\n profile_image_url: options.profileImageUrl,\n client_metadata: options.clientMetadata,\n client_read_only_metadata: options.clientReadOnlyMetadata,\n server_metadata: options.serverMetadata,\n };\n}\n"],"mappings":";;AA4FA,SAAgB,wBAAwB,SAA2D;CACjG,OAAO;EACL,cAAc,QAAQ;EACtB,mBAAmB,QAAQ;EAC3B,iBAAiB,QAAQ;CAC3B;AACF;AAMA,SAAgB,wBAAwB,SAA4B,eAAsD;CACxH,OAAO;EACL,cAAc,QAAQ;EACtB,mBAAmB,QAAQ;EAC3B,iBAAiB;CACnB;AACF;AA6EA,SAAgB,8BAA8B,SAAiE;CAC7G,OAAO;EACL,cAAc,QAAQ;EACtB,mBAAmB,QAAQ;EAC3B,iBAAiB,QAAQ;CAC3B;AACF;AAMA,SAAgB,8BAA8B,SAAiE;CAC7G,OAAO;EACL,cAAc,QAAQ;EACtB,mBAAmB,QAAQ;EAC3B,iBAAiB,QAAQ;EACzB,2BAA2B,QAAQ;EACnC,iBAAiB,QAAQ;CAC3B;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/lib/hexclave-app/teams/index.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 { TeamsCrud } from \"@hexclave/shared/dist/interface/crud/teams\";\nimport { ReadonlyJson } from \"@hexclave/shared/dist/utils/json\";\n\nimport { ApiKeyCreationOptions, TeamApiKey, TeamApiKeyFirstView } from \"../api-keys\";\nimport { AsyncStoreProperty } from \"../common\";\nimport { Customer } from \"../customers\";\nimport { ServerUser } from \"../users\";\n\n\nexport type TeamMemberProfile = {\n displayName: string | null,\n profileImageUrl: string | null,\n}\n\nexport type TeamMemberProfileUpdateOptions = {\n displayName?: string,\n profileImageUrl?: string | null,\n};\n\nexport type EditableTeamMemberProfile = TeamMemberProfile & {\n update(update: TeamMemberProfileUpdateOptions): Promise<void>,\n}\n\nexport type TeamUser = {\n id: string,\n teamProfile: TeamMemberProfile,\n}\n\n/**\n * A team invitation as seen from the team's perspective (ie. the sender).\n *\n * Returned by `team.listInvitations()`. Contains the recipient email and allows\n * revoking the invitation.\n */\nexport type SentTeamInvitation = {\n id: string,\n recipientEmail: string | null,\n expiresAt: Date,\n revoke(): Promise<void>,\n}\n\n/**\n * @deprecated Use `SentTeamInvitation` instead.\n */\nexport type TeamInvitation = SentTeamInvitation;\n\n/**\n * A team invitation as seen from the invited user's perspective (ie. the receiver).\n *\n * Returned by `user.listTeamInvitations()`. Contains information about teams that have\n * sent invitations to any of the user's verified email addresses, and allows accepting\n * the invitation to join the team.\n */\nexport type ReceivedTeamInvitation = {\n id: string,\n teamId: string,\n teamDisplayName: string,\n recipientEmail: string,\n expiresAt: Date,\n\n /**\n * Accepts the invitation, adding the current user to the team.\n *\n * The user must have a verified email address matching the invitation's recipient email.\n */\n accept(): Promise<void>,\n}\n\nexport type Team = {\n id: string,\n displayName: string,\n profileImageUrl: string | null,\n clientMetadata: any,\n clientReadOnlyMetadata: any,\n inviteUser(options: { email: string, callbackUrl?: string }): Promise<void>,\n listUsers(): Promise<TeamUser[]>,\n removeUser(userId: string): Promise<void>,\n listInvitations(): Promise<SentTeamInvitation[]>,\n update(update: TeamUpdateOptions): Promise<void>,\n delete(): Promise<void>,\n createApiKey(options: ApiKeyCreationOptions<\"team\">): Promise<TeamApiKeyFirstView>,\n} & AsyncStoreProperty<\"apiKeys\", [], TeamApiKey[], true> & Customer;\n\nexport type TeamUpdateOptions = {\n displayName?: string,\n profileImageUrl?: string | null,\n clientMetadata?: ReadonlyJson,\n};\nexport function teamUpdateOptionsToCrud(options: TeamUpdateOptions): TeamsCrud[\"Client\"][\"Update\"] {\n return {\n display_name: options.displayName,\n profile_image_url: options.profileImageUrl,\n client_metadata: options.clientMetadata,\n };\n}\n\nexport type TeamCreateOptions = {\n displayName: string,\n profileImageUrl?: string,\n}\nexport function teamCreateOptionsToCrud(options: TeamCreateOptions, creatorUserId: string): TeamsCrud[\"Client\"][\"Create\"] {\n return {\n display_name: options.displayName,\n profile_image_url: options.profileImageUrl,\n creator_user_id: creatorUserId,\n };\n}\n\n\nexport type ServerTeamMemberProfile = TeamMemberProfile;\n\nexport type ServerTeamUser = ServerUser & {\n teamProfile: ServerTeamMemberProfile,\n}\n\nexport type ServerTeam = {\n createdAt: Date,\n serverMetadata: any,\n listUsers(): Promise<ServerTeamUser[]>,\n update(update: ServerTeamUpdateOptions): Promise<void>,\n delete(): Promise<void>,\n addUser(userId: string): Promise<void>,\n inviteUser(options: { email: string, callbackUrl?: string }): Promise<void>,\n removeUser(userId: string): Promise<void>,\n} & Team;\n\ntype ServerListUsersOptionsBase = {\n cursor?: string,\n /**\n * Maximum number of users to return per page. Must be at most 1000.\n */\n limit?: number,\n orderBy?: 'signedUpAt' | 'lastActiveAt',\n desc?: boolean,\n /**\n * Free-text search. Matches user ID (exact UUID), display name, and contact channels (e.g. primary email).\n */\n query?: string,\n /**\n * Exclude users whose primary email domain matches one of these exact domains.\n */\n excludedEmailDomains?: string[],\n /**\n * Only return users who are members of the given team.\n */\n teamId?: string,\n /**\n * Whether to include restricted users (users who haven't completed onboarding requirements).\n * Defaults to false.\n */\n includeRestricted?: boolean,\n /**\n * Whether to include anonymous users (and restricted users).\n * Defaults to false.\n */\n includeAnonymous?: boolean,\n};\n\nexport type ServerListUsersOptions = ServerListUsersOptionsBase & (\n {\n onlyAnonymous?: false,\n } | {\n /**\n * Whether to return only anonymous users.\n * Requires includeAnonymous=true.\n * Defaults to false.\n */\n onlyAnonymous: true,\n includeAnonymous: true,\n }\n);\n\nexport type ServerListTeamsOptions = {\n orderBy?: 'createdAt',\n desc?: boolean,\n cursor?: string,\n limit?: number,\n /**\n * Free-text search. Matches team ID (exact UUID) and display name.\n */\n query?: string,\n};\n\nexport type ServerTeamCreateOptions = TeamCreateOptions & {\n creatorUserId?: string,\n};\nexport function serverTeamCreateOptionsToCrud(options: ServerTeamCreateOptions): TeamsCrud[\"Server\"][\"Create\"] {\n return {\n display_name: options.displayName,\n profile_image_url: options.profileImageUrl,\n creator_user_id: options.creatorUserId,\n };\n}\n\nexport type ServerTeamUpdateOptions = TeamUpdateOptions & {\n clientReadOnlyMetadata?: ReadonlyJson,\n serverMetadata?: ReadonlyJson,\n};\nexport function serverTeamUpdateOptionsToCrud(options: ServerTeamUpdateOptions): TeamsCrud[\"Server\"][\"Update\"] {\n return {\n display_name: options.displayName,\n profile_image_url: options.profileImageUrl,\n client_metadata: options.clientMetadata,\n client_read_only_metadata: options.clientReadOnlyMetadata,\n server_metadata: options.serverMetadata,\n };\n}\n"],"mappings":";;AA4FA,SAAgB,wBAAwB,SAA2D;CACjG,OAAO;EACL,cAAc,QAAQ;EACtB,mBAAmB,QAAQ;EAC3B,iBAAiB,QAAQ;CAC3B;AACF;AAMA,SAAgB,wBAAwB,SAA4B,eAAsD;CACxH,OAAO;EACL,cAAc,QAAQ;EACtB,mBAAmB,QAAQ;EAC3B,iBAAiB;CACnB;AACF;AAgFA,SAAgB,8BAA8B,SAAiE;CAC7G,OAAO;EACL,cAAc,QAAQ;EACtB,mBAAmB,QAAQ;EAC3B,iBAAiB,QAAQ;CAC3B;AACF;AAMA,SAAgB,8BAA8B,SAAiE;CAC7G,OAAO;EACL,cAAc,QAAQ;EACtB,mBAAmB,QAAQ;EAC3B,iBAAiB,QAAQ;EACzB,2BAA2B,QAAQ;EACnC,iBAAiB,QAAQ;CAC3B;AACF"}
@@ -1,2 +1,2 @@
1
- import { At as UserUpdateOptions, Ct as ServerUserCreateOptions, Dt as TokenPartialUser, Et as SyncedPartialUser, Mt as serverUserUpdateOptionsToCrud, Nt as userUpdateOptionsToCrud, Ot as User, Pt as withUserDestructureGuard, St as ServerUser, Tt as SyncedPartialServerUser, _t as OAuthProvider, bt as ServerBaseUser, dt as BaseUser, ft as CurrentInternalServerUser, gt as InternalUserExtra, ht as CurrentUser, jt as serverUserCreateOptionsToCrud, kt as UserExtra, lt as ActiveSession, mt as CurrentServerUser, pt as CurrentInternalUser, ut as Auth, vt as ProjectCurrentServerUser, wt as ServerUserUpdateOptions, xt as ServerOAuthProvider, yt as ProjectCurrentUser } from "../../../client-app-WOX3pOo1.js";
1
+ import { At as UserUpdateOptions, Ct as ServerUserCreateOptions, Dt as TokenPartialUser, Et as SyncedPartialUser, Mt as serverUserUpdateOptionsToCrud, Nt as userUpdateOptionsToCrud, Ot as User, Pt as withUserDestructureGuard, St as ServerUser, Tt as SyncedPartialServerUser, _t as OAuthProvider, bt as ServerBaseUser, dt as BaseUser, ft as CurrentInternalServerUser, gt as InternalUserExtra, ht as CurrentUser, jt as serverUserCreateOptionsToCrud, kt as UserExtra, lt as ActiveSession, mt as CurrentServerUser, pt as CurrentInternalUser, ut as Auth, vt as ProjectCurrentServerUser, wt as ServerUserUpdateOptions, xt as ServerOAuthProvider, yt as ProjectCurrentUser } from "../../../client-app-Dj2NuO6C.js";
2
2
  export { ActiveSession, Auth, BaseUser, CurrentInternalServerUser, CurrentInternalUser, CurrentServerUser, CurrentUser, InternalUserExtra, OAuthProvider, ProjectCurrentServerUser, ProjectCurrentUser, ServerBaseUser, ServerOAuthProvider, ServerUser, ServerUserCreateOptions, ServerUserUpdateOptions, SyncedPartialServerUser, SyncedPartialUser, TokenPartialUser, User, UserExtra, UserUpdateOptions, serverUserCreateOptionsToCrud, serverUserUpdateOptionsToCrud, userUpdateOptionsToCrud, withUserDestructureGuard };
@@ -1,4 +1,4 @@
1
- import { a as StackClientApp } from "../client-app-WOX3pOo1.js";
1
+ import { a as StackClientApp } from "../client-app-Dj2NuO6C.js";
2
2
  //#region src/pushed-config-error-overlay/index.d.ts
3
3
  declare function mountPushedConfigErrorOverlay(app: StackClientApp<true>): () => void;
4
4
  //#endregion
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "//": "THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template (FOR package.json FILES, PLEASE EDIT package-template.json)",
3
3
  "name": "@hexclave/js",
4
- "version": "1.0.76",
4
+ "version": "1.0.78",
5
5
  "repository": "https://github.com/hexclave/hexclave",
6
6
  "sideEffects": false,
7
7
  "main": "./dist/index.js",
@@ -65,7 +65,7 @@
65
65
  "qrcode": "^1.5.4",
66
66
  "rrweb": "^1.1.3",
67
67
  "yup": "^1.7.1",
68
- "@hexclave/shared": "1.0.76"
68
+ "@hexclave/shared": "1.0.78"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@quetzallabs/i18n": "^0.1.19",
@@ -1282,6 +1282,7 @@ export class _HexclaveAdminAppImplIncomplete<HasTokenStore extends boolean, Proj
1282
1282
 
1283
1283
  const items: AdminSessionReplay[] = response.items.map((r) => ({
1284
1284
  id: r.id,
1285
+ refreshTokenId: r.refresh_token_id,
1285
1286
  projectUser: {
1286
1287
  id: r.project_user.id,
1287
1288
  displayName: r.project_user.display_name,
@@ -1303,6 +1304,7 @@ export class _HexclaveAdminAppImplIncomplete<HasTokenStore extends boolean, Proj
1303
1304
  const response = await this._interface.getSessionReplay(sessionReplayId);
1304
1305
  return {
1305
1306
  id: response.id,
1307
+ refreshTokenId: response.refresh_token_id,
1306
1308
  projectUser: {
1307
1309
  id: response.project_user.id,
1308
1310
  displayName: response.project_user.display_name,
@@ -2,9 +2,10 @@
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 { describe, expect, it } from "vitest";
5
+ import { describe, expect, it, vi } from "vitest";
6
6
  import { hexclaveAppInternalsSymbol } from "../../common";
7
7
  import { HexclaveClientApp, HexclaveClientAppConstructorOptions, HexclaveClientAppJson } from "../interfaces/client-app";
8
+ import { stripBrowserActionQueryParam } from "./client-app-impl";
8
9
 
9
10
  const baseOptions = {
10
11
  baseUrl: "http://localhost:12345",
@@ -123,4 +124,40 @@ describe("HexclaveClientApp automatic side effects", () => {
123
124
 
124
125
  expect(second).toBe(first);
125
126
  });
127
+
128
+ it("keeps stripping the browser action parameter after a router restores it", () => {
129
+ vi.useFakeTimers();
130
+ const previousWindow = Reflect.get(globalThis, "window");
131
+ const hadPreviousWindow = Reflect.has(globalThis, "window");
132
+ let currentHref = "http://localhost:12345/?hexclave_action_id=action-id";
133
+ const browserGlobal = {
134
+ location: {
135
+ get href() {
136
+ return currentHref;
137
+ },
138
+ },
139
+ history: {
140
+ state: null,
141
+ replaceState: (_state: null, _title: string, url: string | URL) => {
142
+ currentHref = String(url);
143
+ },
144
+ },
145
+ setTimeout,
146
+ };
147
+
148
+ Reflect.set(globalThis, "window", browserGlobal);
149
+ try {
150
+ stripBrowserActionQueryParam();
151
+ currentHref = "http://localhost:12345/?hexclave_action_id=action-id";
152
+ vi.runAllTimers();
153
+ expect(currentHref).toBe("http://localhost:12345/");
154
+ } finally {
155
+ vi.useRealTimers();
156
+ if (hadPreviousWindow) {
157
+ Reflect.set(globalThis, "window", previousWindow);
158
+ } else {
159
+ Reflect.deleteProperty(globalThis, "window");
160
+ }
161
+ }
162
+ });
126
163
  });
@@ -11,9 +11,8 @@ import { StackClientApp } from "../interfaces/client-app";
11
11
  import { planRedirectToHandler } from "./redirect-page-urls";
12
12
 
13
13
  // Every app in this file is constructed with `devTool: false`. The tests install a mock window and document, which makes
14
- // the SDK believe it is in a browser, and mounting the dev tool kicks off a background `getProject()` against a backend
15
- // that does not exist here. That fetch never settles, and because it runs inside the global store lock, it blocks every
16
- // later `withWriteLock` caller (`_signOut`, most visibly) for the rest of the test file.
14
+ // the SDK believe it is in a browser; mounting the dev tool would then start background requests against a backend that
15
+ // does not exist here and leak that work across test cases.
17
16
  function createAccessTokenString(refreshTokenId: string): string {
18
17
  const encode = (value: unknown) => Buffer.from(JSON.stringify(value)).toString("base64url");
19
18
  const nowSeconds = Math.floor(Date.now() / 1000);