@vonall/auth 0.0.0-stage → 0.1.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.
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +33 -2
- package/dist/client/index.d.ts +17 -0
- package/dist/client/index.js +18 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +10 -0
- package/dist/messages.d.ts +50 -0
- package/dist/messages.js +88 -0
- package/dist/permissions.d.ts +48 -0
- package/dist/permissions.js +17 -0
- package/dist/remote/app_user.remote.d.ts +66 -0
- package/dist/remote/app_user.remote.js +91 -0
- package/dist/remote/einladung.remote.d.ts +27 -0
- package/dist/remote/einladung.remote.js +56 -0
- package/dist/remote/index.d.ts +2 -0
- package/dist/remote/index.js +2 -0
- package/dist/schema/index.d.ts +3683 -0
- package/dist/schema/index.js +265 -0
- package/dist/server/create.d.ts +87 -0
- package/dist/server/create.js +158 -0
- package/dist/server/crypto.d.ts +5 -0
- package/dist/server/crypto.js +15 -0
- package/dist/server/helpers.d.ts +18 -0
- package/dist/server/helpers.js +62 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.js +9 -0
- package/dist/server/loads.d.ts +57 -0
- package/dist/server/loads.js +83 -0
- package/dist/server/registry.d.ts +39 -0
- package/dist/server/registry.js +15 -0
- package/dist/server/repositories/EinladungRepo.d.ts +36 -0
- package/dist/server/repositories/EinladungRepo.js +74 -0
- package/dist/server/repositories/UserRepo.d.ts +19 -0
- package/dist/server/repositories/UserRepo.js +67 -0
- package/dist/server/service/einladung.service.d.ts +48 -0
- package/dist/server/service/einladung.service.js +76 -0
- package/dist/server/service/konto.service.d.ts +7 -0
- package/dist/server/service/konto.service.js +11 -0
- package/dist/server/service/mail.d.ts +12 -0
- package/dist/server/service/mail.js +40 -0
- package/dist/templates/InvitationEmail.svelte +18 -0
- package/dist/templates/InvitationEmail.svelte.d.ts +10 -0
- package/dist/templates/ResetPasswordEmail.svelte +16 -0
- package/dist/templates/ResetPasswordEmail.svelte.d.ts +9 -0
- package/dist/templates/VerifyEmailEmail.svelte +16 -0
- package/dist/templates/VerifyEmailEmail.svelte.d.ts +9 -0
- package/dist/testing/index.d.ts +6 -0
- package/dist/testing/index.js +26 -0
- package/dist/types.d.ts +38 -0
- package/dist/types.js +21 -0
- package/dist/util/fresh.d.ts +11 -0
- package/dist/util/fresh.js +20 -0
- package/dist/util/messageOf.d.ts +5 -0
- package/dist/util/messageOf.js +12 -0
- package/dist/util/names.d.ts +10 -0
- package/dist/util/names.js +19 -0
- package/dist/util/sameSite.d.ts +5 -0
- package/dist/util/sameSite.js +15 -0
- package/dist/util/signup.d.ts +15 -0
- package/dist/util/signup.js +23 -0
- package/package.json +96 -3
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { EmailLayout } from "@vonall/mail";
|
|
3
|
+
import { m } from "../messages.js";
|
|
4
|
+
|
|
5
|
+
let { recipientName, link, appName, appLink }: {
|
|
6
|
+
recipientName: string;
|
|
7
|
+
link: string;
|
|
8
|
+
appName: string;
|
|
9
|
+
appLink: string;
|
|
10
|
+
} = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<EmailLayout title={m().hello(recipientName)} {link} buttonLabel={m().verifyButton} {appName} {appLink}>
|
|
14
|
+
<p>{m().verifyBody(appName)}</p>
|
|
15
|
+
<p>{m().verifyNotYou}</p>
|
|
16
|
+
</EmailLayout>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type $$ComponentProps = {
|
|
2
|
+
recipientName: string;
|
|
3
|
+
link: string;
|
|
4
|
+
appName: string;
|
|
5
|
+
appLink: string;
|
|
6
|
+
};
|
|
7
|
+
declare const VerifyEmailEmail: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type VerifyEmailEmail = ReturnType<typeof VerifyEmailEmail>;
|
|
9
|
+
export default VerifyEmailEmail;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type CreateAuthOptions, type CreatedAuth } from "../server/create.js";
|
|
2
|
+
import type { Db } from "../server/registry.js";
|
|
3
|
+
/** Creates a user directly (the first one becomes admin, as in the app) and returns its id. */
|
|
4
|
+
export declare function createUser(email?: string): Promise<string>;
|
|
5
|
+
/** `createAuth()` with test values: every option on, mail off, unless overridden. */
|
|
6
|
+
export declare function testAuth(db: Db, overrides?: Partial<CreateAuthOptions>): CreatedAuth;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Helpers for a Product's db tests (`tests/db/fixtures.ts`) and this package's own. */
|
|
2
|
+
import { createMailer } from "@vonall/mail";
|
|
3
|
+
import { authSchema } from "../schema/index.js";
|
|
4
|
+
import { createAuth } from "../server/create.js";
|
|
5
|
+
import { UserRepo } from "../server/repositories/UserRepo.js";
|
|
6
|
+
/** Creates a user directly (the first one becomes admin, as in the app) and returns its id. */
|
|
7
|
+
export async function createUser(email = "user@example.com") {
|
|
8
|
+
const id = crypto.randomUUID();
|
|
9
|
+
await UserRepo.insertUser({ id, email, name: "", emailVerified: true, createdAt: new Date(), updatedAt: new Date() });
|
|
10
|
+
return id;
|
|
11
|
+
}
|
|
12
|
+
/** `createAuth()` with test values: every option on, mail off, unless overridden. */
|
|
13
|
+
export function testAuth(db, overrides = {}) {
|
|
14
|
+
return createAuth({
|
|
15
|
+
db,
|
|
16
|
+
schema: authSchema({ admin: true, mcp: true }),
|
|
17
|
+
secret: "test-secret-for-the-db-tests-only",
|
|
18
|
+
origin: "http://localhost:5173",
|
|
19
|
+
appName: "Test",
|
|
20
|
+
locale: "en-GB",
|
|
21
|
+
signupMode: "invite",
|
|
22
|
+
mailer: createMailer({ smtp: null }),
|
|
23
|
+
admin: true,
|
|
24
|
+
...overrides,
|
|
25
|
+
});
|
|
26
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { InferInsertModel, InferSelectModel } from "drizzle-orm";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { FullSchema } from "./schema/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* How people get an account (the Factory's GLOSSARY, "Signup mode"); a Product sets it in its `config.ts`.
|
|
6
|
+
* - `invite`: anyone with an account can create an Einladung, and signup needs one
|
|
7
|
+
* - `open`: anyone can sign up and confirms their email address first (needs mail)
|
|
8
|
+
* - `admin`: only admins create Einladungen
|
|
9
|
+
* The first account needs neither an Einladung nor a confirmation in any mode.
|
|
10
|
+
*/
|
|
11
|
+
export declare const SIGNUP_MODES: readonly ["invite", "open", "admin"];
|
|
12
|
+
export type SignupMode = (typeof SIGNUP_MODES)[number];
|
|
13
|
+
/** Whether someone may create an account now, and if not, why. */
|
|
14
|
+
export declare const SIGNUP_STATES: readonly ["allowed", "needs_einladung", "no_mail"];
|
|
15
|
+
export type SignupState = (typeof SIGNUP_STATES)[number];
|
|
16
|
+
export declare const MIN_PASSWORD_LENGTH = 8;
|
|
17
|
+
/** The user row with every option on; an option that is off leaves its columns unused. */
|
|
18
|
+
export type UserSelect = InferSelectModel<FullSchema["user"]>;
|
|
19
|
+
export type UserInsert = InferInsertModel<FullSchema["user"]>;
|
|
20
|
+
/** The user as the client sees it (no secrets live on the user row, so it is the full row). */
|
|
21
|
+
export type AppUserClient = UserSelect;
|
|
22
|
+
/** The logged-in user of the current request, as better-auth puts it into `locals`. */
|
|
23
|
+
export type SessionUser = NonNullable<App.Locals["user"]>;
|
|
24
|
+
/** What an Einladung link offers, shown before signing up. */
|
|
25
|
+
export type EinladungInfo = {
|
|
26
|
+
id: string;
|
|
27
|
+
inviterName: string;
|
|
28
|
+
expiresAt: Date;
|
|
29
|
+
};
|
|
30
|
+
export type OffeneEinladung = {
|
|
31
|
+
id: string;
|
|
32
|
+
email: string | null;
|
|
33
|
+
expiresAt: Date;
|
|
34
|
+
createdAt: Date;
|
|
35
|
+
};
|
|
36
|
+
export declare const emailSchema: z.ZodEmail;
|
|
37
|
+
export declare const passwordSchema: z.ZodString;
|
|
38
|
+
export declare const nameSchema: z.ZodString;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { m } from "./messages.js";
|
|
3
|
+
/**
|
|
4
|
+
* How people get an account (the Factory's GLOSSARY, "Signup mode"); a Product sets it in its `config.ts`.
|
|
5
|
+
* - `invite`: anyone with an account can create an Einladung, and signup needs one
|
|
6
|
+
* - `open`: anyone can sign up and confirms their email address first (needs mail)
|
|
7
|
+
* - `admin`: only admins create Einladungen
|
|
8
|
+
* The first account needs neither an Einladung nor a confirmation in any mode.
|
|
9
|
+
*/
|
|
10
|
+
export const SIGNUP_MODES = ["invite", "open", "admin"];
|
|
11
|
+
/** Whether someone may create an account now, and if not, why. */
|
|
12
|
+
export const SIGNUP_STATES = ["allowed", "needs_einladung", "no_mail"];
|
|
13
|
+
export const MIN_PASSWORD_LENGTH = 8;
|
|
14
|
+
// The messages are read when a value is checked, not when the module loads, so the Product's configure… call comes first
|
|
15
|
+
export const emailSchema = z.email({ error: () => m().invalidEmail });
|
|
16
|
+
export const passwordSchema = z.string().min(MIN_PASSWORD_LENGTH, { error: () => m().passwordTooShort(MIN_PASSWORD_LENGTH) });
|
|
17
|
+
export const nameSchema = z
|
|
18
|
+
.string()
|
|
19
|
+
.trim()
|
|
20
|
+
.min(1, { error: () => m().nameRequired })
|
|
21
|
+
.max(80, { error: () => m().nameTooLong(80) });
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* better-auth refuses some endpoints (listing the sessions, unlinking an account) for a session created longer than
|
|
3
|
+
* `freshAge` ago; the app then sends the user to log in again, which needs that stale session signed out first.
|
|
4
|
+
*/
|
|
5
|
+
export declare const SESSION_NOT_FRESH = "SESSION_NOT_FRESH";
|
|
6
|
+
/** Whether an error from better-auth (server or client) is its "Session is not fresh". */
|
|
7
|
+
export declare function isSessionNotFresh(e: unknown): boolean;
|
|
8
|
+
/** The login page that signs out a stale session and then returns to `redirectTo`. */
|
|
9
|
+
export declare function reauthPath(redirectTo: string): string;
|
|
10
|
+
/** better-auth's own check: a `freshAge` of 0 turns it off. */
|
|
11
|
+
export declare function isStale(createdAt: Date, freshAgeSeconds: number, now?: Date): boolean;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* better-auth refuses some endpoints (listing the sessions, unlinking an account) for a session created longer than
|
|
3
|
+
* `freshAge` ago; the app then sends the user to log in again, which needs that stale session signed out first.
|
|
4
|
+
*/
|
|
5
|
+
export const SESSION_NOT_FRESH = "SESSION_NOT_FRESH";
|
|
6
|
+
/** Whether an error from better-auth (server or client) is its "Session is not fresh". */
|
|
7
|
+
export function isSessionNotFresh(e) {
|
|
8
|
+
if (!e || typeof e !== "object")
|
|
9
|
+
return false;
|
|
10
|
+
const body = "body" in e ? e.body : e;
|
|
11
|
+
return !!body && typeof body === "object" && "code" in body && body.code === SESSION_NOT_FRESH;
|
|
12
|
+
}
|
|
13
|
+
/** The login page that signs out a stale session and then returns to `redirectTo`. */
|
|
14
|
+
export function reauthPath(redirectTo) {
|
|
15
|
+
return `/auth/login?error=${SESSION_NOT_FRESH.toLowerCase()}&redirectTo=${encodeURIComponent(redirectTo)}`;
|
|
16
|
+
}
|
|
17
|
+
/** better-auth's own check: a `freshAge` of 0 turns it off. */
|
|
18
|
+
export function isStale(createdAt, freshAgeSeconds, now = new Date()) {
|
|
19
|
+
return freshAgeSeconds !== 0 && now.getTime() - createdAt.getTime() >= freshAgeSeconds * 1000;
|
|
20
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The message of a caught error, for showing it to the user. Remote functions reject with plain objects that carry a
|
|
3
|
+
* `message`, so anything with a non-empty string `message` counts.
|
|
4
|
+
*/
|
|
5
|
+
export declare function messageOf(error: unknown, fallback: string): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The message of a caught error, for showing it to the user. Remote functions reject with plain objects that carry a
|
|
3
|
+
* `message`, so anything with a non-empty string `message` counts.
|
|
4
|
+
*/
|
|
5
|
+
export function messageOf(error, fallback) {
|
|
6
|
+
if (typeof error === "object" && error !== null && "message" in error) {
|
|
7
|
+
const { message } = error;
|
|
8
|
+
if (typeof message === "string" && message)
|
|
9
|
+
return message;
|
|
10
|
+
}
|
|
11
|
+
return fallback;
|
|
12
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function displayName(user: {
|
|
2
|
+
name?: string | null;
|
|
3
|
+
email: string;
|
|
4
|
+
} | null | undefined): string;
|
|
5
|
+
export declare function displayInitials(user: {
|
|
6
|
+
name?: string | null;
|
|
7
|
+
email: string;
|
|
8
|
+
}): string;
|
|
9
|
+
/** A readable name from an email address ("lena.meier@…" → "Lena Meier"), for accounts created without one. */
|
|
10
|
+
export declare function nameFromEmail(email: string): string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function displayName(user) {
|
|
2
|
+
if (!user)
|
|
3
|
+
return "";
|
|
4
|
+
return user.name?.trim() || user.email;
|
|
5
|
+
}
|
|
6
|
+
export function displayInitials(user) {
|
|
7
|
+
const words = (user.name ?? "").trim().split(/\s+/).filter(Boolean);
|
|
8
|
+
if (words.length > 0)
|
|
9
|
+
return words.slice(0, 2).map((w) => w.charAt(0).toUpperCase()).join("");
|
|
10
|
+
return user.email.charAt(0).toUpperCase() || "?";
|
|
11
|
+
}
|
|
12
|
+
/** A readable name from an email address ("lena.meier@…" → "Lena Meier"), for accounts created without one. */
|
|
13
|
+
export function nameFromEmail(email) {
|
|
14
|
+
const local = email.split("@")[0] ?? "";
|
|
15
|
+
const words = local.split(/[._\-+]+/).filter(Boolean);
|
|
16
|
+
if (words.length === 0)
|
|
17
|
+
return email;
|
|
18
|
+
return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
|
|
19
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The path of `ziel` if it stays on `origin`, else null. Browsers read "/\\evil.com" or "/\t/evil.com" as another host,
|
|
3
|
+
* so the target is resolved against the origin instead of checking its first characters.
|
|
4
|
+
*/
|
|
5
|
+
export declare function sameSitePath(ziel: string | null, origin: string): string | null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The path of `ziel` if it stays on `origin`, else null. Browsers read "/\\evil.com" or "/\t/evil.com" as another host,
|
|
3
|
+
* so the target is resolved against the origin instead of checking its first characters.
|
|
4
|
+
*/
|
|
5
|
+
export function sameSitePath(ziel, origin) {
|
|
6
|
+
if (!ziel || !ziel.startsWith("/"))
|
|
7
|
+
return null;
|
|
8
|
+
try {
|
|
9
|
+
const url = new URL(ziel, origin);
|
|
10
|
+
return url.origin === origin ? `${url.pathname}${url.search}${url.hash}` : null;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SignupMode, SignupState } from "../types.js";
|
|
2
|
+
/** Whether a user is an admin. Works without the admin option too: the user then has no role and nobody is. */
|
|
3
|
+
export declare function isAdmin(user: object | null | undefined): boolean;
|
|
4
|
+
/** Whether a user may create Einladungen in this signup mode. */
|
|
5
|
+
export declare function mayInvite(mode: SignupMode, admin: boolean): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Whether someone may create an account now. The first account (the admin) always may; after that `open` needs mail
|
|
8
|
+
* (the confirmation link), `invite` and `admin` a usable Einladung.
|
|
9
|
+
*/
|
|
10
|
+
export declare function signupState(input: {
|
|
11
|
+
mode: SignupMode;
|
|
12
|
+
accounts: number;
|
|
13
|
+
einladungUsable: boolean;
|
|
14
|
+
mail: boolean;
|
|
15
|
+
}): SignupState;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Whether a user is an admin. Works without the admin option too: the user then has no role and nobody is. */
|
|
2
|
+
export function isAdmin(user) {
|
|
3
|
+
return Boolean(user && "role" in user && user.role === "admin");
|
|
4
|
+
}
|
|
5
|
+
/** Whether a user may create Einladungen in this signup mode. */
|
|
6
|
+
export function mayInvite(mode, admin) {
|
|
7
|
+
if (mode === "invite")
|
|
8
|
+
return true;
|
|
9
|
+
if (mode === "admin")
|
|
10
|
+
return admin;
|
|
11
|
+
return false; // open: nobody needs one
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Whether someone may create an account now. The first account (the admin) always may; after that `open` needs mail
|
|
15
|
+
* (the confirmation link), `invite` and `admin` a usable Einladung.
|
|
16
|
+
*/
|
|
17
|
+
export function signupState(input) {
|
|
18
|
+
if (input.accounts === 0)
|
|
19
|
+
return "allowed";
|
|
20
|
+
if (input.mode === "open")
|
|
21
|
+
return input.mail ? "allowed" : "no_mail";
|
|
22
|
+
return input.einladungUsable ? "allowed" : "needs_einladung";
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,99 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vonall/auth",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Accounts for a Web App Factory Product: better-auth with the hooks, the protected helpers, Einladungen, Konto, the auth pages and the settings; Admin as an option",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/SebastianvonAllmen/vonall-libs.git",
|
|
9
|
+
"directory": "packages/auth"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"!dist/**/*.test.*",
|
|
15
|
+
"CHANGELOG.md"
|
|
16
|
+
],
|
|
17
|
+
"sideEffects": [
|
|
18
|
+
"**/*.css"
|
|
19
|
+
],
|
|
20
|
+
"svelte": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"svelte": "./dist/index.js",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./messages": {
|
|
29
|
+
"types": "./dist/messages.d.ts",
|
|
30
|
+
"default": "./dist/messages.js"
|
|
31
|
+
},
|
|
32
|
+
"./schema": {
|
|
33
|
+
"types": "./dist/schema/index.d.ts",
|
|
34
|
+
"default": "./dist/schema/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./server": {
|
|
37
|
+
"types": "./dist/server/index.d.ts",
|
|
38
|
+
"default": "./dist/server/index.js"
|
|
39
|
+
},
|
|
40
|
+
"./client": {
|
|
41
|
+
"types": "./dist/client/index.d.ts",
|
|
42
|
+
"default": "./dist/client/index.js"
|
|
43
|
+
},
|
|
44
|
+
"./remote": {
|
|
45
|
+
"types": "./dist/remote/index.d.ts",
|
|
46
|
+
"default": "./dist/remote/index.js"
|
|
47
|
+
},
|
|
48
|
+
"./testing": {
|
|
49
|
+
"types": "./dist/testing/index.d.ts",
|
|
50
|
+
"default": "./dist/testing/index.js"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"@sveltejs/kit": "^3.1.0",
|
|
55
|
+
"svelte": "^5.57.2",
|
|
56
|
+
"drizzle-orm": "^0.45.4",
|
|
57
|
+
"pg": "^8.23.1",
|
|
58
|
+
"zod": "^4.6.7",
|
|
59
|
+
"neverthrow": "^8.2.0"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@sveltejs/kit": "^3.1.0",
|
|
63
|
+
"@sveltejs/package": "^3.0.1",
|
|
64
|
+
"@sveltejs/vite-plugin-svelte": "7.3.1",
|
|
65
|
+
"@types/pg": "^8.23.1",
|
|
66
|
+
"drizzle-kit": "^0.31.11",
|
|
67
|
+
"drizzle-orm": "^0.45.4",
|
|
68
|
+
"neverthrow": "^8.2.0",
|
|
69
|
+
"pg": "^8.23.1",
|
|
70
|
+
"publint": "^0.3.25",
|
|
71
|
+
"svelte": "^5.57.2",
|
|
72
|
+
"svelte-check": "^4.7.7",
|
|
73
|
+
"typescript": "^6.0.3",
|
|
74
|
+
"vite": "8.3.4",
|
|
75
|
+
"vitest": "^5.0.5",
|
|
76
|
+
"zod": "^4.6.7"
|
|
77
|
+
},
|
|
78
|
+
"imports": {
|
|
79
|
+
"#lib": "./src/lib/index.js",
|
|
80
|
+
"#lib/*": "./src/lib/*"
|
|
81
|
+
},
|
|
82
|
+
"engines": {
|
|
83
|
+
"node": ">=24.0.0"
|
|
84
|
+
},
|
|
85
|
+
"publishConfig": {
|
|
86
|
+
"access": "public"
|
|
87
|
+
},
|
|
88
|
+
"dependencies": {
|
|
89
|
+
"@node-rs/argon2": "^2.2.2",
|
|
90
|
+
"better-auth": "^1.7.12",
|
|
91
|
+
"@vonall/mail": "^0.1.1"
|
|
92
|
+
},
|
|
93
|
+
"scripts": {
|
|
94
|
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
95
|
+
"test:unit": "vitest run --project unit --passWithNoTests",
|
|
96
|
+
"test:db": "vitest run --project db --passWithNoTests",
|
|
97
|
+
"build": "svelte-kit sync && svelte-package && publint"
|
|
98
|
+
}
|
|
6
99
|
}
|