nuxt-users 1.45.0 → 1.47.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/dist/cli.mjs CHANGED
@@ -1,16 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  import { defineCommand, runMain } from 'citty';
3
3
  import { readFileSync } from 'node:fs';
4
- import { defaultOptions } from './module.mjs';
5
- import { loadNuxt } from '@nuxt/kit';
4
+ import { d as defaultOptions } from './shared/nuxt-users.BsNZbqYb.mjs';
6
5
  import { defu } from 'defu';
7
- import { runMigrations, createUser as createUser$1, createUsersTable as createUsersTable$1, createPersonalAccessTokensTable as createPersonalAccessTokensTable$1, createPasswordResetTokensTable as createPasswordResetTokensTable$1, createMigrationsTable as createMigrationsTable$1, useDb, checkTableExists, getAppliedMigrations } from '../dist/runtime/server/utils/index.js';
8
- import { g as getPasswordValidationOptions, v as validatePassword } from './shared/nuxt-users.Cvjgn5KJ.mjs';
6
+ import { runMigrations, getAppliedMigrations } from '../dist/runtime/server/utils/migrate.js';
7
+ import { createUser as createUser$1 } from '../dist/runtime/server/utils/user.js';
8
+ import { b as getPasswordValidationOptions, v as validatePassword } from './shared/nuxt-users.9p2ye9P4.mjs';
9
9
  import '../dist/runtime/locales/index.js';
10
10
  import '../dist/runtime/utils/locale.js';
11
11
  import '../dist/runtime/utils/deep-merge.js';
12
+ import { createUsersTable as createUsersTable$1 } from '../dist/runtime/server/utils/create-users-table.js';
13
+ import { createPersonalAccessTokensTable as createPersonalAccessTokensTable$1 } from '../dist/runtime/server/utils/create-personal-access-tokens-table.js';
14
+ import { createPasswordResetTokensTable as createPasswordResetTokensTable$1 } from '../dist/runtime/server/utils/create-password-reset-tokens-table.js';
15
+ import { createMigrationsTable as createMigrationsTable$1 } from '../dist/runtime/server/utils/create-migrations-table.js';
12
16
  import { addActiveToUsers as addActiveToUsers$1 } from '../dist/runtime/server/utils/add-active-to-users.js';
13
- import '../dist/runtime/server/internal/index.js';
17
+ import { useDb, checkTableExists } from '../dist/runtime/server/utils/db.js';
14
18
 
15
19
  const getOptionsFromEnv = () => {
16
20
  const connectorName = process.env.DB_CONNECTOR || "sqlite";
@@ -56,6 +60,7 @@ const loadOptions = async () => {
56
60
  console.log("[Nuxt Users] \u2139\uFE0F Note: CLI commands read .env files. If you use .env.local in development, export variables first:");
57
61
  console.log("[Nuxt Users] set -a; source .env.local; set +a; npx nuxt-users <command>");
58
62
  console.log("[Nuxt Users] In production, environment variables are set directly in the deployment environment.");
63
+ const { loadNuxt } = await import('@nuxt/kit');
59
64
  const nuxt = await loadNuxt({ cwd: process.cwd(), ready: false });
60
65
  const topLevelConfig = nuxt.options.nuxtUsers;
61
66
  const processedRuntimeConfig = nuxt.options.runtimeConfig?.nuxtUsers;
@@ -352,6 +357,7 @@ const projectInfo = defineCommand({
352
357
  },
353
358
  async run() {
354
359
  try {
360
+ const { loadNuxt } = await import('@nuxt/kit');
355
361
  console.log("[Nuxt Users] Loading Nuxt project...");
356
362
  console.log("[Nuxt Users] \u2139\uFE0F Note: CLI commands read .env files. If you use .env.local in development, export variables first:");
357
363
  console.log("[Nuxt Users] set -a; source .env.local; set +a; npx nuxt-users <command>");
package/dist/module.d.mts CHANGED
@@ -1,8 +1,9 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { M as ModuleOptions } from './shared/nuxt-users.DUmdxjpk.mjs';
2
+ import { M as ModuleOptions } from './shared/nuxt-users.bLYb3Bz5.mjs';
3
3
  export * from '../dist/runtime/server/internal/index.js';
4
4
 
5
5
  declare const defaultOptions: ModuleOptions;
6
+
6
7
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
7
8
 
8
9
  export { _default as default, defaultOptions };
package/dist/module.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- import { M as ModuleOptions } from './shared/nuxt-users.DUmdxjpk.js';
2
+ import { M as ModuleOptions } from './shared/nuxt-users.bLYb3Bz5.js';
3
3
  export * from '../dist/runtime/server/internal/index.js';
4
4
 
5
5
  declare const defaultOptions: ModuleOptions;
6
+
6
7
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
7
8
 
8
9
  export { _default as default, defaultOptions };
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.0.0"
6
6
  },
7
- "version": "1.45.0",
7
+ "version": "1.47.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,67 +1,8 @@
1
1
  import { defineNuxtModule, createResolver, addPlugin, addImportsDir, addServerImportsDir, addServerScanDir, addServerHandler, addServerPlugin, addRouteMiddleware, addComponentsDir } from '@nuxt/kit';
2
2
  import { defu } from 'defu';
3
+ import { d as defaultOptions } from './shared/nuxt-users.BsNZbqYb.mjs';
3
4
  export * from '../dist/runtime/server/internal/index.js';
4
5
 
5
- const defaultOptions = {
6
- connector: {
7
- name: "sqlite",
8
- options: {
9
- path: "./data/users.sqlite3"
10
- }
11
- },
12
- apiBasePath: "/api/nuxt-users",
13
- tables: {
14
- migrations: "migrations",
15
- users: "users",
16
- personalAccessTokens: "personal_access_tokens",
17
- passwordResetTokens: "password_reset_tokens"
18
- },
19
- mailer: {
20
- // Added default mailer (example using ethereal.email)
21
- host: "smtp.ethereal.email",
22
- port: 587,
23
- secure: false,
24
- auth: {
25
- user: "user@ethereal.email",
26
- // Replace with actual Ethereal user
27
- pass: "password"
28
- // Replace with actual Ethereal password
29
- },
30
- defaults: {
31
- from: '"Nuxt Users Module" <noreply@example.com>'
32
- }
33
- },
34
- passwordResetUrl: "/reset-password",
35
- emailConfirmationUrl: "/email-confirmation",
36
- auth: {
37
- whitelist: [],
38
- tokenExpiration: 24 * 60,
39
- // 24 hours in minutes
40
- rememberMeExpiration: 30,
41
- // 30 days
42
- permissions: {}
43
- // Empty by default - whitelist approach
44
- },
45
- passwordValidation: {
46
- minLength: 8,
47
- requireUppercase: true,
48
- requireLowercase: true,
49
- requireNumbers: true,
50
- requireSpecialChars: true,
51
- preventCommonPasswords: true
52
- },
53
- hardDelete: false,
54
- locale: {
55
- default: "en",
56
- fallbackLocale: "en",
57
- texts: {}
58
- },
59
- tokenCleanupSchedule: "0 2 * * *",
60
- // Daily at 2 AM
61
- theme: {
62
- enabled: true
63
- }
64
- };
65
6
  const module$1 = defineNuxtModule({
66
7
  meta: {
67
8
  name: "nuxt-users",
@@ -182,6 +123,7 @@ const module$1 = defineNuxtModule({
182
123
  handler: resolver.resolve("./runtime/server/middleware/authorization.server")
183
124
  });
184
125
  addServerPlugin(resolver.resolve("./runtime/server/plugins/auto-migrate"));
126
+ addServerPlugin(resolver.resolve("./runtime/server/plugins/validate-mailer-config"));
185
127
  addRouteMiddleware({
186
128
  name: "authorization.client",
187
129
  path: resolver.resolve("./runtime/middleware/authorization.client"),
@@ -148,13 +148,44 @@ const handleForgotPassword = async () => {
148
148
  :title="showPassword ? props.hidePasswordLabel || t('login.hidePassword') : props.showPasswordLabel || t('login.showPassword')"
149
149
  @click="showPassword = !showPassword"
150
150
  >
151
- <svg v-if="!showPassword" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
152
- <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/>
153
- <line x1="1" y1="1" x2="23" y2="23"/>
151
+ <svg
152
+ v-if="!showPassword"
153
+ xmlns="http://www.w3.org/2000/svg"
154
+ width="20"
155
+ height="20"
156
+ viewBox="0 0 24 24"
157
+ fill="none"
158
+ stroke="currentColor"
159
+ stroke-width="2"
160
+ stroke-linecap="round"
161
+ stroke-linejoin="round"
162
+ >
163
+ <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" />
164
+ <line
165
+ x1="1"
166
+ y1="1"
167
+ x2="23"
168
+ y2="23"
169
+ />
154
170
  </svg>
155
- <svg v-if="showPassword" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
156
- <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
157
- <circle cx="12" cy="12" r="3"/>
171
+ <svg
172
+ v-if="showPassword"
173
+ xmlns="http://www.w3.org/2000/svg"
174
+ width="20"
175
+ height="20"
176
+ viewBox="0 0 24 24"
177
+ fill="none"
178
+ stroke="currentColor"
179
+ stroke-width="2"
180
+ stroke-linecap="round"
181
+ stroke-linejoin="round"
182
+ >
183
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
184
+ <circle
185
+ cx="12"
186
+ cy="12"
187
+ r="3"
188
+ />
158
189
  </svg>
159
190
  </button>
160
191
  </div>
@@ -0,0 +1,3 @@
1
+ import type { NitroAppPlugin } from 'nitropack';
2
+ declare const plugin: NitroAppPlugin;
3
+ export default plugin;
@@ -0,0 +1,33 @@
1
+ import { useRuntimeConfig } from "#imports";
2
+ const INSECURE_DEFAULT_FROM = /@example\.com>/i;
3
+ const DEFAULT_ETHEREAL_HOST = "smtp.ethereal.email";
4
+ const isTestEnvironment = () => process.env.NODE_ENV === "test" || !!process.env.VITEST;
5
+ const validateMailerConfig = (options) => {
6
+ if (isTestEnvironment()) {
7
+ return;
8
+ }
9
+ const mailer = options.mailer;
10
+ if (!mailer?.host || !mailer?.auth?.user || !mailer?.auth?.pass) {
11
+ return;
12
+ }
13
+ const from = mailer.defaults?.from || '"Nuxt Users" <noreply@example.com>';
14
+ if (!INSECURE_DEFAULT_FROM.test(from)) {
15
+ return;
16
+ }
17
+ const isCustomMailer = mailer.host !== DEFAULT_ETHEREAL_HOST;
18
+ if (!isCustomMailer) {
19
+ return;
20
+ }
21
+ throw new Error(
22
+ '[Nuxt Users] Invalid mailer config: mailer.defaults.from must be set to a valid sender address when using a custom SMTP host. Using noreply@example.com causes password reset emails to bounce (DMARC rejection). Set nuxtUsers.mailer.defaults.from in nuxt.config.ts or NUXT_NUXT_USERS_MAILER_DEFAULTS_FROM env var, e.g. "App" <noreply@yourdomain.com>'
23
+ );
24
+ };
25
+ const plugin = () => {
26
+ const config = useRuntimeConfig();
27
+ const options = config.nuxtUsers;
28
+ if (!options) {
29
+ return;
30
+ }
31
+ validateMailerConfig(options);
32
+ };
33
+ export default plugin;
@@ -167,4 +167,4 @@ const getPasswordStrengthText = (strength) => {
167
167
  }
168
168
  };
169
169
 
170
- export { getPasswordStrengthColor as a, getPasswordStrengthText as b, getPasswordValidationOptions as g, validatePassword as v };
170
+ export { getPasswordStrengthText as a, getPasswordValidationOptions as b, getPasswordStrengthColor as g, validatePassword as v };
@@ -0,0 +1,55 @@
1
+ const defaultOptions = {
2
+ connector: {
3
+ name: "sqlite",
4
+ options: {
5
+ path: "./data/users.sqlite3"
6
+ }
7
+ },
8
+ apiBasePath: "/api/nuxt-users",
9
+ tables: {
10
+ migrations: "migrations",
11
+ users: "users",
12
+ personalAccessTokens: "personal_access_tokens",
13
+ passwordResetTokens: "password_reset_tokens"
14
+ },
15
+ mailer: {
16
+ host: "smtp.ethereal.email",
17
+ port: 587,
18
+ secure: false,
19
+ auth: {
20
+ user: "user@ethereal.email",
21
+ pass: "password"
22
+ },
23
+ defaults: {
24
+ from: '"Nuxt Users Module" <noreply@example.com>'
25
+ }
26
+ },
27
+ passwordResetUrl: "/reset-password",
28
+ emailConfirmationUrl: "/email-confirmation",
29
+ auth: {
30
+ whitelist: [],
31
+ tokenExpiration: 24 * 60,
32
+ rememberMeExpiration: 30,
33
+ permissions: {}
34
+ },
35
+ passwordValidation: {
36
+ minLength: 8,
37
+ requireUppercase: true,
38
+ requireLowercase: true,
39
+ requireNumbers: true,
40
+ requireSpecialChars: true,
41
+ preventCommonPasswords: true
42
+ },
43
+ hardDelete: false,
44
+ locale: {
45
+ default: "en",
46
+ fallbackLocale: "en",
47
+ texts: {}
48
+ },
49
+ tokenCleanupSchedule: "0 2 * * *",
50
+ theme: {
51
+ enabled: true
52
+ }
53
+ };
54
+
55
+ export { defaultOptions as d };
@@ -337,4 +337,4 @@ declare const defaultFieldLabels: {
337
337
  };
338
338
 
339
339
  export { defaultDisplayFields as j, defaultFieldLabels as k };
340
- export type { DisplayFieldsProps as D, GoogleOAuthOptions as G, LoginFormData as L, ModuleOptions as M, PersonalAccessToken as P, RuntimeModuleOptions as R, User as U, UserWithoutPassword as a, PasswordResetToken as b, LoginFormProps as c, ResetPasswordFormProps as d, Permission as e, DatabaseType as f, DatabaseConfig as g, LocaleOptions as h, LocaleMessages as i };
340
+ export type { DatabaseConfig as D, GoogleOAuthOptions as G, LocaleMessages as L, ModuleOptions as M, PasswordResetToken as P, ResetPasswordFormProps as R, User as U, DatabaseType as a, DisplayFieldsProps as b, LocaleOptions as c, LoginFormData as d, LoginFormProps as e, Permission as f, PersonalAccessToken as g, RuntimeModuleOptions as h, UserWithoutPassword as i };
@@ -337,4 +337,4 @@ declare const defaultFieldLabels: {
337
337
  };
338
338
 
339
339
  export { defaultDisplayFields as j, defaultFieldLabels as k };
340
- export type { DisplayFieldsProps as D, GoogleOAuthOptions as G, LoginFormData as L, ModuleOptions as M, PersonalAccessToken as P, RuntimeModuleOptions as R, User as U, UserWithoutPassword as a, PasswordResetToken as b, LoginFormProps as c, ResetPasswordFormProps as d, Permission as e, DatabaseType as f, DatabaseConfig as g, LocaleOptions as h, LocaleMessages as i };
340
+ export type { DatabaseConfig as D, GoogleOAuthOptions as G, LocaleMessages as L, ModuleOptions as M, PasswordResetToken as P, ResetPasswordFormProps as R, User as U, DatabaseType as a, DisplayFieldsProps as b, LocaleOptions as c, LoginFormData as d, LoginFormProps as e, Permission as f, PersonalAccessToken as g, RuntimeModuleOptions as h, UserWithoutPassword as i };
package/dist/utils.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { defaultLocaleMessages, en, hu, huFormal } from '../dist/runtime/locales/index.js';
2
2
  export { getNestedValue, getTranslation } from '../dist/runtime/utils/locale.js';
3
3
  export { deepMerge } from '../dist/runtime/utils/deep-merge.js';
4
- export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, G as GoogleOAuthOptions, i as LocaleMessages, h as LocaleOptions, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, j as defaultDisplayFields, k as defaultFieldLabels } from './shared/nuxt-users.DUmdxjpk.mjs';
4
+ export { D as DatabaseConfig, a as DatabaseType, b as DisplayFieldsProps, G as GoogleOAuthOptions, L as LocaleMessages, c as LocaleOptions, d as LoginFormData, e as LoginFormProps, M as ModuleOptions, P as PasswordResetToken, f as Permission, g as PersonalAccessToken, R as ResetPasswordFormProps, h as RuntimeModuleOptions, U as User, i as UserWithoutPassword, j as defaultDisplayFields, k as defaultFieldLabels } from './shared/nuxt-users.bLYb3Bz5.mjs';
5
5
 
6
6
  interface PasswordValidationResult {
7
7
  isValid: boolean;
package/dist/utils.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { defaultLocaleMessages, en, hu, huFormal } from '../dist/runtime/locales/index.js';
2
2
  export { getNestedValue, getTranslation } from '../dist/runtime/utils/locale.js';
3
3
  export { deepMerge } from '../dist/runtime/utils/deep-merge.js';
4
- export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, G as GoogleOAuthOptions, i as LocaleMessages, h as LocaleOptions, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, j as defaultDisplayFields, k as defaultFieldLabels } from './shared/nuxt-users.DUmdxjpk.js';
4
+ export { D as DatabaseConfig, a as DatabaseType, b as DisplayFieldsProps, G as GoogleOAuthOptions, L as LocaleMessages, c as LocaleOptions, d as LoginFormData, e as LoginFormProps, M as ModuleOptions, P as PasswordResetToken, f as Permission, g as PersonalAccessToken, R as ResetPasswordFormProps, h as RuntimeModuleOptions, U as User, i as UserWithoutPassword, j as defaultDisplayFields, k as defaultFieldLabels } from './shared/nuxt-users.bLYb3Bz5.js';
5
5
 
6
6
  interface PasswordValidationResult {
7
7
  isValid: boolean;
package/dist/utils.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { a as getPasswordStrengthColor, b as getPasswordStrengthText, g as getPasswordValidationOptions, v as validatePassword } from './shared/nuxt-users.Cvjgn5KJ.mjs';
1
+ export { g as getPasswordStrengthColor, a as getPasswordStrengthText, b as getPasswordValidationOptions, v as validatePassword } from './shared/nuxt-users.9p2ye9P4.mjs';
2
2
  export { defaultLocaleMessages, en, hu, huFormal } from '../dist/runtime/locales/index.js';
3
3
  export { getNestedValue, getTranslation } from '../dist/runtime/utils/locale.js';
4
4
  export { deepMerge } from '../dist/runtime/utils/deep-merge.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-users",
3
- "version": "1.45.0",
3
+ "version": "1.47.0",
4
4
  "description": "A comprehensive user management module for Nuxt 3 and Nuxt 4 applications with authentication, authorization, database support, and CLI tools",
5
5
  "keywords": [
6
6
  "nuxt",
@@ -100,6 +100,7 @@
100
100
  "dependencies": {
101
101
  "bcrypt": "^6.0.0",
102
102
  "citty": "^0.2.0",
103
+ "db0": "^0.3.4",
103
104
  "defu": "^6.1.4",
104
105
  "google-auth-library": "^10.4.0",
105
106
  "nodemailer": "^7.0.5"