@onmax/nuxt-better-auth 0.0.2-alpha.3 → 0.0.2-alpha.5

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/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.0.0"
6
6
  },
7
- "version": "0.0.2-alpha.3",
7
+ "version": "0.0.2-alpha.5",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -5,6 +5,7 @@ import { consola as consola$1 } from 'consola';
5
5
  import { defu } from 'defu';
6
6
  import { join } from 'pathe';
7
7
  import { toRouteMatcher, createRouter } from 'radix3';
8
+ import pluralize from 'pluralize';
8
9
  export { defineClientAuth, defineServerAuth } from '../dist/runtime/config.js';
9
10
 
10
11
  function setupDevTools(nuxt) {
@@ -22,6 +23,9 @@ function setupDevTools(nuxt) {
22
23
  });
23
24
  }
24
25
 
26
+ function toSnakeCase(str) {
27
+ return str.replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").replace(/([a-z\d])([A-Z])/g, "$1_$2").toLowerCase();
28
+ }
25
29
  function generateDrizzleSchema(tables, dialect, options) {
26
30
  const typedTables = tables;
27
31
  const imports = getImports(dialect, options);
@@ -43,10 +47,12 @@ function getImports(dialect, options) {
43
47
  }
44
48
  function generateTable(tableName, table, dialect, allTables, options) {
45
49
  const tableFunc = dialect === "sqlite" ? "sqliteTable" : dialect === "postgresql" ? "pgTable" : "mysqlTable";
46
- let dbTableName = table.modelName || tableName;
47
- if (options?.usePlural && !table.modelName) {
48
- dbTableName = `${tableName}s`;
49
- }
50
+ const hasCustomModelName = table.modelName && table.modelName !== tableName;
51
+ let dbTableName = hasCustomModelName ? table.modelName : tableName;
52
+ if (options?.casing === "snake_case" && !hasCustomModelName)
53
+ dbTableName = toSnakeCase(dbTableName);
54
+ if (options?.usePlural && !hasCustomModelName)
55
+ dbTableName = pluralize(dbTableName);
50
56
  const fields = Object.entries(table.fields).map(([fieldName, field]) => generateField(fieldName, field, dialect, allTables, options)).join(",\n ");
51
57
  const idField = generateIdField(dialect, options);
52
58
  return `export const ${tableName} = ${tableFunc}('${dbTableName}', {
@@ -67,7 +73,7 @@ function generateIdField(dialect, options) {
67
73
  }
68
74
  }
69
75
  function generateField(fieldName, field, dialect, allTables, options) {
70
- const dbFieldName = fieldName;
76
+ const dbFieldName = options?.casing === "snake_case" ? toSnakeCase(fieldName) : fieldName;
71
77
  const isFkToId = options?.useUuid && field.references?.field === "id";
72
78
  let fieldDef;
73
79
  if (isFkToId && dialect === "postgresql")
@@ -85,11 +91,15 @@ function generateField(fieldName, field, dialect, allTables, options) {
85
91
  fieldDef += `.default(${field.defaultValue})`;
86
92
  else if (typeof field.defaultValue === "string")
87
93
  fieldDef += `.default('${field.defaultValue}')`;
94
+ else if (typeof field.defaultValue === "function")
95
+ fieldDef += `.$defaultFn(${field.defaultValue})`;
88
96
  else
89
97
  fieldDef += `.default(${field.defaultValue})`;
90
98
  if (field.required)
91
99
  fieldDef += ".notNull()";
92
100
  }
101
+ if (typeof field.onUpdate === "function" && field.type === "date")
102
+ fieldDef += `.$onUpdate(${field.onUpdate})`;
93
103
  if (field.references) {
94
104
  const refTable = field.references.model;
95
105
  if (allTables[refTable])
@@ -172,6 +182,20 @@ async function loadUserAuthConfig(configPath, throwOnError = false) {
172
182
  }
173
183
  }
174
184
 
185
+ function getHubDialect(hub) {
186
+ if (!hub?.db)
187
+ return void 0;
188
+ if (typeof hub.db === "string")
189
+ return hub.db;
190
+ if (typeof hub.db === "object" && hub.db !== null)
191
+ return hub.db.dialect;
192
+ return void 0;
193
+ }
194
+ function getHubCasing(hub) {
195
+ if (!hub?.db || typeof hub.db !== "object" || hub.db === null)
196
+ return void 0;
197
+ return hub.db.casing;
198
+ }
175
199
  const consola = consola$1.withTag("nuxt-better-auth");
176
200
  const module$1 = defineNuxtModule({
177
201
  meta: { name: "@onmax/nuxt-better-auth", configKey: "auth", compatibility: { nuxt: ">=3.0.0" } },
@@ -220,7 +244,11 @@ const module$1 = defineNuxtModule({
220
244
  nuxt.options.alias["#nuxt-better-auth"] = resolver.resolve("./runtime/types/augment");
221
245
  nuxt.options.alias["#auth/server"] = serverConfigPath;
222
246
  nuxt.options.alias["#auth/client"] = clientConfigPath;
223
- const secondaryStorageCode = secondaryStorageEnabled ? `import { kv } from 'hub:kv'
247
+ const hubKVPath = nuxt.options.alias["hub:kv"];
248
+ if (secondaryStorageEnabled && !hubKVPath) {
249
+ throw new Error("[nuxt-better-auth] hub:kv alias not found. Ensure @nuxthub/core is loaded before this module.");
250
+ }
251
+ const secondaryStorageCode = secondaryStorageEnabled ? `import { kv } from '${hubKVPath}'
224
252
  export function createSecondaryStorage() {
225
253
  return {
226
254
  get: async (key) => kv.get(\`_auth:\${key}\`),
@@ -234,7 +262,7 @@ export function createSecondaryStorage() {
234
262
  if (hasHubDb && !hubDbPath) {
235
263
  throw new Error("[nuxt-better-auth] hub:db alias not found. Ensure @nuxthub/core is loaded before this module.");
236
264
  }
237
- const hubDialect = typeof hub?.db === "string" ? hub.db : (typeof hub?.db === "object" ? hub.db.dialect : void 0) ?? "sqlite";
265
+ const hubDialect = getHubDialect(hub) ?? "sqlite";
238
266
  const databaseCode = hasHubDb && hubDbPath ? `import { db, schema } from '${hubDbPath}'
239
267
  import { drizzleAdapter } from 'better-auth/adapters/drizzle'
240
268
  const rawDialect = '${hubDialect}'
@@ -367,7 +395,7 @@ declare module 'nitropack/types' {
367
395
  });
368
396
  async function setupBetterAuthSchema(nuxt, serverConfigPath, options) {
369
397
  const hub = nuxt.options.hub;
370
- const dialect = typeof hub?.db === "string" ? hub.db : typeof hub?.db === "object" ? hub.db.dialect : void 0;
398
+ const dialect = getHubDialect(hub);
371
399
  if (!dialect || !["sqlite", "postgresql", "mysql"].includes(dialect)) {
372
400
  consola.warn(`Unsupported database dialect: ${dialect}`);
373
401
  return;
@@ -380,9 +408,19 @@ async function setupBetterAuthSchema(nuxt, serverConfigPath, options) {
380
408
  await nuxt.callHook("better-auth:config:extend", extendedConfig);
381
409
  const plugins = [...userConfig.plugins || [], ...extendedConfig.plugins || []];
382
410
  const { getAuthTables } = await import('better-auth/db');
383
- const tables = getAuthTables({ plugins });
411
+ const tables = getAuthTables({
412
+ plugins,
413
+ secondaryStorage: options.secondaryStorage ? {
414
+ get: async (_key) => null,
415
+ set: async (_key, _value, _ttl) => {
416
+ },
417
+ delete: async (_key) => {
418
+ }
419
+ } : void 0
420
+ });
384
421
  const useUuid = userConfig.advanced?.database?.generateId === "uuid";
385
- const schemaOptions = { ...options.schema, useUuid };
422
+ const hubCasing = getHubCasing(hub);
423
+ const schemaOptions = { ...options.schema, useUuid, casing: options.schema?.casing ?? hubCasing };
386
424
  const schemaCode = generateDrizzleSchema(tables, dialect, schemaOptions);
387
425
  const schemaDir = join(nuxt.options.buildDir, "better-auth");
388
426
  const schemaPath = join(schemaDir, `schema.${dialect}.ts`);
@@ -1,5 +1,6 @@
1
1
  import type { BetterAuthOptions } from 'better-auth';
2
2
  import type { ClientOptions } from 'better-auth/client';
3
+ import type { CasingOption } from '../schema-generator.js';
3
4
  import type { ServerAuthContext } from './types/augment.js';
4
5
  export type { ServerAuthContext };
5
6
  export interface ClientAuthContext {
@@ -26,6 +27,8 @@ export interface BetterAuthModuleOptions {
26
27
  schema?: {
27
28
  /** Plural table names: user → users. Default: false */
28
29
  usePlural?: boolean;
30
+ /** Column/table name casing. Explicit value takes precedence over hub.db.casing. */
31
+ casing?: CasingOption;
29
32
  };
30
33
  }
31
34
  export interface AuthRuntimeConfig {
@@ -9,21 +9,21 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
9
9
  useDatabase: boolean;
10
10
  };
11
11
  server: {
12
- baseURL: string | undefined;
13
- basePath: string;
12
+ baseURL: any;
13
+ basePath: any;
14
14
  socialProviders: string[];
15
- plugins: string[];
16
- trustedOrigins: string[] | ((request: Request) => string[] | Promise<string[]>);
15
+ plugins: any;
16
+ trustedOrigins: any;
17
17
  session: {
18
18
  expiresIn: string;
19
19
  updateAge: string;
20
- cookieCache: boolean;
20
+ cookieCache: any;
21
21
  };
22
22
  emailAndPassword: boolean;
23
- rateLimit: boolean;
23
+ rateLimit: any;
24
24
  advanced: {
25
- useSecureCookies: string | boolean;
26
- disableCSRFCheck: boolean;
25
+ useSecureCookies: any;
26
+ disableCSRFCheck: any;
27
27
  };
28
28
  };
29
29
  };
@@ -1,6 +1,7 @@
1
+ import type { Auth } from 'better-auth';
1
2
  import type { H3Event } from 'h3';
2
- import { betterAuth } from 'better-auth';
3
- type AuthInstance = ReturnType<typeof betterAuth>;
3
+ import createServerAuth from '#auth/server';
4
+ type AuthInstance = Auth<ReturnType<typeof createServerAuth>>;
4
5
  declare module 'h3' {
5
6
  interface H3EventContext {
6
7
  _betterAuth?: AuthInstance;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@onmax/nuxt-better-auth",
3
3
  "type": "module",
4
- "version": "0.0.2-alpha.3",
4
+ "version": "0.0.2-alpha.5",
5
5
  "packageManager": "pnpm@10.15.1",
6
6
  "description": "Nuxt module for Better Auth integration with NuxtHub, route protection, session management, and role-based access",
7
7
  "author": "onmax",
@@ -63,6 +63,7 @@
63
63
  "defu": "^6.1.4",
64
64
  "jiti": "^2.4.2",
65
65
  "pathe": "^2.0.3",
66
+ "pluralize": "^8.0.0",
66
67
  "radix3": "^1.1.2"
67
68
  },
68
69
  "devDependencies": {
@@ -77,6 +78,7 @@
77
78
  "@nuxthub/core": "^0.10.3",
78
79
  "@types/better-sqlite3": "^7.6.13",
79
80
  "@types/node": "latest",
81
+ "@types/pluralize": "^0.0.33",
80
82
  "better-auth": "^1.4.7",
81
83
  "better-sqlite3": "^11.9.1",
82
84
  "bumpp": "^10.3.2",