@protobase/server 0.1.0 → 0.1.2
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
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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.
|
|
3
|
+
"version": "0.1.2",
|
|
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.
|
|
36
|
-
"@protobase/schema": "0.1.
|
|
37
|
-
"@protobase/query": "0.1.
|
|
35
|
+
"@protobase/layout": "0.1.2",
|
|
36
|
+
"@protobase/schema": "0.1.2",
|
|
37
|
+
"@protobase/query": "0.1.2"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "tsdown"
|