@factiii/auth 0.5.3 → 0.5.4

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/bin/init.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync } from 'node:fs';
3
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
4
4
  import { dirname, join, resolve } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
6
 
@@ -17,21 +17,215 @@ function printHelp() {
17
17
  @factiii/auth CLI
18
18
 
19
19
  Usage:
20
- npx @factiii/auth <command>
20
+ npx @factiii/auth <command> [--prisma | --drizzle]
21
21
 
22
22
  Commands:
23
- init Copy the reference Prisma schema to your project
23
+ init Generate the auth schema for your ORM (auto-detected)
24
24
  schema Print the schema path (for manual copying)
25
25
  doctor Check your project setup for common issues
26
26
  help Show this help message
27
27
 
28
+ Flags:
29
+ --prisma Force Prisma mode (skip auto-detection)
30
+ --drizzle Force Drizzle mode (skip auto-detection)
31
+
28
32
  Examples:
29
- npx @factiii/auth init
33
+ npx @factiii/auth init # auto-detects your ORM
34
+ npx @factiii/auth init --drizzle # force Drizzle schema
30
35
  npx @factiii/auth doctor
31
36
  `);
32
37
  }
33
38
 
34
- function init() {
39
+ /**
40
+ * Read package.json deps and detect ORM.
41
+ * Returns 'prisma' | 'drizzle' | 'both' | 'none'.
42
+ */
43
+ function detectORMFromPackageJson() {
44
+ const packageJsonPath = resolve(process.cwd(), 'package.json');
45
+ if (!existsSync(packageJsonPath)) return 'none';
46
+ try {
47
+ const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
48
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
49
+ return detectORM(deps);
50
+ } catch {
51
+ return 'none';
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Resolve which ORM to use for init, considering CLI flags and auto-detection.
57
+ */
58
+ function resolveORMForInit() {
59
+ if (args.includes('--prisma')) return 'prisma';
60
+ if (args.includes('--drizzle')) return 'drizzle';
61
+
62
+ const detected = detectORMFromPackageJson();
63
+
64
+ if (detected === 'both') {
65
+ console.log('Both @prisma/client and drizzle-orm detected.');
66
+ console.log('Use --prisma or --drizzle to specify which schema to generate:');
67
+ console.log(' npx @factiii/auth init --prisma');
68
+ console.log(' npx @factiii/auth init --drizzle');
69
+ process.exit(1);
70
+ }
71
+
72
+ if (detected === 'none') {
73
+ console.log('No ORM detected in package.json.');
74
+ console.log('Install one first, or use a flag to force:');
75
+ console.log(' npm install @prisma/client prisma # then: npx @factiii/auth init');
76
+ console.log(' npm install drizzle-orm # then: npx @factiii/auth init');
77
+ console.log(' npx @factiii/auth init --prisma # force without installing first');
78
+ console.log(' npx @factiii/auth init --drizzle # force without installing first');
79
+ process.exit(1);
80
+ }
81
+
82
+ return detected; // 'prisma' or 'drizzle'
83
+ }
84
+
85
+ // ── Drizzle schema template ─────────────────────────────────────────────────
86
+
87
+ const DRIZZLE_SCHEMA_TEMPLATE = `import { pgTable, pgEnum, serial, text, integer, boolean, timestamp, uniqueIndex } from 'drizzle-orm/pg-core';
88
+ import { relations } from 'drizzle-orm';
89
+
90
+ // ==============================================================================
91
+ // Enums
92
+ // ==============================================================================
93
+
94
+ export const userStatusEnum = pgEnum('UserStatus', ['ACTIVE', 'DEACTIVATED', 'BANNED']);
95
+ export const userTagEnum = pgEnum('UserTag', ['HUMAN', 'BOT']);
96
+ export const emailVerificationStatusEnum = pgEnum('EmailVerificationStatus', ['UNVERIFIED', 'PENDING', 'VERIFIED']);
97
+ export const oauthProviderEnum = pgEnum('OAuthProvider', ['GOOGLE', 'APPLE']);
98
+
99
+ // ==============================================================================
100
+ // Users
101
+ // ==============================================================================
102
+
103
+ export const users = pgTable('User', {
104
+ id: serial('id').primaryKey(),
105
+ createdAt: timestamp('createdAt').defaultNow().notNull(),
106
+ status: userStatusEnum('status').default('ACTIVE').notNull(),
107
+ email: text('email').unique().notNull(),
108
+ emailVerificationStatus: emailVerificationStatusEnum('emailVerificationStatus').default('UNVERIFIED').notNull(),
109
+ password: text('password'),
110
+ username: text('username').unique().notNull(),
111
+ twoFaEnabled: boolean('twoFaEnabled').default(false).notNull(),
112
+ oauthProvider: oauthProviderEnum('oauthProvider'),
113
+ oauthId: text('oauthId'),
114
+ tag: userTagEnum('tag').default('HUMAN').notNull(),
115
+ isActive: boolean('isActive').default(false).notNull(),
116
+ verifiedHumanAt: timestamp('verifiedHumanAt'),
117
+ otpForEmailVerification: text('otpForEmailVerification'),
118
+ });
119
+
120
+ // ==============================================================================
121
+ // Sessions
122
+ // ==============================================================================
123
+
124
+ export const sessions = pgTable('Session', {
125
+ id: serial('id').primaryKey(),
126
+ socketId: text('socketId').unique(),
127
+ twoFaSecret: text('twoFaSecret').unique(),
128
+ issuedAt: timestamp('issuedAt').defaultNow().notNull(),
129
+ browserName: text('browserName').default('Unknown').notNull(),
130
+ lastUsed: timestamp('lastUsed').defaultNow().notNull(),
131
+ deviceId: integer('deviceId').references(() => devices.id),
132
+ userId: integer('userId').references(() => users.id, { onDelete: 'cascade' }).notNull(),
133
+ revokedAt: timestamp('revokedAt'),
134
+ });
135
+
136
+ // ==============================================================================
137
+ // Admins
138
+ // ==============================================================================
139
+
140
+ export const admins = pgTable('Admin', {
141
+ userId: integer('userId').primaryKey().references(() => users.id, { onDelete: 'cascade' }),
142
+ ip: text('ip').notNull(),
143
+ });
144
+
145
+ // ==============================================================================
146
+ // Password Resets
147
+ // ==============================================================================
148
+
149
+ export const passwordResets = pgTable('PasswordReset', {
150
+ id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
151
+ createdAt: timestamp('createdAt').defaultNow().notNull(),
152
+ userId: integer('userId').references(() => users.id, { onDelete: 'cascade' }).notNull(),
153
+ invalidatedAt: timestamp('invalidatedAt'),
154
+ });
155
+
156
+ // ==============================================================================
157
+ // OTPs
158
+ // ==============================================================================
159
+
160
+ export const otps = pgTable('OTP', {
161
+ id: serial('id').primaryKey(),
162
+ code: integer('code').notNull(),
163
+ expiresAt: timestamp('expiresAt').notNull(),
164
+ userId: integer('userId').references(() => users.id, { onDelete: 'cascade' }).notNull(),
165
+ });
166
+
167
+ // ==============================================================================
168
+ // Devices
169
+ // ==============================================================================
170
+
171
+ export const devices = pgTable('Device', {
172
+ id: serial('id').primaryKey(),
173
+ pushToken: text('pushToken').unique().notNull(),
174
+ createdAt: timestamp('createdAt').defaultNow().notNull(),
175
+ });
176
+
177
+ // ==============================================================================
178
+ // Join Tables (many-to-many)
179
+ // ==============================================================================
180
+
181
+ export const devicesToUsers = pgTable('_devices', {
182
+ deviceId: integer('A').references(() => devices.id, { onDelete: 'cascade' }).notNull(),
183
+ userId: integer('B').references(() => users.id, { onDelete: 'cascade' }).notNull(),
184
+ });
185
+
186
+ // ==============================================================================
187
+ // Relations
188
+ // ==============================================================================
189
+
190
+ export const usersRelations = relations(users, ({ many, one }) => ({
191
+ sessions: many(sessions),
192
+ passwordResets: many(passwordResets),
193
+ otps: many(otps),
194
+ devices: many(devicesToUsers),
195
+ admin: one(admins),
196
+ }));
197
+
198
+ export const sessionsRelations = relations(sessions, ({ one }) => ({
199
+ user: one(users, { fields: [sessions.userId], references: [users.id] }),
200
+ device: one(devices, { fields: [sessions.deviceId], references: [devices.id] }),
201
+ }));
202
+
203
+ export const adminsRelations = relations(admins, ({ one }) => ({
204
+ user: one(users, { fields: [admins.userId], references: [users.id] }),
205
+ }));
206
+
207
+ export const passwordResetsRelations = relations(passwordResets, ({ one }) => ({
208
+ user: one(users, { fields: [passwordResets.userId], references: [users.id] }),
209
+ }));
210
+
211
+ export const otpsRelations = relations(otps, ({ one }) => ({
212
+ user: one(users, { fields: [otps.userId], references: [users.id] }),
213
+ }));
214
+
215
+ export const devicesRelations = relations(devices, ({ many }) => ({
216
+ sessions: many(sessions),
217
+ users: many(devicesToUsers),
218
+ }));
219
+
220
+ export const devicesToUsersRelations = relations(devicesToUsers, ({ one }) => ({
221
+ device: one(devices, { fields: [devicesToUsers.deviceId], references: [devices.id] }),
222
+ user: one(users, { fields: [devicesToUsers.userId], references: [users.id] }),
223
+ }));
224
+ `;
225
+
226
+ // ── Init commands ───────────────────────────────────────────────────────────
227
+
228
+ function initPrisma() {
35
229
  // Ensure prisma directory exists
36
230
  if (!existsSync(targetDir)) {
37
231
  mkdirSync(targetDir, { recursive: true });
@@ -48,7 +242,7 @@ function init() {
48
242
  // Copy schema
49
243
  try {
50
244
  copyFileSync(schemaSource, targetFile);
51
- console.log(`✓ Copied schema to ${targetFile}`);
245
+ console.log(`✓ Copied Prisma schema to ${targetFile}`);
52
246
  console.log('');
53
247
  console.log('Next steps:');
54
248
  console.log(' 1. Review and customize the schema for your database provider');
@@ -61,12 +255,92 @@ function init() {
61
255
  }
62
256
  }
63
257
 
258
+ function initDrizzle() {
259
+ // Determine target location
260
+ const candidates = [
261
+ { dir: 'src/db', file: 'src/db/auth-schema.ts' },
262
+ { dir: 'drizzle', file: 'drizzle/auth-schema.ts' },
263
+ ];
264
+
265
+ // Pick the first directory that already exists, or default to src/db
266
+ let target = candidates[0];
267
+ for (const c of candidates) {
268
+ if (existsSync(resolve(process.cwd(), c.dir))) {
269
+ target = c;
270
+ break;
271
+ }
272
+ }
273
+
274
+ const targetDirDrizzle = resolve(process.cwd(), target.dir);
275
+ const targetFileDrizzle = resolve(process.cwd(), target.file);
276
+
277
+ // Ensure directory exists
278
+ if (!existsSync(targetDirDrizzle)) {
279
+ mkdirSync(targetDirDrizzle, { recursive: true });
280
+ console.log(`Created ${target.dir}/ directory`);
281
+ }
282
+
283
+ // Check if file already exists
284
+ if (existsSync(targetFileDrizzle)) {
285
+ console.log(`⚠️ ${target.file} already exists`);
286
+ console.log(' To overwrite, delete it first and run again.');
287
+ process.exit(1);
288
+ }
289
+
290
+ try {
291
+ writeFileSync(targetFileDrizzle, DRIZZLE_SCHEMA_TEMPLATE);
292
+ console.log(`✓ Generated Drizzle schema at ${target.file}`);
293
+ console.log('');
294
+ console.log('Next steps:');
295
+ console.log(' 1. Review and customize the schema (table names, column types, etc.)');
296
+ console.log(' 2. Import and merge into your existing schema (if you have one)');
297
+ console.log(' 3. Create a drizzle.config.ts if you haven\'t already');
298
+ console.log(' 4. Run: npx drizzle-kit generate');
299
+ console.log(' 5. Run: npx drizzle-kit migrate');
300
+ console.log('');
301
+ console.log('Usage with @factiii/auth:');
302
+ console.log(' import { createDrizzleAdapter } from \'@factiii/auth\';');
303
+ console.log(` import * as schema from './${target.file.replace(/\.ts$/, '')}';`);
304
+ console.log(' const adapter = createDrizzleAdapter(db, {');
305
+ console.log(' users: schema.users,');
306
+ console.log(' sessions: schema.sessions,');
307
+ console.log(' otps: schema.otps,');
308
+ console.log(' passwordResets: schema.passwordResets,');
309
+ console.log(' devices: schema.devices,');
310
+ console.log(' admins: schema.admins,');
311
+ console.log(' devicesToUsers: schema.devicesToUsers,');
312
+ console.log(' });');
313
+ } catch (err) {
314
+ console.error('Failed to generate schema:', err.message);
315
+ process.exit(1);
316
+ }
317
+ }
318
+
319
+ function init() {
320
+ const orm = resolveORMForInit();
321
+ console.log(`Detected ORM: ${orm}\n`);
322
+
323
+ if (orm === 'prisma') {
324
+ initPrisma();
325
+ } else if (orm === 'drizzle') {
326
+ initDrizzle();
327
+ }
328
+ }
329
+
64
330
  function printSchemaPath() {
65
- console.log('Schema location:');
66
- console.log(` ${schemaSource}`);
67
- console.log('');
68
- console.log('Copy manually:');
69
- console.log(` cp "${schemaSource}" ./prisma/auth-schema.prisma`);
331
+ const orm = resolveORMForInit();
332
+
333
+ if (orm === 'prisma') {
334
+ console.log('Prisma schema location:');
335
+ console.log(` ${schemaSource}`);
336
+ console.log('');
337
+ console.log('Copy manually:');
338
+ console.log(` cp "${schemaSource}" ./prisma/auth-schema.prisma`);
339
+ } else if (orm === 'drizzle') {
340
+ console.log('Drizzle schema:');
341
+ console.log(' Run: npx @factiii/auth init --drizzle');
342
+ console.log(' This generates a TypeScript schema file with all required tables.');
343
+ }
70
344
  }
71
345
 
72
346
  // ANSI color codes
@@ -182,6 +456,56 @@ function parseReferenceSchema() {
182
456
  return { models, enums, modelFields };
183
457
  }
184
458
 
459
+ /**
460
+ * Detect which ORM the consumer's project uses.
461
+ * Returns 'prisma' | 'drizzle' | 'both' | 'none'.
462
+ */
463
+ function detectORM(deps) {
464
+ const hasPrisma = Boolean(deps['@prisma/client']);
465
+ const hasDrizzle = Boolean(deps['drizzle-orm']);
466
+ if (hasPrisma && hasDrizzle) return 'both';
467
+ if (hasPrisma) return 'prisma';
468
+ if (hasDrizzle) return 'drizzle';
469
+ return 'none';
470
+ }
471
+
472
+ /**
473
+ * Look for Drizzle schema files (*.ts files exporting table definitions).
474
+ * Common patterns: src/db/schema.ts, drizzle/schema.ts, src/schema.ts
475
+ */
476
+ function findDrizzleSchema() {
477
+ const candidates = [
478
+ 'src/db/schema.ts',
479
+ 'src/db/schema/index.ts',
480
+ 'src/schema.ts',
481
+ 'drizzle/schema.ts',
482
+ 'db/schema.ts',
483
+ 'src/db/schema.js',
484
+ 'drizzle/schema.js',
485
+ ];
486
+
487
+ for (const candidate of candidates) {
488
+ const fullPath = resolve(process.cwd(), candidate);
489
+ if (existsSync(fullPath)) {
490
+ return { found: true, location: candidate };
491
+ }
492
+ }
493
+ return { found: false, location: '' };
494
+ }
495
+
496
+ /**
497
+ * Check for drizzle config file (drizzle.config.ts or drizzle.config.js)
498
+ */
499
+ function findDrizzleConfig() {
500
+ const candidates = ['drizzle.config.ts', 'drizzle.config.js', 'drizzle.config.mjs'];
501
+ for (const candidate of candidates) {
502
+ if (existsSync(resolve(process.cwd(), candidate))) {
503
+ return { found: true, location: candidate };
504
+ }
505
+ }
506
+ return { found: false, location: '' };
507
+ }
508
+
185
509
  function doctor() {
186
510
  console.log(`${colors.bold}${colors.cyan}Running diagnostics...${colors.reset}\n`);
187
511
 
@@ -197,24 +521,38 @@ function doctor() {
197
521
  process.exit(1);
198
522
  }
199
523
 
200
- // Check 1: package.json exists
524
+ // Check 1: package.json exists and detect ORM
201
525
  const packageJsonPath = resolve(process.cwd(), 'package.json');
526
+ let orm = 'none';
527
+
202
528
  if (!existsSync(packageJsonPath)) {
203
529
  fail('No package.json found in current directory');
204
530
  issues++;
205
531
  } else {
206
532
  ok('package.json found');
207
533
 
208
- // Check for @prisma/client dependency
209
534
  try {
210
535
  const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
211
536
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
212
- if (deps['@prisma/client']) {
213
- ok('@prisma/client is installed');
214
- } else {
215
- fail('@prisma/client not found in dependencies');
216
- hint('Run: npm install @prisma/client');
217
- issues++;
537
+ orm = detectORM(deps);
538
+
539
+ switch (orm) {
540
+ case 'prisma':
541
+ ok('@prisma/client found — using Prisma adapter');
542
+ break;
543
+ case 'drizzle':
544
+ ok('drizzle-orm found — using Drizzle adapter');
545
+ break;
546
+ case 'both':
547
+ ok('@prisma/client and drizzle-orm both found');
548
+ hint('You can use either createPrismaAdapter() or createDrizzleAdapter()');
549
+ break;
550
+ case 'none':
551
+ fail('No ORM detected — install @prisma/client or drizzle-orm');
552
+ hint('Prisma: npm install @prisma/client prisma');
553
+ hint('Drizzle: npm install drizzle-orm');
554
+ issues++;
555
+ break;
218
556
  }
219
557
  } catch (e) {
220
558
  warn('Could not parse package.json');
@@ -222,70 +560,117 @@ function doctor() {
222
560
  }
223
561
  }
224
562
 
225
- // Check 2: Prisma schema exists (supports single file and modularized schemas)
226
- const { found: schemaFound, schemaContent: schema, location: schemaLocation } = findPrismaSchema();
227
- if (!schemaFound) {
228
- fail('No Prisma schema found');
229
- hint('Checked: prisma/schema.prisma, prisma/schema/*.prisma, prisma/*.prisma');
230
- hint('Run: npx @factiii/auth init');
231
- issues++;
232
- } else {
233
- ok(`Prisma schema found (${schemaLocation})`);
234
-
235
- // Parse user's schema
236
- try {
237
- // Check models
238
- for (const model of reference.models) {
239
- const regex = new RegExp(`model\\s+${model}\\s*\\{`, 'm');
240
- if (regex.test(schema)) {
241
- ok(`Model ${colors.cyan}${model}${colors.reset} found`);
242
- } else {
243
- fail(`Model ${colors.cyan}${model}${colors.reset} not found in schema`);
244
- issues++;
563
+ // Check 2: ORM-specific schema checks
564
+ if (orm === 'prisma' || orm === 'both') {
565
+ console.log(`\n${colors.bold}Prisma checks:${colors.reset}`);
566
+
567
+ const { found: schemaFound, schemaContent: schema, location: schemaLocation } = findPrismaSchema();
568
+ if (!schemaFound) {
569
+ fail('No Prisma schema found');
570
+ hint('Checked: prisma/schema.prisma, prisma/schema/*.prisma, prisma/*.prisma');
571
+ hint('Run: npx @factiii/auth init');
572
+ issues++;
573
+ } else {
574
+ ok(`Prisma schema found (${schemaLocation})`);
575
+
576
+ try {
577
+ // Check models
578
+ for (const model of reference.models) {
579
+ const regex = new RegExp(`model\\s+${model}\\s*\\{`, 'm');
580
+ if (regex.test(schema)) {
581
+ ok(`Model ${colors.cyan}${model}${colors.reset} found`);
582
+ } else {
583
+ fail(`Model ${colors.cyan}${model}${colors.reset} not found in schema`);
584
+ issues++;
585
+ }
245
586
  }
246
- }
247
587
 
248
- // Check enums
249
- for (const enumName of reference.enums) {
250
- const regex = new RegExp(`enum\\s+${enumName}\\s*\\{`, 'm');
251
- if (regex.test(schema)) {
252
- ok(`Enum ${colors.cyan}${enumName}${colors.reset} found`);
253
- } else {
254
- fail(`Enum ${colors.cyan}${enumName}${colors.reset} not found in schema`);
255
- issues++;
588
+ // Check enums
589
+ for (const enumName of reference.enums) {
590
+ const regex = new RegExp(`enum\\s+${enumName}\\s*\\{`, 'm');
591
+ if (regex.test(schema)) {
592
+ ok(`Enum ${colors.cyan}${enumName}${colors.reset} found`);
593
+ } else {
594
+ fail(`Enum ${colors.cyan}${enumName}${colors.reset} not found in schema`);
595
+ issues++;
596
+ }
256
597
  }
257
- }
258
598
 
259
- // Check fields for each model
260
- for (const [model, fields] of Object.entries(reference.modelFields)) {
261
- const modelMatch = schema.match(new RegExp(`model\\s+${model}\\s*\\{([^}]+)\\}`, 'm'));
262
- if (modelMatch) {
263
- const block = modelMatch[1];
264
- for (const field of fields) {
265
- const fieldRegex = new RegExp(`\\b${field}\\b`, 'm');
266
- if (!fieldRegex.test(block)) {
267
- warn(`${model}.${colors.cyan}${field}${colors.reset} field not found`);
268
- warnings++;
599
+ // Check fields for each model
600
+ for (const [model, fields] of Object.entries(reference.modelFields)) {
601
+ const modelMatch = schema.match(new RegExp(`model\\s+${model}\\s*\\{([^}]+)\\}`, 'm'));
602
+ if (modelMatch) {
603
+ const block = modelMatch[1];
604
+ for (const field of fields) {
605
+ const fieldRegex = new RegExp(`\\b${field}\\b`, 'm');
606
+ if (!fieldRegex.test(block)) {
607
+ warn(`${model}.${colors.cyan}${field}${colors.reset} field not found`);
608
+ warnings++;
609
+ }
269
610
  }
270
611
  }
271
612
  }
613
+ } catch (e) {
614
+ warn('Could not parse Prisma schema');
615
+ warnings++;
272
616
  }
273
- } catch (e) {
274
- warn('Could not parse Prisma schema');
617
+ }
618
+ }
619
+
620
+ if (orm === 'drizzle' || orm === 'both') {
621
+ console.log(`\n${colors.bold}Drizzle checks:${colors.reset}`);
622
+
623
+ const drizzleConfig = findDrizzleConfig();
624
+ if (drizzleConfig.found) {
625
+ ok(`Drizzle config found (${drizzleConfig.location})`);
626
+ } else {
627
+ warn('No drizzle.config.ts found (optional but recommended for migrations)');
628
+ warnings++;
629
+ }
630
+
631
+ const drizzleSchema = findDrizzleSchema();
632
+ if (drizzleSchema.found) {
633
+ ok(`Drizzle schema found (${drizzleSchema.location})`);
634
+ } else {
635
+ warn('No Drizzle schema file found');
636
+ hint('Expected in: src/db/schema.ts, drizzle/schema.ts, or src/schema.ts');
637
+ hint('See SETUP.md for required table definitions');
275
638
  warnings++;
276
639
  }
640
+
641
+ // Check that required tables are referenced (basic text scan of schema file)
642
+ if (drizzleSchema.found) {
643
+ try {
644
+ const schemaContent = readFileSync(resolve(process.cwd(), drizzleSchema.location), 'utf-8');
645
+ const requiredTables = ['users', 'sessions', 'admins', 'passwordResets', 'otps', 'devices'];
646
+ for (const table of requiredTables) {
647
+ // Look for pgTable/mysqlTable/sqliteTable calls or export names
648
+ const tableRegex = new RegExp(`(?:Table|export).*${table}`, 'i');
649
+ if (tableRegex.test(schemaContent)) {
650
+ ok(`Table ${colors.cyan}${table}${colors.reset} found`);
651
+ } else {
652
+ warn(`Table ${colors.cyan}${table}${colors.reset} not found in schema`);
653
+ hint(`createDrizzleAdapter() expects a '${table}' table reference`);
654
+ warnings++;
655
+ }
656
+ }
657
+ } catch (e) {
658
+ warn('Could not read Drizzle schema file');
659
+ warnings++;
660
+ }
661
+ }
277
662
  }
278
663
 
279
664
  // Summary
280
665
  console.log(`\n${colors.bold}--- Summary ---${colors.reset}`);
281
666
  if (issues === 0 && warnings === 0) {
282
- console.log(`${colors.green}${colors.bold}All checks passed!${colors.reset} Your setup looks good.`);
667
+ console.log(`${colors.green}${colors.bold}All checks passed!${colors.reset} Your setup looks good.`);
283
668
  } else {
284
669
  if (issues > 0) {
285
- console.log(`${colors.red}${colors.bold}${issues} issue(s) found${colors.reset}`);
670
+ console.log(`${colors.red}${colors.bold}${issues} issue(s) found${colors.reset}`);
286
671
  }
287
672
  if (warnings > 0) {
288
- console.log(`${colors.yellow}${colors.bold}${warnings} warning(s) found${colors.reset}`);
673
+ console.log(`${colors.yellow}${colors.bold}${warnings} warning(s) found${colors.reset}`);
289
674
  }
290
675
  }
291
676
 
@@ -1,3 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/validators.ts
2
9
  import { z } from "zod";
3
10
  var usernameValidationRegex = /^[a-zA-Z0-9_]+$/;
@@ -77,6 +84,7 @@ function createSchemas(extensions) {
77
84
  }
78
85
 
79
86
  export {
87
+ __require,
80
88
  signupSchema,
81
89
  loginSchema,
82
90
  oAuthLoginSchema,