@stackframe/stack 2.3.5 → 2.3.7
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/components/card-frame.d.mts +9 -0
- package/dist/components/card-frame.d.ts +8 -5
- package/dist/components/card-frame.js +58 -23
- package/dist/components/credential-sign-in.d.mts +5 -0
- package/dist/components/credential-sign-in.d.ts +5 -1
- package/dist/components/credential-sign-in.js +109 -41
- package/dist/components/credential-sign-up.d.mts +5 -0
- package/dist/components/credential-sign-up.d.ts +5 -1
- package/dist/components/credential-sign-up.js +140 -62
- package/dist/components/forgot-password.d.mts +7 -0
- package/dist/components/forgot-password.d.ts +6 -2
- package/dist/components/forgot-password.js +83 -26
- package/dist/components/form-warning.d.mts +7 -0
- package/dist/components/form-warning.d.ts +6 -2
- package/dist/components/form-warning.js +34 -8
- package/dist/components/magic-link-sign-in.d.mts +5 -0
- package/dist/components/magic-link-sign-in.d.ts +5 -1
- package/dist/components/magic-link-sign-in.js +89 -31
- package/dist/components/message-card.d.mts +10 -0
- package/dist/components/message-card.d.ts +8 -4
- package/dist/components/message-card.js +45 -6
- package/dist/components/oauth-button.d.mts +8 -0
- package/dist/components/oauth-button.d.ts +6 -2
- package/dist/components/oauth-button.js +142 -63
- package/dist/components/oauth-group.d.mts +7 -0
- package/dist/components/oauth-group.d.ts +6 -2
- package/dist/components/oauth-group.js +46 -8
- package/dist/components/password-field.d.mts +5 -0
- package/dist/components/password-field.d.ts +5 -3
- package/dist/components/password-field.js +111 -41
- package/dist/components/password-reset-inner.d.mts +8 -0
- package/dist/components/password-reset-inner.d.ts +6 -2
- package/dist/components/password-reset-inner.js +120 -58
- package/dist/components/redirect-message-card.d.mts +8 -0
- package/dist/components/redirect-message-card.d.ts +6 -2
- package/dist/components/redirect-message-card.js +110 -58
- package/dist/components/separator-with-text.d.mts +7 -0
- package/dist/components/separator-with-text.d.ts +6 -2
- package/dist/components/separator-with-text.js +35 -5
- package/dist/components/user-avatar.d.mts +13 -0
- package/dist/components/user-avatar.d.ts +11 -3
- package/dist/components/user-avatar.js +34 -6
- package/dist/components/user-button.d.mts +15 -0
- package/dist/components/user-button.d.ts +12 -3
- package/dist/components/user-button.js +156 -26
- package/dist/components-core/avatar.d.mts +8 -0
- package/dist/components-core/avatar.d.ts +7 -5
- package/dist/components-core/avatar.js +73 -18
- package/dist/components-core/button.d.mts +12 -0
- package/dist/components-core/button.d.ts +8 -6
- package/dist/components-core/button.js +177 -113
- package/dist/components-core/card.d.mts +8 -0
- package/dist/components-core/card.d.ts +4 -2
- package/dist/components-core/card.js +73 -22
- package/dist/components-core/collapsible.d.mts +8 -0
- package/dist/components-core/collapsible.d.ts +8 -6
- package/dist/components-core/collapsible.js +48 -5
- package/dist/components-core/container.d.mts +8 -0
- package/dist/components-core/container.d.ts +5 -3
- package/dist/components-core/container.js +61 -11
- package/dist/components-core/dropdown.d.mts +15 -0
- package/dist/components-core/dropdown.d.ts +10 -8
- package/dist/components-core/dropdown.js +108 -36
- package/dist/components-core/index.d.mts +59 -0
- package/dist/components-core/index.d.ts +51 -40
- package/dist/components-core/index.js +144 -46
- package/dist/components-core/input.d.mts +6 -0
- package/dist/components-core/input.d.ts +5 -3
- package/dist/components-core/input.js +97 -28
- package/dist/components-core/label.d.mts +6 -0
- package/dist/components-core/label.d.ts +5 -3
- package/dist/components-core/label.js +65 -15
- package/dist/components-core/link.d.mts +10 -0
- package/dist/components-core/link.d.ts +7 -6
- package/dist/components-core/link.js +72 -18
- package/dist/components-core/loading-indicator.d.mts +13 -0
- package/dist/components-core/loading-indicator.d.ts +11 -4
- package/dist/components-core/loading-indicator.js +46 -6
- package/dist/components-core/popover.d.mts +8 -0
- package/dist/components-core/popover.d.ts +8 -6
- package/dist/components-core/popover.js +72 -16
- package/dist/components-core/separator.d.mts +6 -0
- package/dist/components-core/separator.d.ts +5 -3
- package/dist/components-core/separator.js +66 -16
- package/dist/components-core/skeleton.d.mts +7 -0
- package/dist/components-core/skeleton.d.ts +5 -3
- package/dist/components-core/skeleton.js +75 -21
- package/dist/components-core/tabs.d.mts +9 -0
- package/dist/components-core/tabs.d.ts +8 -6
- package/dist/components-core/tabs.js +87 -20
- package/dist/components-core/text.d.mts +10 -0
- package/dist/components-core/text.d.ts +5 -3
- package/dist/components-core/text.js +95 -40
- package/dist/components-core-joy/button.d.mts +6 -0
- package/dist/components-core-joy/button.d.ts +6 -2
- package/dist/components-core-joy/button.js +86 -28
- package/dist/components-core-joy/input.d.mts +5 -0
- package/dist/components-core-joy/input.d.ts +5 -2
- package/dist/components-core-joy/input.js +51 -6
- package/dist/components-core-joy/separator.d.mts +6 -0
- package/dist/components-core-joy/separator.d.ts +6 -2
- package/dist/components-core-joy/separator.js +50 -6
- package/dist/components-core-joy/tabs.d.mts +9 -0
- package/dist/components-core-joy/tabs.d.ts +9 -5
- package/dist/components-core-joy/tabs.js +62 -16
- package/dist/components-core-joy/text.d.mts +9 -0
- package/dist/components-core-joy/text.d.ts +6 -3
- package/dist/components-core-joy/text.js +68 -28
- package/dist/components-page/account-settings.d.mts +7 -0
- package/dist/components-page/account-settings.d.ts +6 -2
- package/dist/components-page/account-settings.js +213 -81
- package/dist/components-page/auth-page.d.mts +8 -0
- package/dist/components-page/auth-page.d.ts +6 -2
- package/dist/components-page/auth-page.js +79 -19
- package/dist/components-page/email-verification.d.mts +8 -0
- package/dist/components-page/email-verification.d.ts +6 -2
- package/dist/components-page/email-verification.js +65 -28
- package/dist/components-page/forgot-password.d.mts +7 -0
- package/dist/components-page/forgot-password.d.ts +6 -2
- package/dist/components-page/forgot-password.js +64 -20
- package/dist/components-page/magic-link-callback.d.mts +8 -0
- package/dist/components-page/magic-link-callback.d.ts +6 -2
- package/dist/components-page/magic-link-callback.js +72 -34
- package/dist/components-page/oauth-callback.d.mts +5 -0
- package/dist/components-page/oauth-callback.d.ts +5 -1
- package/dist/components-page/oauth-callback.js +52 -16
- package/dist/components-page/password-reset.d.mts +8 -0
- package/dist/components-page/password-reset.d.ts +6 -2
- package/dist/components-page/password-reset.js +70 -34
- package/dist/components-page/sign-in.d.mts +7 -0
- package/dist/components-page/sign-in.d.ts +6 -2
- package/dist/components-page/sign-in.js +41 -5
- package/dist/components-page/sign-out.d.mts +5 -0
- package/dist/components-page/sign-out.d.ts +5 -1
- package/dist/components-page/sign-out.js +47 -11
- package/dist/components-page/sign-up.d.mts +7 -0
- package/dist/components-page/sign-up.d.ts +6 -2
- package/dist/components-page/sign-up.js +41 -5
- package/dist/components-page/stack-handler.d.mts +16 -0
- package/dist/components-page/stack-handler.d.ts +11 -3
- package/dist/components-page/stack-handler.js +102 -64
- package/dist/esm/components/card-frame.js +39 -0
- package/dist/esm/components/credential-sign-in.js +82 -0
- package/dist/esm/components/credential-sign-up.js +114 -0
- package/dist/esm/components/forgot-password.js +55 -0
- package/dist/esm/components/form-warning.js +15 -0
- package/dist/esm/components/magic-link-sign-in.js +61 -0
- package/dist/esm/components/message-card.js +16 -0
- package/dist/esm/components/oauth-button.js +124 -0
- package/dist/esm/components/oauth-group.js +17 -0
- package/dist/esm/components/password-field.js +82 -0
- package/dist/esm/components/password-reset-inner.js +93 -0
- package/dist/esm/components/redirect-message-card.js +83 -0
- package/dist/esm/components/separator-with-text.js +16 -0
- package/dist/esm/components/user-avatar.js +14 -0
- package/dist/esm/components/user-button.js +133 -0
- package/dist/esm/components-core/avatar.js +56 -0
- package/dist/esm/components-core/button.js +165 -0
- package/dist/esm/components-core/card.js +51 -0
- package/dist/esm/components-core/collapsible.js +13 -0
- package/dist/esm/components-core/container.js +35 -0
- package/dist/esm/components-core/dropdown.js +106 -0
- package/dist/esm/components-core/index.js +93 -0
- package/dist/esm/components-core/input.js +80 -0
- package/dist/esm/components-core/label.js +38 -0
- package/dist/esm/components-core/link.js +38 -0
- package/dist/esm/components-core/loading-indicator.js +27 -0
- package/dist/esm/components-core/popover.js +43 -0
- package/dist/esm/components-core/separator.js +36 -0
- package/dist/esm/components-core/skeleton.js +52 -0
- package/dist/esm/components-core/tabs.js +79 -0
- package/dist/esm/components-core/text.js +63 -0
- package/dist/esm/components-core-joy/button.js +53 -0
- package/dist/esm/components-core-joy/input.js +18 -0
- package/dist/esm/components-core-joy/separator.js +17 -0
- package/dist/esm/components-core-joy/tabs.js +29 -0
- package/dist/esm/components-core-joy/text.js +35 -0
- package/dist/esm/components-page/account-settings.js +197 -0
- package/dist/esm/components-page/auth-page.js +50 -0
- package/dist/esm/components-page/email-verification.js +36 -0
- package/dist/esm/components-page/forgot-password.js +35 -0
- package/dist/esm/components-page/magic-link-callback.js +43 -0
- package/dist/esm/components-page/oauth-callback.js +23 -0
- package/dist/esm/components-page/password-reset.js +42 -0
- package/dist/esm/components-page/sign-in.js +12 -0
- package/dist/esm/components-page/sign-out.js +18 -0
- package/dist/esm/components-page/sign-up.js +12 -0
- package/dist/esm/components-page/stack-handler.js +75 -0
- package/dist/esm/index.js +47 -0
- package/dist/esm/joy.js +5 -0
- package/dist/esm/lib/auth.js +62 -0
- package/dist/esm/lib/cookie.js +185 -0
- package/dist/esm/lib/hooks.js +29 -0
- package/dist/esm/lib/stack-app.js +940 -0
- package/dist/esm/providers/component-provider.js +76 -0
- package/dist/esm/providers/design-provider.js +36 -0
- package/dist/esm/providers/joy-provider.js +35 -0
- package/dist/esm/providers/stack-provider-client.js +31 -0
- package/dist/esm/providers/stack-provider.js +21 -0
- package/dist/esm/providers/styled-components-registry.js +24 -0
- package/dist/esm/providers/theme-provider.js +22 -0
- package/dist/esm/utils/browser-script.js +25 -0
- package/dist/esm/utils/constants.js +34 -0
- package/dist/esm/utils/email.js +10 -0
- package/dist/esm/utils/next.js +7 -0
- package/dist/esm/utils/url.js +21 -0
- package/dist/index.d.mts +37 -0
- package/dist/index.d.ts +37 -22
- package/dist/index.js +106 -21
- package/dist/joy.d.mts +16 -0
- package/dist/joy.d.ts +16 -1
- package/dist/joy.js +30 -1
- package/dist/lib/auth.d.mts +11 -0
- package/dist/lib/auth.d.ts +8 -4
- package/dist/lib/auth.js +83 -57
- package/dist/lib/cookie.d.mts +14 -0
- package/dist/lib/cookie.d.ts +8 -6
- package/dist/lib/cookie.js +217 -45
- package/dist/lib/hooks.d.mts +35 -0
- package/dist/lib/hooks.d.ts +14 -8
- package/dist/lib/hooks.js +53 -28
- package/dist/lib/stack-app.d.mts +227 -0
- package/dist/lib/stack-app.d.ts +43 -41
- package/dist/lib/stack-app.js +937 -849
- package/dist/providers/component-provider.d.mts +113 -0
- package/dist/providers/component-provider.d.ts +95 -77
- package/dist/providers/component-provider.js +92 -58
- package/dist/providers/design-provider.d.mts +34 -0
- package/dist/providers/design-provider.d.ts +16 -21
- package/dist/providers/design-provider.js +57 -58
- package/dist/providers/joy-provider.d.mts +36 -0
- package/dist/providers/joy-provider.d.ts +30 -14
- package/dist/providers/joy-provider.js +58 -30
- package/dist/providers/stack-provider-client.d.mts +20 -0
- package/dist/providers/stack-provider-client.d.ts +15 -8
- package/dist/providers/stack-provider-client.js +64 -20
- package/dist/providers/stack-provider.d.mts +14 -0
- package/dist/providers/stack-provider.d.ts +13 -5
- package/dist/providers/stack-provider.js +39 -8
- package/dist/providers/styled-components-registry.d.mts +8 -0
- package/dist/providers/styled-components-registry.d.ts +8 -4
- package/dist/providers/styled-components-registry.js +43 -17
- package/dist/providers/theme-provider.d.mts +22 -0
- package/dist/providers/theme-provider.d.ts +21 -9
- package/dist/providers/theme-provider.js +55 -19
- package/dist/utils/browser-script.d.mts +5 -0
- package/dist/utils/browser-script.d.ts +5 -0
- package/dist/utils/browser-script.js +50 -0
- package/dist/utils/constants.d.mts +48 -0
- package/dist/utils/constants.d.ts +11 -9
- package/dist/utils/constants.js +66 -21
- package/dist/utils/email.d.mts +3 -0
- package/dist/utils/email.d.ts +3 -1
- package/dist/utils/email.js +44 -6
- package/dist/utils/next.d.mts +3 -0
- package/dist/utils/next.d.ts +3 -1
- package/dist/utils/next.js +31 -3
- package/dist/utils/url.d.mts +4 -0
- package/dist/utils/url.d.ts +4 -2
- package/dist/utils/url.js +44 -13
- package/package.json +19 -10
|
@@ -0,0 +1,940 @@
|
|
|
1
|
+
// src/lib/stack-app.ts
|
|
2
|
+
import React, { use, useCallback, useMemo } from "react";
|
|
3
|
+
import { KnownError, StackAdminInterface, StackClientInterface, StackServerInterface } from "@stackframe/stack-shared";
|
|
4
|
+
import { getCookie, setOrDeleteCookie } from "./cookie";
|
|
5
|
+
import { StackAssertionError, throwErr } from "@stackframe/stack-shared/dist/utils/errors";
|
|
6
|
+
import { generateUuid } from "@stackframe/stack-shared/dist/utils/uuids";
|
|
7
|
+
import { AsyncResult, Result } from "@stackframe/stack-shared/dist/utils/results";
|
|
8
|
+
import { suspendIfSsr } from "@stackframe/stack-shared/dist/utils/react";
|
|
9
|
+
import { AsyncStore } from "@stackframe/stack-shared/dist/utils/stores";
|
|
10
|
+
import { getProductionModeErrors } from "@stackframe/stack-shared/dist/interface/clientInterface";
|
|
11
|
+
import { isClient } from "../utils/next";
|
|
12
|
+
import { callOAuthCallback, signInWithOAuth } from "./auth";
|
|
13
|
+
import * as NextNavigation from "next/navigation";
|
|
14
|
+
import { constructRedirectUrl } from "../utils/url";
|
|
15
|
+
import { filterUndefined, omit } from "@stackframe/stack-shared/dist/utils/objects";
|
|
16
|
+
import { neverResolve, resolved, runAsynchronously, wait } from "@stackframe/stack-shared/dist/utils/promises";
|
|
17
|
+
import { AsyncCache } from "@stackframe/stack-shared/dist/utils/caches";
|
|
18
|
+
import { suspend } from "@stackframe/stack-shared/dist/utils/react";
|
|
19
|
+
function getUrls(partial) {
|
|
20
|
+
const handler = partial.handler ?? "/handler";
|
|
21
|
+
return {
|
|
22
|
+
handler,
|
|
23
|
+
signIn: `${handler}/signin`,
|
|
24
|
+
afterSignIn: "/",
|
|
25
|
+
signUp: `${handler}/signup`,
|
|
26
|
+
afterSignUp: "/",
|
|
27
|
+
signOut: `${handler}/signout`,
|
|
28
|
+
afterSignOut: "/",
|
|
29
|
+
emailVerification: `${handler}/email-verification`,
|
|
30
|
+
passwordReset: `${handler}/password-reset`,
|
|
31
|
+
forgotPassword: `${handler}/forgot-password`,
|
|
32
|
+
oauthCallback: `${handler}/oauth-callback`,
|
|
33
|
+
magicLinkCallback: `${handler}/magic-link-callback`,
|
|
34
|
+
home: "/",
|
|
35
|
+
accountSettings: `${handler}/account-settings`,
|
|
36
|
+
...filterUndefined(partial)
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function getDefaultProjectId() {
|
|
40
|
+
return process.env.NEXT_PUBLIC_STACK_PROJECT_ID || throwErr("Welcome to Stack! It seems that you haven't provided a project ID. Please create a project on the Stack dashboard at https://app.stack-auth.com and put it in the NEXT_PUBLIC_STACK_PROJECT_ID environment variable.");
|
|
41
|
+
}
|
|
42
|
+
function getDefaultPublishableClientKey() {
|
|
43
|
+
return process.env.NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY || throwErr("Welcome to Stack! It seems that you haven't provided a publishable client key. Please create an API key for your project on the Stack dashboard at https://app.stack-auth.com and copy your publishable client key into the NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY environment variable.");
|
|
44
|
+
}
|
|
45
|
+
function getDefaultSecretServerKey() {
|
|
46
|
+
return process.env.STACK_SECRET_SERVER_KEY || throwErr("No secret server key provided. Please copy your publishable client key from the Stack dashboard and put your it in the STACK_SECRET_SERVER_KEY environment variable.");
|
|
47
|
+
}
|
|
48
|
+
function getDefaultSuperSecretAdminKey() {
|
|
49
|
+
return process.env.STACK_SUPER_SECRET_ADMIN_KEY || throwErr("No super secret admin key provided. Please copy your publishable client key from the Stack dashboard and put it in the STACK_SUPER_SECRET_ADMIN_KEY environment variable.");
|
|
50
|
+
}
|
|
51
|
+
function getDefaultBaseUrl() {
|
|
52
|
+
return process.env.NEXT_PUBLIC_STACK_URL || defaultBaseUrl;
|
|
53
|
+
}
|
|
54
|
+
var defaultBaseUrl = "https://app.stack-auth.com";
|
|
55
|
+
function createEmptyTokenStore() {
|
|
56
|
+
const store = new AsyncStore();
|
|
57
|
+
store.set({
|
|
58
|
+
refreshToken: null,
|
|
59
|
+
accessToken: null
|
|
60
|
+
});
|
|
61
|
+
return store;
|
|
62
|
+
}
|
|
63
|
+
var memoryTokenStore = createEmptyTokenStore();
|
|
64
|
+
var cookieTokenStore = null;
|
|
65
|
+
var cookieTokenStoreInitializer = () => {
|
|
66
|
+
if (!isClient()) {
|
|
67
|
+
throw new Error("Cannot use cookie token store on the server!");
|
|
68
|
+
}
|
|
69
|
+
if (cookieTokenStore === null) {
|
|
70
|
+
cookieTokenStore = new AsyncStore();
|
|
71
|
+
let hasSucceededInWriting = true;
|
|
72
|
+
setInterval(() => {
|
|
73
|
+
if (hasSucceededInWriting) {
|
|
74
|
+
const newValue = {
|
|
75
|
+
refreshToken: getCookie("stack-refresh"),
|
|
76
|
+
accessToken: getCookie("stack-access")
|
|
77
|
+
};
|
|
78
|
+
const res = cookieTokenStore.get();
|
|
79
|
+
if (res.status !== "ok" || res.data.refreshToken !== newValue.refreshToken || res.data.accessToken !== newValue.accessToken) {
|
|
80
|
+
cookieTokenStore.set(newValue);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}, 10);
|
|
84
|
+
cookieTokenStore.onChange((value) => {
|
|
85
|
+
try {
|
|
86
|
+
setOrDeleteCookie("stack-refresh", value.refreshToken);
|
|
87
|
+
setOrDeleteCookie("stack-access", value.accessToken);
|
|
88
|
+
hasSucceededInWriting = true;
|
|
89
|
+
} catch (e) {
|
|
90
|
+
hasSucceededInWriting = false;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return cookieTokenStore;
|
|
95
|
+
};
|
|
96
|
+
var tokenStoreInitializers = /* @__PURE__ */ new Map([
|
|
97
|
+
["cookie", cookieTokenStoreInitializer],
|
|
98
|
+
["nextjs-cookie", () => {
|
|
99
|
+
if (isClient()) {
|
|
100
|
+
return cookieTokenStoreInitializer();
|
|
101
|
+
} else {
|
|
102
|
+
const store = new AsyncStore();
|
|
103
|
+
store.set({
|
|
104
|
+
refreshToken: getCookie("stack-refresh"),
|
|
105
|
+
accessToken: getCookie("stack-access")
|
|
106
|
+
});
|
|
107
|
+
store.onChange((value) => {
|
|
108
|
+
try {
|
|
109
|
+
setOrDeleteCookie("stack-refresh", value.refreshToken);
|
|
110
|
+
setOrDeleteCookie("stack-access", value.accessToken);
|
|
111
|
+
} catch (e) {
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
return store;
|
|
115
|
+
}
|
|
116
|
+
}],
|
|
117
|
+
["memory", () => memoryTokenStore],
|
|
118
|
+
[null, () => createEmptyTokenStore()]
|
|
119
|
+
]);
|
|
120
|
+
function getTokenStore(tokenStoreOptions) {
|
|
121
|
+
return (tokenStoreInitializers.get(tokenStoreOptions) ?? throwErr(`Invalid token store ${tokenStoreOptions}`))();
|
|
122
|
+
}
|
|
123
|
+
var loadingSentinel = Symbol("stackAppCacheLoadingSentinel");
|
|
124
|
+
function useCache(cache, dependencies, caller) {
|
|
125
|
+
suspendIfSsr(caller);
|
|
126
|
+
const subscribe = useCallback((cb) => {
|
|
127
|
+
const { unsubscribe } = cache.onChange(dependencies, () => cb());
|
|
128
|
+
return unsubscribe;
|
|
129
|
+
}, [cache, ...dependencies]);
|
|
130
|
+
const getSnapshot = useCallback(() => {
|
|
131
|
+
return AsyncResult.or(cache.getIfCached(dependencies), loadingSentinel);
|
|
132
|
+
}, [cache, ...dependencies]);
|
|
133
|
+
const value = React.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
134
|
+
if (value === loadingSentinel) {
|
|
135
|
+
return use(cache.getOrWait(dependencies, "read-write"));
|
|
136
|
+
} else {
|
|
137
|
+
return use(resolved(value));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
var stackAppInternalsSymbol = Symbol.for("StackAppInternals");
|
|
141
|
+
var allClientApps = /* @__PURE__ */ new Map();
|
|
142
|
+
var createCache = (fetcher) => {
|
|
143
|
+
return new AsyncCache(
|
|
144
|
+
async (dependencies) => await fetcher(dependencies),
|
|
145
|
+
{}
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
var createCacheByTokenStore = (fetcher) => {
|
|
149
|
+
return new AsyncCache(
|
|
150
|
+
async ([tokenStore, ...extraDependencies]) => await fetcher(tokenStore, extraDependencies),
|
|
151
|
+
{
|
|
152
|
+
onSubscribe: ([tokenStore], refresh) => {
|
|
153
|
+
const handlerObj = tokenStore.onChange((newValue, oldValue) => {
|
|
154
|
+
if (JSON.stringify(newValue) === JSON.stringify(oldValue))
|
|
155
|
+
return;
|
|
156
|
+
refresh();
|
|
157
|
+
});
|
|
158
|
+
return () => handlerObj.unsubscribe();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
};
|
|
163
|
+
var _StackClientAppImpl = class __StackClientAppImpl {
|
|
164
|
+
_uniqueIdentifier;
|
|
165
|
+
_interface;
|
|
166
|
+
_tokenStoreOptions;
|
|
167
|
+
_urlOptions;
|
|
168
|
+
__DEMO_ENABLE_SLIGHT_FETCH_DELAY = false;
|
|
169
|
+
_currentUserCache = createCacheByTokenStore(async (tokenStore) => {
|
|
170
|
+
if (this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY) {
|
|
171
|
+
await wait(2e3);
|
|
172
|
+
}
|
|
173
|
+
const user = await this._interface.getClientUserByToken(tokenStore);
|
|
174
|
+
return Result.or(user, null);
|
|
175
|
+
});
|
|
176
|
+
_currentProjectCache = createCache(async () => {
|
|
177
|
+
return Result.orThrow(await this._interface.getClientProject());
|
|
178
|
+
});
|
|
179
|
+
_ownedProjectsCache = createCacheByTokenStore(async (tokenStore) => {
|
|
180
|
+
return await this._interface.listProjects(tokenStore);
|
|
181
|
+
});
|
|
182
|
+
constructor(options) {
|
|
183
|
+
if ("interface" in options) {
|
|
184
|
+
this._interface = options.interface;
|
|
185
|
+
} else {
|
|
186
|
+
this._interface = new StackClientInterface({
|
|
187
|
+
baseUrl: options.baseUrl ?? getDefaultBaseUrl(),
|
|
188
|
+
projectId: options.projectId ?? getDefaultProjectId(),
|
|
189
|
+
publishableClientKey: options.publishableClientKey ?? getDefaultPublishableClientKey()
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
this._tokenStoreOptions = options.tokenStore;
|
|
193
|
+
this._urlOptions = options.urls ?? {};
|
|
194
|
+
this._uniqueIdentifier = options.uniqueIdentifier ?? generateUuid();
|
|
195
|
+
if (allClientApps.has(this._uniqueIdentifier)) {
|
|
196
|
+
throw new StackAssertionError("A Stack client app with the same unique identifier already exists");
|
|
197
|
+
}
|
|
198
|
+
allClientApps.set(this._uniqueIdentifier, [options.checkString ?? "default check string", this]);
|
|
199
|
+
}
|
|
200
|
+
hasPersistentTokenStore() {
|
|
201
|
+
return this._tokenStoreOptions !== null;
|
|
202
|
+
}
|
|
203
|
+
_ensurePersistentTokenStore() {
|
|
204
|
+
if (!this.hasPersistentTokenStore()) {
|
|
205
|
+
throw new Error("Cannot call this function on a Stack app without a persistent token store. Make sure the tokenStore option is set to a non-null value when initializing Stack.");
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
isInternalProject() {
|
|
209
|
+
return this.projectId === "internal";
|
|
210
|
+
}
|
|
211
|
+
_ensureInternalProject() {
|
|
212
|
+
if (!this.isInternalProject()) {
|
|
213
|
+
throw new Error("Cannot call this function on a Stack app with a project ID other than 'internal'.");
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
_userFromJson(json) {
|
|
217
|
+
return {
|
|
218
|
+
projectId: json.projectId,
|
|
219
|
+
id: json.id,
|
|
220
|
+
displayName: json.displayName,
|
|
221
|
+
primaryEmail: json.primaryEmail,
|
|
222
|
+
primaryEmailVerified: json.primaryEmailVerified,
|
|
223
|
+
profileImageUrl: json.profileImageUrl,
|
|
224
|
+
signedUpAt: new Date(json.signedUpAtMillis),
|
|
225
|
+
clientMetadata: json.clientMetadata,
|
|
226
|
+
authMethod: json.authMethod,
|
|
227
|
+
hasPassword: json.hasPassword,
|
|
228
|
+
authWithEmail: json.authWithEmail,
|
|
229
|
+
oauthProviders: json.oauthProviders,
|
|
230
|
+
toJson() {
|
|
231
|
+
return json;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
_currentUserFromJson(json, tokenStore) {
|
|
236
|
+
if (json === null)
|
|
237
|
+
return null;
|
|
238
|
+
const app = this;
|
|
239
|
+
const currentUser = {
|
|
240
|
+
...this._userFromJson(json),
|
|
241
|
+
tokenStore,
|
|
242
|
+
update(update) {
|
|
243
|
+
return app._updateUser(update, tokenStore);
|
|
244
|
+
},
|
|
245
|
+
signOut() {
|
|
246
|
+
return app._signOut(tokenStore);
|
|
247
|
+
},
|
|
248
|
+
sendVerificationEmail() {
|
|
249
|
+
return app._sendVerificationEmail(tokenStore);
|
|
250
|
+
},
|
|
251
|
+
updatePassword(options) {
|
|
252
|
+
return app._updatePassword(options, tokenStore);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
if (this.isInternalProject()) {
|
|
256
|
+
const internalUser = {
|
|
257
|
+
...currentUser,
|
|
258
|
+
createProject(newProject) {
|
|
259
|
+
return app._createProject(newProject);
|
|
260
|
+
},
|
|
261
|
+
listOwnedProjects() {
|
|
262
|
+
return app._listOwnedProjects();
|
|
263
|
+
},
|
|
264
|
+
useOwnedProjects() {
|
|
265
|
+
return app._useOwnedProjects();
|
|
266
|
+
},
|
|
267
|
+
onOwnedProjectsChange(callback) {
|
|
268
|
+
return app._onOwnedProjectsChange(callback);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
Object.freeze(internalUser);
|
|
272
|
+
return internalUser;
|
|
273
|
+
} else {
|
|
274
|
+
Object.freeze(currentUser);
|
|
275
|
+
return currentUser;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
_userToJson(user) {
|
|
279
|
+
return {
|
|
280
|
+
projectId: user.projectId,
|
|
281
|
+
id: user.id,
|
|
282
|
+
displayName: user.displayName,
|
|
283
|
+
primaryEmail: user.primaryEmail,
|
|
284
|
+
primaryEmailVerified: user.primaryEmailVerified,
|
|
285
|
+
profileImageUrl: user.profileImageUrl,
|
|
286
|
+
signedUpAtMillis: user.signedUpAt.getTime(),
|
|
287
|
+
clientMetadata: user.clientMetadata,
|
|
288
|
+
authMethod: user.authMethod,
|
|
289
|
+
hasPassword: user.hasPassword,
|
|
290
|
+
authWithEmail: user.authWithEmail,
|
|
291
|
+
oauthProviders: user.oauthProviders
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
_projectAdminFromJson(data, adminInterface, onRefresh) {
|
|
295
|
+
if (data.id !== adminInterface.projectId) {
|
|
296
|
+
throw new Error(`The project ID of the provided project JSON (${data.id}) does not match the project ID of the app (${adminInterface.projectId})! This is a Stack bug.`);
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
id: data.id,
|
|
300
|
+
displayName: data.displayName,
|
|
301
|
+
description: data.description,
|
|
302
|
+
createdAt: new Date(data.createdAtMillis),
|
|
303
|
+
userCount: data.userCount,
|
|
304
|
+
isProductionMode: data.isProductionMode,
|
|
305
|
+
evaluatedConfig: {
|
|
306
|
+
id: data.evaluatedConfig.id,
|
|
307
|
+
credentialEnabled: data.evaluatedConfig.credentialEnabled,
|
|
308
|
+
magicLinkEnabled: data.evaluatedConfig.magicLinkEnabled,
|
|
309
|
+
allowLocalhost: data.evaluatedConfig.allowLocalhost,
|
|
310
|
+
oauthProviders: data.evaluatedConfig.oauthProviders,
|
|
311
|
+
emailConfig: data.evaluatedConfig.emailConfig,
|
|
312
|
+
domains: data.evaluatedConfig.domains
|
|
313
|
+
},
|
|
314
|
+
async update(update) {
|
|
315
|
+
await adminInterface.updateProject(update);
|
|
316
|
+
await onRefresh();
|
|
317
|
+
},
|
|
318
|
+
toJson() {
|
|
319
|
+
return data;
|
|
320
|
+
},
|
|
321
|
+
getProductionModeErrors() {
|
|
322
|
+
return getProductionModeErrors(this.toJson());
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
_createAdminInterface(forProjectId, tokenStore) {
|
|
327
|
+
return new StackAdminInterface({
|
|
328
|
+
baseUrl: this._interface.options.baseUrl,
|
|
329
|
+
projectId: forProjectId,
|
|
330
|
+
projectOwnerTokens: tokenStore
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
get projectId() {
|
|
334
|
+
return this._interface.projectId;
|
|
335
|
+
}
|
|
336
|
+
get urls() {
|
|
337
|
+
return getUrls(this._urlOptions);
|
|
338
|
+
}
|
|
339
|
+
_redirectTo(handlerName) {
|
|
340
|
+
if (!this.urls[handlerName]) {
|
|
341
|
+
throw new Error(`No URL for handler name ${handlerName}`);
|
|
342
|
+
}
|
|
343
|
+
window.location.href = this.urls[handlerName];
|
|
344
|
+
return neverResolve();
|
|
345
|
+
}
|
|
346
|
+
async redirectToSignIn() {
|
|
347
|
+
return await this._redirectTo("signIn");
|
|
348
|
+
}
|
|
349
|
+
async redirectToSignUp() {
|
|
350
|
+
return await this._redirectTo("signUp");
|
|
351
|
+
}
|
|
352
|
+
async redirectToSignOut() {
|
|
353
|
+
return await this._redirectTo("signOut");
|
|
354
|
+
}
|
|
355
|
+
async redirectToEmailVerification() {
|
|
356
|
+
return await this._redirectTo("emailVerification");
|
|
357
|
+
}
|
|
358
|
+
async redirectToPasswordReset() {
|
|
359
|
+
return await this._redirectTo("passwordReset");
|
|
360
|
+
}
|
|
361
|
+
async redirectToForgotPassword() {
|
|
362
|
+
return await this._redirectTo("forgotPassword");
|
|
363
|
+
}
|
|
364
|
+
async redirectToHome() {
|
|
365
|
+
return await this._redirectTo("home");
|
|
366
|
+
}
|
|
367
|
+
async redirectToOAuthCallback() {
|
|
368
|
+
return await this._redirectTo("oauthCallback");
|
|
369
|
+
}
|
|
370
|
+
async redirectToMagicLinkCallback() {
|
|
371
|
+
return await this._redirectTo("magicLinkCallback");
|
|
372
|
+
}
|
|
373
|
+
async redirectToAfterSignIn() {
|
|
374
|
+
return await this._redirectTo("afterSignIn");
|
|
375
|
+
}
|
|
376
|
+
async redirectToAfterSignUp() {
|
|
377
|
+
return await this._redirectTo("afterSignUp");
|
|
378
|
+
}
|
|
379
|
+
async redirectToAfterSignOut() {
|
|
380
|
+
return await this._redirectTo("afterSignOut");
|
|
381
|
+
}
|
|
382
|
+
async redirectToAccountSettings() {
|
|
383
|
+
return await this._redirectTo("accountSettings");
|
|
384
|
+
}
|
|
385
|
+
async sendForgotPasswordEmail(email) {
|
|
386
|
+
const redirectUrl = constructRedirectUrl(this.urls.passwordReset);
|
|
387
|
+
const error = await this._interface.sendForgotPasswordEmail(email, redirectUrl);
|
|
388
|
+
return error;
|
|
389
|
+
}
|
|
390
|
+
async sendMagicLinkEmail(email) {
|
|
391
|
+
const magicLinkRedirectUrl = constructRedirectUrl(this.urls.magicLinkCallback);
|
|
392
|
+
const error = await this._interface.sendMagicLinkEmail(email, magicLinkRedirectUrl);
|
|
393
|
+
return error;
|
|
394
|
+
}
|
|
395
|
+
async resetPassword(options) {
|
|
396
|
+
const error = await this._interface.resetPassword(options);
|
|
397
|
+
return error;
|
|
398
|
+
}
|
|
399
|
+
async verifyPasswordResetCode(code) {
|
|
400
|
+
return await this._interface.verifyPasswordResetCode(code);
|
|
401
|
+
}
|
|
402
|
+
async verifyEmail(code) {
|
|
403
|
+
return await this._interface.verifyEmail(code);
|
|
404
|
+
}
|
|
405
|
+
async getUser(options) {
|
|
406
|
+
this._ensurePersistentTokenStore();
|
|
407
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
408
|
+
const userJson = await this._currentUserCache.getOrWait([tokenStore], "write-only");
|
|
409
|
+
if (userJson === null) {
|
|
410
|
+
switch (options?.or) {
|
|
411
|
+
case "redirect": {
|
|
412
|
+
NextNavigation.redirect(this.urls.signIn, NextNavigation.RedirectType.replace);
|
|
413
|
+
throw new Error("redirect should never return!");
|
|
414
|
+
}
|
|
415
|
+
case "throw": {
|
|
416
|
+
throw new Error("User is not signed in but getUser was called with { or: 'throw' }");
|
|
417
|
+
}
|
|
418
|
+
default: {
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return this._currentUserFromJson(userJson, tokenStore);
|
|
424
|
+
}
|
|
425
|
+
useUser(options) {
|
|
426
|
+
this._ensurePersistentTokenStore();
|
|
427
|
+
const router = NextNavigation.useRouter();
|
|
428
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
429
|
+
const userJson = useCache(this._currentUserCache, [tokenStore], "useUser()");
|
|
430
|
+
if (userJson === null) {
|
|
431
|
+
switch (options?.or) {
|
|
432
|
+
case "redirect": {
|
|
433
|
+
router.replace(this.urls.signIn);
|
|
434
|
+
suspend();
|
|
435
|
+
throw new Error("suspend should never return! This is a bug in Stack.");
|
|
436
|
+
}
|
|
437
|
+
case "throw": {
|
|
438
|
+
throw new Error("User is not signed in but useUser was called with { or: 'throw' }");
|
|
439
|
+
}
|
|
440
|
+
case void 0:
|
|
441
|
+
case "return-null": {
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return useMemo(() => {
|
|
446
|
+
return this._currentUserFromJson(userJson, tokenStore);
|
|
447
|
+
}, [userJson, tokenStore, options?.or]);
|
|
448
|
+
}
|
|
449
|
+
onUserChange(callback) {
|
|
450
|
+
this._ensurePersistentTokenStore();
|
|
451
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
452
|
+
return this._currentUserCache.onChange([tokenStore], (userJson) => {
|
|
453
|
+
callback(this._currentUserFromJson(userJson, tokenStore));
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
async _updateUser(update, tokenStore) {
|
|
457
|
+
const res = await this._interface.setClientUserCustomizableData(update, tokenStore);
|
|
458
|
+
await this._refreshUser(tokenStore);
|
|
459
|
+
return res;
|
|
460
|
+
}
|
|
461
|
+
async signInWithOAuth(provider) {
|
|
462
|
+
this._ensurePersistentTokenStore();
|
|
463
|
+
await signInWithOAuth(this._interface, { provider, redirectUrl: this.urls.oauthCallback });
|
|
464
|
+
}
|
|
465
|
+
async signInWithCredential(options) {
|
|
466
|
+
this._ensurePersistentTokenStore();
|
|
467
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
468
|
+
const errorCode = await this._interface.signInWithCredential(options.email, options.password, tokenStore);
|
|
469
|
+
if (!errorCode) {
|
|
470
|
+
window.location.assign(this.urls.afterSignIn);
|
|
471
|
+
}
|
|
472
|
+
return errorCode;
|
|
473
|
+
}
|
|
474
|
+
async signUpWithCredential(options) {
|
|
475
|
+
this._ensurePersistentTokenStore();
|
|
476
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
477
|
+
const emailVerificationRedirectUrl = constructRedirectUrl(this.urls.emailVerification);
|
|
478
|
+
const errorCode = await this._interface.signUpWithCredential(
|
|
479
|
+
options.email,
|
|
480
|
+
options.password,
|
|
481
|
+
emailVerificationRedirectUrl,
|
|
482
|
+
tokenStore
|
|
483
|
+
);
|
|
484
|
+
if (!errorCode) {
|
|
485
|
+
window.location.assign(this.urls.afterSignUp);
|
|
486
|
+
}
|
|
487
|
+
return errorCode;
|
|
488
|
+
}
|
|
489
|
+
async signInWithMagicLink(code) {
|
|
490
|
+
this._ensurePersistentTokenStore();
|
|
491
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
492
|
+
const result = await this._interface.signInWithMagicLink(code, tokenStore);
|
|
493
|
+
if (result instanceof KnownError) {
|
|
494
|
+
return result;
|
|
495
|
+
}
|
|
496
|
+
if (result.newUser) {
|
|
497
|
+
window.location.replace(this.urls.afterSignUp);
|
|
498
|
+
} else {
|
|
499
|
+
window.location.replace(this.urls.afterSignIn);
|
|
500
|
+
}
|
|
501
|
+
await neverResolve();
|
|
502
|
+
}
|
|
503
|
+
async callOAuthCallback() {
|
|
504
|
+
this._ensurePersistentTokenStore();
|
|
505
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
506
|
+
const result = await callOAuthCallback(this._interface, tokenStore, this.urls.oauthCallback);
|
|
507
|
+
if (result?.newUser) {
|
|
508
|
+
window.location.replace(this.urls.afterSignUp);
|
|
509
|
+
} else {
|
|
510
|
+
window.location.replace(this.urls.afterSignIn);
|
|
511
|
+
}
|
|
512
|
+
await neverResolve();
|
|
513
|
+
}
|
|
514
|
+
async _signOut(tokenStore) {
|
|
515
|
+
await this._interface.signOut(tokenStore);
|
|
516
|
+
window.location.assign(this.urls.afterSignOut);
|
|
517
|
+
}
|
|
518
|
+
async _sendVerificationEmail(tokenStore) {
|
|
519
|
+
const emailVerificationRedirectUrl = constructRedirectUrl(this.urls.emailVerification);
|
|
520
|
+
return await this._interface.sendVerificationEmail(emailVerificationRedirectUrl, tokenStore);
|
|
521
|
+
}
|
|
522
|
+
async _updatePassword(options, tokenStore) {
|
|
523
|
+
return await this._interface.updatePassword(options, tokenStore);
|
|
524
|
+
}
|
|
525
|
+
async signOut() {
|
|
526
|
+
const user = await this.getUser();
|
|
527
|
+
if (user) {
|
|
528
|
+
await user.signOut();
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
async getProject() {
|
|
532
|
+
return await this._currentProjectCache.getOrWait([], "write-only");
|
|
533
|
+
}
|
|
534
|
+
useProject() {
|
|
535
|
+
return useCache(this._currentProjectCache, [], "useProject()");
|
|
536
|
+
}
|
|
537
|
+
onProjectChange(callback) {
|
|
538
|
+
return this._currentProjectCache.onChange([], callback);
|
|
539
|
+
}
|
|
540
|
+
async _listOwnedProjects() {
|
|
541
|
+
this._ensureInternalProject();
|
|
542
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
543
|
+
const json = await this._ownedProjectsCache.getOrWait([tokenStore], "write-only");
|
|
544
|
+
return json.map((j) => this._projectAdminFromJson(
|
|
545
|
+
j,
|
|
546
|
+
this._createAdminInterface(j.id, tokenStore),
|
|
547
|
+
() => this._refreshOwnedProjects(tokenStore)
|
|
548
|
+
));
|
|
549
|
+
}
|
|
550
|
+
_useOwnedProjects() {
|
|
551
|
+
this._ensureInternalProject();
|
|
552
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
553
|
+
const json = useCache(this._ownedProjectsCache, [tokenStore], "useOwnedProjects()");
|
|
554
|
+
return useMemo(() => json.map((j) => this._projectAdminFromJson(
|
|
555
|
+
j,
|
|
556
|
+
this._createAdminInterface(j.id, tokenStore),
|
|
557
|
+
() => this._refreshOwnedProjects(tokenStore)
|
|
558
|
+
)), [json]);
|
|
559
|
+
}
|
|
560
|
+
_onOwnedProjectsChange(callback) {
|
|
561
|
+
this._ensureInternalProject();
|
|
562
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
563
|
+
return this._ownedProjectsCache.onChange([tokenStore], (projects) => {
|
|
564
|
+
callback(projects.map((j) => this._projectAdminFromJson(
|
|
565
|
+
j,
|
|
566
|
+
this._createAdminInterface(j.id, tokenStore),
|
|
567
|
+
() => this._refreshOwnedProjects(tokenStore)
|
|
568
|
+
)));
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
async _createProject(newProject) {
|
|
572
|
+
this._ensureInternalProject();
|
|
573
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
574
|
+
const json = await this._interface.createProject(newProject, tokenStore);
|
|
575
|
+
const res = this._projectAdminFromJson(
|
|
576
|
+
json,
|
|
577
|
+
this._createAdminInterface(json.id, tokenStore),
|
|
578
|
+
() => this._refreshOwnedProjects(tokenStore)
|
|
579
|
+
);
|
|
580
|
+
await this._refreshOwnedProjects(tokenStore);
|
|
581
|
+
return res;
|
|
582
|
+
}
|
|
583
|
+
async _refreshUser(tokenStore) {
|
|
584
|
+
await this._currentUserCache.refresh([tokenStore]);
|
|
585
|
+
}
|
|
586
|
+
async _refreshUsers() {
|
|
587
|
+
}
|
|
588
|
+
async _refreshProject() {
|
|
589
|
+
await this._currentProjectCache.refresh([]);
|
|
590
|
+
}
|
|
591
|
+
async _refreshOwnedProjects(tokenStore) {
|
|
592
|
+
await this._ownedProjectsCache.refresh([tokenStore]);
|
|
593
|
+
}
|
|
594
|
+
static get [stackAppInternalsSymbol]() {
|
|
595
|
+
return {
|
|
596
|
+
fromClientJson: (json) => {
|
|
597
|
+
const providedCheckString = JSON.stringify(omit(json, [
|
|
598
|
+
/* none currently */
|
|
599
|
+
]));
|
|
600
|
+
const existing = allClientApps.get(json.uniqueIdentifier);
|
|
601
|
+
if (existing) {
|
|
602
|
+
const [existingCheckString, clientApp] = existing;
|
|
603
|
+
if (existingCheckString !== providedCheckString) {
|
|
604
|
+
throw new StackAssertionError("The provided app JSON does not match the configuration of the existing client app with the same unique identifier", { providedObj: json, existingString: existingCheckString });
|
|
605
|
+
}
|
|
606
|
+
return clientApp;
|
|
607
|
+
}
|
|
608
|
+
return new __StackClientAppImpl({
|
|
609
|
+
...json,
|
|
610
|
+
checkString: providedCheckString
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
get [stackAppInternalsSymbol]() {
|
|
616
|
+
return {
|
|
617
|
+
toClientJson: () => {
|
|
618
|
+
if (!("publishableClientKey" in this._interface.options)) {
|
|
619
|
+
throw Error("Cannot serialize to JSON from an application without a publishable client key");
|
|
620
|
+
}
|
|
621
|
+
return {
|
|
622
|
+
baseUrl: this._interface.options.baseUrl,
|
|
623
|
+
projectId: this.projectId,
|
|
624
|
+
publishableClientKey: this._interface.options.publishableClientKey,
|
|
625
|
+
tokenStore: this._tokenStoreOptions,
|
|
626
|
+
urls: this._urlOptions,
|
|
627
|
+
uniqueIdentifier: this._uniqueIdentifier
|
|
628
|
+
};
|
|
629
|
+
},
|
|
630
|
+
setCurrentUser: (userJsonPromise) => {
|
|
631
|
+
runAsynchronously(this._currentUserCache.forceSetCachedValueAsync([getTokenStore(this._tokenStoreOptions)], userJsonPromise));
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
var _StackServerAppImpl = class extends _StackClientAppImpl {
|
|
637
|
+
// TODO override the client user cache to use the server user cache, so we save some requests
|
|
638
|
+
_currentServerUserCache = createCacheByTokenStore(async (tokenStore) => {
|
|
639
|
+
const user = await this._interface.getServerUserByToken(tokenStore);
|
|
640
|
+
return Result.or(user, null);
|
|
641
|
+
});
|
|
642
|
+
_serverUsersCache = createCache(async () => {
|
|
643
|
+
return await this._interface.listUsers();
|
|
644
|
+
});
|
|
645
|
+
constructor(options) {
|
|
646
|
+
if ("interface" in options) {
|
|
647
|
+
super({
|
|
648
|
+
interface: options.interface,
|
|
649
|
+
tokenStore: options.tokenStore,
|
|
650
|
+
urls: options.urls
|
|
651
|
+
});
|
|
652
|
+
} else {
|
|
653
|
+
super({
|
|
654
|
+
interface: new StackServerInterface({
|
|
655
|
+
baseUrl: options.baseUrl ?? getDefaultBaseUrl(),
|
|
656
|
+
projectId: options.projectId ?? getDefaultProjectId(),
|
|
657
|
+
publishableClientKey: options.publishableClientKey ?? getDefaultPublishableClientKey(),
|
|
658
|
+
secretServerKey: options.secretServerKey ?? getDefaultSecretServerKey()
|
|
659
|
+
}),
|
|
660
|
+
tokenStore: options.tokenStore,
|
|
661
|
+
urls: options.urls ?? {}
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
_serverUserFromJson(json) {
|
|
666
|
+
if (json === null)
|
|
667
|
+
return null;
|
|
668
|
+
const app = this;
|
|
669
|
+
return {
|
|
670
|
+
...this._userFromJson(json),
|
|
671
|
+
serverMetadata: json.serverMetadata,
|
|
672
|
+
async delete() {
|
|
673
|
+
const res = await app._interface.deleteServerUser(this.id);
|
|
674
|
+
await app._refreshUsers();
|
|
675
|
+
return res;
|
|
676
|
+
},
|
|
677
|
+
async update(update) {
|
|
678
|
+
const res = await app._interface.setServerUserCustomizableData(this.id, update);
|
|
679
|
+
await app._refreshUsers();
|
|
680
|
+
return res;
|
|
681
|
+
},
|
|
682
|
+
getClientUser() {
|
|
683
|
+
return app._userFromJson(json);
|
|
684
|
+
},
|
|
685
|
+
toJson() {
|
|
686
|
+
return app._serverUserToJson(this);
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
_currentServerUserFromJson(json, tokenStore) {
|
|
691
|
+
if (json === null)
|
|
692
|
+
return null;
|
|
693
|
+
const app = this;
|
|
694
|
+
const nonCurrentServerUser = this._serverUserFromJson(json);
|
|
695
|
+
const currentUser = {
|
|
696
|
+
...nonCurrentServerUser,
|
|
697
|
+
tokenStore,
|
|
698
|
+
async delete() {
|
|
699
|
+
const res = await nonCurrentServerUser.delete();
|
|
700
|
+
await app._refreshUser(tokenStore);
|
|
701
|
+
return res;
|
|
702
|
+
},
|
|
703
|
+
async update(update) {
|
|
704
|
+
const res = await nonCurrentServerUser.update(update);
|
|
705
|
+
await app._refreshUser(tokenStore);
|
|
706
|
+
return res;
|
|
707
|
+
},
|
|
708
|
+
signOut() {
|
|
709
|
+
return app._signOut(tokenStore);
|
|
710
|
+
},
|
|
711
|
+
getClientUser() {
|
|
712
|
+
return app._currentUserFromJson(json, tokenStore);
|
|
713
|
+
},
|
|
714
|
+
sendVerificationEmail() {
|
|
715
|
+
return app._sendVerificationEmail(tokenStore);
|
|
716
|
+
},
|
|
717
|
+
updatePassword(options) {
|
|
718
|
+
return app._updatePassword(options, tokenStore);
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
if (this.isInternalProject()) {
|
|
722
|
+
const internalUser = {
|
|
723
|
+
...currentUser,
|
|
724
|
+
createProject(newProject) {
|
|
725
|
+
return app._createProject(newProject);
|
|
726
|
+
},
|
|
727
|
+
listOwnedProjects() {
|
|
728
|
+
return app._listOwnedProjects();
|
|
729
|
+
},
|
|
730
|
+
useOwnedProjects() {
|
|
731
|
+
return app._useOwnedProjects();
|
|
732
|
+
},
|
|
733
|
+
onOwnedProjectsChange(callback) {
|
|
734
|
+
return app._onOwnedProjectsChange(callback);
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
Object.freeze(internalUser);
|
|
738
|
+
return internalUser;
|
|
739
|
+
} else {
|
|
740
|
+
Object.freeze(currentUser);
|
|
741
|
+
return currentUser;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
_serverUserToJson(user) {
|
|
745
|
+
return {
|
|
746
|
+
projectId: user.projectId,
|
|
747
|
+
id: user.id,
|
|
748
|
+
displayName: user.displayName,
|
|
749
|
+
primaryEmail: user.primaryEmail,
|
|
750
|
+
primaryEmailVerified: user.primaryEmailVerified,
|
|
751
|
+
profileImageUrl: user.profileImageUrl,
|
|
752
|
+
signedUpAtMillis: user.signedUpAt.getTime(),
|
|
753
|
+
clientMetadata: user.clientMetadata,
|
|
754
|
+
serverMetadata: user.serverMetadata,
|
|
755
|
+
authMethod: user.authMethod,
|
|
756
|
+
hasPassword: user.hasPassword,
|
|
757
|
+
authWithEmail: user.authWithEmail,
|
|
758
|
+
oauthProviders: user.oauthProviders
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
async getServerUser() {
|
|
762
|
+
this._ensurePersistentTokenStore();
|
|
763
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
764
|
+
const userJson = await this._currentServerUserCache.getOrWait([tokenStore], "write-only");
|
|
765
|
+
return this._currentServerUserFromJson(userJson, tokenStore);
|
|
766
|
+
}
|
|
767
|
+
useServerUser(options) {
|
|
768
|
+
this._ensurePersistentTokenStore();
|
|
769
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
770
|
+
const userJson = useCache(this._currentServerUserCache, [tokenStore], "useServerUser()");
|
|
771
|
+
return useMemo(() => {
|
|
772
|
+
if (options?.required && userJson === null) {
|
|
773
|
+
use(this.redirectToSignIn());
|
|
774
|
+
}
|
|
775
|
+
return this._currentServerUserFromJson(userJson, tokenStore);
|
|
776
|
+
}, [userJson, tokenStore, options?.required]);
|
|
777
|
+
}
|
|
778
|
+
onServerUserChange(callback) {
|
|
779
|
+
this._ensurePersistentTokenStore();
|
|
780
|
+
const tokenStore = getTokenStore(this._tokenStoreOptions);
|
|
781
|
+
return this._currentServerUserCache.onChange([tokenStore], (userJson) => {
|
|
782
|
+
callback(this._currentServerUserFromJson(userJson, tokenStore));
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
async listServerUsers() {
|
|
786
|
+
const json = await this._serverUsersCache.getOrWait([], "write-only");
|
|
787
|
+
return json.map((j) => this._serverUserFromJson(j));
|
|
788
|
+
}
|
|
789
|
+
useServerUsers() {
|
|
790
|
+
const json = useCache(this._serverUsersCache, [], "useServerUsers()");
|
|
791
|
+
return useMemo(() => {
|
|
792
|
+
return json.map((j) => this._serverUserFromJson(j));
|
|
793
|
+
}, [json]);
|
|
794
|
+
}
|
|
795
|
+
onServerUsersChange(callback) {
|
|
796
|
+
return this._serverUsersCache.onChange([], (users) => {
|
|
797
|
+
callback(users.map((j) => this._serverUserFromJson(j)));
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
async _refreshUser(tokenStore) {
|
|
801
|
+
await Promise.all([
|
|
802
|
+
super._refreshUser(tokenStore),
|
|
803
|
+
this._currentServerUserCache.refresh([tokenStore])
|
|
804
|
+
]);
|
|
805
|
+
}
|
|
806
|
+
async _refreshUsers() {
|
|
807
|
+
await Promise.all([
|
|
808
|
+
super._refreshUsers(),
|
|
809
|
+
this._serverUsersCache.refresh([])
|
|
810
|
+
]);
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
var _StackAdminAppImpl = class extends _StackServerAppImpl {
|
|
814
|
+
_adminProjectCache = createCache(async () => {
|
|
815
|
+
return await this._interface.getProject();
|
|
816
|
+
});
|
|
817
|
+
_apiKeySetsCache = createCache(async () => {
|
|
818
|
+
return await this._interface.listApiKeySets();
|
|
819
|
+
});
|
|
820
|
+
constructor(options) {
|
|
821
|
+
super({
|
|
822
|
+
interface: new StackAdminInterface({
|
|
823
|
+
baseUrl: options.baseUrl ?? getDefaultBaseUrl(),
|
|
824
|
+
projectId: options.projectId ?? getDefaultProjectId(),
|
|
825
|
+
..."projectOwnerTokens" in options ? {
|
|
826
|
+
projectOwnerTokens: options.projectOwnerTokens
|
|
827
|
+
} : {
|
|
828
|
+
publishableClientKey: options.publishableClientKey ?? getDefaultPublishableClientKey(),
|
|
829
|
+
secretServerKey: options.secretServerKey ?? getDefaultSecretServerKey(),
|
|
830
|
+
superSecretAdminKey: options.superSecretAdminKey ?? getDefaultSuperSecretAdminKey()
|
|
831
|
+
}
|
|
832
|
+
}),
|
|
833
|
+
tokenStore: options.tokenStore,
|
|
834
|
+
urls: options.urls
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
_createApiKeySetBaseFromJson(data) {
|
|
838
|
+
const app = this;
|
|
839
|
+
return {
|
|
840
|
+
id: data.id,
|
|
841
|
+
description: data.description,
|
|
842
|
+
expiresAt: new Date(data.expiresAtMillis),
|
|
843
|
+
manuallyRevokedAt: data.manuallyRevokedAtMillis ? new Date(data.manuallyRevokedAtMillis) : null,
|
|
844
|
+
createdAt: new Date(data.createdAtMillis),
|
|
845
|
+
isValid() {
|
|
846
|
+
return this.whyInvalid() === null;
|
|
847
|
+
},
|
|
848
|
+
whyInvalid() {
|
|
849
|
+
if (this.expiresAt.getTime() < Date.now())
|
|
850
|
+
return "expired";
|
|
851
|
+
if (this.manuallyRevokedAt)
|
|
852
|
+
return "manually-revoked";
|
|
853
|
+
return null;
|
|
854
|
+
},
|
|
855
|
+
async revoke() {
|
|
856
|
+
const res = await app._interface.revokeApiKeySetById(data.id);
|
|
857
|
+
await app._refreshApiKeySets();
|
|
858
|
+
return res;
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
_createApiKeySetFromJson(data) {
|
|
863
|
+
return {
|
|
864
|
+
...this._createApiKeySetBaseFromJson(data),
|
|
865
|
+
publishableClientKey: data.publishableClientKey ? { lastFour: data.publishableClientKey.lastFour } : null,
|
|
866
|
+
secretServerKey: data.secretServerKey ? { lastFour: data.secretServerKey.lastFour } : null,
|
|
867
|
+
superSecretAdminKey: data.superSecretAdminKey ? { lastFour: data.superSecretAdminKey.lastFour } : null
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
_createApiKeySetFirstViewFromJson(data) {
|
|
871
|
+
return {
|
|
872
|
+
...this._createApiKeySetBaseFromJson(data),
|
|
873
|
+
publishableClientKey: data.publishableClientKey,
|
|
874
|
+
secretServerKey: data.secretServerKey,
|
|
875
|
+
superSecretAdminKey: data.superSecretAdminKey
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
async getProjectAdmin() {
|
|
879
|
+
return this._projectAdminFromJson(
|
|
880
|
+
await this._adminProjectCache.getOrWait([], "write-only"),
|
|
881
|
+
this._interface,
|
|
882
|
+
() => this._refreshProject()
|
|
883
|
+
);
|
|
884
|
+
}
|
|
885
|
+
useProjectAdmin() {
|
|
886
|
+
const json = useCache(this._adminProjectCache, [], "useProjectAdmin()");
|
|
887
|
+
return useMemo(() => this._projectAdminFromJson(
|
|
888
|
+
json,
|
|
889
|
+
this._interface,
|
|
890
|
+
() => this._refreshProject()
|
|
891
|
+
), [json]);
|
|
892
|
+
}
|
|
893
|
+
onProjectAdminChange(callback) {
|
|
894
|
+
return this._adminProjectCache.onChange([], (project) => {
|
|
895
|
+
callback(this._projectAdminFromJson(
|
|
896
|
+
project,
|
|
897
|
+
this._interface,
|
|
898
|
+
() => this._refreshProject()
|
|
899
|
+
));
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
async listApiKeySets() {
|
|
903
|
+
const json = await this._apiKeySetsCache.getOrWait([], "write-only");
|
|
904
|
+
return json.map((j) => this._createApiKeySetFromJson(j));
|
|
905
|
+
}
|
|
906
|
+
useApiKeySets() {
|
|
907
|
+
const json = useCache(this._apiKeySetsCache, [], "useApiKeySets()");
|
|
908
|
+
return useMemo(() => {
|
|
909
|
+
return json.map((j) => this._createApiKeySetFromJson(j));
|
|
910
|
+
}, [json]);
|
|
911
|
+
}
|
|
912
|
+
onApiKeySetsChange(callback) {
|
|
913
|
+
return this._apiKeySetsCache.onChange([], (apiKeySets) => {
|
|
914
|
+
callback(apiKeySets.map((j) => this._createApiKeySetFromJson(j)));
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
async createApiKeySet(options) {
|
|
918
|
+
const json = await this._interface.createApiKeySet(options);
|
|
919
|
+
await this._refreshApiKeySets();
|
|
920
|
+
return this._createApiKeySetFirstViewFromJson(json);
|
|
921
|
+
}
|
|
922
|
+
async _refreshProject() {
|
|
923
|
+
await Promise.all([
|
|
924
|
+
super._refreshProject(),
|
|
925
|
+
this._adminProjectCache.refresh([])
|
|
926
|
+
]);
|
|
927
|
+
}
|
|
928
|
+
async _refreshApiKeySets() {
|
|
929
|
+
await this._apiKeySetsCache.refresh([]);
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
var StackClientApp = _StackClientAppImpl;
|
|
933
|
+
var StackServerApp = _StackServerAppImpl;
|
|
934
|
+
var StackAdminApp = _StackAdminAppImpl;
|
|
935
|
+
export {
|
|
936
|
+
StackAdminApp,
|
|
937
|
+
StackClientApp,
|
|
938
|
+
StackServerApp,
|
|
939
|
+
stackAppInternalsSymbol
|
|
940
|
+
};
|