@stackframe/stack-shared 2.4.8 → 2.4.10

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/CHANGELOG.md ADDED
@@ -0,0 +1,171 @@
1
+ # @stackframe/stack-shared
2
+
3
+ ## 2.4.10
4
+
5
+ ### Patch Changes
6
+
7
+ - Bug fixes
8
+ - Updated dependencies
9
+ - @stackframe/stack-sc@1.5.5
10
+
11
+ ## 2.4.9
12
+
13
+ ### Patch Changes
14
+
15
+ - Bugfixes
16
+ - Updated dependencies
17
+ - @stackframe/stack-sc@1.5.4
18
+
19
+ ## 2.4.8
20
+
21
+ ### Patch Changes
22
+
23
+ - Improved UUID generation
24
+
25
+ ## 2.4.7
26
+
27
+ ### Patch Changes
28
+
29
+ - Bugfixes
30
+ - Updated dependencies
31
+ - @stackframe/stack-sc@1.5.3
32
+
33
+ ## 2.4.6
34
+
35
+ ### Patch Changes
36
+
37
+ - Remove crypto-browserify dependency
38
+
39
+ ## 2.4.5
40
+
41
+ ### Patch Changes
42
+
43
+ - Team selection
44
+
45
+ ## 2.4.4
46
+
47
+ ### Patch Changes
48
+
49
+ - UX improvements
50
+
51
+ ## 2.4.3
52
+
53
+ ### Patch Changes
54
+
55
+ - CRUD schemas
56
+ - Updated dependencies
57
+ - @stackframe/stack-sc@1.5.2
58
+
59
+ ## 2.4.2
60
+
61
+ ### Patch Changes
62
+
63
+ - New projects page
64
+
65
+ ## 2.4.1
66
+
67
+ ### Patch Changes
68
+
69
+ - Teams, permissions and RBAC
70
+ - Updated dependencies
71
+ - @stackframe/stack-sc@1.5.1
72
+
73
+ ## 2.4.0
74
+
75
+ ### Minor Changes
76
+
77
+ - Middleware support
78
+
79
+ ## 2.3.6
80
+
81
+ ### Patch Changes
82
+
83
+ - Bugfixes
84
+
85
+ ## 2.3.5
86
+
87
+ ### Patch Changes
88
+
89
+ - CommonJS support
90
+
91
+ ## 2.3.4
92
+
93
+ ### Patch Changes
94
+
95
+ - Bugfixes
96
+
97
+ ## 2.3.3
98
+
99
+ ### Patch Changes
100
+
101
+ - Partial pre-rendering
102
+
103
+ ## 2.3.2
104
+
105
+ ### Patch Changes
106
+
107
+ - Magic link configuration
108
+
109
+ ## 2.3.1
110
+
111
+ ### Patch Changes
112
+
113
+ - Add README file
114
+
115
+ ## 2.3.0
116
+
117
+ ### Minor Changes
118
+
119
+ - 96c26a7: added magic link
120
+
121
+ ### Patch Changes
122
+
123
+ - Various small improvements
124
+
125
+ ## 2.2.2
126
+
127
+ ### Patch Changes
128
+
129
+ - 5909ecd: fixed bugs
130
+
131
+ ## 2.2.1
132
+
133
+ ### Patch Changes
134
+
135
+ - fixed minor errors
136
+
137
+ ## 2.2.0
138
+
139
+ ### Minor Changes
140
+
141
+ - 2995d96: Added new UserButton component and Account setting page
142
+
143
+ ## 2.1.0
144
+
145
+ ### Minor Changes
146
+
147
+ - 9e9907f: Added new stack UI system
148
+
149
+ ## 2.0.0
150
+
151
+ ### Major Changes
152
+
153
+ - 948252f: removed redirect URL in function options, redirect automatically to default URL
154
+
155
+ ## 1.2.1
156
+
157
+ ### Patch Changes
158
+
159
+ - fixed import bugs
160
+
161
+ ## 1.2.0
162
+
163
+ ### Minor Changes
164
+
165
+ - Fixed infinite reload bug, added dashboard provider update
166
+
167
+ ## 1.1.0
168
+
169
+ ### Minor Changes
170
+
171
+ - fixed bugs
@@ -44,7 +44,8 @@ export type ClientInterfaceOptions = {
44
44
  } & ({
45
45
  publishableClientKey: string;
46
46
  } | {
47
- projectOwnerTokens: ReadonlyTokenStore;
47
+ projectOwnerTokens: TokenStore;
48
+ refreshProjectOwnerTokens: () => Promise<void>;
48
49
  });
49
50
  export type SharedProvider = "shared-github" | "shared-google" | "shared-facebook" | "shared-microsoft";
50
51
  export declare const sharedProviders: readonly ["shared-github", "shared-google", "shared-facebook", "shared-microsoft"];
@@ -135,7 +136,7 @@ export declare class StackClientInterface {
135
136
  constructor(options: ClientInterfaceOptions);
136
137
  get projectId(): string;
137
138
  getApiUrl(): string;
138
- protected refreshAccessToken(tokenStore: TokenStore): Promise<void>;
139
+ refreshAccessToken(tokenStore: TokenStore): Promise<void>;
139
140
  protected sendClientRequest(path: string, requestOptions: RequestInit, tokenStoreOrNull: TokenStore | null, requestType?: "client" | "server" | "admin"): Promise<Response & {
140
141
  usedTokens: Readonly<{
141
142
  refreshToken: string | null;
@@ -119,6 +119,16 @@ export class StackClientInterface {
119
119
  await this.refreshAccessToken(tokenStore);
120
120
  tokenObj = await tokenStore.getOrWait();
121
121
  }
122
+ let adminTokenStore = null;
123
+ let adminTokenObj = null;
124
+ if ("projectOwnerTokens" in this.options) {
125
+ adminTokenStore = this.options.projectOwnerTokens;
126
+ adminTokenObj = await adminTokenStore.getOrWait();
127
+ if (!adminTokenObj.accessToken) {
128
+ await this.options.refreshProjectOwnerTokens();
129
+ adminTokenObj = await adminTokenStore.getOrWait();
130
+ }
131
+ }
122
132
  // all requests should be dynamic to prevent Next.js caching
123
133
  cookies?.();
124
134
  const url = this.getApiUrl() + path;
@@ -129,8 +139,13 @@ export class StackClientInterface {
129
139
  *
130
140
  * To help debugging, also omit cookies on same-origin, so we don't accidentally
131
141
  * implement reliance on cookies anywhere.
142
+ *
143
+ * However, Cloudflare Workers don't actually support `credentials`, so we only set it
144
+ * if Cloudflare-exclusive globals are not detected. https://github.com/cloudflare/workers-sdk/issues/2514
132
145
  */
133
- credentials: "omit",
146
+ ..."WebSocketPair" in globalThis ? {} : {
147
+ credentials: "omit",
148
+ },
134
149
  ...options,
135
150
  headers: {
136
151
  "X-Stack-Override-Error-Status": "true",
@@ -147,15 +162,39 @@ export class StackClientInterface {
147
162
  ...'publishableClientKey' in this.options ? {
148
163
  "X-Stack-Publishable-Client-Key": this.options.publishableClientKey,
149
164
  } : {},
150
- ...'projectOwnerTokens' in this.options ? {
151
- "X-Stack-Admin-Access-Token": (await this.options.projectOwnerTokens?.getOrWait())?.accessToken ?? "",
165
+ ...adminTokenObj ? {
166
+ "X-Stack-Admin-Access-Token": adminTokenObj.accessToken ?? "",
152
167
  } : {},
168
+ /**
169
+ * Next.js until v15 would cache fetch requests by default, and forcefully disabling it was nearly impossible.
170
+ *
171
+ * This header is used to change the cache key and hence always disable it, because we do our own caching.
172
+ *
173
+ * When we drop support for Next.js <15, we may be able to remove this header, but please make sure that this is
174
+ * the case (I haven't actually tested.)
175
+ */
153
176
  "X-Stack-Random-Nonce": generateSecureRandomString(),
154
177
  ...options.headers,
155
178
  },
156
- cache: "no-store",
179
+ /**
180
+ * Cloudflare Workers does not support cache, so don't pass it there
181
+ */
182
+ ..."WebSocketPair" in globalThis ? {} : {
183
+ cache: "no-store",
184
+ },
157
185
  };
158
- const rawRes = await fetch(url, params);
186
+ let rawRes;
187
+ try {
188
+ rawRes = await fetch(url, params);
189
+ }
190
+ catch (e) {
191
+ if (e instanceof TypeError) {
192
+ // Network error, retry
193
+ console.log("Stack detected a network error, retrying.", e);
194
+ return Result.error(e);
195
+ }
196
+ throw e;
197
+ }
159
198
  const processedRes = await this._processResponse(rawRes);
160
199
  if (processedRes.status === "error") {
161
200
  // If the access token is expired, reset it and retry
@@ -166,6 +205,15 @@ export class StackClientInterface {
166
205
  });
167
206
  return Result.error(new Error("Access token expired"));
168
207
  }
208
+ // Same for the admin access token
209
+ // TODO HACK: Some of the backend hasn't been ported to use the new error codes, so if we have project owner tokens we need to check for ApiKeyNotFound too. Once the migration to smartRouteHandlers is complete, we can check for AdminAccessTokenExpired only.
210
+ if (adminTokenStore && (processedRes.error instanceof KnownErrors.AdminAccessTokenExpired || processedRes.error instanceof KnownErrors.ApiKeyNotFound)) {
211
+ adminTokenStore.set({
212
+ accessToken: null,
213
+ refreshToken: adminTokenObj.refreshToken,
214
+ });
215
+ return Result.error(new Error("Admin access token expired"));
216
+ }
169
217
  // Known errors are client side errors, and should hence not be retried (except for access token expired above).
170
218
  // Hence, throw instead of returning an error
171
219
  throw processedRes.error;
@@ -23,7 +23,7 @@ export declare const currentUserCrud: {
23
23
  primaryEmail: undefined;
24
24
  primaryEmailVerified: undefined;
25
25
  displayName: undefined;
26
- clientMetadata: {};
26
+ clientMetadata: undefined;
27
27
  selectedTeamId: undefined;
28
28
  profileImageUrl: undefined;
29
29
  signedUpAtMillis: undefined;
@@ -31,7 +31,7 @@ export declare const currentUserCrud: {
31
31
  hasPassword: undefined;
32
32
  authWithEmail: undefined;
33
33
  oauthProviders: undefined;
34
- serverMetadata: {};
34
+ serverMetadata: undefined;
35
35
  }, "">;
36
36
  updateSchema: yup.ObjectSchema<{
37
37
  displayName: string | undefined;
@@ -70,7 +70,7 @@ export declare const currentUserCrud: {
70
70
  primaryEmail: undefined;
71
71
  primaryEmailVerified: undefined;
72
72
  displayName: undefined;
73
- clientMetadata: {};
73
+ clientMetadata: undefined;
74
74
  selectedTeamId: undefined;
75
75
  profileImageUrl: undefined;
76
76
  signedUpAtMillis: undefined;
@@ -78,7 +78,7 @@ export declare const currentUserCrud: {
78
78
  hasPassword: undefined;
79
79
  authWithEmail: undefined;
80
80
  oauthProviders: undefined;
81
- serverMetadata: {};
81
+ serverMetadata: undefined;
82
82
  }, "">;
83
83
  updateSchema: yup.ObjectSchema<{
84
84
  displayName: string | undefined;
@@ -120,7 +120,7 @@ export declare const currentUserCrud: {
120
120
  primaryEmail: undefined;
121
121
  primaryEmailVerified: undefined;
122
122
  displayName: undefined;
123
- clientMetadata: {};
123
+ clientMetadata: undefined;
124
124
  selectedTeamId: undefined;
125
125
  profileImageUrl: undefined;
126
126
  signedUpAtMillis: undefined;
@@ -128,7 +128,7 @@ export declare const currentUserCrud: {
128
128
  hasPassword: undefined;
129
129
  authWithEmail: undefined;
130
130
  oauthProviders: undefined;
131
- serverMetadata: {};
131
+ serverMetadata: undefined;
132
132
  }, "">;
133
133
  updateSchema: yup.ObjectSchema<{
134
134
  displayName: string | undefined;
@@ -36,7 +36,7 @@ export declare const usersCrudServerReadSchema: yup.ObjectSchema<{
36
36
  primaryEmail: undefined;
37
37
  primaryEmailVerified: undefined;
38
38
  displayName: undefined;
39
- clientMetadata: {};
39
+ clientMetadata: undefined;
40
40
  selectedTeamId: undefined;
41
41
  profileImageUrl: undefined;
42
42
  signedUpAtMillis: undefined;
@@ -44,7 +44,7 @@ export declare const usersCrudServerReadSchema: yup.ObjectSchema<{
44
44
  hasPassword: undefined;
45
45
  authWithEmail: undefined;
46
46
  oauthProviders: undefined;
47
- serverMetadata: {};
47
+ serverMetadata: undefined;
48
48
  }, "">;
49
49
  export declare const usersCrud: {
50
50
  client: {
@@ -76,7 +76,7 @@ export declare const usersCrud: {
76
76
  primaryEmail: undefined;
77
77
  primaryEmailVerified: undefined;
78
78
  displayName: undefined;
79
- clientMetadata: {};
79
+ clientMetadata: undefined;
80
80
  selectedTeamId: undefined;
81
81
  profileImageUrl: undefined;
82
82
  signedUpAtMillis: undefined;
@@ -84,7 +84,7 @@ export declare const usersCrud: {
84
84
  hasPassword: undefined;
85
85
  authWithEmail: undefined;
86
86
  oauthProviders: undefined;
87
- serverMetadata: {};
87
+ serverMetadata: undefined;
88
88
  }, "">;
89
89
  updateSchema: yup.ObjectSchema<{
90
90
  displayName: string | undefined;
@@ -102,7 +102,9 @@ export declare const usersCrud: {
102
102
  selectedTeamId: undefined;
103
103
  }, "">;
104
104
  deleteSchema: yup.MixedSchema<{} | undefined, yup.AnyObject, undefined, "">;
105
- };
105
+ }; /**
106
+ * not used anymore, for backwards compatibility
107
+ */
106
108
  admin: {
107
109
  createSchema: undefined;
108
110
  readSchema: yup.ObjectSchema<{
@@ -126,7 +128,7 @@ export declare const usersCrud: {
126
128
  primaryEmail: undefined;
127
129
  primaryEmailVerified: undefined;
128
130
  displayName: undefined;
129
- clientMetadata: {};
131
+ clientMetadata: undefined;
130
132
  selectedTeamId: undefined;
131
133
  profileImageUrl: undefined;
132
134
  signedUpAtMillis: undefined;
@@ -134,7 +136,7 @@ export declare const usersCrud: {
134
136
  hasPassword: undefined;
135
137
  authWithEmail: undefined;
136
138
  oauthProviders: undefined;
137
- serverMetadata: {};
139
+ serverMetadata: undefined;
138
140
  }, "">;
139
141
  updateSchema: yup.ObjectSchema<{
140
142
  displayName: string | undefined;
@@ -1,5 +1,6 @@
1
1
  import { createCrud } from "../../crud";
2
2
  import * as yup from "yup";
3
+ import { yupJson } from "../../utils/yup";
3
4
  export const usersCrudServerUpdateSchema = yup.object({
4
5
  displayName: yup.string().optional(),
5
6
  clientMetadata: yup.object().optional(),
@@ -14,7 +15,7 @@ export const usersCrudServerReadSchema = yup.object({
14
15
  primaryEmail: yup.string().nullable().defined(),
15
16
  primaryEmailVerified: yup.boolean().required(),
16
17
  displayName: yup.string().nullable().defined(),
17
- clientMetadata: yup.object().nullable().defined().transform((value) => JSON.parse(JSON.stringify(value))),
18
+ clientMetadata: yupJson,
18
19
  selectedTeamId: yup.string().nullable().defined(),
19
20
  profileImageUrl: yup.string().nullable().defined(),
20
21
  signedUpAtMillis: yup.number().required(),
@@ -25,7 +26,7 @@ export const usersCrudServerReadSchema = yup.object({
25
26
  hasPassword: yup.boolean().required(),
26
27
  authWithEmail: yup.boolean().required(),
27
28
  oauthProviders: yup.array(yup.string().required()).required(),
28
- serverMetadata: yup.object().nullable().defined().transform((value) => JSON.parse(JSON.stringify(value))),
29
+ serverMetadata: yupJson,
29
30
  }).required();
30
31
  const serverDeleteSchema = yup.mixed();
31
32
  export const usersCrud = createCrud({
@@ -1,4 +1,4 @@
1
- import { StatusError, throwErr, throwStackErr } from "./utils/errors";
1
+ import { StatusError, throwErr } from "./utils/errors";
2
2
  import { identityArgs } from "./utils/functions";
3
3
  import { deindent } from "./utils/strings";
4
4
  export class KnownError extends StatusError {
@@ -26,7 +26,7 @@ export class KnownError extends StatusError {
26
26
  };
27
27
  }
28
28
  get errorCode() {
29
- return this.constructor.errorCode ?? throwStackErr(`Can't find error code for this KnownError. Is its constructor a KnownErrorConstructor? ${this}`);
29
+ return this.constructor.errorCode ?? throwErr(`Can't find error code for this KnownError. Is its constructor a KnownErrorConstructor? ${this}`);
30
30
  }
31
31
  static constructorArgsFromJson(json) {
32
32
  return [
@@ -1,12 +1,11 @@
1
1
  import { Json } from "./json";
2
- export declare function throwErr(errorMessage: string): never;
2
+ export declare function throwErr(errorMessage: string, extraData?: any): never;
3
3
  export declare function throwErr(error: Error): never;
4
4
  export declare function throwErr(...args: StatusErrorConstructorParameters): never;
5
5
  export declare class StackAssertionError extends Error {
6
6
  readonly extraData?: Record<string, any> | undefined;
7
7
  constructor(message: string, extraData?: Record<string, any> | undefined, options?: ErrorOptions);
8
8
  }
9
- export declare function throwStackErr(message: string, extraData?: any): never;
10
9
  export declare function registerErrorSink(sink: (location: string, error: unknown) => void): void;
11
10
  export declare function captureError(location: string, error: unknown): void;
12
11
  type Status = {
@@ -1,6 +1,6 @@
1
1
  export function throwErr(...args) {
2
2
  if (typeof args[0] === "string") {
3
- throw new StackAssertionError(args[0]);
3
+ throw new StackAssertionError(args[0], args[1]);
4
4
  }
5
5
  else if (args[0] instanceof Error) {
6
6
  throw args[0];
@@ -19,9 +19,6 @@ export class StackAssertionError extends Error {
19
19
  }
20
20
  }
21
21
  StackAssertionError.prototype.name = "StackAssertionError";
22
- export function throwStackErr(message, extraData) {
23
- throw new StackAssertionError(message, extraData);
24
- }
25
22
  const errorSinks = new Set();
26
23
  export function registerErrorSink(sink) {
27
24
  if (errorSinks.has(sink)) {
@@ -0,0 +1,2 @@
1
+ import * as yup from "yup";
2
+ export declare const yupJson: yup.MixedSchema<{} | null, yup.AnyObject, undefined, "">;
@@ -0,0 +1,2 @@
1
+ import * as yup from "yup";
2
+ export const yupJson = yup.mixed().nullable().defined().transform((value) => JSON.parse(JSON.stringify(value)));
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@stackframe/stack-shared",
3
- "version": "2.4.8",
3
+ "version": "2.4.10",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
7
7
  "README.md",
8
- "dist"
8
+ "dist",
9
+ "CHANGELOG.md",
10
+ "LICENSE"
9
11
  ],
10
12
  "peerDependencies": {
11
13
  "react": "^18.2",
@@ -24,7 +26,7 @@
24
26
  "jose": "^5.2.2",
25
27
  "oauth4webapi": "^2.10.3",
26
28
  "uuid": "^9.0.1",
27
- "@stackframe/stack-sc": "1.5.3"
29
+ "@stackframe/stack-sc": "1.5.5"
28
30
  },
29
31
  "devDependencies": {
30
32
  "@types/bcrypt": "^5.0.2",