@stackframe/stack 1.0.0

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 (73) hide show
  1. package/LICENSE +7 -0
  2. package/dist/components/EmailVerification.d.ts +5 -0
  3. package/dist/components/EmailVerification.js +29 -0
  4. package/dist/components/ForgotPassword.d.ts +3 -0
  5. package/dist/components/ForgotPassword.js +22 -0
  6. package/dist/components/OauthCallback.d.ts +1 -0
  7. package/dist/components/OauthCallback.js +20 -0
  8. package/dist/components/PasswordReset.d.ts +4 -0
  9. package/dist/components/PasswordReset.js +36 -0
  10. package/dist/components/SignIn.d.ts +4 -0
  11. package/dist/components/SignIn.js +18 -0
  12. package/dist/components/SignOut.d.ts +3 -0
  13. package/dist/components/SignOut.js +12 -0
  14. package/dist/components/SignUp.d.ts +4 -0
  15. package/dist/components/SignUp.js +18 -0
  16. package/dist/components/StackHandler.d.ts +8 -0
  17. package/dist/components/StackHandler.js +58 -0
  18. package/dist/elements/Button.d.ts +10 -0
  19. package/dist/elements/Button.js +18 -0
  20. package/dist/elements/CardFrame.d.ts +5 -0
  21. package/dist/elements/CardFrame.js +10 -0
  22. package/dist/elements/CardHeader.d.ts +5 -0
  23. package/dist/elements/CardHeader.js +4 -0
  24. package/dist/elements/CredentialSignIn.d.ts +3 -0
  25. package/dist/elements/CredentialSignIn.js +57 -0
  26. package/dist/elements/CredentialSignUp.d.ts +3 -0
  27. package/dist/elements/CredentialSignUp.js +73 -0
  28. package/dist/elements/DividerWithText.d.ts +3 -0
  29. package/dist/elements/DividerWithText.js +5 -0
  30. package/dist/elements/ForgotPassword.d.ts +3 -0
  31. package/dist/elements/ForgotPassword.js +32 -0
  32. package/dist/elements/FormWarning.d.ts +3 -0
  33. package/dist/elements/FormWarning.js +7 -0
  34. package/dist/elements/MessageCard.d.ts +6 -0
  35. package/dist/elements/MessageCard.js +5 -0
  36. package/dist/elements/OauthButton.d.ts +5 -0
  37. package/dist/elements/OauthButton.js +67 -0
  38. package/dist/elements/OauthGroup.d.ts +4 -0
  39. package/dist/elements/OauthGroup.js +11 -0
  40. package/dist/elements/PasswordField.d.ts +2 -0
  41. package/dist/elements/PasswordField.js +27 -0
  42. package/dist/elements/PasswordResetInner.d.ts +4 -0
  43. package/dist/elements/PasswordResetInner.js +61 -0
  44. package/dist/elements/RedirectMessageCard.d.ts +4 -0
  45. package/dist/elements/RedirectMessageCard.js +49 -0
  46. package/dist/index.d.ts +11 -0
  47. package/dist/index.js +12 -0
  48. package/dist/lib/auth.d.ts +19 -0
  49. package/dist/lib/auth.js +85 -0
  50. package/dist/lib/cookie.d.ts +12 -0
  51. package/dist/lib/cookie.js +60 -0
  52. package/dist/lib/hooks.d.ts +21 -0
  53. package/dist/lib/hooks.js +21 -0
  54. package/dist/lib/stack-app.d.ts +172 -0
  55. package/dist/lib/stack-app.js +575 -0
  56. package/dist/providers/StackProvider.d.ts +6 -0
  57. package/dist/providers/StackProvider.js +6 -0
  58. package/dist/providers/StackProviderClient.d.ts +9 -0
  59. package/dist/providers/StackProviderClient.js +14 -0
  60. package/dist/tailwind.css +1293 -0
  61. package/dist/utils/email.d.ts +1 -0
  62. package/dist/utils/email.js +7 -0
  63. package/dist/utils/next.d.ts +1 -0
  64. package/dist/utils/next.js +4 -0
  65. package/dist/utils/react.d.ts +1 -0
  66. package/dist/utils/react.js +6 -0
  67. package/dist/utils/results.d.ts +24 -0
  68. package/dist/utils/results.js +46 -0
  69. package/dist/utils/types.d.ts +3 -0
  70. package/dist/utils/types.js +1 -0
  71. package/dist/utils/url.d.ts +2 -0
  72. package/dist/utils/url.js +16 -0
  73. package/package.json +50 -0
@@ -0,0 +1,575 @@
1
+ import React, { use, useCallback } from "react";
2
+ import { StackAdminInterface, StackClientInterface, StackServerInterface } from "@stackframe/stack-shared";
3
+ import { getCookie, setOrDeleteCookie } from "./cookie";
4
+ import { throwErr } from "@stackframe/stack-shared/dist/utils/errors";
5
+ import { generateUuid } from "@stackframe/stack-shared/dist/utils/uuids";
6
+ import { AsyncResult } from "@stackframe/stack-shared/dist/utils/results";
7
+ import { suspendIfSsr } from "@stackframe/stack-shared/dist/utils/react";
8
+ import { AsyncStore } from "@stackframe/stack-shared/dist/utils/stores";
9
+ import { isClient } from "../utils/next";
10
+ import { callOauthCallback, signInWithCredential, signInWithOauth, signUpWithCredential } from "./auth";
11
+ import { RedirectType, redirect, useRouter } from "next/navigation";
12
+ import { constructRedirectUrl } from "../utils/url";
13
+ import { filterUndefined } from "@stackframe/stack-shared/dist/utils/objects";
14
+ import { neverResolve, resolved } from "@stackframe/stack-shared/dist/utils/promises";
15
+ function getUrls(partial) {
16
+ const handler = partial.handler ?? "/handler";
17
+ return {
18
+ handler,
19
+ signIn: `${handler}/signin`,
20
+ signUp: `${handler}/signup`,
21
+ signOut: `${handler}/signout`,
22
+ emailVerification: `${handler}/email-verification`,
23
+ passwordReset: `${handler}/password-reset`,
24
+ forgotPassword: `${handler}/forgot-password`,
25
+ oauthCallback: `${handler}/oauth-callback`,
26
+ home: "/",
27
+ userHome: "/",
28
+ ...filterUndefined(partial),
29
+ };
30
+ }
31
+ function getDefaultProjectId() {
32
+ return process.env.NEXT_PUBLIC_STACK_PROJECT_ID || throwErr("No project ID provided. Please copy your project ID from the Stack dashboard and put it in the NEXT_PUBLIC_STACK_PROJECT_ID environment variable.");
33
+ }
34
+ function getDefaultPublishableClientKey() {
35
+ return process.env.NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY || throwErr("No publishable client key provided. Please copy your publishable client key from the Stack dashboard and put it in the NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY environment variable.");
36
+ }
37
+ function getDefaultSecretServerKey() {
38
+ 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.");
39
+ }
40
+ function getDefaultSuperSecretAdminKey() {
41
+ 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.");
42
+ }
43
+ function getDefaultBaseUrl() {
44
+ return process.env.NEXT_PUBLIC_STACK_URL || defaultBaseUrl;
45
+ }
46
+ const defaultBaseUrl = "https://api.stackframe.co";
47
+ function createEmptyTokenStore() {
48
+ const store = new AsyncStore();
49
+ store.set({
50
+ refreshToken: null,
51
+ accessToken: null,
52
+ });
53
+ return store;
54
+ }
55
+ const memoryTokenStore = createEmptyTokenStore();
56
+ let cookieTokenStore = null;
57
+ const cookieTokenStoreInitializer = () => {
58
+ if (!isClient()) {
59
+ throw new Error("Cannot use cookie token store on the server!");
60
+ }
61
+ if (cookieTokenStore === null) {
62
+ cookieTokenStore = new AsyncStore();
63
+ let hasSucceededInWriting = true;
64
+ setInterval(() => {
65
+ if (hasSucceededInWriting) {
66
+ const newValue = {
67
+ refreshToken: getCookie('stack-refresh'),
68
+ accessToken: getCookie('stack-access'),
69
+ };
70
+ const res = cookieTokenStore.get();
71
+ if (res.status !== "ok"
72
+ || res.data.refreshToken !== newValue.refreshToken
73
+ || res.data.accessToken !== newValue.accessToken) {
74
+ cookieTokenStore.set(newValue);
75
+ }
76
+ }
77
+ }, 10);
78
+ cookieTokenStore.onChange((value) => {
79
+ try {
80
+ setOrDeleteCookie('stack-refresh', value.refreshToken);
81
+ setOrDeleteCookie('stack-access', value.accessToken);
82
+ hasSucceededInWriting = true;
83
+ }
84
+ catch (e) {
85
+ hasSucceededInWriting = false;
86
+ }
87
+ });
88
+ }
89
+ return cookieTokenStore;
90
+ };
91
+ const tokenStoreInitializers = new Map([
92
+ ["cookie", cookieTokenStoreInitializer],
93
+ ["nextjs-cookie", () => {
94
+ if (isClient()) {
95
+ return cookieTokenStoreInitializer();
96
+ }
97
+ else {
98
+ const store = new AsyncStore();
99
+ store.set({
100
+ refreshToken: getCookie('stack-refresh'),
101
+ accessToken: getCookie('stack-access'),
102
+ });
103
+ store.onChange((value) => {
104
+ try {
105
+ setOrDeleteCookie('stack-refresh', value.refreshToken);
106
+ setOrDeleteCookie('stack-access', value.accessToken);
107
+ }
108
+ catch (e) {
109
+ // ignore
110
+ }
111
+ });
112
+ return store;
113
+ }
114
+ }],
115
+ ["memory", () => memoryTokenStore],
116
+ [null, () => createEmptyTokenStore()],
117
+ ]);
118
+ function getTokenStore(tokenStoreOptions) {
119
+ return (tokenStoreInitializers.get(tokenStoreOptions) ?? throwErr(`Invalid token store ${tokenStoreOptions}`))();
120
+ }
121
+ const loadingSentinel = Symbol("stackAppCacheLoadingSentinel");
122
+ function useValueCache(cache) {
123
+ // we explicitly don't want to run this hook in SSR
124
+ suspendIfSsr();
125
+ const subscribe = useCallback((cb) => {
126
+ const { unsubscribe } = cache.onChange(() => cb());
127
+ return unsubscribe;
128
+ }, [cache]);
129
+ const getSnapshot = useCallback(() => {
130
+ return AsyncResult.or(cache.get(), loadingSentinel);
131
+ }, [cache]);
132
+ // note: we must use React.useSyncExternalStore instead of importing the function directly, as it will otherwise
133
+ // throw an error ("can't import useSyncExternalStore from the server")
134
+ const value = React.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
135
+ if (value === loadingSentinel) {
136
+ return use(cache.getOrWait());
137
+ }
138
+ else {
139
+ // still need to call `use` because React expects the control flow to not change
140
+ return use(resolved(value));
141
+ }
142
+ }
143
+ export const stackAppInternalsSymbol = Symbol.for("StackAppInternals");
144
+ const allClientApps = new Map();
145
+ class _StackClientAppImpl {
146
+ _uniqueIdentifier;
147
+ _interface;
148
+ _tokenStoreOptions;
149
+ _urlOptions;
150
+ constructor(options) {
151
+ if ("interface" in options) {
152
+ this._interface = options.interface;
153
+ }
154
+ else {
155
+ this._interface = new StackClientInterface({
156
+ baseUrl: options.baseUrl ?? getDefaultBaseUrl(),
157
+ projectId: options.projectId ?? getDefaultProjectId(),
158
+ publishableClientKey: options.publishableClientKey ?? getDefaultPublishableClientKey(),
159
+ });
160
+ }
161
+ this._tokenStoreOptions = options.tokenStore;
162
+ this._urlOptions = options.urls ?? {};
163
+ this._uniqueIdentifier = options.uniqueIdentifier ?? generateUuid();
164
+ if (allClientApps.has(this._uniqueIdentifier)) {
165
+ throw new Error("A Stack client app with the same unique identifier already exists");
166
+ }
167
+ allClientApps.set(this._uniqueIdentifier, [options.checkString ?? "default check string", this]);
168
+ }
169
+ _ensurePersistentTokenStore() {
170
+ if (!this._tokenStoreOptions) {
171
+ 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.");
172
+ }
173
+ }
174
+ _ensureInternalProject() {
175
+ if (this.projectId !== "internal") {
176
+ throw new Error("Cannot call this function on a Stack app with a project ID other than 'internal'.");
177
+ }
178
+ }
179
+ _userFromJson(json) {
180
+ return {
181
+ projectId: json.projectId,
182
+ id: json.id,
183
+ displayName: json.displayName,
184
+ primaryEmail: json.primaryEmail,
185
+ primaryEmailVerified: json.primaryEmailVerified,
186
+ profileImageUrl: json.profileImageUrl,
187
+ signedUpAt: new Date(json.signedUpAtMillis),
188
+ clientMetadata: json.clientMetadata,
189
+ toJson() {
190
+ return json;
191
+ }
192
+ };
193
+ }
194
+ _currentUserFromJson(json, tokenStore) {
195
+ if (json === null)
196
+ return null;
197
+ const app = this;
198
+ const res = {
199
+ ...this._userFromJson(json),
200
+ get accessToken() {
201
+ return AsyncResult.or(tokenStore.get(), null)?.accessToken ?? null;
202
+ },
203
+ get refreshToken() {
204
+ return AsyncResult.or(tokenStore.get(), null)?.refreshToken ?? null;
205
+ },
206
+ update(update) {
207
+ return app._updateUser(update, tokenStore);
208
+ },
209
+ signOut(redirectUrl) {
210
+ return app._signOut(tokenStore, redirectUrl);
211
+ },
212
+ };
213
+ Object.freeze(res);
214
+ return res;
215
+ }
216
+ _userToJson(user) {
217
+ return {
218
+ projectId: user.projectId,
219
+ id: user.id,
220
+ displayName: user.displayName,
221
+ primaryEmail: user.primaryEmail,
222
+ primaryEmailVerified: user.primaryEmailVerified,
223
+ profileImageUrl: user.profileImageUrl,
224
+ signedUpAtMillis: user.signedUpAt.getTime(),
225
+ clientMetadata: user.clientMetadata,
226
+ };
227
+ }
228
+ _projectAdminFromJson(data) {
229
+ return {
230
+ id: data.id,
231
+ displayName: data.displayName,
232
+ description: data.description,
233
+ createdAt: new Date(data.createdAtMillis),
234
+ userCount: data.userCount,
235
+ isProductionMode: data.isProductionMode,
236
+ evaluatedConfig: {
237
+ id: data.evaluatedConfig.id,
238
+ allowLocalhost: data.evaluatedConfig.allowLocalhost,
239
+ oauthProviders: data.evaluatedConfig.oauthProviders,
240
+ emailConfig: data.evaluatedConfig.emailConfig,
241
+ domains: data.evaluatedConfig.domains,
242
+ },
243
+ };
244
+ }
245
+ get projectId() {
246
+ return this._interface.projectId;
247
+ }
248
+ get urls() {
249
+ return getUrls(this._urlOptions);
250
+ }
251
+ _redirectTo(handlerName) {
252
+ if (!this.urls[handlerName]) {
253
+ throw new Error(`No URL for handler name ${handlerName}`);
254
+ }
255
+ window.location.href = this.urls[handlerName];
256
+ return neverResolve();
257
+ }
258
+ async redirectToHandler() { return await this._redirectTo("handler"); }
259
+ async redirectToSignIn() { return await this._redirectTo("signIn"); }
260
+ async redirectToSignUp() { return await this._redirectTo("signUp"); }
261
+ async redirectToSignOut() { return await this._redirectTo("signOut"); }
262
+ async redirectToEmailVerification() { return await this._redirectTo("emailVerification"); }
263
+ async redirectToPasswordReset() { return await this._redirectTo("passwordReset"); }
264
+ async redirectToForgotPassword() { return await this._redirectTo("forgotPassword"); }
265
+ async redirectToHome() { return await this._redirectTo("home"); }
266
+ async redirectToUserHome() { return await this._redirectTo("userHome"); }
267
+ async redirectToOauthCallback() { return await this._redirectTo("oauthCallback"); }
268
+ async sendForgotPasswordEmail(email) {
269
+ const redirectUrl = constructRedirectUrl(this.urls.passwordReset);
270
+ await this._interface.sendForgotPasswordEmail(email, redirectUrl);
271
+ }
272
+ async resetPassword(options) {
273
+ return await this._interface.resetPassword(options);
274
+ }
275
+ async verifyPasswordResetCode(code) {
276
+ return await this._interface.verifyPasswordResetCode(code);
277
+ }
278
+ async verifyEmail(code) {
279
+ return await this._interface.verifyEmail(code);
280
+ }
281
+ async getUser(options) {
282
+ this._ensurePersistentTokenStore();
283
+ const tokenStore = getTokenStore(this._tokenStoreOptions);
284
+ const userJson = await this._interface.currentUserCache.getOrWait(tokenStore);
285
+ if (userJson === null) {
286
+ switch (options?.or) {
287
+ case 'redirect': {
288
+ redirect(this.urls.signIn, RedirectType.replace);
289
+ throw new Error("redirect should never return!");
290
+ }
291
+ case 'throw': {
292
+ throw new Error("User is not signed in");
293
+ }
294
+ default: {
295
+ return null;
296
+ }
297
+ }
298
+ }
299
+ return this._currentUserFromJson(userJson, tokenStore);
300
+ }
301
+ useUser(options) {
302
+ this._ensurePersistentTokenStore();
303
+ const router = useRouter();
304
+ const tokenStore = getTokenStore(this._tokenStoreOptions);
305
+ const userJson = useValueCache(this._interface.currentUserCache.getValueCache(tokenStore));
306
+ if (userJson === null) {
307
+ switch (options?.or) {
308
+ case 'redirect': {
309
+ router.replace(this.urls.signIn);
310
+ break;
311
+ }
312
+ case 'throw': {
313
+ throw new Error("User is not signed in");
314
+ }
315
+ default: {
316
+ return null;
317
+ }
318
+ }
319
+ }
320
+ return this._currentUserFromJson(userJson, tokenStore);
321
+ }
322
+ onUserChange(callback) {
323
+ this._ensurePersistentTokenStore();
324
+ const tokenStore = getTokenStore(this._tokenStoreOptions);
325
+ return this._interface.currentUserCache.getValueCache(tokenStore).onChange((userJson) => {
326
+ callback(this._currentUserFromJson(userJson, tokenStore));
327
+ });
328
+ }
329
+ async _updateUser(update, tokenStore) {
330
+ return await this._interface.setClientUserCustomizableData(update, tokenStore);
331
+ }
332
+ async signInWithOauth(provider) {
333
+ this._ensurePersistentTokenStore();
334
+ await signInWithOauth(this._interface, { provider, redirectUrl: this.urls.oauthCallback });
335
+ }
336
+ async signInWithCredential(options) {
337
+ if (!options.redirectUrl) {
338
+ options.redirectUrl = constructRedirectUrl(options.redirectUrl);
339
+ }
340
+ this._ensurePersistentTokenStore();
341
+ const tokenStore = getTokenStore(this._tokenStoreOptions);
342
+ return await signInWithCredential(this._interface, tokenStore, options);
343
+ }
344
+ async signUpWithCredential(options) {
345
+ if (!options.redirectUrl) {
346
+ options.redirectUrl = constructRedirectUrl(options.redirectUrl);
347
+ }
348
+ this._ensurePersistentTokenStore();
349
+ const tokenStore = getTokenStore(this._tokenStoreOptions);
350
+ return await signUpWithCredential(this._interface, tokenStore, options);
351
+ }
352
+ async callOauthCallback(options = {}) {
353
+ this._ensurePersistentTokenStore();
354
+ const tokenStore = getTokenStore(this._tokenStoreOptions);
355
+ await callOauthCallback(this._interface, tokenStore, options.redirectUrl);
356
+ }
357
+ async _signOut(tokenStore, redirectUrl) {
358
+ redirectUrl = constructRedirectUrl(redirectUrl);
359
+ await this._interface.signOut(tokenStore);
360
+ window.location.assign(redirectUrl);
361
+ return await neverResolve();
362
+ }
363
+ async signOut(redirectUrl) {
364
+ const user = await this.getUser();
365
+ if (user) {
366
+ await user.signOut(redirectUrl);
367
+ }
368
+ window.location.assign(redirectUrl);
369
+ return await neverResolve();
370
+ }
371
+ async getProject() {
372
+ return await this._interface.clientProjectCache.getOrWait();
373
+ }
374
+ useProject() {
375
+ return useValueCache(this._interface.clientProjectCache);
376
+ }
377
+ onProjectChange(callback) {
378
+ return this._interface.clientProjectCache.onChange(callback);
379
+ }
380
+ async listOwnedProjects() {
381
+ this._ensureInternalProject();
382
+ const tokenStore = getTokenStore(this._tokenStoreOptions);
383
+ const json = await this._interface.listProjects(tokenStore);
384
+ return json.map((j) => this._projectAdminFromJson(j));
385
+ }
386
+ async createProject(newProject) {
387
+ this._ensureInternalProject();
388
+ const tokenStore = getTokenStore(this._tokenStoreOptions);
389
+ const json = await this._interface.createProject(newProject, tokenStore);
390
+ return this._projectAdminFromJson(json);
391
+ }
392
+ static get [stackAppInternalsSymbol]() {
393
+ return {
394
+ fromClientJson: (json) => {
395
+ const existing = allClientApps.get(json.uniqueIdentifier);
396
+ if (existing) {
397
+ const [checkString, clientApp] = existing;
398
+ if (checkString !== JSON.stringify(json)) {
399
+ throw new Error("The provided app JSON does not match the configuration of the existing client app with the same unique identifier");
400
+ }
401
+ return clientApp;
402
+ }
403
+ return new _StackClientAppImpl({
404
+ ...json,
405
+ checkString: JSON.stringify(json),
406
+ });
407
+ }
408
+ };
409
+ }
410
+ get [stackAppInternalsSymbol]() {
411
+ return {
412
+ toClientJson: async () => {
413
+ if (!("publishableClientKey" in this._interface.options)) {
414
+ // TODO find a way to do this
415
+ throw Error("Cannot serialize to JSON from an application without a publishable client key");
416
+ }
417
+ return {
418
+ baseUrl: this._interface.options.baseUrl,
419
+ projectId: this.projectId,
420
+ publishableClientKey: this._interface.options.publishableClientKey,
421
+ tokenStore: this._tokenStoreOptions,
422
+ urls: this._urlOptions,
423
+ uniqueIdentifier: this._uniqueIdentifier,
424
+ };
425
+ }
426
+ };
427
+ }
428
+ ;
429
+ }
430
+ class _StackServerAppImpl extends _StackClientAppImpl {
431
+ constructor(options) {
432
+ if ("interface" in options) {
433
+ super({
434
+ interface: options.interface,
435
+ tokenStore: options.tokenStore,
436
+ urls: options.urls,
437
+ });
438
+ }
439
+ else {
440
+ super({
441
+ interface: new StackServerInterface({
442
+ baseUrl: options.baseUrl ?? getDefaultBaseUrl(),
443
+ projectId: options.projectId ?? getDefaultProjectId(),
444
+ publishableClientKey: options.publishableClientKey ?? getDefaultPublishableClientKey(),
445
+ secretServerKey: options.secretServerKey ?? getDefaultSecretServerKey(),
446
+ }),
447
+ tokenStore: options.tokenStore,
448
+ urls: options.urls ?? {},
449
+ });
450
+ }
451
+ }
452
+ _serverUserFromJson(json) {
453
+ if (json === null)
454
+ return null;
455
+ const app = this;
456
+ return {
457
+ ...this._userFromJson(json),
458
+ serverMetadata: json.serverMetadata,
459
+ async delete() {
460
+ await app._interface.deleteServerUser(this.id);
461
+ },
462
+ async update(update) {
463
+ await app._interface.setServerUserCustomizableData(this.id, update);
464
+ },
465
+ getClientUser() {
466
+ return {
467
+ ...app._userFromJson(json),
468
+ };
469
+ },
470
+ toJson() {
471
+ return app._serverUserToJson(this);
472
+ },
473
+ };
474
+ }
475
+ _currentServerUserFromJson(json, tokenStore) {
476
+ if (json === null)
477
+ return null;
478
+ const app = this;
479
+ const res = {
480
+ ...this._serverUserFromJson(json),
481
+ get accessToken() {
482
+ return AsyncResult.or(tokenStore.get(), null)?.accessToken ?? null;
483
+ },
484
+ get refreshToken() {
485
+ return AsyncResult.or(tokenStore.get(), null)?.refreshToken ?? null;
486
+ },
487
+ signOut(redirectUrl) {
488
+ return app._signOut(tokenStore, redirectUrl);
489
+ },
490
+ getClientUser() {
491
+ const serverUser = this;
492
+ return {
493
+ ...app._userFromJson(json),
494
+ get accessToken() {
495
+ return serverUser.accessToken;
496
+ },
497
+ get refreshToken() {
498
+ return serverUser.refreshToken;
499
+ },
500
+ update(update) {
501
+ return serverUser.update(update);
502
+ },
503
+ signOut(redirectUrl) {
504
+ return serverUser.signOut(redirectUrl);
505
+ },
506
+ };
507
+ },
508
+ };
509
+ Object.freeze(res);
510
+ return res;
511
+ }
512
+ _serverUserToJson(user) {
513
+ return {
514
+ projectId: user.projectId,
515
+ id: user.id,
516
+ displayName: user.displayName,
517
+ primaryEmail: user.primaryEmail,
518
+ primaryEmailVerified: user.primaryEmailVerified,
519
+ profileImageUrl: user.profileImageUrl,
520
+ signedUpAtMillis: user.signedUpAt.getTime(),
521
+ clientMetadata: user.clientMetadata,
522
+ serverMetadata: user.serverMetadata,
523
+ };
524
+ }
525
+ async getServerUser() {
526
+ this._ensurePersistentTokenStore();
527
+ const tokenStore = getTokenStore(this._tokenStoreOptions);
528
+ const userJson = await this._interface.currentServerUserCache.getOrWait(tokenStore);
529
+ return this._currentServerUserFromJson(userJson, tokenStore);
530
+ }
531
+ useServerUser(options) {
532
+ this._ensurePersistentTokenStore();
533
+ const router = useRouter();
534
+ const tokenStore = getTokenStore(this._tokenStoreOptions);
535
+ const userJson = useValueCache(this._interface.currentServerUserCache.getValueCache(tokenStore));
536
+ if (options?.required && userJson === null) {
537
+ use(this.redirectToSignIn());
538
+ }
539
+ return this._currentServerUserFromJson(userJson, tokenStore);
540
+ }
541
+ onServerUserChange(callback) {
542
+ this._ensurePersistentTokenStore();
543
+ const tokenStore = getTokenStore(this._tokenStoreOptions);
544
+ return this._interface.currentServerUserCache.getValueCache(tokenStore).onChange((userJson) => {
545
+ callback(this._currentServerUserFromJson(userJson, tokenStore));
546
+ });
547
+ }
548
+ }
549
+ class _StackAdminAppImpl extends _StackServerAppImpl {
550
+ constructor(options) {
551
+ super({
552
+ interface: new StackAdminInterface({
553
+ baseUrl: options.baseUrl ?? getDefaultBaseUrl(),
554
+ projectId: options.projectId ?? getDefaultProjectId(),
555
+ publishableClientKey: options.publishableClientKey ?? getDefaultPublishableClientKey(),
556
+ secretServerKey: options.secretServerKey ?? getDefaultSecretServerKey(),
557
+ superSecretAdminKey: options.superSecretAdminKey ?? getDefaultSuperSecretAdminKey(),
558
+ }),
559
+ tokenStore: options.tokenStore,
560
+ urls: options.urls,
561
+ });
562
+ }
563
+ async getProjectAdmin() {
564
+ return this._projectAdminFromJson(await this._interface.projectCache.getOrWait());
565
+ }
566
+ useProjectAdmin() {
567
+ return this._projectAdminFromJson(useValueCache(this._interface.projectCache));
568
+ }
569
+ onProjectAdminChange(callback) {
570
+ return this._interface.projectCache.onChange((j) => callback(this._projectAdminFromJson(j)));
571
+ }
572
+ }
573
+ export const StackClientApp = _StackClientAppImpl;
574
+ export const StackServerApp = _StackServerAppImpl;
575
+ export const StackAdminApp = _StackAdminAppImpl;
@@ -0,0 +1,6 @@
1
+ import { ReactNode } from 'react';
2
+ import { StackClientApp } from '../lib/stack-app';
3
+ export default function StackProvider({ children, app, }: {
4
+ children: ReactNode;
5
+ app: StackClientApp<true>;
6
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { stackAppInternalsSymbol } from '../lib/stack-app';
3
+ import { StackProviderClient } from './StackProviderClient';
4
+ export default function StackProvider({ children, app, }) {
5
+ return (_jsx(StackProviderClient, { appJsonPromise: app[stackAppInternalsSymbol].toClientJson(), children: children }));
6
+ }
@@ -0,0 +1,9 @@
1
+ import { StackClientApp, StackClientAppJson } from "../lib/stack-app";
2
+ import React from "react";
3
+ export declare const StackContext: React.Context<{
4
+ app: StackClientApp<true>;
5
+ } | null>;
6
+ export declare function StackProviderClient(props: {
7
+ appJsonPromise: Promise<StackClientAppJson<true, string>>;
8
+ children?: React.ReactNode;
9
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { use } from "react";
4
+ import { StackClientApp, stackAppInternalsSymbol } from "../lib/stack-app";
5
+ import React from "react";
6
+ export const StackContext = React.createContext(null);
7
+ export function StackProviderClient(props) {
8
+ const appJson = use(props.appJsonPromise);
9
+ const app = StackClientApp[stackAppInternalsSymbol].fromClientJson(appJson);
10
+ if (process.env.NODE_ENV === "development") {
11
+ globalThis.stackApp = app;
12
+ }
13
+ return (_jsx(StackContext.Provider, { value: { app }, children: props.children }));
14
+ }