@protobase/server 0.1.0 → 0.1.1

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.
@@ -25,27 +25,16 @@ export type CreateAuthOptions = {
25
25
  * turns reset off whatever the environment says.
26
26
  */
27
27
  mailer?: Mailer | false;
28
+ /**
29
+ * Sign-in providers for Better Auth, for example `{ github: { clientId, clientSecret } }`; the callback is
30
+ * `{baseURL}/api/auth/callback/<provider>`. A provider also signs up people without an account, with the default role.
31
+ * Default none.
32
+ */
33
+ socialProviders?: BetterAuthOptions['socialProviders'];
28
34
  };
29
35
  /** The configured roles with `admin` first; `admin` is added when missing. */
30
36
  export declare const normalizeRoles: (roles?: string[]) => string[];
31
37
  export declare const createAuth: (options: CreateAuthOptions) => import("better-auth").Auth<{
32
- database: any;
33
- baseURL: string;
34
- basePath: string;
35
- secret: string;
36
- trustedOrigins: string[];
37
- emailAndPassword: {
38
- resetPasswordTokenExpiresIn?: number | undefined;
39
- revokeSessionsOnPasswordReset?: true | undefined;
40
- sendResetPassword?: (({ user, url }: {
41
- user: import("better-auth").User;
42
- url: string;
43
- token: string;
44
- }) => Promise<void>) | undefined;
45
- enabled: true;
46
- disableSignUp: true;
47
- minPasswordLength: number;
48
- };
49
38
  plugins: [{
50
39
  id: "admin";
51
40
  version: string;
@@ -1235,10 +1224,29 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
1235
1224
  handler: () => void;
1236
1225
  };
1237
1226
  };
1227
+ socialProviders?: import("better-auth").SocialProviders | undefined;
1228
+ database: any;
1229
+ baseURL: string;
1230
+ basePath: string;
1231
+ secret: string;
1232
+ trustedOrigins: string[];
1233
+ emailAndPassword: {
1234
+ resetPasswordTokenExpiresIn?: number | undefined;
1235
+ revokeSessionsOnPasswordReset?: true | undefined;
1236
+ sendResetPassword?: (({ user, url }: {
1237
+ user: import("better-auth").User;
1238
+ url: string;
1239
+ token: string;
1240
+ }) => Promise<void>) | undefined;
1241
+ enabled: true;
1242
+ disableSignUp: true;
1243
+ minPasswordLength: number;
1244
+ };
1238
1245
  }> & {
1239
1246
  roles: string[];
1240
1247
  defaultRole: string | undefined;
1241
1248
  passwordReset: boolean;
1249
+ socialProviders: string[];
1242
1250
  };
1243
1251
  export type AdminAuth = ReturnType<typeof createAuth>;
1244
1252
  //#endregion
@@ -24,14 +24,10 @@ const normalizeRoles = (roles = ["admin", "user"]) => {
24
24
  if (bad !== void 0) throw new Error(`Invalid role "${bad}": use lowercase letters, digits, "_" or "-"`);
25
25
  return ["admin", ...new Set(roles.filter((role) => role !== "admin"))];
26
26
  };
27
- const createAuth = (options) => {
27
+ /** The options `createAuth` gives Better Auth, with the roles, default role and mailer already resolved. */
28
+ const betterAuthOptions = (options, { roles, defaultRole, mailer }) => {
28
29
  const secure = options.baseURL.startsWith("https://");
29
- const roles = normalizeRoles(options.roles);
30
- if (options.defaultRole !== void 0 && !roles.includes(options.defaultRole)) throw new Error(`defaultRole "${options.defaultRole}" is not one of the roles: ${roles.join(", ")}`);
31
- const others = roles.filter((role) => role !== "admin");
32
- const defaultRole = options.defaultRole ?? (others.length === 1 ? others[0] : void 0);
33
- const mailer = options.mailer === void 0 ? platformMailer() : options.mailer || void 0;
34
- const auth = betterAuth({
30
+ return {
35
31
  database: options.database,
36
32
  baseURL: options.baseURL,
37
33
  basePath: authBasePath,
@@ -47,6 +43,7 @@ const createAuth = (options) => {
47
43
  minPasswordLength: 12,
48
44
  ...mailer && passwordResetOptions(mailer)
49
45
  },
46
+ ...options.socialProviders && { socialProviders: options.socialProviders },
50
47
  plugins: [admin({
51
48
  defaultRole: defaultRole ?? "unassigned",
52
49
  roles: Object.fromEntries(roles.map((role) => [role, role === "admin" ? adminAc : userAc]))
@@ -82,12 +79,26 @@ const createAuth = (options) => {
82
79
  },
83
80
  backgroundTasks: { handler: () => {} }
84
81
  }
85
- });
82
+ };
83
+ };
84
+ const createAuth = (options) => {
85
+ const roles = normalizeRoles(options.roles);
86
+ if (options.defaultRole !== void 0 && !roles.includes(options.defaultRole)) throw new Error(`defaultRole "${options.defaultRole}" is not one of the roles: ${roles.join(", ")}`);
87
+ const others = roles.filter((role) => role !== "admin");
88
+ const defaultRole = options.defaultRole ?? (others.length === 1 ? others[0] : void 0);
89
+ const mailer = options.mailer === void 0 ? platformMailer() : options.mailer || void 0;
90
+ const auth = betterAuth(betterAuthOptions(options, {
91
+ roles,
92
+ defaultRole,
93
+ mailer
94
+ }));
95
+ const socialProviders = Object.keys(options.socialProviders ?? {});
86
96
  return Object.assign(auth, {
87
97
  roles,
88
98
  defaultRole,
89
- passwordReset: Boolean(mailer)
99
+ passwordReset: Boolean(mailer),
100
+ socialProviders
90
101
  });
91
102
  };
92
103
  //#endregion
93
- export { authBasePath, createAuth, normalizeRoles };
104
+ export { authBasePath, betterAuthOptions, createAuth, normalizeRoles };
@@ -3,13 +3,15 @@ import { Hono } from "hono";
3
3
  //#region src/better-auth/status-route.ts
4
4
  /**
5
5
  * `GET {authBase}/status`: `needsAdmin` while the admin store has no user, so a login page can say how to create one,
6
- * and `passwordReset` when reset mail can be sent, so it offers "Forgot password?" only then.
6
+ * `passwordReset` when reset mail can be sent, so it offers "Forgot password?" only then, and the ids of the configured
7
+ * `socialProviders`, so it offers "Continue with GitHub" when `github` is one.
7
8
  */
8
9
  const statusRoute = (auth) => {
9
10
  const app = new Hono();
10
11
  app.get("/status", async (c) => c.json({
11
12
  needsAdmin: !await hasUsers(auth),
12
- passwordReset: auth.passwordReset
13
+ passwordReset: auth.passwordReset,
14
+ socialProviders: auth.socialProviders
13
15
  }));
14
16
  return app;
15
17
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -32,9 +32,9 @@
32
32
  "kysely": "^0.29.6",
33
33
  "nodemailer": "^10.0.16",
34
34
  "zod": "^4.6.5",
35
- "@protobase/layout": "0.1.0",
36
- "@protobase/schema": "0.1.0",
37
- "@protobase/query": "0.1.0"
35
+ "@protobase/layout": "0.1.1",
36
+ "@protobase/query": "0.1.1",
37
+ "@protobase/schema": "0.1.1"
38
38
  },
39
39
  "scripts": {
40
40
  "build": "tsdown"