@protobase/client 0.4.1 → 0.6.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.
@@ -47,6 +47,14 @@ export declare const accountSecurity: (client: BetterAuthClient) => {
47
47
  /** Turns on two-factor authentication with a code emailed at each sign-in. */
48
48
  turnOnEmailedCodes: (password?: string) => Promise<void>;
49
49
  turnOffTwoFactor: (password?: string) => Promise<void>;
50
+ /** The ids of the sign-in providers the account is linked to, for example `github`. */
51
+ linkedProviders: () => Promise<string[]>;
52
+ /**
53
+ * Starts linking the account to a provider such as `github`, whatever address the provider has: resolves with the
54
+ * provider's authorization URL, for the page to go to. The provider sends the browser back to `callbackURL`, with
55
+ * `?error=<code>` when the link did not go through, for example `account_already_linked_to_different_user`.
56
+ */
57
+ linkProvider: (provider: string, callbackURL: string) => Promise<string>;
50
58
  /** New backup codes for the authenticator app; the old ones stop working. */
51
59
  newBackupCodes: (password?: string) => Promise<string[]>;
52
60
  };
@@ -64,6 +64,27 @@ const accountSecurity = (client) => ({
64
64
  const { error } = await client.twoFactor.disable(password ? { password } : {});
65
65
  if (error) throw authError(error, "Could not turn off two-factor authentication");
66
66
  },
67
+ /** The ids of the sign-in providers the account is linked to, for example `github`. */
68
+ linkedProviders: async () => {
69
+ const { data, error } = await client.listAccounts();
70
+ if (error || !data) throw authError(error, "Could not read your linked accounts");
71
+ return [...new Set(data.map((account) => account.providerId).filter((provider) => provider !== "credential"))];
72
+ },
73
+ /**
74
+ * Starts linking the account to a provider such as `github`, whatever address the provider has: resolves with the
75
+ * provider's authorization URL, for the page to go to. The provider sends the browser back to `callbackURL`, with
76
+ * `?error=<code>` when the link did not go through, for example `account_already_linked_to_different_user`.
77
+ */
78
+ linkProvider: async (provider, callbackURL) => {
79
+ const { data, error } = await client.linkSocial({
80
+ provider,
81
+ callbackURL,
82
+ errorCallbackURL: callbackURL,
83
+ disableRedirect: true
84
+ });
85
+ if (error || !data?.url) throw authError(error, "Could not start linking the account");
86
+ return data.url;
87
+ },
67
88
  /** New backup codes for the authenticator app; the old ones stop working. */
68
89
  newBackupCodes: async (password) => {
69
90
  const { data, error } = await client.twoFactor.generateBackupCodes(password ? { password } : {});
@@ -25,6 +25,12 @@ export type AssistantClient = {
25
25
  send: (text: string, page?: string) => Promise<void>;
26
26
  /** Sends a click on a card's button; the backend answers with events. Rejects with `ApiError`. */
27
27
  act: (partId: string, actionId: string) => Promise<void>;
28
+ /**
29
+ * Calls the backend beyond the protocol, such as a widget reading what it shows: `path` resolves against the
30
+ * backend's URL and is refused, before any request, when it lands on another origin, so the user's token goes only
31
+ * to the backend. Sends the token like every request; rejects with `ApiError` on an answer that is not 2xx.
32
+ */
33
+ fetch: (path: string, init?: RequestInit) => Promise<Response>;
28
34
  };
29
35
  /** A client of an assistant backend: the protocol's event stream and its two requests, with the user's token. */
30
36
  export declare const createAssistantClient: (options: AssistantClientOptions) => AssistantClient;
package/dist/assistant.js CHANGED
@@ -9,6 +9,14 @@ const pause = (ms, signal) => new Promise((resolve) => {
9
9
  resolve();
10
10
  }, { once: true });
11
11
  });
12
+ const sameOrigin = "http://same-origin.invalid";
13
+ /** The URL `path` names on the backend at `base`, or an error when it is on another origin. */
14
+ const backendUrl = (base, path) => {
15
+ const backend = new URL(base, sameOrigin);
16
+ const url = new URL(path, `${backend.href}/`);
17
+ if (url.origin !== backend.origin) throw new Error(`${path} is not on the assistant backend's origin`);
18
+ return backend.origin === sameOrigin ? `${url.pathname}${url.search}` : url.href;
19
+ };
12
20
  /** A client of an assistant backend: the protocol's event stream and its two requests, with the user's token. */
13
21
  const createAssistantClient = (options) => {
14
22
  const base = options.url.replace(/\/+$/, "");
@@ -76,6 +84,18 @@ const createAssistantClient = (options) => {
76
84
  actionId
77
85
  }
78
86
  });
87
+ },
88
+ fetch: async (path, init = {}) => {
89
+ const url = backendUrl(base, path);
90
+ const token = await options.token();
91
+ const headers = new Headers(init.headers);
92
+ if (token) headers.set("authorization", `Bearer ${token}`);
93
+ const response = await doFetch(url, {
94
+ ...init,
95
+ headers
96
+ });
97
+ if (!response.ok) throw await readProblem(response);
98
+ return response;
79
99
  }
80
100
  };
81
101
  };
@@ -17,16 +17,23 @@ export type SignInResult = {
17
17
  kind: 'two-factor';
18
18
  methods: TwoFactorMethod[];
19
19
  };
20
+ /** The sign-in provider the platform adds to the app: its id, as in `socialProviders`, and the name to show. */
21
+ export type PlatformSignIn = {
22
+ provider: string;
23
+ name: string;
24
+ };
20
25
  /**
21
26
  * `needsAdmin` while no user exists yet; `signInMethods` the ways to sign in the server's policy leaves on;
22
27
  * `passwordReset` when the server can email reset links; `socialProviders` the ids of the sign-in providers, for example
23
- * `github`; `staffSignIn` the operator provider's name when its staff can sign in as people.
28
+ * `github`; `platformSignIn` the one of them the platform adds; `staffSignIn` the operator provider's name when its staff
29
+ * can sign in as people.
24
30
  */
25
31
  export type SetupStatus = {
26
32
  needsAdmin: boolean;
27
33
  signInMethods: SignInMethod[];
28
34
  passwordReset: boolean;
29
35
  socialProviders: string[];
36
+ platformSignIn?: PlatformSignIn;
30
37
  staffSignIn?: string;
31
38
  };
32
39
  //#endregion
package/dist/auth.d.ts CHANGED
@@ -26,7 +26,8 @@ export declare const tokenExpiry: (token: string) => number;
26
26
  export declare const createAuthSession: (options?: AuthSessionOptions) => {
27
27
  /**
28
28
  * Starts sign-in with a provider such as `github`: resolves with the provider's authorization URL, for the page to go to.
29
- * The provider sends the browser back to `callbackURL` signed in, or with `?error=<code>`.
29
+ * The provider sends the browser back to `callbackURL` signed in, or with `?error=<code>`, for example
30
+ * `signup_disabled` when no account here has that provider account or its address.
30
31
  */
31
32
  signInSocial: (provider: string, callbackURL: string) => Promise<string>;
32
33
  signOut: () => Promise<void>;
@@ -47,6 +48,8 @@ export declare const createAuthSession: (options?: AuthSessionOptions) => {
47
48
  confirmAuthenticatorApp: (code: string) => Promise<void>;
48
49
  turnOnEmailedCodes: (password?: string) => Promise<void>;
49
50
  turnOffTwoFactor: (password?: string) => Promise<void>;
51
+ linkedProviders: () => Promise<string[]>;
52
+ linkProvider: (provider: string, callbackURL: string) => Promise<string>;
50
53
  newBackupCodes: (password?: string) => Promise<string[]>;
51
54
  };
52
55
  signInPolicy: {
package/dist/auth.js CHANGED
@@ -71,6 +71,7 @@ const createAuthSession = (options = {}) => {
71
71
  signInMethods: body.signInMethods ?? ["password"],
72
72
  passwordReset: Boolean(body.passwordReset),
73
73
  socialProviders: body.socialProviders ?? [],
74
+ ...body.platformSignIn && { platformSignIn: body.platformSignIn },
74
75
  ...body.staffSignIn && { staffSignIn: body.staffSignIn }
75
76
  };
76
77
  },
@@ -82,7 +83,8 @@ const createAuthSession = (options = {}) => {
82
83
  ...signInFlows(client, () => token({ refresh: true })),
83
84
  /**
84
85
  * Starts sign-in with a provider such as `github`: resolves with the provider's authorization URL, for the page to go to.
85
- * The provider sends the browser back to `callbackURL` signed in, or with `?error=<code>`.
86
+ * The provider sends the browser back to `callbackURL` signed in, or with `?error=<code>`, for example
87
+ * `signup_disabled` when no account here has that provider account or its address.
86
88
  */
87
89
  signInSocial: async (provider, callbackURL) => {
88
90
  const { data, error } = await client.signIn.social({
package/dist/index.d.ts CHANGED
@@ -6,10 +6,10 @@ import { ApiError, PreconditionFailedError, ProblemDetails, ProblemError, isApiE
6
6
  import { SignInPolicy, SignInPolicyClient, SignInPolicyState, SignInRule, StaffAccessRule } from "./sign-in-policy.js";
7
7
  import { AccountSecurity, AccountSignIn, AuthenticatorSetup, Passkey, RequiredSetup } from "./account-security.js";
8
8
  import { StaffSignIn, StaffSignInClient } from "./staff-sign-in.js";
9
- import { AuthUser, SetupStatus, SignInMethod, SignInResult, TwoFactorMethod } from "./auth-types.js";
9
+ import { AuthUser, PlatformSignIn, SetupStatus, SignInMethod, SignInResult, TwoFactorMethod } from "./auth-types.js";
10
10
  import { AuthError } from "./auth-error.js";
11
11
  import { AuthSession, AuthSessionOptions, createAuthSession, tokenExpiry } from "./auth.js";
12
12
  import { createStaticSession } from "./static-session.js";
13
13
  import { AssistantClient, AssistantClientOptions, AssistantConnection, createAssistantClient } from "./assistant.js";
14
14
  import { RuntimeClient, RuntimeClientOptions, RuntimePolicy, RuntimeStatus, createRuntimeClient } from "./runtime.js";
15
- export { type AccountSecurity, type AccountSignIn, ApiError, type AssistantClient, type AssistantClientOptions, type AssistantConnection, AuthError, type AuthSession, type AuthSessionOptions, type AuthUser, type AuthenticatorSetup, type BatchOp, type BatchRef, type BatchResult, type Client, type ClientOptions, type Facet, type FilterInput, type Histogram, type HistogramBucket, type ListPage, type ListParams, type Meta, type MetaResult, type Passkey, PreconditionFailedError, type ProblemDetails, type ProblemError, type RecordOf, type RecordPermissions, type RequiredSetup, type ResourcePermissions, type ResourceRef, type RuntimeClient, type RuntimeClientOptions, type RuntimePolicy, type RuntimeStatus, type Series, type SeriesParams, type SeriesPoint, type SetupStatus, type SignInMethod, type SignInPolicy, type SignInPolicyClient, type SignInPolicyState, type SignInResult, type SignInRule, type StaffAccessRule, type StaffSignIn, type StaffSignInClient, type Stored, type TwoFactorMethod, createAssistantClient, createAuthSession, createClient, createRuntimeClient, createStaticSession, filterText, isApiError, listWire, tokenExpiry };
15
+ export { type AccountSecurity, type AccountSignIn, ApiError, type AssistantClient, type AssistantClientOptions, type AssistantConnection, AuthError, type AuthSession, type AuthSessionOptions, type AuthUser, type AuthenticatorSetup, type BatchOp, type BatchRef, type BatchResult, type Client, type ClientOptions, type Facet, type FilterInput, type Histogram, type HistogramBucket, type ListPage, type ListParams, type Meta, type MetaResult, type Passkey, type PlatformSignIn, PreconditionFailedError, type ProblemDetails, type ProblemError, type RecordOf, type RecordPermissions, type RequiredSetup, type ResourcePermissions, type ResourceRef, type RuntimeClient, type RuntimeClientOptions, type RuntimePolicy, type RuntimeStatus, type Series, type SeriesParams, type SeriesPoint, type SetupStatus, type SignInMethod, type SignInPolicy, type SignInPolicyClient, type SignInPolicyState, type SignInResult, type SignInRule, type StaffAccessRule, type StaffSignIn, type StaffSignInClient, type Stored, type TwoFactorMethod, createAssistantClient, createAuthSession, createClient, createRuntimeClient, createStaticSession, filterText, isApiError, listWire, tokenExpiry };
@@ -5,8 +5,8 @@ export type SignInRule = 'allowed' | 'required' | 'forbidden';
5
5
  export type StaffAccessRule = 'allowed' | 'notify' | 'forbidden';
6
6
  /**
7
7
  * How people may sign in, as the server stores it: passwords and emailed codes are allowed or forbidden, passkeys and
8
- * two-factor authentication can also be required (everyone without one is asked to set it up), and staff of the
9
- * operator may sign in as people, with or without telling them, or not.
8
+ * two-factor authentication can also be required (everyone without one is asked to set it up), staff of the operator
9
+ * may sign in as people, with or without telling them, or not, and the sign-in provider the platform adds is on or off.
10
10
  */
11
11
  export type SignInPolicy = {
12
12
  password: 'allowed' | 'forbidden';
@@ -14,17 +14,20 @@ export type SignInPolicy = {
14
14
  passkey: SignInRule;
15
15
  twoFactor: SignInRule;
16
16
  staffAccess: StaffAccessRule;
17
+ platformSignIn: 'allowed' | 'forbidden';
17
18
  };
18
19
  /**
19
20
  * The saved policy, how it applies (`effective`: emailed codes need mail, and without mail passwords stay on and staff
20
- * who would have to tell the person cannot sign in), the name of the operator provider when staff can sign in at all,
21
- * and who saved it when.
21
+ * who would have to tell the person cannot sign in; the platform's provider is off while a second step is required), the
22
+ * name of the operator provider when staff can sign in at all, the name of the platform's sign-in provider when it adds
23
+ * one, and who saved it when.
22
24
  */
23
25
  export type SignInPolicyState = {
24
26
  policy: SignInPolicy;
25
27
  effective: SignInPolicy;
26
28
  mail: boolean;
27
29
  operator?: string;
30
+ platformSignIn?: string;
28
31
  savedAt?: string;
29
32
  savedBy?: string;
30
33
  };
@@ -45,7 +45,8 @@ const createStaticSession = (token, user = {
45
45
  emailCode: "allowed",
46
46
  passkey: "allowed",
47
47
  twoFactor: "allowed",
48
- staffAccess: "allowed"
48
+ staffAccess: "allowed",
49
+ platformSignIn: "allowed"
49
50
  },
50
51
  mail: false,
51
52
  account: {
@@ -64,7 +65,9 @@ const createStaticSession = (token, user = {
64
65
  confirmAuthenticatorApp: unsupported("turn on two-factor authentication"),
65
66
  turnOnEmailedCodes: unsupported("turn on two-factor authentication"),
66
67
  turnOffTwoFactor: unsupported("turn off two-factor authentication"),
67
- newBackupCodes: unsupported("make backup codes")
68
+ newBackupCodes: unsupported("make backup codes"),
69
+ linkedProviders: async () => [],
70
+ linkProvider: unsupported("link a sign-in provider")
68
71
  },
69
72
  signInPolicy: {
70
73
  read: unsupported("read the sign-in policy"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/client",
3
- "version": "0.4.1",
3
+ "version": "0.6.0",
4
4
  "description": "Typed fetch client for the Protobase REST API.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -30,8 +30,8 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@better-auth/passkey": "^1.7.7",
33
- "@protobase/layout": "0.4.1",
34
- "@protobase/schema": "0.4.1",
33
+ "@protobase/layout": "0.6.0",
34
+ "@protobase/schema": "0.6.0",
35
35
  "better-auth": "^1.7.7"
36
36
  }
37
37
  }