@absolutejs/auth 0.80.0 → 0.81.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.
@@ -0,0 +1,131 @@
1
+ # Persistent email/password sign-in (Bun + Elysia 2)
2
+
3
+ Use this credentials-only setup instead of the social-login manifest recipe.
4
+ The same API pattern passed synthetic browser signup, login, logout, booking and
5
+ full-container restart tests in Studio using auth 0.80.0. The example deliberately
6
+ sends no email and refuses production. For a real business configure email
7
+ verification, delivery, password policy, backups and the application's user schema.
8
+
9
+ Install published auth and a compatible Drizzle release. Set AUTH_DATABASE_URL
10
+ securely to a real isolated PostgreSQL database; never substitute a placeholder.
11
+ The application owns user records. The auth package owns credentials and sessions.
12
+
13
+ ```ts
14
+ import { auth } from '@absolutejs/auth/server';
15
+ import { createPostgresAuthSessionStore, createPostgresCredentialStore, runMigrations } from '@absolutejs/auth';
16
+ import { SQL } from 'bun';
17
+ import { Database } from 'bun:sqlite';
18
+ import { drizzle } from 'drizzle-orm/bun-sql';
19
+ import { mkdirSync } from 'node:fs';
20
+
21
+ if (process.env.NODE_ENV === 'production') throw new Error('Synthetic example: configure verified email and real business policy before production');
22
+ type Customer = { id: string; email: string };
23
+ const databaseUrl = process.env.AUTH_DATABASE_URL;
24
+ if (!databaseUrl)
25
+ throw new Error(
26
+ "AUTH_DATABASE_URL must point to the isolated acceptance database",
27
+ );
28
+ const migrationClient = new SQL({ url: databaseUrl, max: 1, prepare: false });
29
+ try {
30
+ await runMigrations({
31
+ blocks: ["sessions", "credentials"],
32
+ client: {
33
+ query: async (text, values) => ({
34
+ rows: await migrationClient.unsafe(text, values ? [...values] : []),
35
+ }),
36
+ },
37
+ log: () => undefined,
38
+ });
39
+ } finally {
40
+ await migrationClient.close();
41
+ }
42
+ const authDb = drizzle({ client: new SQL(databaseUrl) });
43
+ const decodeCustomer = (value: unknown): Customer => {
44
+ if (typeof value !== "object" || value === null)
45
+ throw new Error("Invalid customer session");
46
+ const id: unknown = Reflect.get(value, "id");
47
+ const email: unknown = Reflect.get(value, "email");
48
+ if (typeof id !== "string" || typeof email !== "string")
49
+ throw new Error("Invalid customer session");
50
+ return { id, email };
51
+ };
52
+ mkdirSync(".data", { recursive: true });
53
+ const db = new Database(".data/customer-example.sqlite", { create: true });
54
+ db.exec(
55
+ "PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000; CREATE TABLE IF NOT EXISTS customers(id TEXT PRIMARY KEY, email TEXT NOT NULL UNIQUE);",
56
+ );
57
+ const userById = db.query<Customer, [string]>(
58
+ "SELECT id,email FROM customers WHERE id=?",
59
+ );
60
+ const userByEmail = db.query<Customer, [string]>(
61
+ "SELECT id,email FROM customers WHERE email=?",
62
+ );
63
+ const insertUser = db.query("INSERT INTO customers(id,email) VALUES(?,?)");
64
+ const sessions = createPostgresAuthSessionStore(authDb, decodeCustomer);
65
+ export const authentication = await auth<Customer>({
66
+ providersConfiguration: {},
67
+ getUser: (id) => userById.get(String(id)) ?? null,
68
+ authSessionStore: sessions,
69
+ cookieSecure: true,
70
+ credentials: {
71
+ credentialStore: createPostgresCredentialStore(authDb),
72
+ getUserByEmail: (email) => userByEmail.get(email) ?? null,
73
+ onCreateCredentialUser: ({ email }) => {
74
+ const user = { id: crypto.randomUUID(), email };
75
+ insertUser.run(user.id, email);
76
+ return user;
77
+ },
78
+ // Local synthetic mode deliberately delivers no messages.
79
+ onSendEmail: () => undefined,
80
+ requireEmailVerification: false,
81
+ passwordPolicy: { minLength: 12, checkBreaches: false },
82
+ },
83
+ });
84
+
85
+ ```
86
+
87
+ Important API details:
88
+
89
+ - `auth` is asynchronous and comes from `@absolutejs/auth/server`.
90
+ - `authSessionStore` is top-level. `credentialStore` and credential callbacks
91
+ belong inside `credentials`. There is no top-level `sessionStore` option.
92
+ - Stores do not have `.runMigrations()`. Import `runMigrations` from the package
93
+ root and supply its query client as shown above.
94
+ - With Drizzle 1's Bun driver use `drizzle({ client })`, not `drizzle(client)`.
95
+ - Keep `prepare: false` on the migration client only. Application queries need
96
+ Bun's default prepared mode to encode JSON session data correctly.
97
+ - The built-in sign-out route is `DELETE /oauth2/signout`.
98
+ - Use `createAuthContext<Customer>({ authSessionStore: sessions })` from `/server` to read typed authenticated
99
+ users. Business APIs must check the session server-side and scope records to
100
+ that user. Do not implement a second password or cookie system.
101
+ - Preserve cookie headers when exposing a narrow typed JSON wrapper around the
102
+ package's configurable credential routes. Never store session tokens in browser
103
+ localStorage. Browser business requests belong in typed Eden + React Query.
104
+
105
+ ## Typed credential routes (0.81.0+)
106
+
107
+ Use `createCredentialsApi` from `@absolutejs/auth/server` for fixed, directly
108
+ Eden-typed login, registration, verification and password-reset routes. Supply
109
+ application-owned credentials callbacks, cookie policy and a durable session
110
+ store. Mount this subapp instead of the `credentials` block on `auth`; keep
111
+ `auth` for OAuth/sign-out. No forwarding wrappers are needed.
112
+
113
+ The manifest tool `get_credentials_integration` returns the exact integration
114
+ source and required bindings. `credentialsConfiguration` is your application
115
+ module, not a package export: it supplies `authSessionStore`, `credentialStore`,
116
+ `getUserByEmail`, `onCreateCredentialUser`, and real `onSendEmail` delivery.
117
+ Configure trusted origins, verification and password policy. Never invent these
118
+ bindings, substitute in-memory production storage, or silently disable delivery.
119
+
120
+ Browser code imports only `typeof credentialsApi` and creates
121
+ `treaty<typeof credentialsApi>(origin)`. Call `client.auth.login.post(...)` in a
122
+ React Query `mutationFn`. Inspect errors and preserve `mfa_required` and
123
+ `verification_required` flows: a successful HTTP response does not always mean
124
+ an authenticated session.
125
+
126
+ For protected business routes use `createAuthContext({ authSessionStore })`,
127
+ read `absoluteAuthStatus.user`, return `status(401, { error: 'Sign in required' })`
128
+ when absent, and scope database access to that user. Export the narrow business
129
+ subapp type for its own Eden client inside React Query. A compiler pass is
130
+ necessary, but real signup, login, reset, authorization and persistence tests
131
+ are still required.
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.80.0",
2
+ "version": "0.81.0",
3
3
  "name": "@absolutejs/auth",
4
4
  "description": "An authorization library for absolutejs",
5
5
  "repository": {
@@ -24,9 +24,10 @@
24
24
  "lint": "absolute eslint",
25
25
  "typecheck": "absolute typecheck",
26
26
  "verify-package": "absolute-manifest verify-package",
27
- "check:package": "bun run typecheck && bun run lint && bun run test && bun run build && bun run verify-package && absolute-changelog check",
27
+ "check:package": "bun run typecheck && bun run typecheck:credentials && bun run lint && bun run test && bun run build && bun run verify-package && absolute-changelog check",
28
28
  "release": "bun run format && bun run check:package && npm publish",
29
- "prepublishOnly": "bun run check:package"
29
+ "prepublishOnly": "bun run check:package",
30
+ "typecheck:credentials": "tsc --project tsconfig.credentials.json"
30
31
  },
31
32
  "keywords": [
32
33
  "authorization",