@stackframe/stack-shared 2.5.9 → 2.5.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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # @stackframe/stack-shared
2
2
 
3
+ ## 2.5.10
4
+
5
+ ### Patch Changes
6
+
7
+ - Facebook Business support
8
+ - @stackframe/stack-sc@2.5.10
9
+
3
10
  ## 2.5.9
4
11
 
5
12
  ### Patch Changes
@@ -21,6 +21,13 @@ export declare class StackClientInterface {
21
21
  constructor(options: ClientInterfaceOptions);
22
22
  get projectId(): string;
23
23
  getApiUrl(): string;
24
+ runNetworkDiagnostics(session?: InternalSession | null, requestType?: "client" | "server" | "admin"): Promise<{
25
+ cfTrace: string;
26
+ apiRoot: string;
27
+ baseUrlBackend: string;
28
+ prodDashboard: string;
29
+ prodBackend: string;
30
+ }>;
24
31
  fetchNewAccessToken(refreshToken: RefreshToken): Promise<AccessToken | null>;
25
32
  protected sendClientRequest(path: string, requestOptions: RequestInit, session: InternalSession | null, requestType?: "client" | "server" | "admin"): Promise<Response & {
26
33
  usedTokens: {
@@ -6,6 +6,7 @@ import { generateSecureRandomString } from '../utils/crypto';
6
6
  import { StackAssertionError, throwErr } from '../utils/errors';
7
7
  import { globalVar } from '../utils/globals';
8
8
  import { Result } from "../utils/results";
9
+ import { deindent } from '../utils/strings';
9
10
  export class StackClientInterface {
10
11
  constructor(options) {
11
12
  this.options = options;
@@ -17,6 +18,54 @@ export class StackClientInterface {
17
18
  getApiUrl() {
18
19
  return this.options.baseUrl + "/api/v1";
19
20
  }
21
+ async runNetworkDiagnostics(session, requestType) {
22
+ const tryRequest = async (cb) => {
23
+ try {
24
+ await cb();
25
+ return "OK";
26
+ }
27
+ catch (e) {
28
+ return `${e}`;
29
+ }
30
+ };
31
+ const cfTrace = await tryRequest(async () => {
32
+ const res = await fetch("https://1.1.1.1/cdn-cgi/trace");
33
+ if (!res.ok) {
34
+ throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
35
+ }
36
+ });
37
+ const apiRoot = session !== undefined && requestType !== undefined ? await tryRequest(async () => {
38
+ const res = await this.sendClientRequestInner("/", {}, session, requestType);
39
+ if (res.status === "error") {
40
+ throw res.error;
41
+ }
42
+ }) : "Not tested";
43
+ const baseUrlBackend = await tryRequest(async () => {
44
+ const res = await fetch(new URL("/health", this.getApiUrl()));
45
+ if (!res.ok) {
46
+ throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
47
+ }
48
+ });
49
+ const prodDashboard = await tryRequest(async () => {
50
+ const res = await fetch("https://app.stackframe.com/health");
51
+ if (!res.ok) {
52
+ throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
53
+ }
54
+ });
55
+ const prodBackend = await tryRequest(async () => {
56
+ const res = await fetch("https://api.stackframe.com/health");
57
+ if (!res.ok) {
58
+ throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
59
+ }
60
+ });
61
+ return {
62
+ cfTrace,
63
+ apiRoot,
64
+ baseUrlBackend,
65
+ prodDashboard,
66
+ prodBackend,
67
+ };
68
+ }
20
69
  async fetchNewAccessToken(refreshToken) {
21
70
  if (!('publishableClientKey' in this.options)) {
22
71
  // TODO support it
@@ -59,7 +108,23 @@ export class StackClientInterface {
59
108
  session ??= this.createSession({
60
109
  refreshToken: null,
61
110
  });
62
- return await Result.orThrowAsync(Result.retry(() => this.sendClientRequestInner(path, requestOptions, session, requestType), 5, { exponentialDelayBase: 1000 }));
111
+ const retriedResult = await Result.retry(() => this.sendClientRequestInner(path, requestOptions, session, requestType), 5, { exponentialDelayBase: 1000 });
112
+ // try to diagnose the error for the user
113
+ if (retriedResult.status === "error") {
114
+ if (!navigator.onLine) {
115
+ throw new Error("Failed to send Stack request. It seems like you are offline. (window.navigator.onLine is falsy)", { cause: retriedResult.error });
116
+ }
117
+ throw new Error(deindent `
118
+ Stack is unable to connect to the server. Please check your internet connection and try again.
119
+
120
+ If the problem persists, please contact Stack support and provide a screenshot of your entire browser console.
121
+
122
+ ${retriedResult.error}
123
+
124
+ ${JSON.stringify(await this.runNetworkDiagnostics(session, requestType), null, 2)}
125
+ `, { cause: retriedResult.error });
126
+ }
127
+ return retriedResult.data;
63
128
  }
64
129
  createSession(options) {
65
130
  const session = new InternalSession({
@@ -14,6 +14,7 @@ export declare const projectsCrudServerReadSchema: import("yup").ObjectSchema<{
14
14
  oauth_providers: {
15
15
  client_id?: string | undefined;
16
16
  client_secret?: string | undefined;
17
+ facebook_config_id?: string | undefined;
17
18
  type: NonNullable<"shared" | "standard" | undefined>;
18
19
  id: NonNullable<"google" | "github" | "facebook" | "microsoft" | "spotify" | undefined>;
19
20
  enabled: NonNullable<boolean | undefined>;
@@ -101,6 +102,7 @@ export declare const projectsCrudServerUpdateSchema: import("yup").ObjectSchema<
101
102
  oauth_providers?: {
102
103
  client_id?: string | undefined;
103
104
  client_secret?: string | undefined;
105
+ facebook_config_id?: string | undefined;
104
106
  type: NonNullable<"shared" | "standard" | undefined>;
105
107
  id: NonNullable<"google" | "github" | "facebook" | "microsoft" | "spotify" | undefined>;
106
108
  enabled: NonNullable<boolean | undefined>;
@@ -143,6 +145,7 @@ export declare const projectsCrudServerCreateSchema: import("yup").ObjectSchema<
143
145
  oauth_providers?: {
144
146
  client_id?: string | undefined;
145
147
  client_secret?: string | undefined;
148
+ facebook_config_id?: string | undefined;
146
149
  type: NonNullable<"shared" | "standard" | undefined>;
147
150
  id: NonNullable<"google" | "github" | "facebook" | "microsoft" | "spotify" | undefined>;
148
151
  enabled: NonNullable<boolean | undefined>;
@@ -211,6 +214,7 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
211
214
  oauth_providers: {
212
215
  client_id?: string | undefined;
213
216
  client_secret?: string | undefined;
217
+ facebook_config_id?: string | undefined;
214
218
  type: NonNullable<"shared" | "standard" | undefined>;
215
219
  id: NonNullable<"google" | "github" | "facebook" | "microsoft" | "spotify" | undefined>;
216
220
  enabled: NonNullable<boolean | undefined>;
@@ -279,6 +283,7 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
279
283
  oauth_providers?: {
280
284
  client_id?: string | undefined;
281
285
  client_secret?: string | undefined;
286
+ facebook_config_id?: string | undefined;
282
287
  type: NonNullable<"shared" | "standard" | undefined>;
283
288
  id: NonNullable<"google" | "github" | "facebook" | "microsoft" | "spotify" | undefined>;
284
289
  enabled: NonNullable<boolean | undefined>;
@@ -345,6 +350,7 @@ export declare const internalProjectsCrud: import("../../crud").CrudSchemaFromOp
345
350
  oauth_providers: {
346
351
  client_id?: string | undefined;
347
352
  client_secret?: string | undefined;
353
+ facebook_config_id?: string | undefined;
348
354
  type: NonNullable<"shared" | "standard" | undefined>;
349
355
  id: NonNullable<"google" | "github" | "facebook" | "microsoft" | "spotify" | undefined>;
350
356
  enabled: NonNullable<boolean | undefined>;
@@ -413,6 +419,7 @@ export declare const internalProjectsCrud: import("../../crud").CrudSchemaFromOp
413
419
  oauth_providers?: {
414
420
  client_id?: string | undefined;
415
421
  client_secret?: string | undefined;
422
+ facebook_config_id?: string | undefined;
416
423
  type: NonNullable<"shared" | "standard" | undefined>;
417
424
  id: NonNullable<"google" | "github" | "facebook" | "microsoft" | "spotify" | undefined>;
418
425
  enabled: NonNullable<boolean | undefined>;
@@ -10,6 +10,8 @@ const oauthProviderSchema = yupObject({
10
10
  type: schemaFields.oauthTypeSchema.required(),
11
11
  client_id: yupRequiredWhen(schemaFields.oauthClientIdSchema, 'type', 'standard'),
12
12
  client_secret: yupRequiredWhen(schemaFields.oauthClientSecretSchema, 'type', 'standard'),
13
+ // extra params
14
+ facebook_config_id: yupString().optional().meta({ openapiField: { description: 'This parameter is the configuration id for Facebook business login (for things like ads and marketing).' } }),
13
15
  });
14
16
  const enabledOAuthProviderSchema = yupObject({
15
17
  id: schemaFields.oauthIdSchema.required(),
@@ -86,13 +86,18 @@ function mapResult(result, fn) {
86
86
  }
87
87
  class RetryError extends AggregateError {
88
88
  constructor(errors) {
89
+ const strings = errors.map(e => String(e));
90
+ const isAllSame = strings.length > 1 && strings.every(s => s === strings[0]);
89
91
  super(errors, deindent `
90
92
  Error after retrying ${errors.length} times.
91
93
 
92
- ${errors.map((e, i) => deindent `
93
- Attempt ${i + 1}:
94
- ${e}
95
- `).join("\n\n")}
94
+ ${isAllSame ? deindent `
95
+ Attempts 1-${errors.length}:
96
+ ${errors[0]}
97
+ ` : errors.map((e, i) => deindent `
98
+ Attempt ${i + 1}:
99
+ ${e}
100
+ `).join("\n\n")}
96
101
  `, { cause: errors[errors.length - 1] });
97
102
  this.errors = errors;
98
103
  this.name = "RetryError";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackframe/stack-shared",
3
- "version": "2.5.9",
3
+ "version": "2.5.10",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -36,7 +36,7 @@
36
36
  "jose": "^5.2.2",
37
37
  "oauth4webapi": "^2.10.3",
38
38
  "uuid": "^9.0.1",
39
- "@stackframe/stack-sc": "2.5.9"
39
+ "@stackframe/stack-sc": "2.5.10"
40
40
  },
41
41
  "devDependencies": {
42
42
  "rimraf": "^5.0.5",