@fortressauth/adapter-sql 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Damilola Michael Ige
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # @fortressauth/adapter-sql
2
+
3
+ SQL database adapter for FortressAuth using Kysely query builder.
4
+
5
+ ## Features
6
+
7
+ - 🗄️ **Multi-Database Support**: PostgreSQL, MySQL, SQLite
8
+ - 🔍 **Type-Safe Queries**: Powered by Kysely
9
+ - 🔄 **Transactions**: Full transaction support
10
+ - 📊 **Migrations**: Built-in migration system
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @fortressauth/adapter-sql @fortressauth/core kysely
16
+ # or
17
+ pnpm add @fortressauth/adapter-sql @fortressauth/core kysely
18
+ # or
19
+ yarn add @fortressauth/adapter-sql @fortressauth/core kysely
20
+ ```
21
+
22
+ You'll also need a database driver:
23
+
24
+ ```bash
25
+ # For PostgreSQL
26
+ npm install pg
27
+
28
+ # For MySQL
29
+ npm install mysql2
30
+
31
+ # For SQLite
32
+ npm install better-sqlite3
33
+ ```
34
+
35
+ ## Quick Start
36
+
37
+ ### SQLite
38
+
39
+ ```typescript
40
+ import Database from 'better-sqlite3';
41
+ import { Kysely, SqliteDialect } from 'kysely';
42
+ import { SqlAdapter, up } from '@fortressauth/adapter-sql';
43
+
44
+ const sqlite = new Database('./auth.db');
45
+ const db = new Kysely({
46
+ dialect: new SqliteDialect({ database: sqlite }),
47
+ });
48
+
49
+ // Run migrations
50
+ await up(db);
51
+
52
+ // Create adapter
53
+ const adapter = new SqlAdapter(db, { dialect: 'sqlite' });
54
+ ```
55
+
56
+ ### PostgreSQL
57
+
58
+ ```typescript
59
+ import { Kysely, PostgresDialect } from 'kysely';
60
+ import { Pool } from 'pg';
61
+ import { SqlAdapter, up } from '@fortressauth/adapter-sql';
62
+
63
+ const db = new Kysely({
64
+ dialect: new PostgresDialect({
65
+ pool: new Pool({
66
+ host: 'localhost',
67
+ database: 'auth',
68
+ }),
69
+ }),
70
+ });
71
+
72
+ await up(db);
73
+ const adapter = new SqlAdapter(db, { dialect: 'postgres' });
74
+ ```
75
+
76
+ ### MySQL
77
+
78
+ ```typescript
79
+ import { Kysely, MysqlDialect } from 'kysely';
80
+ import { createPool } from 'mysql2';
81
+ import { SqlAdapter, up } from '@fortressauth/adapter-sql';
82
+
83
+ const db = new Kysely({
84
+ dialect: new MysqlDialect({
85
+ pool: createPool({
86
+ host: 'localhost',
87
+ database: 'auth',
88
+ }),
89
+ }),
90
+ });
91
+
92
+ await up(db);
93
+ const adapter = new SqlAdapter(db, { dialect: 'mysql' });
94
+ ```
95
+
96
+ ## Database Schema
97
+
98
+ The adapter creates four tables:
99
+
100
+ - **users**: User accounts with email verification and lockout support
101
+ - **accounts**: Provider-specific accounts (email, OAuth)
102
+ - **sessions**: Active user sessions with expiration
103
+ - **login_attempts**: Login attempt history for rate limiting
104
+
105
+ ## Migrations
106
+
107
+ ```typescript
108
+ import { up, down } from '@fortressauth/adapter-sql';
109
+
110
+ // Apply migrations
111
+ await up(db);
112
+
113
+ // Rollback migrations
114
+ await down(db);
115
+ ```
116
+
117
+ ## Transactions
118
+
119
+ ```typescript
120
+ await adapter.transaction(async (txRepo) => {
121
+ const user = User.create('user@example.com');
122
+ await txRepo.createUser(user);
123
+
124
+ const account = Account.createEmailAccount(
125
+ user.id,
126
+ 'user@example.com',
127
+ passwordHash
128
+ );
129
+ await txRepo.createAccount(account);
130
+ });
131
+ ```
132
+
133
+ ## License
134
+
135
+ MIT
@@ -0,0 +1,33 @@
1
+ import { Account, type AuthRepository, type LoginAttempt, type Result, Session, User } from '@fortressauth/core';
2
+ import type { Kysely } from 'kysely';
3
+ import type { Database } from './schema.js';
4
+ export type DatabaseDialect = 'sqlite' | 'postgres' | 'mysql';
5
+ export interface SqlAdapterOptions {
6
+ /** Database dialect for proper type handling. Defaults to 'sqlite'. */
7
+ dialect?: DatabaseDialect;
8
+ }
9
+ export declare class SqlAdapter implements AuthRepository {
10
+ private readonly db;
11
+ private readonly dialect;
12
+ constructor(db: Kysely<Database>, options?: SqlAdapterOptions);
13
+ private isSqlite;
14
+ private parseBoolean;
15
+ private serializeBoolean;
16
+ private parseDate;
17
+ private serializeDate;
18
+ findUserByEmail(email: string): Promise<User | null>;
19
+ findUserById(id: string): Promise<User | null>;
20
+ createUser(user: User): Promise<Result<void, 'EMAIL_EXISTS'>>;
21
+ updateUser(user: User): Promise<void>;
22
+ findAccountByProvider(providerId: string, providerUserId: string): Promise<Account | null>;
23
+ findEmailAccountByUserId(userId: string): Promise<Account | null>;
24
+ createAccount(account: Account): Promise<void>;
25
+ findSessionByTokenHash(tokenHash: string): Promise<Session | null>;
26
+ createSession(session: Session): Promise<void>;
27
+ deleteSession(sessionId: string): Promise<void>;
28
+ deleteSessionsByUserId(userId: string): Promise<void>;
29
+ recordLoginAttempt(attempt: LoginAttempt): Promise<void>;
30
+ countRecentFailedAttempts(email: string, windowMs: number): Promise<number>;
31
+ transaction<T>(fn: (repo: AuthRepository) => Promise<T>): Promise<T>;
32
+ }
33
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,KAAK,cAAc,EAEnB,KAAK,YAAY,EAEjB,KAAK,MAAM,EACX,OAAO,EACP,IAAI,EACL,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;AAE9D,MAAM,WAAW,iBAAiB;IAChC,uEAAuE;IACvE,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAED,qBAAa,UAAW,YAAW,cAAc;IAI7C,OAAO,CAAC,QAAQ,CAAC,EAAE;IAHrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;gBAGvB,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,EACrC,OAAO,GAAE,iBAAsB;IAKjC,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,aAAa;IAIf,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAqBpD,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAqB9C,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IA6B7D,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAarC,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAsB1F,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAsBjE,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAc9C,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAsBlE,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAe9C,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxD,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgB3E,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAQ3E"}
@@ -0,0 +1,224 @@
1
+ import { Account, err, ok, Session, User, } from '@fortressauth/core';
2
+ export class SqlAdapter {
3
+ db;
4
+ dialect;
5
+ constructor(db, options = {}) {
6
+ this.db = db;
7
+ this.dialect = options.dialect ?? 'sqlite';
8
+ }
9
+ isSqlite() {
10
+ return this.dialect === 'sqlite';
11
+ }
12
+ parseBoolean(value) {
13
+ return typeof value === 'boolean' ? value : value === 1;
14
+ }
15
+ serializeBoolean(value) {
16
+ return this.isSqlite() ? (value ? 1 : 0) : value;
17
+ }
18
+ parseDate(value) {
19
+ return typeof value === 'string' ? new Date(value) : value;
20
+ }
21
+ serializeDate(value) {
22
+ return this.isSqlite() ? value.toISOString() : value;
23
+ }
24
+ async findUserByEmail(email) {
25
+ const row = await this.db
26
+ .selectFrom('users')
27
+ .selectAll()
28
+ .where('email', '=', email.toLowerCase())
29
+ .executeTakeFirst();
30
+ if (!row) {
31
+ return null;
32
+ }
33
+ return User.rehydrate({
34
+ id: row.id,
35
+ email: row.email,
36
+ emailVerified: this.parseBoolean(row.email_verified),
37
+ createdAt: this.parseDate(row.created_at),
38
+ updatedAt: this.parseDate(row.updated_at),
39
+ lockedUntil: row.locked_until ? this.parseDate(row.locked_until) : null,
40
+ });
41
+ }
42
+ async findUserById(id) {
43
+ const row = await this.db
44
+ .selectFrom('users')
45
+ .selectAll()
46
+ .where('id', '=', id)
47
+ .executeTakeFirst();
48
+ if (!row) {
49
+ return null;
50
+ }
51
+ return User.rehydrate({
52
+ id: row.id,
53
+ email: row.email,
54
+ emailVerified: this.parseBoolean(row.email_verified),
55
+ createdAt: this.parseDate(row.created_at),
56
+ updatedAt: this.parseDate(row.updated_at),
57
+ lockedUntil: row.locked_until ? this.parseDate(row.locked_until) : null,
58
+ });
59
+ }
60
+ async createUser(user) {
61
+ try {
62
+ await this.db
63
+ .insertInto('users')
64
+ .values({
65
+ id: user.id,
66
+ email: user.email,
67
+ email_verified: this.serializeBoolean(user.emailVerified),
68
+ created_at: this.serializeDate(user.createdAt),
69
+ updated_at: this.serializeDate(user.updatedAt),
70
+ locked_until: user.lockedUntil ? this.serializeDate(user.lockedUntil) : null,
71
+ })
72
+ .execute();
73
+ return ok(undefined);
74
+ }
75
+ catch (error) {
76
+ // Check for unique constraint violation across different database drivers
77
+ const isUniqueViolation = error instanceof Error &&
78
+ (('code' in error && (error.code === 'SQLITE_CONSTRAINT' || error.code === '23505')) ||
79
+ error.message?.includes('UNIQUE constraint failed') ||
80
+ error.message?.includes('duplicate key'));
81
+ if (isUniqueViolation) {
82
+ return err('EMAIL_EXISTS');
83
+ }
84
+ throw error;
85
+ }
86
+ }
87
+ async updateUser(user) {
88
+ await this.db
89
+ .updateTable('users')
90
+ .set({
91
+ email: user.email,
92
+ email_verified: this.serializeBoolean(user.emailVerified),
93
+ updated_at: this.serializeDate(user.updatedAt),
94
+ locked_until: user.lockedUntil ? this.serializeDate(user.lockedUntil) : null,
95
+ })
96
+ .where('id', '=', user.id)
97
+ .execute();
98
+ }
99
+ async findAccountByProvider(providerId, providerUserId) {
100
+ const row = await this.db
101
+ .selectFrom('accounts')
102
+ .selectAll()
103
+ .where('provider_id', '=', providerId)
104
+ .where('provider_user_id', '=', providerUserId)
105
+ .executeTakeFirst();
106
+ if (!row) {
107
+ return null;
108
+ }
109
+ return Account.rehydrate({
110
+ id: row.id,
111
+ userId: row.user_id,
112
+ providerId: row.provider_id,
113
+ providerUserId: row.provider_user_id,
114
+ passwordHash: row.password_hash,
115
+ createdAt: this.parseDate(row.created_at),
116
+ });
117
+ }
118
+ async findEmailAccountByUserId(userId) {
119
+ const row = await this.db
120
+ .selectFrom('accounts')
121
+ .selectAll()
122
+ .where('user_id', '=', userId)
123
+ .where('provider_id', '=', 'email')
124
+ .executeTakeFirst();
125
+ if (!row) {
126
+ return null;
127
+ }
128
+ return Account.rehydrate({
129
+ id: row.id,
130
+ userId: row.user_id,
131
+ providerId: row.provider_id,
132
+ providerUserId: row.provider_user_id,
133
+ passwordHash: row.password_hash,
134
+ createdAt: this.parseDate(row.created_at),
135
+ });
136
+ }
137
+ async createAccount(account) {
138
+ await this.db
139
+ .insertInto('accounts')
140
+ .values({
141
+ id: account.id,
142
+ user_id: account.userId,
143
+ provider_id: account.providerId,
144
+ provider_user_id: account.providerUserId,
145
+ password_hash: account.passwordHash,
146
+ created_at: this.serializeDate(account.createdAt),
147
+ })
148
+ .execute();
149
+ }
150
+ async findSessionByTokenHash(tokenHash) {
151
+ const row = await this.db
152
+ .selectFrom('sessions')
153
+ .selectAll()
154
+ .where('token_hash', '=', tokenHash)
155
+ .executeTakeFirst();
156
+ if (!row) {
157
+ return null;
158
+ }
159
+ return Session.rehydrate({
160
+ id: row.id,
161
+ userId: row.user_id,
162
+ tokenHash: row.token_hash,
163
+ expiresAt: this.parseDate(row.expires_at),
164
+ ipAddress: row.ip_address,
165
+ userAgent: row.user_agent,
166
+ createdAt: this.parseDate(row.created_at),
167
+ });
168
+ }
169
+ async createSession(session) {
170
+ await this.db
171
+ .insertInto('sessions')
172
+ .values({
173
+ id: session.id,
174
+ user_id: session.userId,
175
+ token_hash: session.tokenHash,
176
+ expires_at: this.serializeDate(session.expiresAt),
177
+ ip_address: session.ipAddress,
178
+ user_agent: session.userAgent,
179
+ created_at: this.serializeDate(session.createdAt),
180
+ })
181
+ .execute();
182
+ }
183
+ async deleteSession(sessionId) {
184
+ await this.db.deleteFrom('sessions').where('id', '=', sessionId).execute();
185
+ }
186
+ async deleteSessionsByUserId(userId) {
187
+ await this.db.deleteFrom('sessions').where('user_id', '=', userId).execute();
188
+ }
189
+ async recordLoginAttempt(attempt) {
190
+ await this.db
191
+ .insertInto('login_attempts')
192
+ .values({
193
+ id: attempt.id,
194
+ user_id: attempt.userId,
195
+ email: attempt.email,
196
+ ip_address: attempt.ipAddress,
197
+ success: this.serializeBoolean(attempt.success),
198
+ created_at: this.serializeDate(attempt.createdAt),
199
+ })
200
+ .execute();
201
+ }
202
+ async countRecentFailedAttempts(email, windowMs) {
203
+ const cutoffDate = new Date(Date.now() - windowMs);
204
+ // For SQLite, we need to compare as ISO string; for other DBs, use Date
205
+ const cutoffValue = this.isSqlite() ? cutoffDate.toISOString() : cutoffDate;
206
+ const result = await this.db
207
+ .selectFrom('login_attempts')
208
+ .select((eb) => eb.fn.countAll().as('count'))
209
+ .where('email', '=', email.toLowerCase())
210
+ .where('success', '=', this.serializeBoolean(false))
211
+ .where('created_at', '>=', cutoffValue)
212
+ .executeTakeFirst();
213
+ return Number(result?.count ?? 0);
214
+ }
215
+ async transaction(fn) {
216
+ return await this.db.transaction().execute(async (trx) => {
217
+ const txAdapter = new SqlAdapter(trx, {
218
+ dialect: this.dialect,
219
+ });
220
+ return await fn(txAdapter);
221
+ });
222
+ }
223
+ }
224
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export type { DatabaseDialect, SqlAdapterOptions } from './adapter.js';
2
+ export { SqlAdapter } from './adapter.js';
3
+ export { down, up } from './migrations/001_initial.js';
4
+ export type { Database } from './schema.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AACvD,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { SqlAdapter } from './adapter.js';
2
+ export { down, up } from './migrations/001_initial.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Kysely } from 'kysely';
2
+ export declare function up<T>(db: Kysely<T>): Promise<void>;
3
+ export declare function down<T>(db: Kysely<T>): Promise<void>;
4
+ //# sourceMappingURL=001_initial.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"001_initial.d.ts","sourceRoot":"","sources":["../../src/migrations/001_initial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGrC,wBAAsB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA8DxD;AAED,wBAAsB,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAK1D"}
@@ -0,0 +1,62 @@
1
+ // Generic type parameter allows any database schema since migrations only use schema builder
2
+ export async function up(db) {
3
+ await db.schema
4
+ .createTable('users')
5
+ .addColumn('id', 'text', (col) => col.primaryKey())
6
+ .addColumn('email', 'text', (col) => col.notNull().unique())
7
+ .addColumn('email_verified', 'boolean', (col) => col.notNull().defaultTo(false))
8
+ .addColumn('created_at', 'timestamp', (col) => col.notNull())
9
+ .addColumn('updated_at', 'timestamp', (col) => col.notNull())
10
+ .addColumn('locked_until', 'timestamp')
11
+ .execute();
12
+ // Note: email already has a unique constraint which creates an implicit index
13
+ await db.schema
14
+ .createTable('accounts')
15
+ .addColumn('id', 'text', (col) => col.primaryKey())
16
+ .addColumn('user_id', 'text', (col) => col.notNull().references('users.id').onDelete('cascade'))
17
+ .addColumn('provider_id', 'text', (col) => col.notNull())
18
+ .addColumn('provider_user_id', 'text', (col) => col.notNull())
19
+ .addColumn('password_hash', 'text')
20
+ .addColumn('created_at', 'timestamp', (col) => col.notNull())
21
+ .execute();
22
+ await db.schema
23
+ .createIndex('accounts_provider_idx')
24
+ .on('accounts')
25
+ .columns(['provider_id', 'provider_user_id'])
26
+ .unique()
27
+ .execute();
28
+ await db.schema.createIndex('accounts_user_id_idx').on('accounts').column('user_id').execute();
29
+ await db.schema
30
+ .createTable('sessions')
31
+ .addColumn('id', 'text', (col) => col.primaryKey())
32
+ .addColumn('user_id', 'text', (col) => col.notNull().references('users.id').onDelete('cascade'))
33
+ .addColumn('token_hash', 'text', (col) => col.notNull().unique())
34
+ .addColumn('expires_at', 'timestamp', (col) => col.notNull())
35
+ .addColumn('ip_address', 'text')
36
+ .addColumn('user_agent', 'text')
37
+ .addColumn('created_at', 'timestamp', (col) => col.notNull())
38
+ .execute();
39
+ // Note: token_hash already has a unique constraint which creates an implicit index
40
+ await db.schema.createIndex('sessions_user_id_idx').on('sessions').column('user_id').execute();
41
+ await db.schema
42
+ .createTable('login_attempts')
43
+ .addColumn('id', 'text', (col) => col.primaryKey())
44
+ .addColumn('user_id', 'text', (col) => col.references('users.id').onDelete('set null'))
45
+ .addColumn('email', 'text', (col) => col.notNull())
46
+ .addColumn('ip_address', 'text', (col) => col.notNull())
47
+ .addColumn('success', 'boolean', (col) => col.notNull())
48
+ .addColumn('created_at', 'timestamp', (col) => col.notNull())
49
+ .execute();
50
+ await db.schema
51
+ .createIndex('login_attempts_email_created_idx')
52
+ .on('login_attempts')
53
+ .columns(['email', 'created_at'])
54
+ .execute();
55
+ }
56
+ export async function down(db) {
57
+ await db.schema.dropTable('login_attempts').execute();
58
+ await db.schema.dropTable('sessions').execute();
59
+ await db.schema.dropTable('accounts').execute();
60
+ await db.schema.dropTable('users').execute();
61
+ }
62
+ //# sourceMappingURL=001_initial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"001_initial.js","sourceRoot":"","sources":["../../src/migrations/001_initial.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type { ColumnType } from 'kysely';
2
+ export interface UsersTable {
3
+ id: string;
4
+ email: string;
5
+ email_verified: number | boolean;
6
+ created_at: ColumnType<Date, Date | string, Date | string>;
7
+ updated_at: ColumnType<Date, Date | string, Date | string>;
8
+ locked_until: ColumnType<Date | null, Date | string | null, Date | string | null>;
9
+ }
10
+ export interface AccountsTable {
11
+ id: string;
12
+ user_id: string;
13
+ provider_id: string;
14
+ provider_user_id: string;
15
+ password_hash: string | null;
16
+ created_at: ColumnType<Date, Date | string, Date | string>;
17
+ }
18
+ export interface SessionsTable {
19
+ id: string;
20
+ user_id: string;
21
+ token_hash: string;
22
+ expires_at: ColumnType<Date, Date | string, Date | string>;
23
+ ip_address: string | null;
24
+ user_agent: string | null;
25
+ created_at: ColumnType<Date, Date | string, Date | string>;
26
+ }
27
+ export interface LoginAttemptsTable {
28
+ id: string;
29
+ user_id: string | null;
30
+ email: string;
31
+ ip_address: string;
32
+ success: number | boolean;
33
+ created_at: ColumnType<Date, Date | string, Date | string>;
34
+ }
35
+ export interface Database {
36
+ users: UsersTable;
37
+ accounts: AccountsTable;
38
+ sessions: SessionsTable;
39
+ login_attempts: LoginAttemptsTable;
40
+ }
41
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEzC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;IAC3D,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;IAC3D,YAAY,EAAE,UAAU,CAAC,IAAI,GAAG,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;CACnF;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;IAC3D,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,aAAa,CAAC;IACxB,cAAc,EAAE,kBAAkB,CAAC;CACpC"}
package/dist/schema.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@fortressauth/adapter-sql",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "dependencies": {
14
+ "kysely": "^0.28.8",
15
+ "@fortressauth/core": "0.1.0"
16
+ },
17
+ "devDependencies": {
18
+ "@biomejs/biome": "^2.3.8",
19
+ "@types/better-sqlite3": "^7.6.13",
20
+ "@vitest/coverage-v8": "^4.0.15",
21
+ "better-sqlite3": "^12.5.0",
22
+ "typescript": "^5.9.3",
23
+ "vitest": "^4.0.15"
24
+ },
25
+ "scripts": {
26
+ "build": "tsc",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "test:coverage": "vitest run --coverage",
30
+ "lint": "biome check .",
31
+ "typecheck": "tsc --noEmit"
32
+ }
33
+ }