@wizeworks/lens-cloud 0.0.0-stage → 0.3.0-alpha.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.
- package/LICENSE +21 -0
- package/README.md +115 -2
- package/dist/alerts/evaluate.d.ts +10 -0
- package/dist/alerts/evaluate.d.ts.map +1 -0
- package/dist/alerts/evaluate.js +81 -0
- package/dist/alerts/evaluate.js.map +1 -0
- package/dist/alerts/notify.d.ts +28 -0
- package/dist/alerts/notify.d.ts.map +1 -0
- package/dist/alerts/notify.js +52 -0
- package/dist/alerts/notify.js.map +1 -0
- package/dist/app.d.ts +26 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +2 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/auth.d.ts +51 -0
- package/dist/auth/auth.d.ts.map +1 -0
- package/dist/auth/auth.js +63 -0
- package/dist/auth/auth.js.map +1 -0
- package/dist/auth/bridge.d.ts +7 -0
- package/dist/auth/bridge.d.ts.map +1 -0
- package/dist/auth/bridge.js +39 -0
- package/dist/auth/bridge.js.map +1 -0
- package/dist/auth/crypto.d.ts +14 -0
- package/dist/auth/crypto.d.ts.map +1 -0
- package/dist/auth/crypto.js +16 -0
- package/dist/auth/crypto.js.map +1 -0
- package/dist/auth/delete-user.d.ts +16 -0
- package/dist/auth/delete-user.d.ts.map +1 -0
- package/dist/auth/delete-user.js +21 -0
- package/dist/auth/delete-user.js.map +1 -0
- package/dist/auth/deps.d.ts +27 -0
- package/dist/auth/deps.d.ts.map +1 -0
- package/dist/auth/deps.js +3 -0
- package/dist/auth/deps.js.map +1 -0
- package/dist/auth/email-token.d.ts +8 -0
- package/dist/auth/email-token.d.ts.map +1 -0
- package/dist/auth/email-token.js +15 -0
- package/dist/auth/email-token.js.map +1 -0
- package/dist/auth/hooks.d.ts +4 -0
- package/dist/auth/hooks.d.ts.map +1 -0
- package/dist/auth/hooks.js +143 -0
- package/dist/auth/hooks.js.map +1 -0
- package/dist/auth/options.d.ts +17 -0
- package/dist/auth/options.d.ts.map +1 -0
- package/dist/auth/options.js +98 -0
- package/dist/auth/options.js.map +1 -0
- package/dist/auth/password.d.ts +10 -0
- package/dist/auth/password.d.ts.map +1 -0
- package/dist/auth/password.js +22 -0
- package/dist/auth/password.js.map +1 -0
- package/dist/auth/plugins.d.ts +4 -0
- package/dist/auth/plugins.d.ts.map +1 -0
- package/dist/auth/plugins.js +45 -0
- package/dist/auth/plugins.js.map +1 -0
- package/dist/auth/principal.d.ts +38 -0
- package/dist/auth/principal.d.ts.map +1 -0
- package/dist/auth/principal.js +69 -0
- package/dist/auth/principal.js.map +1 -0
- package/dist/auth/roles.d.ts +50 -0
- package/dist/auth/roles.d.ts.map +1 -0
- package/dist/auth/roles.js +18 -0
- package/dist/auth/roles.js.map +1 -0
- package/dist/auth/schema-names.d.ts +130 -0
- package/dist/auth/schema-names.d.ts.map +1 -0
- package/dist/auth/schema-names.js +53 -0
- package/dist/auth/schema-names.js.map +1 -0
- package/dist/auth/secret.d.ts +12 -0
- package/dist/auth/secret.d.ts.map +1 -0
- package/dist/auth/secret.js +32 -0
- package/dist/auth/secret.js.map +1 -0
- package/dist/auth/security-notices.d.ts +34 -0
- package/dist/auth/security-notices.d.ts.map +1 -0
- package/dist/auth/security-notices.js +81 -0
- package/dist/auth/security-notices.js.map +1 -0
- package/dist/auth/signup.d.ts +23 -0
- package/dist/auth/signup.d.ts.map +1 -0
- package/dist/auth/signup.js +61 -0
- package/dist/auth/signup.js.map +1 -0
- package/dist/auth/sso.d.ts +21 -0
- package/dist/auth/sso.d.ts.map +1 -0
- package/dist/auth/sso.js +35 -0
- package/dist/auth/sso.js.map +1 -0
- package/dist/auth/wire.d.ts +16 -0
- package/dist/auth/wire.d.ts.map +1 -0
- package/dist/auth/wire.js +47 -0
- package/dist/auth/wire.js.map +1 -0
- package/dist/cli-args.d.ts +5 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +86 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +44 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +55 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +55 -0
- package/dist/config.js.map +1 -0
- package/dist/db/db.d.ts +22 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +64 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/migrate.d.ts +6 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +35 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/schema-auth.d.ts +2 -0
- package/dist/db/schema-auth.d.ts.map +1 -0
- package/dist/db/schema-auth.js +93 -0
- package/dist/db/schema-auth.js.map +1 -0
- package/dist/db/schema-mail.d.ts +2 -0
- package/dist/db/schema-mail.d.ts.map +1 -0
- package/dist/db/schema-mail.js +8 -0
- package/dist/db/schema-mail.js.map +1 -0
- package/dist/db/schema-notify.d.ts +2 -0
- package/dist/db/schema-notify.d.ts.map +1 -0
- package/dist/db/schema-notify.js +26 -0
- package/dist/db/schema-notify.js.map +1 -0
- package/dist/db/schema-sso.d.ts +2 -0
- package/dist/db/schema-sso.d.ts.map +1 -0
- package/dist/db/schema-sso.js +17 -0
- package/dist/db/schema-sso.js.map +1 -0
- package/dist/db/schema.d.ts +3 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +208 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/http/http.d.ts +19 -0
- package/dist/http/http.d.ts.map +1 -0
- package/dist/http/http.js +66 -0
- package/dist/http/http.js.map +1 -0
- package/dist/http/limiter.d.ts +11 -0
- package/dist/http/limiter.d.ts.map +1 -0
- package/dist/http/limiter.js +31 -0
- package/dist/http/limiter.js.map +1 -0
- package/dist/http/router.d.ts +21 -0
- package/dist/http/router.d.ts.map +1 -0
- package/dist/http/router.js +28 -0
- package/dist/http/router.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs.d.ts +4 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +53 -0
- package/dist/jobs.js.map +1 -0
- package/dist/mail/blocks.d.ts +14 -0
- package/dist/mail/blocks.d.ts.map +1 -0
- package/dist/mail/blocks.js +35 -0
- package/dist/mail/blocks.js.map +1 -0
- package/dist/mail/content.d.ts +68 -0
- package/dist/mail/content.d.ts.map +1 -0
- package/dist/mail/content.js +6 -0
- package/dist/mail/content.js.map +1 -0
- package/dist/mail/emails-digest.d.ts +10 -0
- package/dist/mail/emails-digest.d.ts.map +1 -0
- package/dist/mail/emails-digest.js +55 -0
- package/dist/mail/emails-digest.js.map +1 -0
- package/dist/mail/emails-health.d.ts +6 -0
- package/dist/mail/emails-health.d.ts.map +1 -0
- package/dist/mail/emails-health.js +36 -0
- package/dist/mail/emails-health.js.map +1 -0
- package/dist/mail/emails-security.d.ts +14 -0
- package/dist/mail/emails-security.d.ts.map +1 -0
- package/dist/mail/emails-security.js +27 -0
- package/dist/mail/emails-security.js.map +1 -0
- package/dist/mail/emails-team.d.ts +11 -0
- package/dist/mail/emails-team.d.ts.map +1 -0
- package/dist/mail/emails-team.js +45 -0
- package/dist/mail/emails-team.js.map +1 -0
- package/dist/mail/emails.d.ts +9 -0
- package/dist/mail/emails.d.ts.map +1 -0
- package/dist/mail/emails.js +49 -0
- package/dist/mail/emails.js.map +1 -0
- package/dist/mail/layout.d.ts +6 -0
- package/dist/mail/layout.d.ts.map +1 -0
- package/dist/mail/layout.js +10 -0
- package/dist/mail/layout.js.map +1 -0
- package/dist/mail/mailer.d.ts +25 -0
- package/dist/mail/mailer.d.ts.map +1 -0
- package/dist/mail/mailer.js +49 -0
- package/dist/mail/mailer.js.map +1 -0
- package/dist/mail/preview.d.ts +6 -0
- package/dist/mail/preview.d.ts.map +1 -0
- package/dist/mail/preview.js +26 -0
- package/dist/mail/preview.js.map +1 -0
- package/dist/mail/resend.d.ts +11 -0
- package/dist/mail/resend.d.ts.map +1 -0
- package/dist/mail/resend.js +34 -0
- package/dist/mail/resend.js.map +1 -0
- package/dist/mail/samples.d.ts +3 -0
- package/dist/mail/samples.d.ts.map +1 -0
- package/dist/mail/samples.js +63 -0
- package/dist/mail/samples.js.map +1 -0
- package/dist/mail/stop-route.d.ts +4 -0
- package/dist/mail/stop-route.d.ts.map +1 -0
- package/dist/mail/stop-route.js +41 -0
- package/dist/mail/stop-route.js.map +1 -0
- package/dist/mail/svix.d.ts +8 -0
- package/dist/mail/svix.d.ts.map +1 -0
- package/dist/mail/svix.js +17 -0
- package/dist/mail/svix.js.map +1 -0
- package/dist/mail/templates.d.ts +12 -0
- package/dist/mail/templates.d.ts.map +1 -0
- package/dist/mail/templates.js +18 -0
- package/dist/mail/templates.js.map +1 -0
- package/dist/mail/text.d.ts +4 -0
- package/dist/mail/text.d.ts.map +1 -0
- package/dist/mail/text.js +17 -0
- package/dist/mail/text.js.map +1 -0
- package/dist/mail/theme.d.ts +26 -0
- package/dist/mail/theme.d.ts.map +1 -0
- package/dist/mail/theme.js +21 -0
- package/dist/mail/theme.js.map +1 -0
- package/dist/mail/unsubscribe.d.ts +14 -0
- package/dist/mail/unsubscribe.d.ts.map +1 -0
- package/dist/mail/unsubscribe.js +39 -0
- package/dist/mail/unsubscribe.js.map +1 -0
- package/dist/mail/webhook.d.ts +5 -0
- package/dist/mail/webhook.d.ts.map +1 -0
- package/dist/mail/webhook.js +41 -0
- package/dist/mail/webhook.js.map +1 -0
- package/dist/notify/digest-data.d.ts +31 -0
- package/dist/notify/digest-data.d.ts.map +1 -0
- package/dist/notify/digest-data.js +37 -0
- package/dist/notify/digest-data.js.map +1 -0
- package/dist/notify/digest.d.ts +17 -0
- package/dist/notify/digest.d.ts.map +1 -0
- package/dist/notify/digest.js +76 -0
- package/dist/notify/digest.js.map +1 -0
- package/dist/notify/health.d.ts +6 -0
- package/dist/notify/health.d.ts.map +1 -0
- package/dist/notify/health.js +43 -0
- package/dist/notify/health.js.map +1 -0
- package/dist/notify/team-describe.d.ts +22 -0
- package/dist/notify/team-describe.d.ts.map +1 -0
- package/dist/notify/team-describe.js +67 -0
- package/dist/notify/team-describe.js.map +1 -0
- package/dist/notify/team.d.ts +6 -0
- package/dist/notify/team.d.ts.map +1 -0
- package/dist/notify/team.js +56 -0
- package/dist/notify/team.js.map +1 -0
- package/dist/repo/alerts.d.ts +52 -0
- package/dist/repo/alerts.d.ts.map +1 -0
- package/dist/repo/alerts.js +38 -0
- package/dist/repo/alerts.js.map +1 -0
- package/dist/repo/audit.d.ts +11 -0
- package/dist/repo/audit.d.ts.map +1 -0
- package/dist/repo/audit.js +17 -0
- package/dist/repo/audit.js.map +1 -0
- package/dist/repo/auth-prune.d.ts +4 -0
- package/dist/repo/auth-prune.d.ts.map +1 -0
- package/dist/repo/auth-prune.js +8 -0
- package/dist/repo/auth-prune.js.map +1 -0
- package/dist/repo/mail-prefs.d.ts +35 -0
- package/dist/repo/mail-prefs.d.ts.map +1 -0
- package/dist/repo/mail-prefs.js +34 -0
- package/dist/repo/mail-prefs.js.map +1 -0
- package/dist/repo/metric-read.d.ts +12 -0
- package/dist/repo/metric-read.d.ts.map +1 -0
- package/dist/repo/metric-read.js +11 -0
- package/dist/repo/metric-read.js.map +1 -0
- package/dist/repo/metric-write.d.ts +9 -0
- package/dist/repo/metric-write.d.ts.map +1 -0
- package/dist/repo/metric-write.js +53 -0
- package/dist/repo/metric-write.js.map +1 -0
- package/dist/repo/orgs.d.ts +37 -0
- package/dist/repo/orgs.d.ts.map +1 -0
- package/dist/repo/orgs.js +33 -0
- package/dist/repo/orgs.js.map +1 -0
- package/dist/repo/projects.d.ts +37 -0
- package/dist/repo/projects.d.ts.map +1 -0
- package/dist/repo/projects.js +57 -0
- package/dist/repo/projects.js.map +1 -0
- package/dist/repo/suppressions.d.ts +8 -0
- package/dist/repo/suppressions.d.ts.map +1 -0
- package/dist/repo/suppressions.js +16 -0
- package/dist/repo/suppressions.js.map +1 -0
- package/dist/repo/trace-read.d.ts +28 -0
- package/dist/repo/trace-read.d.ts.map +1 -0
- package/dist/repo/trace-read.js +76 -0
- package/dist/repo/trace-read.js.map +1 -0
- package/dist/repo/trace-write.d.ts +9 -0
- package/dist/repo/trace-write.d.ts.map +1 -0
- package/dist/repo/trace-write.js +82 -0
- package/dist/repo/trace-write.js.map +1 -0
- package/dist/repo/users.d.ts +13 -0
- package/dist/repo/users.d.ts.map +1 -0
- package/dist/repo/users.js +7 -0
- package/dist/repo/users.js.map +1 -0
- package/dist/routes/alerts.d.ts +4 -0
- package/dist/routes/alerts.d.ts.map +1 -0
- package/dist/routes/alerts.js +116 -0
- package/dist/routes/alerts.js.map +1 -0
- package/dist/routes/data.d.ts +7 -0
- package/dist/routes/data.d.ts.map +1 -0
- package/dist/routes/data.js +74 -0
- package/dist/routes/data.js.map +1 -0
- package/dist/routes/index.d.ts +5 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +25 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/ingest.d.ts +8 -0
- package/dist/routes/ingest.d.ts.map +1 -0
- package/dist/routes/ingest.js +38 -0
- package/dist/routes/ingest.js.map +1 -0
- package/dist/routes/mcp.d.ts +4 -0
- package/dist/routes/mcp.d.ts.map +1 -0
- package/dist/routes/mcp.js +52 -0
- package/dist/routes/mcp.js.map +1 -0
- package/dist/routes/me.d.ts +4 -0
- package/dist/routes/me.d.ts.map +1 -0
- package/dist/routes/me.js +37 -0
- package/dist/routes/me.js.map +1 -0
- package/dist/routes/metrics.d.ts +13 -0
- package/dist/routes/metrics.d.ts.map +1 -0
- package/dist/routes/metrics.js +29 -0
- package/dist/routes/metrics.js.map +1 -0
- package/dist/routes/models.d.ts +4 -0
- package/dist/routes/models.d.ts.map +1 -0
- package/dist/routes/models.js +71 -0
- package/dist/routes/models.js.map +1 -0
- package/dist/routes/notify.d.ts +4 -0
- package/dist/routes/notify.d.ts.map +1 -0
- package/dist/routes/notify.js +55 -0
- package/dist/routes/notify.js.map +1 -0
- package/dist/routes/orgs.d.ts +4 -0
- package/dist/routes/orgs.d.ts.map +1 -0
- package/dist/routes/orgs.js +73 -0
- package/dist/routes/orgs.js.map +1 -0
- package/dist/routes/projects.d.ts +4 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +55 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/shares.d.ts +11 -0
- package/dist/routes/shares.d.ts.map +1 -0
- package/dist/routes/shares.js +61 -0
- package/dist/routes/shares.js.map +1 -0
- package/dist/scale-exec.d.ts +11 -0
- package/dist/scale-exec.d.ts.map +1 -0
- package/dist/scale-exec.js +26 -0
- package/dist/scale-exec.js.map +1 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +126 -0
- package/dist/server.js.map +1 -0
- package/dist/settle.d.ts +26 -0
- package/dist/settle.d.ts.map +1 -0
- package/dist/settle.js +85 -0
- package/dist/settle.js.map +1 -0
- package/package.json +76 -3
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { getCurrentAdapter } from "better-auth";
|
|
3
|
+
import { ssoProviderOf, ssoTrusts } from "./sso.js";
|
|
4
|
+
export const SETUP_HEADER = "x-wizelens-setup-token";
|
|
5
|
+
export const INVITE_HEADER = "x-wizelens-invite";
|
|
6
|
+
const same = (a, b) => a.length === b.length && timingSafeEqual(Buffer.from(a), Buffer.from(b));
|
|
7
|
+
/** An open invite for this email (read through Better Auth's adapter, inside its transaction); without real mail, its id too. */
|
|
8
|
+
async function invitedNow(deps, ctx, email) {
|
|
9
|
+
const db = await getCurrentAdapter(ctx.context.adapter);
|
|
10
|
+
const rows = await db.findMany({ model: "invitation", where: [{ field: "email", value: email.toLowerCase() }, { field: "status", value: "pending" }] });
|
|
11
|
+
const open = rows.filter((r) => new Date(r.expiresAt).getTime() > Date.now());
|
|
12
|
+
if (deps.mailer.live)
|
|
13
|
+
return open.length > 0;
|
|
14
|
+
const id = ctx.headers?.get(INVITE_HEADER) ?? "";
|
|
15
|
+
return open.some((r) => same(r.id, id));
|
|
16
|
+
}
|
|
17
|
+
/** Who may make an account: by SSO, only from a proven domain; the first needs the setup token; then the invited, or anyone with open sign-up. */
|
|
18
|
+
export function signupGate(deps) {
|
|
19
|
+
return async ({ user, source }, ctx) => {
|
|
20
|
+
if (source.action !== "create-user")
|
|
21
|
+
return;
|
|
22
|
+
const db = await getCurrentAdapter(ctx.context.adapter);
|
|
23
|
+
const viaSso = ssoProviderOf(source);
|
|
24
|
+
if (viaSso)
|
|
25
|
+
return (await ssoTrusts(db, viaSso, String(user.email ?? ""))) ? undefined : { error: "sso_domain", errorDescription: "Single sign-on works only for emails at the provider's verified domain." };
|
|
26
|
+
if ((await db.count({ model: "user" })) === 0) {
|
|
27
|
+
const want = deps.setup.token();
|
|
28
|
+
if (want && same(ctx.headers?.get(SETUP_HEADER) ?? "", want))
|
|
29
|
+
return;
|
|
30
|
+
return { error: "setup_token", errorDescription: "The first account needs the setup link printed when the cloud started." };
|
|
31
|
+
}
|
|
32
|
+
if (deps.signup === "open" || (await invitedNow(deps, ctx, String(user.email ?? ""))))
|
|
33
|
+
return;
|
|
34
|
+
return { error: "signup_closed", errorDescription: "Sign-up needs an invite. Ask your team for one." };
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** A new account from single sign-on: the provider's organization takes it in. */
|
|
38
|
+
const bySso = (ctx) => String(ctx?.path ?? "").startsWith("/sso/");
|
|
39
|
+
/** The provider proved the domain and the gate checked the email, so an SSO account starts confirmed. */
|
|
40
|
+
export async function confirmSsoEmail(user, ctx) {
|
|
41
|
+
const providerId = ctx?.params?.providerId;
|
|
42
|
+
if (!bySso(ctx) || typeof providerId !== "string")
|
|
43
|
+
return undefined;
|
|
44
|
+
const db = await getCurrentAdapter(ctx.context.adapter);
|
|
45
|
+
return (await ssoTrusts(db, providerId, user.email)) ? { data: { ...user, emailVerified: true } } : undefined;
|
|
46
|
+
}
|
|
47
|
+
/** Runs after the new user is saved: the first account and open sign-ups get their own organization and project. */
|
|
48
|
+
export function afterSignup(deps, createOrg) {
|
|
49
|
+
return async (user, ctx) => {
|
|
50
|
+
if (!ctx || bySso(ctx))
|
|
51
|
+
return;
|
|
52
|
+
const [count] = await deps.db.query("SELECT count(*)::int AS n FROM users");
|
|
53
|
+
const [pending] = await deps.db.query("SELECT EXISTS (SELECT 1 FROM invites WHERE email = $1 AND status = 'pending' AND expires_at > now()) AS invited", [user.email.toLowerCase()]);
|
|
54
|
+
const first = count?.n === 1;
|
|
55
|
+
if (first)
|
|
56
|
+
deps.setup.done();
|
|
57
|
+
if (first || (deps.signup === "open" && !pending?.invited))
|
|
58
|
+
await createOrg(user.id, `${user.name.trim()}'s team`);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=signup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signup.js","sourceRoot":"","sources":["../../src/auth/signup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BetterAuthPlugin } from "better-auth";
|
|
2
|
+
import type { AuthDeps } from "./deps.js";
|
|
3
|
+
/** The DNS record that proves a domain: `_wizelens-sso-<providerId>.<domain>` TXT `<token>`. */
|
|
4
|
+
export declare const SSO_TOKEN_PREFIX = "wizelens-sso";
|
|
5
|
+
interface Finder {
|
|
6
|
+
findOne<T>(a: {
|
|
7
|
+
model: string;
|
|
8
|
+
where: {
|
|
9
|
+
field: string;
|
|
10
|
+
value: string;
|
|
11
|
+
}[];
|
|
12
|
+
}): Promise<T | null>;
|
|
13
|
+
}
|
|
14
|
+
/** The SSO provider behind a new account, when Better Auth makes it from a single sign-on. */
|
|
15
|
+
export declare function ssoProviderOf(source: unknown): string | undefined;
|
|
16
|
+
/** True when an organization's provider has a proven domain and the email is at exactly that domain. */
|
|
17
|
+
export declare function ssoTrusts(db: Finder, providerId: string, email: string): Promise<boolean>;
|
|
18
|
+
/** Organization SSO with OIDC or SAML. Sign-in works once the domain is proven in DNS; new people join that organization as members. */
|
|
19
|
+
export declare function ssoPlugin(deps: AuthDeps): BetterAuthPlugin;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=sso.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sso.d.ts","sourceRoot":"","sources":["../../src/auth/sso.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1C,gGAAgG;AAChG,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,UAAU,MAAM;IACd,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;CAChG;AAQD,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAGjE;AAED,wGAAwG;AACxG,wBAAsB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAK/F;AAED,wIAAwI;AACxI,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,gBAAgB,CAc1D"}
|
package/dist/auth/sso.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { sso } from "@better-auth/sso";
|
|
2
|
+
import { audit } from "../repo/audit.js";
|
|
3
|
+
import { ssoSchema } from "./schema-names.js";
|
|
4
|
+
/** The DNS record that proves a domain: `_wizelens-sso-<providerId>.<domain>` TXT `<token>`. */
|
|
5
|
+
export const SSO_TOKEN_PREFIX = "wizelens-sso";
|
|
6
|
+
/** The SSO provider behind a new account, when Better Auth makes it from a single sign-on. */
|
|
7
|
+
export function ssoProviderOf(source) {
|
|
8
|
+
const s = source;
|
|
9
|
+
return s?.method?.startsWith("sso-") && typeof s.sso?.providerId === "string" ? s.sso.providerId : undefined;
|
|
10
|
+
}
|
|
11
|
+
/** True when an organization's provider has a proven domain and the email is at exactly that domain. */
|
|
12
|
+
export async function ssoTrusts(db, providerId, email) {
|
|
13
|
+
const p = await db.findOne({ model: "ssoProvider", where: [{ field: "providerId", value: providerId }] });
|
|
14
|
+
const at = email.trim().toLowerCase().split("@")[1] ?? "";
|
|
15
|
+
const domains = (p?.domain ?? "").toLowerCase().split(",").map((d) => d.trim());
|
|
16
|
+
return !!p?.organizationId && p.domainVerified === true && !!at && domains.includes(at);
|
|
17
|
+
}
|
|
18
|
+
/** Organization SSO with OIDC or SAML. Sign-in works once the domain is proven in DNS; new people join that organization as members. */
|
|
19
|
+
export function ssoPlugin(deps) {
|
|
20
|
+
return sso({
|
|
21
|
+
schema: ssoSchema,
|
|
22
|
+
providersLimit: 20,
|
|
23
|
+
domainVerification: { enabled: true, tokenPrefix: SSO_TOKEN_PREFIX },
|
|
24
|
+
organizationProvisioning: {
|
|
25
|
+
defaultRole: "member",
|
|
26
|
+
getRole: async ({ user, provider }) => {
|
|
27
|
+
if (provider.organizationId)
|
|
28
|
+
await audit(deps.db, provider.organizationId, `user:${user.id}`, "member.join", { via: "sso", providerId: provider.providerId }, Date.now());
|
|
29
|
+
return "member";
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
saml: { enableInResponseToValidation: true, allowIdpInitiated: false, requireTimestamps: true, clockSkew: 2 * 60_000, algorithms: { onDeprecated: "reject" } },
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=sso.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sso.js","sourceRoot":"","sources":["../../src/auth/sso.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,gGAAgG;AAChG,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAY/C,8FAA8F;AAC9F,MAAM,UAAU,aAAa,CAAC,MAAe;IAC3C,MAAM,CAAC,GAAG,MAAyE,CAAC;IACpF,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/G,CAAC;AAED,wGAAwG;AACxG,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAU,EAAE,UAAkB,EAAE,KAAa;IAC3E,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,OAAO,CAAc,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;IACvH,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1D,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAChF,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,IAAI,CAAC,CAAC,cAAc,KAAK,IAAI,IAAI,CAAC,CAAC,EAAE,IAAI,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED,wIAAwI;AACxI,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,OAAO,GAAG,CAAC;QACT,MAAM,EAAE,SAAS;QACjB,cAAc,EAAE,EAAE;QAClB,kBAAkB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,gBAAgB,EAAE;QACpE,wBAAwB,EAAE;YACxB,WAAW,EAAE,QAAQ;YACrB,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;gBACpC,IAAI,QAAQ,CAAC,cAAc;oBAAE,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,cAAc,EAAE,QAAQ,IAAI,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;gBAC1K,OAAO,QAAQ,CAAC;YAClB,CAAC;SACF;QACD,IAAI,EAAE,EAAE,4BAA4B,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE;KAC/J,CAAgC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CloudConfig } from "../config.js";
|
|
2
|
+
import type { Db } from "../db/db.js";
|
|
3
|
+
import type { Mailer } from "../mail/mailer.js";
|
|
4
|
+
import { type WizeAuth } from "./auth.js";
|
|
5
|
+
import { type AuthSecret } from "./secret.js";
|
|
6
|
+
export interface AuthWiring {
|
|
7
|
+
/** Build Better Auth for the address the cloud listens on. */
|
|
8
|
+
start(listenUrl: string): WizeAuth;
|
|
9
|
+
/** The first account's link while no account exists, else null. */
|
|
10
|
+
setupLink(): string | null;
|
|
11
|
+
/** The auth secrets, newest first. Unsubscribe links are signed with them too. */
|
|
12
|
+
secrets: AuthSecret[];
|
|
13
|
+
}
|
|
14
|
+
/** Secrets, the setup gate, and the rest Better Auth needs; Better Auth itself starts once the address is known. */
|
|
15
|
+
export declare function wireAuth(db: Db, config: CloudConfig, mailer: Mailer): Promise<AuthWiring>;
|
|
16
|
+
//# sourceMappingURL=wire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../../src/auth/wire.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,EAAE,KAAK,UAAU,EAAgC,MAAM,aAAa,CAAC;AAE5E,MAAM,WAAW,UAAU;IACzB,8DAA8D;IAC9D,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,CAAC;IACnC,mEAAmE;IACnE,SAAS,IAAI,MAAM,GAAG,IAAI,CAAC;IAC3B,kFAAkF;IAClF,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAgBD,oHAAoH;AACpH,wBAAsB,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA2B/F"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { userCount } from "../repo/users.js";
|
|
3
|
+
import { createAuth } from "./auth.js";
|
|
4
|
+
import { clearAuthEnv, resolveSecrets } from "./secret.js";
|
|
5
|
+
/** The one-time setup token: from the config, or new. Gone once the first account exists. */
|
|
6
|
+
async function setupGate(db, configured) {
|
|
7
|
+
let open = (await userCount(db)) === 0;
|
|
8
|
+
const token = configured ?? randomBytes(24).toString("base64url");
|
|
9
|
+
return { token: () => (open ? token : null), done: () => void (open = false) };
|
|
10
|
+
}
|
|
11
|
+
/** The public origin, plus 127.0.0.1 next to localhost (or the reverse) when the cloud runs on its default local address. */
|
|
12
|
+
function originsOf(publicUrl, local) {
|
|
13
|
+
const origin = new URL(publicUrl).origin;
|
|
14
|
+
if (!local)
|
|
15
|
+
return [origin];
|
|
16
|
+
return [origin, origin.includes("//localhost") ? origin.replace("//localhost", "//127.0.0.1") : origin.replace("//127.0.0.1", "//localhost")];
|
|
17
|
+
}
|
|
18
|
+
/** Secrets, the setup gate, and the rest Better Auth needs; Better Auth itself starts once the address is known. */
|
|
19
|
+
export async function wireAuth(db, config, mailer) {
|
|
20
|
+
clearAuthEnv();
|
|
21
|
+
const [secrets, setup] = await Promise.all([resolveSecrets(db, config.authSecret), setupGate(db, config.setupToken)]);
|
|
22
|
+
let base = config.publicUrl;
|
|
23
|
+
return {
|
|
24
|
+
secrets,
|
|
25
|
+
start: (listenUrl) => {
|
|
26
|
+
base = config.publicUrl ?? listenUrl.replace("//127.0.0.1", "//localhost");
|
|
27
|
+
const deps = {
|
|
28
|
+
db,
|
|
29
|
+
publicUrl: new URL(base).origin,
|
|
30
|
+
trustedOrigins: originsOf(base, !config.publicUrl),
|
|
31
|
+
ssoOrigins: config.ssoOrigins,
|
|
32
|
+
secrets,
|
|
33
|
+
signup: config.signup,
|
|
34
|
+
mailer,
|
|
35
|
+
setup,
|
|
36
|
+
checkPwned: config.checkPwnedPasswords ?? db.kind === "postgres",
|
|
37
|
+
retentionDays: config.retentionDays,
|
|
38
|
+
};
|
|
39
|
+
return createAuth(deps);
|
|
40
|
+
},
|
|
41
|
+
setupLink: () => {
|
|
42
|
+
const token = setup.token();
|
|
43
|
+
return token && base ? `${base}/_wizelens/#/setup?token=${token}` : null;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=wire.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire.js","sourceRoot":"","sources":["../../src/auth/wire.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAiB,MAAM,WAAW,CAAC;AAEtD,OAAO,EAAmB,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAW5E,6FAA6F;AAC7F,KAAK,UAAU,SAAS,CAAC,EAAM,EAAE,UAA8B;IAC7D,IAAI,IAAI,GAAG,CAAC,MAAM,SAAS,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,UAAU,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAClE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;AACjF,CAAC;AAED,6HAA6H;AAC7H,SAAS,SAAS,CAAC,SAAiB,EAAE,KAAc;IAClD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IACzC,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC;AAChJ,CAAC;AAED,oHAAoH;AACpH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,EAAM,EAAE,MAAmB,EAAE,MAAc;IACxE,YAAY,EAAE,CAAC;IACf,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACtH,IAAI,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;IAC5B,OAAO;QACL,OAAO;QACP,KAAK,EAAE,CAAC,SAAS,EAAE,EAAE;YACnB,IAAI,GAAG,MAAM,CAAC,SAAS,IAAI,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;YAC3E,MAAM,IAAI,GAAa;gBACrB,EAAE;gBACF,SAAS,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM;gBAC/B,cAAc,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC;gBAClD,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,OAAO;gBACP,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,MAAM;gBACN,KAAK;gBACL,UAAU,EAAE,MAAM,CAAC,mBAAmB,IAAI,EAAE,CAAC,IAAI,KAAK,UAAU;gBAChE,aAAa,EAAE,MAAM,CAAC,aAAa;aACpC,CAAC;YACF,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5B,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,4BAA4B,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC3E,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CloudOptions } from "./config.js";
|
|
2
|
+
export declare const USAGE = "wizelens-cloud: the WizeLens service for many teams.\n\nUsage: wizelens-cloud [options]\n\n --database <url> postgres://..., pglite:<folder>, or memory.\n Default pglite:./.wizelens-cloud. (DATABASE_URL)\n --port <n> Default 5970. (PORT)\n --host <addr> Default 0.0.0.0. (WIZELENS_CLOUD_HOST)\n --public-url <url> The address people use, for links. (WIZELENS_CLOUD_PUBLIC_URL)\n --signup <invite|open> Who can make an account. Default invite. (WIZELENS_CLOUD_SIGNUP)\n --retention-days <n> Default for new organizations. Default 30. (WIZELENS_CLOUD_RETENTION_DAYS)\n --allow-private-webhooks Let alert webhooks reach private addresses. (WIZELENS_CLOUD_ALLOW_PRIVATE_WEBHOOKS=1)\n --auth-secret <text> Signs sessions, encrypts 2FA secrets. 32+ (WIZELENS_CLOUD_AUTH_SECRET)\n characters; \"2:new,1:old\" rotates.\n Required with Postgres.\n --resend-api-key <key> Outgoing mail through Resend (re_...). (WIZELENS_CLOUD_RESEND_API_KEY)\n Needs --public-url.\n --resend-webhook-secret <s> The Resend webhook's whsec_ secret: (WIZELENS_CLOUD_RESEND_WEBHOOK_SECRET)\n bounces and complaints stop later mail.\n Webhook URL: <public-url>/_wizelens/api/mail/resend\n --smtp-url <url> Or mail over SMTP: smtp://user:pass@host:587 (WIZELENS_CLOUD_SMTP_URL)\n or smtps://...:465. Needs --public-url.\n --mail-from <address> Sender, e.g. \"WizeLens <a@b.com>\". (WIZELENS_CLOUD_MAIL_FROM)\n --trust-proxy Read the client address from the last (WIZELENS_CLOUD_TRUST_PROXY=1)\n X-Forwarded-For entry (your own proxy only).\n --setup-token <text> The first account's token. Default: random, (WIZELENS_CLOUD_SETUP_TOKEN)\n printed at start while no account exists.\n --check-pwned-passwords Refuse breached passwords. Default on with (WIZELENS_CLOUD_CHECK_PWNED=1|0)\n --no-check-pwned-passwords Postgres, off with PGlite.\n --sso-origins <list> Identity provider origins for OIDC single (WIZELENS_CLOUD_SSO_ORIGINS)\n sign-on, comma separated, for example\n https://acme.okta.com. SAML needs none.\n --help Show this help.\n";
|
|
3
|
+
/** Options from the command line, then from the environment. */
|
|
4
|
+
export declare function optionsFromArgs(argv: string[], env: NodeJS.ProcessEnv): CloudOptions | "help";
|
|
5
|
+
//# sourceMappingURL=cli-args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AAE5D,eAAO,MAAM,KAAK,y/EAiCjB,CAAC;AAgCF,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,YAAY,GAAG,MAAM,CAqB7F"}
|
package/dist/cli-args.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
export const USAGE = `wizelens-cloud: the WizeLens service for many teams.
|
|
3
|
+
|
|
4
|
+
Usage: wizelens-cloud [options]
|
|
5
|
+
|
|
6
|
+
--database <url> postgres://..., pglite:<folder>, or memory.
|
|
7
|
+
Default pglite:./.wizelens-cloud. (DATABASE_URL)
|
|
8
|
+
--port <n> Default 5970. (PORT)
|
|
9
|
+
--host <addr> Default 0.0.0.0. (WIZELENS_CLOUD_HOST)
|
|
10
|
+
--public-url <url> The address people use, for links. (WIZELENS_CLOUD_PUBLIC_URL)
|
|
11
|
+
--signup <invite|open> Who can make an account. Default invite. (WIZELENS_CLOUD_SIGNUP)
|
|
12
|
+
--retention-days <n> Default for new organizations. Default 30. (WIZELENS_CLOUD_RETENTION_DAYS)
|
|
13
|
+
--allow-private-webhooks Let alert webhooks reach private addresses. (WIZELENS_CLOUD_ALLOW_PRIVATE_WEBHOOKS=1)
|
|
14
|
+
--auth-secret <text> Signs sessions, encrypts 2FA secrets. 32+ (WIZELENS_CLOUD_AUTH_SECRET)
|
|
15
|
+
characters; "2:new,1:old" rotates.
|
|
16
|
+
Required with Postgres.
|
|
17
|
+
--resend-api-key <key> Outgoing mail through Resend (re_...). (WIZELENS_CLOUD_RESEND_API_KEY)
|
|
18
|
+
Needs --public-url.
|
|
19
|
+
--resend-webhook-secret <s> The Resend webhook's whsec_ secret: (WIZELENS_CLOUD_RESEND_WEBHOOK_SECRET)
|
|
20
|
+
bounces and complaints stop later mail.
|
|
21
|
+
Webhook URL: <public-url>/_wizelens/api/mail/resend
|
|
22
|
+
--smtp-url <url> Or mail over SMTP: smtp://user:pass@host:587 (WIZELENS_CLOUD_SMTP_URL)
|
|
23
|
+
or smtps://...:465. Needs --public-url.
|
|
24
|
+
--mail-from <address> Sender, e.g. "WizeLens <a@b.com>". (WIZELENS_CLOUD_MAIL_FROM)
|
|
25
|
+
--trust-proxy Read the client address from the last (WIZELENS_CLOUD_TRUST_PROXY=1)
|
|
26
|
+
X-Forwarded-For entry (your own proxy only).
|
|
27
|
+
--setup-token <text> The first account's token. Default: random, (WIZELENS_CLOUD_SETUP_TOKEN)
|
|
28
|
+
printed at start while no account exists.
|
|
29
|
+
--check-pwned-passwords Refuse breached passwords. Default on with (WIZELENS_CLOUD_CHECK_PWNED=1|0)
|
|
30
|
+
--no-check-pwned-passwords Postgres, off with PGlite.
|
|
31
|
+
--sso-origins <list> Identity provider origins for OIDC single (WIZELENS_CLOUD_SSO_ORIGINS)
|
|
32
|
+
sign-on, comma separated, for example
|
|
33
|
+
https://acme.okta.com. SAML needs none.
|
|
34
|
+
--help Show this help.
|
|
35
|
+
`;
|
|
36
|
+
const int = (v) => (v && /^\d+$/.test(v) ? Number(v) : undefined);
|
|
37
|
+
const signupOf = (v) => (v === "open" || v === "invite" ? v : undefined);
|
|
38
|
+
const text = (...v) => v.find((x) => x !== undefined && x !== "");
|
|
39
|
+
const list = (v) => v?.split(",").map((s) => s.trim()).filter(Boolean);
|
|
40
|
+
const flag = (v) => (v === "1" || v === "true" ? true : v === "0" || v === "false" ? false : undefined);
|
|
41
|
+
const OPTIONS = {
|
|
42
|
+
database: { type: "string" },
|
|
43
|
+
port: { type: "string" },
|
|
44
|
+
host: { type: "string" },
|
|
45
|
+
"public-url": { type: "string" },
|
|
46
|
+
signup: { type: "string" },
|
|
47
|
+
"retention-days": { type: "string" },
|
|
48
|
+
"allow-private-webhooks": { type: "boolean" },
|
|
49
|
+
"auth-secret": { type: "string" },
|
|
50
|
+
"smtp-url": { type: "string" },
|
|
51
|
+
"resend-api-key": { type: "string" },
|
|
52
|
+
"resend-webhook-secret": { type: "string" },
|
|
53
|
+
"mail-from": { type: "string" },
|
|
54
|
+
"trust-proxy": { type: "boolean" },
|
|
55
|
+
"setup-token": { type: "string" },
|
|
56
|
+
"check-pwned-passwords": { type: "boolean" },
|
|
57
|
+
"no-check-pwned-passwords": { type: "boolean" },
|
|
58
|
+
"sso-origins": { type: "string" },
|
|
59
|
+
help: { type: "boolean", short: "h" },
|
|
60
|
+
};
|
|
61
|
+
const pwnedOf = (a, env) => a["no-check-pwned-passwords"] ? false : (a["check-pwned-passwords"] ?? flag(env.WIZELENS_CLOUD_CHECK_PWNED));
|
|
62
|
+
/** Options from the command line, then from the environment. */
|
|
63
|
+
export function optionsFromArgs(argv, env) {
|
|
64
|
+
const { values: a } = parseArgs({ args: argv, options: OPTIONS });
|
|
65
|
+
if (a.help)
|
|
66
|
+
return "help";
|
|
67
|
+
return {
|
|
68
|
+
database: a.database ?? env.DATABASE_URL,
|
|
69
|
+
port: int(a.port ?? env.PORT),
|
|
70
|
+
host: a.host ?? env.WIZELENS_CLOUD_HOST,
|
|
71
|
+
publicUrl: text(a["public-url"], env.WIZELENS_CLOUD_PUBLIC_URL),
|
|
72
|
+
signup: signupOf(a.signup ?? env.WIZELENS_CLOUD_SIGNUP),
|
|
73
|
+
retentionDays: int(a["retention-days"] ?? env.WIZELENS_CLOUD_RETENTION_DAYS),
|
|
74
|
+
allowPrivateWebhooks: a["allow-private-webhooks"] ?? env.WIZELENS_CLOUD_ALLOW_PRIVATE_WEBHOOKS === "1",
|
|
75
|
+
authSecret: text(a["auth-secret"], env.WIZELENS_CLOUD_AUTH_SECRET),
|
|
76
|
+
smtpUrl: text(a["smtp-url"], env.WIZELENS_CLOUD_SMTP_URL),
|
|
77
|
+
resendApiKey: text(a["resend-api-key"], env.WIZELENS_CLOUD_RESEND_API_KEY),
|
|
78
|
+
resendWebhookSecret: text(a["resend-webhook-secret"], env.WIZELENS_CLOUD_RESEND_WEBHOOK_SECRET),
|
|
79
|
+
mailFrom: text(a["mail-from"], env.WIZELENS_CLOUD_MAIL_FROM),
|
|
80
|
+
trustProxy: a["trust-proxy"] ?? env.WIZELENS_CLOUD_TRUST_PROXY === "1",
|
|
81
|
+
setupToken: text(a["setup-token"], env.WIZELENS_CLOUD_SETUP_TOKEN),
|
|
82
|
+
checkPwnedPasswords: pwnedOf(a, env),
|
|
83
|
+
ssoOrigins: list(text(a["sso-origins"], env.WIZELENS_CLOUD_SSO_ORIGINS)),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=cli-args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { optionsFromArgs, USAGE } from "./cli-args.js";
|
|
3
|
+
import { CLOUD_VERSION, createCloud } from "./server.js";
|
|
4
|
+
function notes(cloud) {
|
|
5
|
+
const { app } = cloud;
|
|
6
|
+
const out = [];
|
|
7
|
+
if (app.db.kind === "pglite")
|
|
8
|
+
out.push(" Note: PGlite is for trials and tests. Use Postgres for real teams.");
|
|
9
|
+
if (!app.mailer.live)
|
|
10
|
+
out.push(" Note: no --resend-api-key or --smtp-url, so emails are written to this log and email addresses are not confirmed.");
|
|
11
|
+
if (app.mailer.via === "resend" && !app.config.resendWebhookSecret)
|
|
12
|
+
out.push(" Note: no --resend-webhook-secret, so bounced addresses keep getting mail.");
|
|
13
|
+
if (app.db.kind === "postgres" && !app.config.publicUrl?.startsWith("https://"))
|
|
14
|
+
out.push(" Note: set --public-url to an https:// address, so sign-in cookies are Secure.");
|
|
15
|
+
const setup = cloud.setupLink();
|
|
16
|
+
if (setup)
|
|
17
|
+
out.push("", " No account yet. Open this link to make the first one (it works once):", ` ${setup}`);
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
async function main() {
|
|
21
|
+
const options = optionsFromArgs(process.argv.slice(2), process.env);
|
|
22
|
+
if (options === "help")
|
|
23
|
+
return void process.stdout.write(USAGE);
|
|
24
|
+
const cloud = await createCloud(options);
|
|
25
|
+
const url = await cloud.listen();
|
|
26
|
+
const db = cloud.app.db.kind === "postgres" ? "Postgres" : `PGlite (${cloud.app.config.database})`;
|
|
27
|
+
console.info([
|
|
28
|
+
`WizeLens Cloud ${CLOUD_VERSION}`,
|
|
29
|
+
` Dashboard ${url}/_wizelens/`,
|
|
30
|
+
` Add-ons WIZELENS_HUB=${url} WIZELENS_HUB_TOKEN=<ingest key>`,
|
|
31
|
+
` OTLP/HTTP OTEL_EXPORTER_OTLP_ENDPOINT=${url} (header Authorization=Bearer <ingest key>)`,
|
|
32
|
+
` Database ${db}`,
|
|
33
|
+
` Mail ${{ resend: "Resend", smtp: "SMTP", test: "test sender", log: "log only" }[cloud.app.mailer.via]}`,
|
|
34
|
+
...notes(cloud),
|
|
35
|
+
].join("\n"));
|
|
36
|
+
const stop = () => void cloud.close().then(() => process.exit(0));
|
|
37
|
+
process.once("SIGINT", stop);
|
|
38
|
+
process.once("SIGTERM", stop);
|
|
39
|
+
}
|
|
40
|
+
main().catch((err) => {
|
|
41
|
+
console.error(`[wizelens-cloud] ${err instanceof Error ? err.message : String(err)}`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Mail } from "./mail/mailer.js";
|
|
2
|
+
export type SignupMode = "open" | "invite";
|
|
3
|
+
export interface CloudOptions {
|
|
4
|
+
/** "postgres://...", "pglite:<folder>", or "memory". Default "pglite:./.wizelens-cloud". */
|
|
5
|
+
database?: string;
|
|
6
|
+
/** Default 5970. 0 picks a free port. */
|
|
7
|
+
port?: number;
|
|
8
|
+
/** Default "0.0.0.0". */
|
|
9
|
+
host?: string;
|
|
10
|
+
/** The address people use, for links in invites and shares. Default http://localhost:<port>. */
|
|
11
|
+
publicUrl?: string;
|
|
12
|
+
/** "invite": only the first account and invited people can sign up. "open": anyone can. Default "invite". */
|
|
13
|
+
signup?: SignupMode;
|
|
14
|
+
/** Default retention for new organizations, in days. Default 30. */
|
|
15
|
+
retentionDays?: number;
|
|
16
|
+
/** Ingest calls per key per minute. Default 1200. */
|
|
17
|
+
ingestPerMinute?: number;
|
|
18
|
+
/** How often alert rules run, in ms. Default 60000. */
|
|
19
|
+
alertIntervalMs?: number;
|
|
20
|
+
/** Let alert webhooks call private and local addresses, and plain http. For self-hosting on a private network. Default false. */
|
|
21
|
+
allowPrivateWebhooks?: boolean;
|
|
22
|
+
/** Outgoing mail: "smtp://user:pass@host:587" (STARTTLS) or "smtps://user:pass@host:465". Without it, mail is written to the log. */
|
|
23
|
+
smtpUrl?: string;
|
|
24
|
+
/** Outgoing mail through the Resend API (a `re_` key). Used in place of `smtpUrl`. */
|
|
25
|
+
resendApiKey?: string;
|
|
26
|
+
/** The `whsec_` signing secret of the Resend webhook, so bounces and spam complaints reach the suppression list. */
|
|
27
|
+
resendWebhookSecret?: string;
|
|
28
|
+
/** The sender of every email, for example "WizeLens <alerts@example.com>". */
|
|
29
|
+
mailFrom?: string;
|
|
30
|
+
/** Take the client address from X-Forwarded-For (behind a proxy you run). Default false. */
|
|
31
|
+
trustProxy?: boolean;
|
|
32
|
+
/** Signs sessions and encrypts 2FA secrets: 32+ random characters, or "2:new,1:old" to rotate. Required with Postgres. */
|
|
33
|
+
authSecret?: string;
|
|
34
|
+
/** The one-time token the first account needs. Default: a new random one, printed at start while no account exists. */
|
|
35
|
+
setupToken?: string;
|
|
36
|
+
/** Refuse passwords found in known breaches (sends a 5-character hash prefix to api.pwnedpasswords.com). Default: on with Postgres. */
|
|
37
|
+
checkPwnedPasswords?: boolean;
|
|
38
|
+
/** Identity provider origins for OIDC single sign-on, for example https://acme.okta.com. The cloud fetches OIDC settings only from these. */
|
|
39
|
+
ssoOrigins?: string[];
|
|
40
|
+
redactKeys?: string[];
|
|
41
|
+
uiDir?: string;
|
|
42
|
+
/** For tests: the clock, the HTTP client alerts use, and a mail sender in place of SMTP. */
|
|
43
|
+
now?: () => number;
|
|
44
|
+
fetch?: typeof fetch;
|
|
45
|
+
sendMail?: (mail: Mail) => Promise<void>;
|
|
46
|
+
/** For tests: false keeps background jobs off, so a test runs them itself. Default true. */
|
|
47
|
+
jobs?: boolean;
|
|
48
|
+
}
|
|
49
|
+
type Optional = "uiDir" | "publicUrl" | "smtpUrl" | "resendApiKey" | "resendWebhookSecret" | "sendMail" | "authSecret" | "setupToken" | "checkPwnedPasswords";
|
|
50
|
+
export type CloudConfig = Required<Omit<CloudOptions, Optional>> & Pick<CloudOptions, Optional> & {
|
|
51
|
+
secureCookies: boolean;
|
|
52
|
+
};
|
|
53
|
+
export declare function resolveConfig(o?: CloudOptions): CloudConfig;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6GAA6G;IAC7G,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iIAAiI;IACjI,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qIAAqI;IACrI,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oHAAoH;IACpH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4FAA4F;IAC5F,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0HAA0H;IAC1H,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uHAAuH;IACvH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uIAAuI;IACvI,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,6IAA6I;IAC7I,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,4FAA4F;IAC5F,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,KAAK,QAAQ,GAAG,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,cAAc,GAAG,qBAAqB,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,qBAAqB,CAAC;AAC9J,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG;IAAE,aAAa,EAAE,OAAO,CAAA;CAAE,CAAC;AAqB7H,wBAAgB,aAAa,CAAC,CAAC,GAAE,YAAiB,GAAG,WAAW,CA6B/D"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { DEFAULT_REDACT_KEYS } from "@wizeworks/lens-core";
|
|
2
|
+
/** Mail links must use the public address: a link built from the request's Host header could point anywhere. */
|
|
3
|
+
function checkMail(o) {
|
|
4
|
+
if ((o.smtpUrl || o.resendApiKey) && !o.publicUrl)
|
|
5
|
+
throw new Error("Sending mail needs --public-url, so links in emails point at this cloud.");
|
|
6
|
+
if (o.smtpUrl && o.resendApiKey)
|
|
7
|
+
throw new Error("Pick one mail service: --resend-api-key or --smtp-url, not both.");
|
|
8
|
+
if (o.smtpUrl && !/^smtps?:\/\//.test(o.smtpUrl))
|
|
9
|
+
throw new Error("--smtp-url must start with smtp:// or smtps://.");
|
|
10
|
+
if (o.resendApiKey && !o.resendApiKey.startsWith("re_"))
|
|
11
|
+
throw new Error("--resend-api-key must be a Resend API key (it starts with re_).");
|
|
12
|
+
if (o.resendWebhookSecret && !o.resendWebhookSecret.startsWith("whsec_"))
|
|
13
|
+
throw new Error("--resend-webhook-secret must start with whsec_.");
|
|
14
|
+
}
|
|
15
|
+
/** Each SSO origin as a bare origin: https, or http on this machine only. */
|
|
16
|
+
function ssoOriginsOf(list) {
|
|
17
|
+
return list.map((raw) => {
|
|
18
|
+
const url = URL.canParse(raw) ? new URL(raw) : null;
|
|
19
|
+
const local = url?.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
|
|
20
|
+
if (!url || (url.protocol !== "https:" && !local) || raw.includes("*"))
|
|
21
|
+
throw new Error(`--sso-origins: "${raw}" must be an https:// origin, like https://acme.okta.com.`);
|
|
22
|
+
return url.origin;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export function resolveConfig(o = {}) {
|
|
26
|
+
checkMail(o);
|
|
27
|
+
return {
|
|
28
|
+
database: o.database ?? "pglite:./.wizelens-cloud",
|
|
29
|
+
port: o.port ?? 5970,
|
|
30
|
+
host: o.host ?? "0.0.0.0",
|
|
31
|
+
publicUrl: o.publicUrl?.replace(/\/+$/, ""),
|
|
32
|
+
signup: o.signup ?? "invite",
|
|
33
|
+
retentionDays: o.retentionDays ?? 30,
|
|
34
|
+
ingestPerMinute: o.ingestPerMinute ?? 1200,
|
|
35
|
+
alertIntervalMs: o.alertIntervalMs ?? 60_000,
|
|
36
|
+
allowPrivateWebhooks: o.allowPrivateWebhooks ?? false,
|
|
37
|
+
smtpUrl: o.smtpUrl,
|
|
38
|
+
resendApiKey: o.resendApiKey,
|
|
39
|
+
resendWebhookSecret: o.resendWebhookSecret,
|
|
40
|
+
mailFrom: o.mailFrom ?? `WizeLens <no-reply@${o.publicUrl ? new URL(o.publicUrl).hostname : "localhost"}>`,
|
|
41
|
+
trustProxy: o.trustProxy ?? false,
|
|
42
|
+
sendMail: o.sendMail,
|
|
43
|
+
jobs: o.jobs ?? true,
|
|
44
|
+
authSecret: o.authSecret,
|
|
45
|
+
setupToken: o.setupToken,
|
|
46
|
+
checkPwnedPasswords: o.checkPwnedPasswords,
|
|
47
|
+
ssoOrigins: ssoOriginsOf(o.ssoOrigins ?? []),
|
|
48
|
+
redactKeys: o.redactKeys ?? [...DEFAULT_REDACT_KEYS],
|
|
49
|
+
uiDir: o.uiDir,
|
|
50
|
+
now: o.now ?? Date.now,
|
|
51
|
+
fetch: o.fetch ?? fetch,
|
|
52
|
+
secureCookies: !!o.publicUrl?.startsWith("https://"),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/db/db.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BetterAuthOptions } from "better-auth";
|
|
2
|
+
/** Something that runs SQL: the database, or one transaction. Postgres syntax, `$1` parameters. */
|
|
3
|
+
export interface Queryable {
|
|
4
|
+
query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
5
|
+
}
|
|
6
|
+
export interface Db extends Queryable {
|
|
7
|
+
/** Run `fn` in one transaction. It rolls back when `fn` throws. */
|
|
8
|
+
tx<T>(fn: (q: Queryable) => Promise<T>): Promise<T>;
|
|
9
|
+
/** Run several statements without parameters (migrations, before anything else uses the database). */
|
|
10
|
+
exec(sql: string): Promise<void>;
|
|
11
|
+
close(): Promise<void>;
|
|
12
|
+
readonly kind: "postgres" | "pglite";
|
|
13
|
+
/** The same database, for Better Auth. */
|
|
14
|
+
readonly authDatabase: NonNullable<BetterAuthOptions["database"]>;
|
|
15
|
+
}
|
|
16
|
+
/** A managed Postgres, from a `postgres://` URL. */
|
|
17
|
+
export declare function openPostgres(url: string): Promise<Db>;
|
|
18
|
+
/** PGlite (a folder, or memory), for tests and trials. All queries share one Kysely queue with Better Auth: PGlite has one connection. */
|
|
19
|
+
export declare function openPglite(dir?: string): Promise<Db>;
|
|
20
|
+
/** "postgres://..." opens Postgres; "pglite:<folder>" or "memory" opens PGlite. */
|
|
21
|
+
export declare function openDb(url: string): Promise<Db>;
|
|
22
|
+
//# sourceMappingURL=db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD,mGAAmG;AACnG,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CACnF;AAED,MAAM,WAAW,EAAG,SAAQ,SAAS;IACnC,mEAAmE;IACnE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACpD,sGAAsG;IACtG,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAC;IACrC,0CAA0C;IAC1C,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC;CACnE;AAMD,oDAAoD;AACpD,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAyB3D;AAED,0IAA0I;AAC1I,wBAAsB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAmB1D;AAED,mFAAmF;AACnF,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAK/C"}
|
package/dist/db/db.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const wrap = (client) => ({
|
|
2
|
+
query: async (sql, params = []) => (await client.query(sql, params)).rows,
|
|
3
|
+
});
|
|
4
|
+
/** A managed Postgres, from a `postgres://` URL. */
|
|
5
|
+
export async function openPostgres(url) {
|
|
6
|
+
const { default: pg } = await import("pg");
|
|
7
|
+
// Times are stored as double precision, so no bigint parsing is needed.
|
|
8
|
+
const pool = new pg.Pool({ connectionString: url, max: 10 });
|
|
9
|
+
return {
|
|
10
|
+
kind: "postgres",
|
|
11
|
+
authDatabase: pool,
|
|
12
|
+
...wrap(pool),
|
|
13
|
+
async tx(fn) {
|
|
14
|
+
const client = await pool.connect();
|
|
15
|
+
try {
|
|
16
|
+
await client.query("BEGIN");
|
|
17
|
+
const out = await fn(wrap(client));
|
|
18
|
+
await client.query("COMMIT");
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
await client.query("ROLLBACK");
|
|
23
|
+
throw err;
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
client.release();
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
exec: async (sql) => void (await pool.query(sql)),
|
|
30
|
+
close: () => pool.end(),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** PGlite (a folder, or memory), for tests and trials. All queries share one Kysely queue with Better Auth: PGlite has one connection. */
|
|
34
|
+
export async function openPglite(dir) {
|
|
35
|
+
const [{ PGlite }, { Kysely, CompiledQuery }, { PGliteDialect }] = await Promise.all([
|
|
36
|
+
import("@electric-sql/pglite"),
|
|
37
|
+
import("kysely"),
|
|
38
|
+
import("kysely-pglite-dialect"),
|
|
39
|
+
]);
|
|
40
|
+
const lite = await PGlite.create(dir);
|
|
41
|
+
const kysely = new Kysely({ dialect: new PGliteDialect(lite) });
|
|
42
|
+
const run = (k) => ({
|
|
43
|
+
query: async (sql, params = []) => (await k.executeQuery(CompiledQuery.raw(sql, params))).rows,
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
kind: "pglite",
|
|
47
|
+
authDatabase: { db: kysely, type: "postgres", transaction: true },
|
|
48
|
+
...run(kysely),
|
|
49
|
+
tx: (fn) => kysely.transaction().execute((t) => fn(run(t))),
|
|
50
|
+
exec: async (sql) => void (await lite.exec(sql)),
|
|
51
|
+
close: () => kysely.destroy(),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** "postgres://..." opens Postgres; "pglite:<folder>" or "memory" opens PGlite. */
|
|
55
|
+
export function openDb(url) {
|
|
56
|
+
if (/^postgres(ql)?:\/\//i.test(url))
|
|
57
|
+
return openPostgres(url);
|
|
58
|
+
if (url === "memory")
|
|
59
|
+
return openPglite();
|
|
60
|
+
if (url.startsWith("pglite:"))
|
|
61
|
+
return openPglite(url.slice("pglite:".length));
|
|
62
|
+
throw new Error(`Unknown database URL "${url}". Use postgres://..., pglite:<folder>, or memory.`);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"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"}
|