@kyro-cms/core 0.1.2 → 0.1.3

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/dist/index.d.cts CHANGED
@@ -20,6 +20,7 @@ export { createHonoApp, createRESTAPI } from './rest/index.cjs';
20
20
  export { TemplateConfig, allSettingsGlobals, blogCollections, blogGlobals, coreSettingsGlobals, createTemplateConfig, ecommerceCollections, ecommerceGlobals, ecommerceSettingsGlobals, kitchenSinkCollections, mediaCollections, minimalCollections } from './templates/index.cjs';
21
21
  import Redis from 'ioredis';
22
22
  import { SentMessageInfo } from 'nodemailer';
23
+ import Database from 'better-sqlite3';
23
24
  import 'ws';
24
25
  import 'drizzle-orm/postgres-js';
25
26
  import 'postgres';
@@ -391,6 +392,47 @@ declare class RedisAuthAdapter implements AuthAdapter {
391
392
  private hashToSession;
392
393
  }
393
394
 
395
+ interface SQLiteAuthAdapterOptions {
396
+ path?: string;
397
+ db?: Database.Database;
398
+ saltRounds?: number;
399
+ }
400
+ declare class SQLiteAuthAdapter implements AuthAdapter {
401
+ private db;
402
+ private path;
403
+ private saltRounds;
404
+ private externalDb;
405
+ constructor(options?: SQLiteAuthAdapterOptions);
406
+ connect(): Promise<void>;
407
+ disconnect(): Promise<void>;
408
+ private ensureTables;
409
+ createUser(data: {
410
+ email: string;
411
+ passwordHash: string;
412
+ role?: UserRole;
413
+ tenantId?: string;
414
+ }): Promise<AuthUser>;
415
+ findUserByEmail(email: string): Promise<AuthUser | null>;
416
+ findUserById(userId: string): Promise<AuthUser | null>;
417
+ updateUser(userId: string, data: Partial<AuthUser>): Promise<AuthUser | null>;
418
+ deleteUser(userId: string): Promise<boolean>;
419
+ hashPassword(password: string): Promise<string>;
420
+ verifyPassword(password: string, hash: string): Promise<boolean>;
421
+ createSession(userId: string, data?: {
422
+ ipAddress?: string;
423
+ userAgent?: string;
424
+ }): Promise<Session>;
425
+ findSessionByToken(token: string): Promise<Session | null>;
426
+ findSessionByRefreshToken(refreshToken: string): Promise<Session | null>;
427
+ deleteSession(sessionId: string): Promise<boolean>;
428
+ deleteUserSessions(userId: string): Promise<number>;
429
+ hasAnyUsers(): Promise<boolean>;
430
+ addPasswordToHistory(userId: string, passwordHash: string): Promise<void>;
431
+ getPasswordHistory(userId: string, count?: number): Promise<string[]>;
432
+ private rowToUser;
433
+ private rowToSession;
434
+ }
435
+
394
436
  interface EmailConfig {
395
437
  host: string;
396
438
  port: number;
@@ -836,4 +878,4 @@ declare function defineConfig(config: {
836
878
  debug?: KyroConfig["debug"];
837
879
  }): KyroConfig;
838
880
 
839
- export { AbstractBaseAdapter, AccountLockout, type AdapterOptions, type AdminStylingConfig, AnalyticsPlugin, type AuditAction, type AuditLog, type AuditLogFilter, AuditLogger, Auth, AuthAdapter, AuthResult, Session as AuthSession, AuthTokenConfig, AuthUser, BaseAdapter, CSSGenerator, CollectionConfig, CommentsPlugin, type CompareVersionsOptions, ConfigValidationError, CreateArgs, type CreateVersionOptions, type DatabaseConnectionOptions, type DatabaseType, DeleteArgs, type DraftPublishConfig, type DrizzleAdapterOptions, EmailTransport, Field, type FieldStyling, FindArgs, FindByIDArgs, FindResult, GlobalConfig, Hook, JWTPayload, Kyro, type KyroAuthConfig, KyroConfig, KyroPlugin, KyroPubSub, KyroWSServer, LocalAdapter, LoginCredentials, type MongoDBAdapterOptions, PasswordPolicy, type PluginAPI, type PluginHooks, PluginManager, type PublishVersionOptions, RateLimiter, RedisAuthAdapter, RegisterData, Registry, Request$1 as Request, ReviewsPlugin, SEOPLugin, type StylingConfig, type StylingMode, type ThemeBorderRadius, type ThemeColors, type ThemeConfig, type ThemeFonts, type ThemeShadows, type ThemeSpacing, UpdateArgs, User, UserRole, type Version, type VersionAdapter, type VersionDiff, type VersionHistoryOptions, VersionManager, type VersionPublishSchedule, type VersionStatus, WishlistPlugin, authConfig, autoBootstrap, bootstrapAdmin, collectionToCreateZod, collectionToUpdateZod, collectionToWhereZod, collectionToZod, createAdminStyling, createAuditContext, createAuth, createAuthConfig, createKyro, createLocalAdapter, createVersionManager, defaultDarkTheme, defaultFieldStyling, defaultLightTheme, defineConfig, ecommerce2026Theme, fieldToZod, generateCSSVariables, generateTailwindConfig, getBootstrapFromEnv, getDefaultDraftPublishConfig, globalToZod, isArchived, isDraft, isPublished, presetPlugins, validateCollection, validateConfig, validateFields, validateGlobal };
881
+ export { AbstractBaseAdapter, AccountLockout, type AdapterOptions, type AdminStylingConfig, AnalyticsPlugin, type AuditAction, type AuditLog, type AuditLogFilter, AuditLogger, Auth, AuthAdapter, AuthResult, Session as AuthSession, AuthTokenConfig, AuthUser, BaseAdapter, CSSGenerator, CollectionConfig, CommentsPlugin, type CompareVersionsOptions, ConfigValidationError, CreateArgs, type CreateVersionOptions, type DatabaseConnectionOptions, type DatabaseType, DeleteArgs, type DraftPublishConfig, type DrizzleAdapterOptions, EmailTransport, Field, type FieldStyling, FindArgs, FindByIDArgs, FindResult, GlobalConfig, Hook, JWTPayload, Kyro, type KyroAuthConfig, KyroConfig, KyroPlugin, KyroPubSub, KyroWSServer, LocalAdapter, LoginCredentials, type MongoDBAdapterOptions, PasswordPolicy, type PluginAPI, type PluginHooks, PluginManager, type PublishVersionOptions, RateLimiter, RedisAuthAdapter, RegisterData, Registry, Request$1 as Request, ReviewsPlugin, SEOPLugin, SQLiteAuthAdapter, type StylingConfig, type StylingMode, type ThemeBorderRadius, type ThemeColors, type ThemeConfig, type ThemeFonts, type ThemeShadows, type ThemeSpacing, UpdateArgs, User, UserRole, type Version, type VersionAdapter, type VersionDiff, type VersionHistoryOptions, VersionManager, type VersionPublishSchedule, type VersionStatus, WishlistPlugin, authConfig, autoBootstrap, bootstrapAdmin, collectionToCreateZod, collectionToUpdateZod, collectionToWhereZod, collectionToZod, createAdminStyling, createAuditContext, createAuth, createAuthConfig, createKyro, createLocalAdapter, createVersionManager, defaultDarkTheme, defaultFieldStyling, defaultLightTheme, defineConfig, ecommerce2026Theme, fieldToZod, generateCSSVariables, generateTailwindConfig, getBootstrapFromEnv, getDefaultDraftPublishConfig, globalToZod, isArchived, isDraft, isPublished, presetPlugins, validateCollection, validateConfig, validateFields, validateGlobal };
package/dist/index.d.ts CHANGED
@@ -20,6 +20,7 @@ export { createHonoApp, createRESTAPI } from './rest/index.js';
20
20
  export { TemplateConfig, allSettingsGlobals, blogCollections, blogGlobals, coreSettingsGlobals, createTemplateConfig, ecommerceCollections, ecommerceGlobals, ecommerceSettingsGlobals, kitchenSinkCollections, mediaCollections, minimalCollections } from './templates/index.js';
21
21
  import Redis from 'ioredis';
22
22
  import { SentMessageInfo } from 'nodemailer';
23
+ import Database from 'better-sqlite3';
23
24
  import 'ws';
24
25
  import 'drizzle-orm/postgres-js';
25
26
  import 'postgres';
@@ -391,6 +392,47 @@ declare class RedisAuthAdapter implements AuthAdapter {
391
392
  private hashToSession;
392
393
  }
393
394
 
395
+ interface SQLiteAuthAdapterOptions {
396
+ path?: string;
397
+ db?: Database.Database;
398
+ saltRounds?: number;
399
+ }
400
+ declare class SQLiteAuthAdapter implements AuthAdapter {
401
+ private db;
402
+ private path;
403
+ private saltRounds;
404
+ private externalDb;
405
+ constructor(options?: SQLiteAuthAdapterOptions);
406
+ connect(): Promise<void>;
407
+ disconnect(): Promise<void>;
408
+ private ensureTables;
409
+ createUser(data: {
410
+ email: string;
411
+ passwordHash: string;
412
+ role?: UserRole;
413
+ tenantId?: string;
414
+ }): Promise<AuthUser>;
415
+ findUserByEmail(email: string): Promise<AuthUser | null>;
416
+ findUserById(userId: string): Promise<AuthUser | null>;
417
+ updateUser(userId: string, data: Partial<AuthUser>): Promise<AuthUser | null>;
418
+ deleteUser(userId: string): Promise<boolean>;
419
+ hashPassword(password: string): Promise<string>;
420
+ verifyPassword(password: string, hash: string): Promise<boolean>;
421
+ createSession(userId: string, data?: {
422
+ ipAddress?: string;
423
+ userAgent?: string;
424
+ }): Promise<Session>;
425
+ findSessionByToken(token: string): Promise<Session | null>;
426
+ findSessionByRefreshToken(refreshToken: string): Promise<Session | null>;
427
+ deleteSession(sessionId: string): Promise<boolean>;
428
+ deleteUserSessions(userId: string): Promise<number>;
429
+ hasAnyUsers(): Promise<boolean>;
430
+ addPasswordToHistory(userId: string, passwordHash: string): Promise<void>;
431
+ getPasswordHistory(userId: string, count?: number): Promise<string[]>;
432
+ private rowToUser;
433
+ private rowToSession;
434
+ }
435
+
394
436
  interface EmailConfig {
395
437
  host: string;
396
438
  port: number;
@@ -836,4 +878,4 @@ declare function defineConfig(config: {
836
878
  debug?: KyroConfig["debug"];
837
879
  }): KyroConfig;
838
880
 
839
- export { AbstractBaseAdapter, AccountLockout, type AdapterOptions, type AdminStylingConfig, AnalyticsPlugin, type AuditAction, type AuditLog, type AuditLogFilter, AuditLogger, Auth, AuthAdapter, AuthResult, Session as AuthSession, AuthTokenConfig, AuthUser, BaseAdapter, CSSGenerator, CollectionConfig, CommentsPlugin, type CompareVersionsOptions, ConfigValidationError, CreateArgs, type CreateVersionOptions, type DatabaseConnectionOptions, type DatabaseType, DeleteArgs, type DraftPublishConfig, type DrizzleAdapterOptions, EmailTransport, Field, type FieldStyling, FindArgs, FindByIDArgs, FindResult, GlobalConfig, Hook, JWTPayload, Kyro, type KyroAuthConfig, KyroConfig, KyroPlugin, KyroPubSub, KyroWSServer, LocalAdapter, LoginCredentials, type MongoDBAdapterOptions, PasswordPolicy, type PluginAPI, type PluginHooks, PluginManager, type PublishVersionOptions, RateLimiter, RedisAuthAdapter, RegisterData, Registry, Request$1 as Request, ReviewsPlugin, SEOPLugin, type StylingConfig, type StylingMode, type ThemeBorderRadius, type ThemeColors, type ThemeConfig, type ThemeFonts, type ThemeShadows, type ThemeSpacing, UpdateArgs, User, UserRole, type Version, type VersionAdapter, type VersionDiff, type VersionHistoryOptions, VersionManager, type VersionPublishSchedule, type VersionStatus, WishlistPlugin, authConfig, autoBootstrap, bootstrapAdmin, collectionToCreateZod, collectionToUpdateZod, collectionToWhereZod, collectionToZod, createAdminStyling, createAuditContext, createAuth, createAuthConfig, createKyro, createLocalAdapter, createVersionManager, defaultDarkTheme, defaultFieldStyling, defaultLightTheme, defineConfig, ecommerce2026Theme, fieldToZod, generateCSSVariables, generateTailwindConfig, getBootstrapFromEnv, getDefaultDraftPublishConfig, globalToZod, isArchived, isDraft, isPublished, presetPlugins, validateCollection, validateConfig, validateFields, validateGlobal };
881
+ export { AbstractBaseAdapter, AccountLockout, type AdapterOptions, type AdminStylingConfig, AnalyticsPlugin, type AuditAction, type AuditLog, type AuditLogFilter, AuditLogger, Auth, AuthAdapter, AuthResult, Session as AuthSession, AuthTokenConfig, AuthUser, BaseAdapter, CSSGenerator, CollectionConfig, CommentsPlugin, type CompareVersionsOptions, ConfigValidationError, CreateArgs, type CreateVersionOptions, type DatabaseConnectionOptions, type DatabaseType, DeleteArgs, type DraftPublishConfig, type DrizzleAdapterOptions, EmailTransport, Field, type FieldStyling, FindArgs, FindByIDArgs, FindResult, GlobalConfig, Hook, JWTPayload, Kyro, type KyroAuthConfig, KyroConfig, KyroPlugin, KyroPubSub, KyroWSServer, LocalAdapter, LoginCredentials, type MongoDBAdapterOptions, PasswordPolicy, type PluginAPI, type PluginHooks, PluginManager, type PublishVersionOptions, RateLimiter, RedisAuthAdapter, RegisterData, Registry, Request$1 as Request, ReviewsPlugin, SEOPLugin, SQLiteAuthAdapter, type StylingConfig, type StylingMode, type ThemeBorderRadius, type ThemeColors, type ThemeConfig, type ThemeFonts, type ThemeShadows, type ThemeSpacing, UpdateArgs, User, UserRole, type Version, type VersionAdapter, type VersionDiff, type VersionHistoryOptions, VersionManager, type VersionPublishSchedule, type VersionStatus, WishlistPlugin, authConfig, autoBootstrap, bootstrapAdmin, collectionToCreateZod, collectionToUpdateZod, collectionToWhereZod, collectionToZod, createAdminStyling, createAuditContext, createAuth, createAuthConfig, createKyro, createLocalAdapter, createVersionManager, defaultDarkTheme, defaultFieldStyling, defaultLightTheme, defineConfig, ecommerce2026Theme, fieldToZod, generateCSSVariables, generateTailwindConfig, getBootstrapFromEnv, getDefaultDraftPublishConfig, globalToZod, isArchived, isDraft, isPublished, presetPlugins, validateCollection, validateConfig, validateFields, validateGlobal };
package/dist/index.js CHANGED
@@ -20,8 +20,9 @@ export { AbstractBaseAdapter } from './chunk-BXMWDUED.js';
20
20
  import './chunk-PZ5AY32C.js';
21
21
  import { z } from 'zod';
22
22
  export { z } from 'zod';
23
- import bcrypt from 'bcrypt';
23
+ import bcrypt2 from 'bcrypt';
24
24
  import jwt2 from 'jsonwebtoken';
25
+ import bcrypt from 'bcryptjs';
25
26
  import { randomBytes } from 'crypto';
26
27
 
27
28
  // src/registry/validator.ts
@@ -1999,6 +2000,277 @@ var defaultFieldStyling = {
1999
2000
  }
2000
2001
  }
2001
2002
  };
2003
+ var SQLiteAuthAdapter = class {
2004
+ db = null;
2005
+ path;
2006
+ saltRounds;
2007
+ externalDb;
2008
+ constructor(options = {}) {
2009
+ this.path = options.path || "./data.db";
2010
+ this.saltRounds = options.saltRounds || 12;
2011
+ this.externalDb = !!options.db;
2012
+ if (options.db) {
2013
+ this.db = options.db;
2014
+ }
2015
+ }
2016
+ async connect() {
2017
+ if (this.db) return;
2018
+ const Database = (await import('better-sqlite3')).default;
2019
+ this.db = new Database(this.path);
2020
+ this.db.pragma("journal_mode = WAL");
2021
+ this.db.pragma("foreign_keys = ON");
2022
+ this.ensureTables();
2023
+ }
2024
+ async disconnect() {
2025
+ if (this.db && !this.externalDb) {
2026
+ this.db.close();
2027
+ this.db = null;
2028
+ }
2029
+ }
2030
+ ensureTables() {
2031
+ if (!this.db) return;
2032
+ this.db.exec(`
2033
+ CREATE TABLE IF NOT EXISTS kyro_users (
2034
+ id TEXT PRIMARY KEY,
2035
+ email TEXT UNIQUE NOT NULL,
2036
+ password_hash TEXT NOT NULL,
2037
+ role TEXT NOT NULL DEFAULT 'customer',
2038
+ tenant_id TEXT,
2039
+ email_verified INTEGER DEFAULT 0,
2040
+ locked INTEGER DEFAULT 0,
2041
+ last_login TEXT,
2042
+ failed_login_attempts INTEGER DEFAULT 0,
2043
+ locked_until TEXT,
2044
+ created_at TEXT NOT NULL,
2045
+ updated_at TEXT NOT NULL
2046
+ );
2047
+
2048
+ CREATE TABLE IF NOT EXISTS kyro_sessions (
2049
+ id TEXT PRIMARY KEY,
2050
+ user_id TEXT NOT NULL,
2051
+ token TEXT NOT NULL,
2052
+ refresh_token TEXT,
2053
+ expires_at TEXT NOT NULL,
2054
+ created_at TEXT NOT NULL,
2055
+ ip_address TEXT,
2056
+ user_agent TEXT,
2057
+ FOREIGN KEY (user_id) REFERENCES kyro_users(id) ON DELETE CASCADE
2058
+ );
2059
+
2060
+ CREATE TABLE IF NOT EXISTS kyro_password_history (
2061
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
2062
+ user_id TEXT NOT NULL,
2063
+ password_hash TEXT NOT NULL,
2064
+ created_at TEXT NOT NULL,
2065
+ FOREIGN KEY (user_id) REFERENCES kyro_users(id) ON DELETE CASCADE
2066
+ );
2067
+
2068
+ CREATE INDEX IF NOT EXISTS idx_kyro_users_email ON kyro_users(email);
2069
+ CREATE INDEX IF NOT EXISTS idx_kyro_sessions_user_id ON kyro_sessions(user_id);
2070
+ CREATE INDEX IF NOT EXISTS idx_kyro_sessions_token ON kyro_sessions(token);
2071
+ CREATE INDEX IF NOT EXISTS idx_kyro_sessions_refresh_token ON kyro_sessions(refresh_token);
2072
+ CREATE INDEX IF NOT EXISTS idx_kyro_password_history_user_id ON kyro_password_history(user_id);
2073
+ `);
2074
+ }
2075
+ async createUser(data) {
2076
+ if (!this.db) throw new Error("Not connected");
2077
+ const id = randomBytes(16).toString("hex");
2078
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2079
+ const user = {
2080
+ id,
2081
+ email: data.email.toLowerCase(),
2082
+ passwordHash: data.passwordHash,
2083
+ role: data.role || "customer",
2084
+ tenantId: data.tenantId,
2085
+ createdAt: now,
2086
+ updatedAt: now
2087
+ };
2088
+ this.db.prepare(
2089
+ `INSERT INTO kyro_users (id, email, password_hash, role, tenant_id, created_at, updated_at)
2090
+ VALUES (?, ?, ?, ?, ?, ?, ?)`
2091
+ ).run(
2092
+ id,
2093
+ user.email,
2094
+ user.passwordHash,
2095
+ user.role,
2096
+ user.tenantId,
2097
+ now,
2098
+ now
2099
+ );
2100
+ return user;
2101
+ }
2102
+ async findUserByEmail(email) {
2103
+ if (!this.db) throw new Error("Not connected");
2104
+ const row = this.db.prepare("SELECT * FROM kyro_users WHERE email = ?").get(email.toLowerCase());
2105
+ if (!row) return null;
2106
+ return this.rowToUser(row);
2107
+ }
2108
+ async findUserById(userId) {
2109
+ if (!this.db) throw new Error("Not connected");
2110
+ const row = this.db.prepare("SELECT * FROM kyro_users WHERE id = ?").get(userId);
2111
+ if (!row) return null;
2112
+ return this.rowToUser(row);
2113
+ }
2114
+ async updateUser(userId, data) {
2115
+ if (!this.db) throw new Error("Not connected");
2116
+ const existing = await this.findUserById(userId);
2117
+ if (!existing) return null;
2118
+ const updates = [];
2119
+ const values = [];
2120
+ if (data.email !== void 0) {
2121
+ updates.push("email = ?");
2122
+ values.push(data.email.toLowerCase());
2123
+ }
2124
+ if (data.passwordHash !== void 0) {
2125
+ updates.push("password_hash = ?");
2126
+ values.push(data.passwordHash);
2127
+ }
2128
+ if (data.role !== void 0) {
2129
+ updates.push("role = ?");
2130
+ values.push(data.role);
2131
+ }
2132
+ if (data.tenantId !== void 0) {
2133
+ updates.push("tenant_id = ?");
2134
+ values.push(data.tenantId);
2135
+ }
2136
+ if (data.emailVerified !== void 0) {
2137
+ updates.push("email_verified = ?");
2138
+ values.push(data.emailVerified ? 1 : 0);
2139
+ }
2140
+ if (data.locked !== void 0) {
2141
+ updates.push("locked = ?");
2142
+ values.push(data.locked ? 1 : 0);
2143
+ }
2144
+ if (data.lastLogin !== void 0) {
2145
+ updates.push("last_login = ?");
2146
+ values.push(data.lastLogin);
2147
+ }
2148
+ if (data.failedLoginAttempts !== void 0) {
2149
+ updates.push("failed_login_attempts = ?");
2150
+ values.push(data.failedLoginAttempts);
2151
+ }
2152
+ updates.push("updated_at = ?");
2153
+ values.push((/* @__PURE__ */ new Date()).toISOString());
2154
+ values.push(userId);
2155
+ this.db.prepare(`UPDATE kyro_users SET ${updates.join(", ")} WHERE id = ?`).run(...values);
2156
+ return this.findUserById(userId);
2157
+ }
2158
+ async deleteUser(userId) {
2159
+ if (!this.db) throw new Error("Not connected");
2160
+ const result = this.db.prepare("DELETE FROM kyro_users WHERE id = ?").run(userId);
2161
+ return result.changes > 0;
2162
+ }
2163
+ async hashPassword(password) {
2164
+ return bcrypt.hash(password, this.saltRounds);
2165
+ }
2166
+ async verifyPassword(password, hash) {
2167
+ return bcrypt.compare(password, hash);
2168
+ }
2169
+ async createSession(userId, data = {}) {
2170
+ if (!this.db) throw new Error("Not connected");
2171
+ const id = randomBytes(32).toString("hex");
2172
+ const token = randomBytes(32).toString("base64url");
2173
+ const refreshToken = randomBytes(32).toString("base64url");
2174
+ const now = /* @__PURE__ */ new Date();
2175
+ const expiresAt = new Date(now.getTime() + 864e5).toISOString();
2176
+ const session = {
2177
+ id,
2178
+ userId,
2179
+ token,
2180
+ refreshToken,
2181
+ expiresAt,
2182
+ createdAt: now.toISOString(),
2183
+ ipAddress: data.ipAddress,
2184
+ userAgent: data.userAgent
2185
+ };
2186
+ this.db.prepare(
2187
+ `INSERT INTO kyro_sessions (id, user_id, token, refresh_token, expires_at, created_at, ip_address, user_agent)
2188
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
2189
+ ).run(
2190
+ session.id,
2191
+ session.userId,
2192
+ session.token,
2193
+ session.refreshToken,
2194
+ session.expiresAt,
2195
+ session.createdAt,
2196
+ session.ipAddress,
2197
+ session.userAgent
2198
+ );
2199
+ return session;
2200
+ }
2201
+ async findSessionByToken(token) {
2202
+ if (!this.db) throw new Error("Not connected");
2203
+ const row = this.db.prepare("SELECT * FROM kyro_sessions WHERE token = ?").get(token);
2204
+ if (!row) return null;
2205
+ return this.rowToSession(row);
2206
+ }
2207
+ async findSessionByRefreshToken(refreshToken) {
2208
+ if (!this.db) throw new Error("Not connected");
2209
+ const row = this.db.prepare("SELECT * FROM kyro_sessions WHERE refresh_token = ?").get(refreshToken);
2210
+ if (!row) return null;
2211
+ return this.rowToSession(row);
2212
+ }
2213
+ async deleteSession(sessionId) {
2214
+ if (!this.db) throw new Error("Not connected");
2215
+ const result = this.db.prepare("DELETE FROM kyro_sessions WHERE id = ? OR token = ?").run(sessionId, sessionId);
2216
+ return result.changes > 0;
2217
+ }
2218
+ async deleteUserSessions(userId) {
2219
+ if (!this.db) throw new Error("Not connected");
2220
+ const result = this.db.prepare("DELETE FROM kyro_sessions WHERE user_id = ?").run(userId);
2221
+ return result.changes;
2222
+ }
2223
+ async hasAnyUsers() {
2224
+ if (!this.db) throw new Error("Not connected");
2225
+ const row = this.db.prepare("SELECT COUNT(*) as count FROM kyro_users").get();
2226
+ return row.count > 0;
2227
+ }
2228
+ async addPasswordToHistory(userId, passwordHash) {
2229
+ if (!this.db) throw new Error("Not connected");
2230
+ this.db.prepare(
2231
+ "INSERT INTO kyro_password_history (user_id, password_hash, created_at) VALUES (?, ?, ?)"
2232
+ ).run(userId, passwordHash, (/* @__PURE__ */ new Date()).toISOString());
2233
+ this.db.prepare(
2234
+ `DELETE FROM kyro_password_history WHERE id IN (
2235
+ SELECT id FROM kyro_password_history WHERE user_id = ? ORDER BY created_at DESC LIMIT -1 OFFSET 5
2236
+ )`
2237
+ ).run(userId);
2238
+ }
2239
+ async getPasswordHistory(userId, count = 5) {
2240
+ if (!this.db) throw new Error("Not connected");
2241
+ const rows = this.db.prepare(
2242
+ "SELECT password_hash FROM kyro_password_history WHERE user_id = ? ORDER BY created_at DESC LIMIT ?"
2243
+ ).all(userId, count);
2244
+ return rows.map((r) => r.password_hash);
2245
+ }
2246
+ rowToUser(row) {
2247
+ return {
2248
+ id: row.id,
2249
+ email: row.email,
2250
+ passwordHash: row.password_hash,
2251
+ role: row.role,
2252
+ tenantId: row.tenant_id,
2253
+ emailVerified: row.email_verified === 1,
2254
+ locked: row.locked === 1,
2255
+ lastLogin: row.last_login,
2256
+ failedLoginAttempts: row.failed_login_attempts || 0,
2257
+ createdAt: row.created_at,
2258
+ updatedAt: row.updated_at
2259
+ };
2260
+ }
2261
+ rowToSession(row) {
2262
+ return {
2263
+ id: row.id,
2264
+ userId: row.user_id,
2265
+ token: row.token,
2266
+ refreshToken: row.refresh_token,
2267
+ expiresAt: row.expires_at,
2268
+ createdAt: row.created_at,
2269
+ ipAddress: row.ip_address,
2270
+ userAgent: row.user_agent
2271
+ };
2272
+ }
2273
+ };
2002
2274
 
2003
2275
  // src/auth/security/lockout.ts
2004
2276
  var DEFAULT_LOCKOUT_CONFIG = {
@@ -3218,7 +3490,7 @@ var Auth = class {
3218
3490
  return jwt2.sign(payload, this.config.secret, signOptions);
3219
3491
  }
3220
3492
  async hashPassword(password) {
3221
- return bcrypt.hash(password, this.config.saltRounds);
3493
+ return bcrypt2.hash(password, this.config.saltRounds);
3222
3494
  }
3223
3495
  parseExpiresIn(value) {
3224
3496
  if (typeof value === "number") return value;
@@ -3419,6 +3691,6 @@ function defineConfig(config) {
3419
3691
  };
3420
3692
  }
3421
3693
 
3422
- export { ALL_FIELD_TYPES, AccountLockout, AnalyticsPlugin, AuditLogger, Auth, COMPLEX_FIELD_TYPES, CSSGenerator, CommentsPlugin, ConfigValidationError, Kyro, KyroPlugin, LAYOUT_FIELD_TYPES, LocalAdapter, PRIMITIVE_FIELD_TYPES, PluginManager, RELATIONAL_FIELD_TYPES, RateLimiter, Registry, ReviewsPlugin, SEOPLugin, VersionManager, WishlistPlugin, authConfig, collectionToCreateZod, collectionToUpdateZod, collectionToWhereZod, collectionToZod, createAdminStyling, createAuditContext, createAuth, createAuthConfig, createKyro, createLocalAdapter, createRegistry, createVersionManager, defaultDarkTheme, defaultFieldStyling, defaultLightTheme, defineConfig, ecommerce2026Theme, fieldToZod, generateCSSVariables, generateTailwindConfig, getDefaultDraftPublishConfig, getRegistry, globalToZod, isArchived, isArrayField, isBlocksField, isDraft, isGroupField, isLayoutField, isNumberField, isPublished, isRelationshipField, isRichTextField, isSelectField, isTextField, isUploadField, presetPlugins, resetRegistry, runFieldHooks, runHooks, validateCollection, validateConfig, validateFields, validateGlobal };
3694
+ export { ALL_FIELD_TYPES, AccountLockout, AnalyticsPlugin, AuditLogger, Auth, COMPLEX_FIELD_TYPES, CSSGenerator, CommentsPlugin, ConfigValidationError, Kyro, KyroPlugin, LAYOUT_FIELD_TYPES, LocalAdapter, PRIMITIVE_FIELD_TYPES, PluginManager, RELATIONAL_FIELD_TYPES, RateLimiter, Registry, ReviewsPlugin, SEOPLugin, SQLiteAuthAdapter, VersionManager, WishlistPlugin, authConfig, collectionToCreateZod, collectionToUpdateZod, collectionToWhereZod, collectionToZod, createAdminStyling, createAuditContext, createAuth, createAuthConfig, createKyro, createLocalAdapter, createRegistry, createVersionManager, defaultDarkTheme, defaultFieldStyling, defaultLightTheme, defineConfig, ecommerce2026Theme, fieldToZod, generateCSSVariables, generateTailwindConfig, getDefaultDraftPublishConfig, getRegistry, globalToZod, isArchived, isArrayField, isBlocksField, isDraft, isGroupField, isLayoutField, isNumberField, isPublished, isRelationshipField, isRichTextField, isSelectField, isTextField, isUploadField, presetPlugins, resetRegistry, runFieldHooks, runHooks, validateCollection, validateConfig, validateFields, validateGlobal };
3423
3695
  //# sourceMappingURL=index.js.map
3424
3696
  //# sourceMappingURL=index.js.map