@stackframe/stack 2.3.7 → 2.4.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.
@@ -43,11 +43,20 @@ var import_jsx_runtime = require("react/jsx-runtime");
43
43
  function OAuthCallback() {
44
44
  const app = (0, import__.useStackApp)();
45
45
  const called = (0, import_react.useRef)(false);
46
+ const [error, setError] = (0, import_react.useState)(null);
46
47
  (0, import_react.useEffect)(() => (0, import_promises.runAsynchronously)(async () => {
47
48
  if (called.current)
48
49
  return;
49
50
  called.current = true;
50
- await app.callOAuthCallback();
51
+ try {
52
+ await app.callOAuthCallback();
53
+ } catch (e) {
54
+ setError(e);
55
+ }
51
56
  }), []);
52
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_message_card.default, { title: "Redirecting...", fullPage: true });
57
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_message_card.default, { title: "Redirecting...", fullPage: true, children: error ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
58
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "Something went wrong while processing the OAuth callback:" }),
59
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { children: JSON.stringify(error, null, 2) }),
60
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "This is most likely an error in Stack. Please report it." })
61
+ ] }) : null });
53
62
  }
@@ -2,21 +2,30 @@
2
2
  "use client";
3
3
 
4
4
  // src/components-page/oauth-callback.tsx
5
- import { useRef, useEffect } from "react";
5
+ import { useRef, useEffect, useState } from "react";
6
6
  import { useStackApp } from "..";
7
7
  import { runAsynchronously } from "@stackframe/stack-shared/dist/utils/promises";
8
8
  import MessageCard from "../components/message-card";
9
- import { jsx } from "react/jsx-runtime";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
10
  function OAuthCallback() {
11
11
  const app = useStackApp();
12
12
  const called = useRef(false);
13
+ const [error, setError] = useState(null);
13
14
  useEffect(() => runAsynchronously(async () => {
14
15
  if (called.current)
15
16
  return;
16
17
  called.current = true;
17
- await app.callOAuthCallback();
18
+ try {
19
+ await app.callOAuthCallback();
20
+ } catch (e) {
21
+ setError(e);
22
+ }
18
23
  }), []);
19
- return /* @__PURE__ */ jsx(MessageCard, { title: "Redirecting...", fullPage: true });
24
+ return /* @__PURE__ */ jsx(MessageCard, { title: "Redirecting...", fullPage: true, children: error ? /* @__PURE__ */ jsxs("div", { children: [
25
+ /* @__PURE__ */ jsx("p", { children: "Something went wrong while processing the OAuth callback:" }),
26
+ /* @__PURE__ */ jsx("pre", { children: JSON.stringify(error, null, 2) }),
27
+ /* @__PURE__ */ jsx("p", { children: "This is most likely an error in Stack. Please report it." })
28
+ ] }) : null });
20
29
  }
21
30
  export {
22
31
  OAuthCallback as default
@@ -128,40 +128,61 @@ var expectNoState = Symbol();
128
128
  // src/lib/cookie.ts
129
129
  import Cookies from "js-cookie";
130
130
  import { cookies as rscCookies } from "@stackframe/stack-sc";
131
+ function isRscCookieUnavailableError(e) {
132
+ const allowedMessageSnippets = ["was called outside a request scope", "cookies() expects to have requestAsyncStorage"];
133
+ return typeof e?.message === "string" && allowedMessageSnippets.some((msg) => e.message.includes(msg));
134
+ }
131
135
  function getCookie(name) {
132
- if (rscCookies) {
136
+ try {
133
137
  return rscCookies().get(name)?.value ?? null;
134
- } else {
135
- return Cookies.get(name) ?? null;
138
+ } catch (e) {
139
+ if (isRscCookieUnavailableError(e)) {
140
+ return Cookies.get(name) ?? null;
141
+ } else {
142
+ throw e;
143
+ }
136
144
  }
137
145
  }
138
- function setOrDeleteCookie(name, value) {
146
+ function setOrDeleteCookie(name, value, options = {}) {
139
147
  if (value === null) {
140
148
  deleteCookie(name);
141
149
  } else {
142
- setCookie(name, value);
150
+ setCookie(name, value, options);
143
151
  }
144
152
  }
145
153
  function deleteCookie(name) {
146
- if (rscCookies) {
154
+ try {
147
155
  rscCookies().delete(name);
148
- } else {
149
- Cookies.remove(name);
156
+ } catch (e) {
157
+ if (isRscCookieUnavailableError(e)) {
158
+ Cookies.remove(name);
159
+ } else {
160
+ throw e;
161
+ }
150
162
  }
151
163
  }
152
- function setCookie(name, value) {
153
- if (rscCookies) {
154
- rscCookies().set(name, value);
155
- } else {
156
- Cookies.set(name, value, { secure: window.location.protocol === "https:" });
164
+ function setCookie(name, value, options = {}) {
165
+ try {
166
+ rscCookies().set(name, value, {
167
+ maxAge: options.maxAge
168
+ });
169
+ } catch (e) {
170
+ if (isRscCookieUnavailableError(e)) {
171
+ Cookies.set(name, value, {
172
+ secure: window.location.protocol === "https:",
173
+ expires: options.maxAge === void 0 ? void 0 : new Date(Date.now() + options.maxAge * 1e3)
174
+ });
175
+ } else {
176
+ throw e;
177
+ }
157
178
  }
158
179
  }
159
180
  async function saveVerifierAndState() {
160
181
  const codeVerifier = generateRandomCodeVerifier();
161
182
  const codeChallenge = await calculatePKCECodeChallenge(codeVerifier);
162
183
  const state = generateRandomState();
163
- setCookie("stack-code-verifier", codeVerifier);
164
- setCookie("stack-state", state);
184
+ setCookie("stack-code-verifier", codeVerifier, { maxAge: 60 * 10 });
185
+ setCookie("stack-state", state, { maxAge: 60 * 10 });
165
186
  return {
166
187
  codeChallenge,
167
188
  state
@@ -83,8 +83,8 @@ var cookieTokenStoreInitializer = () => {
83
83
  }, 10);
84
84
  cookieTokenStore.onChange((value) => {
85
85
  try {
86
- setOrDeleteCookie("stack-refresh", value.refreshToken);
87
- setOrDeleteCookie("stack-access", value.accessToken);
86
+ setOrDeleteCookie("stack-refresh", value.refreshToken, { maxAge: 60 * 60 * 24 * 365 });
87
+ setOrDeleteCookie("stack-access", value.accessToken, { maxAge: 60 * 60 * 24 });
88
88
  hasSucceededInWriting = true;
89
89
  } catch (e) {
90
90
  hasSucceededInWriting = false;
@@ -106,8 +106,8 @@ var tokenStoreInitializers = /* @__PURE__ */ new Map([
106
106
  });
107
107
  store.onChange((value) => {
108
108
  try {
109
- setOrDeleteCookie("stack-refresh", value.refreshToken);
110
- setOrDeleteCookie("stack-access", value.accessToken);
109
+ setOrDeleteCookie("stack-refresh", value.refreshToken, { maxAge: 60 * 60 * 24 * 365 });
110
+ setOrDeleteCookie("stack-access", value.accessToken, { maxAge: 60 * 60 * 24 });
111
111
  } catch (e) {
112
112
  }
113
113
  });
@@ -504,10 +504,12 @@ var _StackClientAppImpl = class __StackClientAppImpl {
504
504
  this._ensurePersistentTokenStore();
505
505
  const tokenStore = getTokenStore(this._tokenStoreOptions);
506
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);
507
+ if (result) {
508
+ if (result.newUser) {
509
+ window.location.replace(this.urls.afterSignUp);
510
+ } else {
511
+ window.location.replace(this.urls.afterSignIn);
512
+ }
511
513
  }
512
514
  await neverResolve();
513
515
  }
@@ -1,7 +1,10 @@
1
+ type SetCookieOptions = {
2
+ maxAge?: number;
3
+ };
1
4
  declare function getCookie(name: string): string | null;
2
- declare function setOrDeleteCookie(name: string, value: string | null): void;
5
+ declare function setOrDeleteCookie(name: string, value: string | null, options?: SetCookieOptions): void;
3
6
  declare function deleteCookie(name: string): void;
4
- declare function setCookie(name: string, value: string): void;
7
+ declare function setCookie(name: string, value: string, options?: SetCookieOptions): void;
5
8
  declare function saveVerifierAndState(): Promise<{
6
9
  codeChallenge: string;
7
10
  state: string;
@@ -1,7 +1,10 @@
1
+ type SetCookieOptions = {
2
+ maxAge?: number;
3
+ };
1
4
  declare function getCookie(name: string): string | null;
2
- declare function setOrDeleteCookie(name: string, value: string | null): void;
5
+ declare function setOrDeleteCookie(name: string, value: string | null, options?: SetCookieOptions): void;
3
6
  declare function deleteCookie(name: string): void;
4
- declare function setCookie(name: string, value: string): void;
7
+ declare function setCookie(name: string, value: string, options?: SetCookieOptions): void;
5
8
  declare function saveVerifierAndState(): Promise<{
6
9
  codeChallenge: string;
7
10
  state: string;
@@ -169,40 +169,61 @@ var expectNoState = Symbol();
169
169
  // src/lib/cookie.ts
170
170
  var import_js_cookie = __toESM(require("js-cookie"));
171
171
  var import_stack_sc = require("@stackframe/stack-sc");
172
+ function isRscCookieUnavailableError(e) {
173
+ const allowedMessageSnippets = ["was called outside a request scope", "cookies() expects to have requestAsyncStorage"];
174
+ return typeof e?.message === "string" && allowedMessageSnippets.some((msg) => e.message.includes(msg));
175
+ }
172
176
  function getCookie(name) {
173
- if (import_stack_sc.cookies) {
177
+ try {
174
178
  return (0, import_stack_sc.cookies)().get(name)?.value ?? null;
175
- } else {
176
- return import_js_cookie.default.get(name) ?? null;
179
+ } catch (e) {
180
+ if (isRscCookieUnavailableError(e)) {
181
+ return import_js_cookie.default.get(name) ?? null;
182
+ } else {
183
+ throw e;
184
+ }
177
185
  }
178
186
  }
179
- function setOrDeleteCookie(name, value) {
187
+ function setOrDeleteCookie(name, value, options = {}) {
180
188
  if (value === null) {
181
189
  deleteCookie(name);
182
190
  } else {
183
- setCookie(name, value);
191
+ setCookie(name, value, options);
184
192
  }
185
193
  }
186
194
  function deleteCookie(name) {
187
- if (import_stack_sc.cookies) {
195
+ try {
188
196
  (0, import_stack_sc.cookies)().delete(name);
189
- } else {
190
- import_js_cookie.default.remove(name);
197
+ } catch (e) {
198
+ if (isRscCookieUnavailableError(e)) {
199
+ import_js_cookie.default.remove(name);
200
+ } else {
201
+ throw e;
202
+ }
191
203
  }
192
204
  }
193
- function setCookie(name, value) {
194
- if (import_stack_sc.cookies) {
195
- (0, import_stack_sc.cookies)().set(name, value);
196
- } else {
197
- import_js_cookie.default.set(name, value, { secure: window.location.protocol === "https:" });
205
+ function setCookie(name, value, options = {}) {
206
+ try {
207
+ (0, import_stack_sc.cookies)().set(name, value, {
208
+ maxAge: options.maxAge
209
+ });
210
+ } catch (e) {
211
+ if (isRscCookieUnavailableError(e)) {
212
+ import_js_cookie.default.set(name, value, {
213
+ secure: window.location.protocol === "https:",
214
+ expires: options.maxAge === void 0 ? void 0 : new Date(Date.now() + options.maxAge * 1e3)
215
+ });
216
+ } else {
217
+ throw e;
218
+ }
198
219
  }
199
220
  }
200
221
  async function saveVerifierAndState() {
201
222
  const codeVerifier = generateRandomCodeVerifier();
202
223
  const codeChallenge = await calculatePKCECodeChallenge(codeVerifier);
203
224
  const state = generateRandomState();
204
- setCookie("stack-code-verifier", codeVerifier);
205
- setCookie("stack-state", state);
225
+ setCookie("stack-code-verifier", codeVerifier, { maxAge: 60 * 10 });
226
+ setCookie("stack-state", state, { maxAge: 60 * 10 });
206
227
  return {
207
228
  codeChallenge,
208
229
  state
@@ -120,8 +120,8 @@ var cookieTokenStoreInitializer = () => {
120
120
  }, 10);
121
121
  cookieTokenStore.onChange((value) => {
122
122
  try {
123
- (0, import_cookie.setOrDeleteCookie)("stack-refresh", value.refreshToken);
124
- (0, import_cookie.setOrDeleteCookie)("stack-access", value.accessToken);
123
+ (0, import_cookie.setOrDeleteCookie)("stack-refresh", value.refreshToken, { maxAge: 60 * 60 * 24 * 365 });
124
+ (0, import_cookie.setOrDeleteCookie)("stack-access", value.accessToken, { maxAge: 60 * 60 * 24 });
125
125
  hasSucceededInWriting = true;
126
126
  } catch (e) {
127
127
  hasSucceededInWriting = false;
@@ -143,8 +143,8 @@ var tokenStoreInitializers = /* @__PURE__ */ new Map([
143
143
  });
144
144
  store.onChange((value) => {
145
145
  try {
146
- (0, import_cookie.setOrDeleteCookie)("stack-refresh", value.refreshToken);
147
- (0, import_cookie.setOrDeleteCookie)("stack-access", value.accessToken);
146
+ (0, import_cookie.setOrDeleteCookie)("stack-refresh", value.refreshToken, { maxAge: 60 * 60 * 24 * 365 });
147
+ (0, import_cookie.setOrDeleteCookie)("stack-access", value.accessToken, { maxAge: 60 * 60 * 24 });
148
148
  } catch (e) {
149
149
  }
150
150
  });
@@ -541,10 +541,12 @@ var _StackClientAppImpl = class __StackClientAppImpl {
541
541
  this._ensurePersistentTokenStore();
542
542
  const tokenStore = getTokenStore(this._tokenStoreOptions);
543
543
  const result = await (0, import_auth.callOAuthCallback)(this._interface, tokenStore, this.urls.oauthCallback);
544
- if (result?.newUser) {
545
- window.location.replace(this.urls.afterSignUp);
546
- } else {
547
- window.location.replace(this.urls.afterSignIn);
544
+ if (result) {
545
+ if (result.newUser) {
546
+ window.location.replace(this.urls.afterSignUp);
547
+ } else {
548
+ window.location.replace(this.urls.afterSignIn);
549
+ }
548
550
  }
549
551
  await (0, import_promises.neverResolve)();
550
552
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackframe/stack",
3
- "version": "2.3.7",
3
+ "version": "2.4.0",
4
4
  "sideEffects": false,
5
5
  "exports": {
6
6
  ".": {
@@ -42,8 +42,8 @@
42
42
  "server-only": "^0.0.1",
43
43
  "styled-components": "^6.1.8",
44
44
  "yup": "^1.4.0",
45
- "@stackframe/stack-sc": "1.4.1",
46
- "@stackframe/stack-shared": "2.3.5"
45
+ "@stackframe/stack-sc": "1.5.0",
46
+ "@stackframe/stack-shared": "2.4.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@mui/joy": "^5.0.0-beta.30",
@@ -59,7 +59,8 @@
59
59
  "@types/color": "^3.0.6",
60
60
  "@types/js-cookie": "^3.0.6",
61
61
  "@types/react": "^18.2.66",
62
- "esbuild": "^0.20.2"
62
+ "esbuild": "^0.20.2",
63
+ "tsup": "^8.0.2"
63
64
  },
64
65
  "scripts": {
65
66
  "typecheck": "tsc --noEmit",