create-nuxt-base 1.2.0 → 2.0.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.
Files changed (35) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/nuxt-base-template/app/components/Modal/ModalBackupCodes.vue +2 -1
  3. package/nuxt-base-template/app/components/Upload/TusFileUpload.vue +7 -7
  4. package/nuxt-base-template/app/interfaces/user.interface.ts +5 -12
  5. package/nuxt-base-template/app/layouts/default.vue +1 -1
  6. package/nuxt-base-template/app/middleware/admin.global.ts +2 -2
  7. package/nuxt-base-template/app/middleware/auth.global.ts +2 -2
  8. package/nuxt-base-template/app/middleware/guest.global.ts +2 -2
  9. package/nuxt-base-template/app/pages/app/index.vue +1 -1
  10. package/nuxt-base-template/app/pages/app/settings/security.vue +2 -2
  11. package/nuxt-base-template/app/pages/auth/2fa.vue +2 -3
  12. package/nuxt-base-template/app/pages/auth/forgot-password.vue +2 -1
  13. package/nuxt-base-template/app/pages/auth/login.vue +2 -2
  14. package/nuxt-base-template/app/pages/auth/register.vue +1 -1
  15. package/nuxt-base-template/app/pages/auth/reset-password.vue +2 -1
  16. package/nuxt-base-template/docs/pages/docs.vue +1 -1
  17. package/nuxt-base-template/nuxt.config.ts +38 -1
  18. package/nuxt-base-template/package-lock.json +136 -2905
  19. package/nuxt-base-template/package.json +1 -0
  20. package/package.json +1 -1
  21. package/nuxt-base-template/app/components/Transition/TransitionFade.vue +0 -27
  22. package/nuxt-base-template/app/components/Transition/TransitionFadeScale.vue +0 -27
  23. package/nuxt-base-template/app/components/Transition/TransitionSlide.vue +0 -12
  24. package/nuxt-base-template/app/components/Transition/TransitionSlideBottom.vue +0 -12
  25. package/nuxt-base-template/app/components/Transition/TransitionSlideRevert.vue +0 -12
  26. package/nuxt-base-template/app/composables/use-better-auth.ts +0 -597
  27. package/nuxt-base-template/app/composables/use-file.ts +0 -71
  28. package/nuxt-base-template/app/composables/use-share.ts +0 -38
  29. package/nuxt-base-template/app/composables/use-tus-upload.ts +0 -278
  30. package/nuxt-base-template/app/composables/use-tw.ts +0 -1
  31. package/nuxt-base-template/app/interfaces/upload.interface.ts +0 -58
  32. package/nuxt-base-template/app/lib/auth-client.ts +0 -229
  33. package/nuxt-base-template/app/lib/auth-state.ts +0 -206
  34. package/nuxt-base-template/app/plugins/auth-interceptor.client.ts +0 -151
  35. package/nuxt-base-template/app/utils/crypto.ts +0 -44
package/CHANGELOG.md CHANGED
@@ -2,6 +2,39 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [2.0.0](https://github.com/lenneTech/nuxt-base-starter/compare/v1.2.0...v2.0.0) (2026-01-24)
6
+
7
+
8
+ ### ⚠ BREAKING CHANGES
9
+
10
+ * Local auth, upload, and utility files replaced by package
11
+
12
+ Migration to @lenne.tech/nuxt-extensions v1.0.1:
13
+ - Remove local composables (use-better-auth, use-tus-upload, use-file, use-share, use-tw)
14
+ - Remove local lib files (auth-client, auth-state)
15
+ - Remove local plugins (auth-interceptor.client)
16
+ - Remove local utils (crypto)
17
+ - Remove local interfaces (upload.interface)
18
+ - Remove local Transition components (now provided by package as Lt* prefix)
19
+ - Simplify user.interface.ts to re-export LtUser from package
20
+ - Update all imports to use auto-imported composables (useLtAuth, useLtTusUpload, etc.)
21
+ - Update package.json to use npm package instead of yalc
22
+
23
+ All authentication features now provided by the package:
24
+ - Cookie/JWT dual-mode authentication
25
+ - Passkey/WebAuthn support
26
+ - 2FA/TOTP support
27
+ - Auto-logout on 401
28
+
29
+ Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
30
+
31
+ ### Bug Fixes
32
+
33
+ * use exact version 1.0.1 for [@lenne](https://github.com/lenne).tech/nuxt-extensions ([fe8d4c2](https://github.com/lenneTech/nuxt-base-starter/commit/fe8d4c21575977bd093a304adc2e18c7edc61110))
34
+
35
+
36
+ * migrate to [@lenne](https://github.com/lenne).tech/nuxt-extensions package ([4c8b732](https://github.com/lenneTech/nuxt-base-starter/commit/4c8b732b9d017a0ff7fb21ef09136dcd7fff81f0))
37
+
5
38
  ## [1.2.0](https://github.com/lenneTech/nuxt-base-starter/compare/v1.1.2...v1.2.0) (2026-01-22)
6
39
 
7
40
 
@@ -7,7 +7,8 @@ import type { InferOutput } from 'valibot';
7
7
 
8
8
  import * as v from 'valibot';
9
9
 
10
- import { authClient } from '~/lib/auth-client';
10
+ // Auth client from @lenne.tech/nuxt-extensions (auto-imported as ltAuthClient)
11
+ const authClient = ltAuthClient;
11
12
 
12
13
  // ============================================================================
13
14
  // Props & Emits
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import type { UploadItem } from '~/interfaces/upload.interface';
2
+ import type { LtUploadItem } from '@lenne.tech/nuxt-extensions';
3
3
 
4
4
  // ============================================================================
5
5
  // Props & Emits
@@ -45,11 +45,11 @@ const props = withDefaults(defineProps<Props>(), {
45
45
 
46
46
  const emit = defineEmits<{
47
47
  /** Alle Uploads abgeschlossen */
48
- complete: [items: UploadItem[]];
48
+ complete: [items: LtUploadItem[]];
49
49
  /** Upload-Fehler */
50
- error: [item: UploadItem, error: Error];
50
+ error: [item: LtUploadItem, error: Error];
51
51
  /** Ein Upload abgeschlossen */
52
- success: [item: UploadItem];
52
+ success: [item: LtUploadItem];
53
53
  /** Files geaendert */
54
54
  'update:modelValue': [files: File[]];
55
55
  }>();
@@ -58,12 +58,12 @@ const emit = defineEmits<{
58
58
  // Composables
59
59
  // ============================================================================
60
60
  const toast = useToast();
61
- const { formatDuration, formatFileSize } = useFile();
61
+ const { formatDuration, formatFileSize } = useLtFile();
62
62
 
63
63
  // ============================================================================
64
64
  // TUS Upload Setup
65
65
  // ============================================================================
66
- const { addFiles, cancelAll, cancelUpload, clearCompleted, isUploading, pauseAll, pauseUpload, resumeAll, resumeUpload, retryUpload, totalProgress, uploads } = useTusUpload({
66
+ const { addFiles, cancelAll, cancelUpload, clearCompleted, isUploading, pauseAll, pauseUpload, resumeAll, resumeUpload, retryUpload, totalProgress, uploads } = useLtTusUpload({
67
67
  autoStart: props.autoStart,
68
68
  chunkSize: props.chunkSize,
69
69
  endpoint: props.endpoint,
@@ -162,7 +162,7 @@ function getStatusLabel(status: string): string {
162
162
  // ============================================================================
163
163
  // Helpers
164
164
  // ============================================================================
165
- function getUploadForFile(file: File, index: number): undefined | UploadItem {
165
+ function getUploadForFile(file: File, index: number): undefined | LtUploadItem {
166
166
  // Versuche ueber Index zu matchen (funktioniert wenn Reihenfolge gleich)
167
167
  const upload = uploads.value[index];
168
168
  if (upload?.file.name === file.name && upload?.file.size === file.size) {
@@ -1,12 +1,5 @@
1
- export interface User {
2
- banExpires?: Date;
3
- banned?: boolean;
4
- banReason?: string;
5
- email: string;
6
- emailVerified: boolean;
7
- id: string;
8
- image?: string;
9
- name?: string;
10
- role?: string;
11
- twoFactorEnabled?: boolean;
12
- }
1
+ /**
2
+ * Re-export LtUser from @lenne.tech/nuxt-extensions as User
3
+ * This provides backwards compatibility while using the package type
4
+ */
5
+ export type { LtUser as User } from '@lenne.tech/nuxt-extensions';
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import type { NavigationMenuItem } from '@nuxt/ui';
3
3
 
4
- const { isAuthenticated, signOut, user } = useBetterAuth();
4
+ const { isAuthenticated, signOut, user } = useLtAuth();
5
5
 
6
6
  async function handleLogout() {
7
7
  await signOut();
@@ -10,7 +10,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
10
10
  // On client, read directly from document.cookie for accurate state
11
11
  if (import.meta.client) {
12
12
  try {
13
- const cookie = document.cookie.split('; ').find((row) => row.startsWith('auth-state='));
13
+ const cookie = document.cookie.split('; ').find((row) => row.startsWith('lt-auth-state='));
14
14
  if (cookie) {
15
15
  const parts = cookie.split('=');
16
16
  const value = parts.length > 1 ? decodeURIComponent(parts.slice(1).join('=')) : '';
@@ -23,7 +23,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
23
23
  }
24
24
  } else {
25
25
  // On server, use useCookie
26
- const authStateCookie = useCookie<{ user: { role?: string } | null; authMode: string } | null>('auth-state');
26
+ const authStateCookie = useCookie<{ user: { role?: string } | null; authMode: string } | null>('lt-auth-state');
27
27
  isAuthenticated = !!authStateCookie.value?.user;
28
28
  isAdmin = authStateCookie.value?.user?.role === 'admin';
29
29
  }
@@ -9,7 +9,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
9
9
  // On client, read directly from document.cookie for accurate state
10
10
  if (import.meta.client) {
11
11
  try {
12
- const cookie = document.cookie.split('; ').find((row) => row.startsWith('auth-state='));
12
+ const cookie = document.cookie.split('; ').find((row) => row.startsWith('lt-auth-state='));
13
13
  if (cookie) {
14
14
  const parts = cookie.split('=');
15
15
  const value = parts.length > 1 ? decodeURIComponent(parts.slice(1).join('=')) : '';
@@ -21,7 +21,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
21
21
  }
22
22
  } else {
23
23
  // On server, use useCookie
24
- const authStateCookie = useCookie<{ user: unknown; authMode: string } | null>('auth-state');
24
+ const authStateCookie = useCookie<{ user: unknown; authMode: string } | null>('lt-auth-state');
25
25
  isAuthenticated = !!authStateCookie.value?.user;
26
26
  }
27
27
 
@@ -9,7 +9,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
9
9
  // On client, read directly from document.cookie for accurate state
10
10
  if (import.meta.client) {
11
11
  try {
12
- const cookie = document.cookie.split('; ').find((row) => row.startsWith('auth-state='));
12
+ const cookie = document.cookie.split('; ').find((row) => row.startsWith('lt-auth-state='));
13
13
  if (cookie) {
14
14
  const parts = cookie.split('=');
15
15
  const value = parts.length > 1 ? decodeURIComponent(parts.slice(1).join('=')) : '';
@@ -21,7 +21,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
21
21
  }
22
22
  } else {
23
23
  // On server, use useCookie
24
- const authStateCookie = useCookie<{ user: unknown; authMode: string } | null>('auth-state');
24
+ const authStateCookie = useCookie<{ user: unknown; authMode: string } | null>('lt-auth-state');
25
25
  isAuthenticated = !!authStateCookie.value?.user;
26
26
  }
27
27
 
@@ -2,7 +2,7 @@
2
2
  // ============================================================================
3
3
  // Composables
4
4
  // ============================================================================
5
- const { user, signOut } = useBetterAuth();
5
+ const { user, signOut } = useLtAuth();
6
6
 
7
7
  // ============================================================================
8
8
  // Variables
@@ -8,7 +8,6 @@ import type { InferOutput } from 'valibot';
8
8
  import * as v from 'valibot';
9
9
 
10
10
  import ModalBackupCodes from '~/components/Modal/ModalBackupCodes.vue';
11
- import { authClient } from '~/lib/auth-client';
12
11
 
13
12
  // ============================================================================
14
13
  // Interfaces
@@ -24,7 +23,8 @@ interface Passkey {
24
23
  // ============================================================================
25
24
  const toast = useToast();
26
25
  const overlay = useOverlay();
27
- const { is2FAEnabled, registerPasskey, setUser, user } = useBetterAuth();
26
+ const { is2FAEnabled, registerPasskey, setUser, user } = useLtAuth();
27
+ const authClient = useLtAuthClient();
28
28
 
29
29
  // ============================================================================
30
30
  // Variables
@@ -7,13 +7,12 @@ import type { InferOutput } from 'valibot';
7
7
 
8
8
  import * as v from 'valibot';
9
9
 
10
- import { authClient } from '~/lib/auth-client';
11
-
12
10
  // ============================================================================
13
11
  // Composables
14
12
  // ============================================================================
15
13
  const toast = useToast();
16
- const { fetchWithAuth, setUser, switchToJwtMode, jwtToken } = useBetterAuth();
14
+ const { fetchWithAuth, setUser, switchToJwtMode, jwtToken } = useLtAuth();
15
+ const authClient = useLtAuthClient();
17
16
 
18
17
  // ============================================================================
19
18
  // Page Meta
@@ -7,7 +7,8 @@ import type { InferOutput } from 'valibot';
7
7
 
8
8
  import * as v from 'valibot';
9
9
 
10
- import { authClient } from '~/lib/auth-client';
10
+ // Auth client from @lenne.tech/nuxt-extensions (auto-imported as ltAuthClient)
11
+ const authClient = ltAuthClient;
11
12
 
12
13
  // ============================================================================
13
14
  // Composables
@@ -11,7 +11,7 @@ import * as v from 'valibot';
11
11
  // Composables
12
12
  // ============================================================================
13
13
  const toast = useToast();
14
- const { signIn, setUser, isLoading, validateSession, authenticateWithPasskey } = useBetterAuth();
14
+ const { signIn, setUser, isLoading, validateSession, authenticateWithPasskey } = useLtAuth();
15
15
 
16
16
  // ============================================================================
17
17
  // Page Meta
@@ -135,7 +135,7 @@ async function onSubmit(payload: FormSubmitEvent<Schema>): Promise<void> {
135
135
  // Check if login was successful (user data in response)
136
136
  const userData = 'user' in result ? result.user : 'data' in result ? result.data?.user : null;
137
137
  if (userData) {
138
- // Auth state is already stored by useBetterAuth
138
+ // Auth state is already stored by useLtAuth
139
139
  // Navigate to app
140
140
  await navigateTo('/app');
141
141
  } else {
@@ -11,7 +11,7 @@ import * as v from 'valibot';
11
11
  // Composables
12
12
  // ============================================================================
13
13
  const toast = useToast();
14
- const { signUp, signIn, registerPasskey } = useBetterAuth();
14
+ const { signUp, signIn, registerPasskey } = useLtAuth();
15
15
 
16
16
  // ============================================================================
17
17
  // Page Meta
@@ -7,7 +7,8 @@ import type { InferOutput } from 'valibot';
7
7
 
8
8
  import * as v from 'valibot';
9
9
 
10
- import { authClient } from '~/lib/auth-client';
10
+ // Auth client from @lenne.tech/nuxt-extensions (auto-imported as ltAuthClient)
11
+ const authClient = ltAuthClient;
11
12
 
12
13
  // ============================================================================
13
14
  // Composables
@@ -182,7 +182,7 @@ async function handleFormSubmit(): Promise<void> {
182
182
  }
183
183
 
184
184
  async function handleShare(): Promise<void> {
185
- const { share } = useShare();
185
+ const { share } = useLtShare();
186
186
  await share('Nuxt Base Starter', 'Check out this Nuxt Base Starter Template!', window.location.href);
187
187
 
188
188
  toast.add({
@@ -67,12 +67,36 @@ export default defineNuxtConfig({
67
67
  dirs: ['./states', './stores', './forms', './interfaces', './base', './plugins'],
68
68
  },
69
69
 
70
+ // ============================================================================
71
+ // lenne.tech Nuxt Extensions
72
+ // ============================================================================
73
+ ltExtensions: {
74
+ auth: {
75
+ enabled: true,
76
+ basePath: '/iam',
77
+ loginPath: '/auth/login',
78
+ twoFactorRedirectPath: '/auth/2fa',
79
+ enableAdmin: true,
80
+ enableTwoFactor: true,
81
+ enablePasskey: true,
82
+ interceptor: {
83
+ enabled: true,
84
+ publicPaths: ['/auth/login', '/auth/register', '/auth/forgot-password', '/auth/reset-password'],
85
+ },
86
+ },
87
+ tus: {
88
+ defaultEndpoint: '/files/upload',
89
+ defaultChunkSize: 5 * 1024 * 1024,
90
+ },
91
+ },
92
+
70
93
  // ============================================================================
71
94
  // Nuxt Modules
72
95
  // ============================================================================
73
96
  modules: [
97
+ '@lenne.tech/nuxt-extensions', // Auth, Upload, Transitions
74
98
  '@nuxt/test-utils/module', // E2E testing with Playwright
75
- '@lenne.tech/bug.lt', // Bug reporting to Linear
99
+ // '@lenne.tech/bug.lt', // Bug reporting to Linear - TEMPORARILY DISABLED FOR TESTING
76
100
  '@vueuse/nuxt', // Vue composition utilities
77
101
  'dayjs-nuxt', // Date/time handling
78
102
  '@nuxt/image', // Image optimization
@@ -158,5 +182,18 @@ export default defineNuxtConfig({
158
182
  exclude: ['@tailwindcss/vite', 'lightningcss', '@vue/devtools-core', '@vue/devtools-kit', '@internationalized/date'],
159
183
  },
160
184
  plugins: [tailwindcss()],
185
+ server: {
186
+ proxy: {
187
+ '/api': {
188
+ target: 'http://localhost:3000',
189
+ changeOrigin: true,
190
+ rewrite: (path: string) => path.replace(/^\/api/, ''),
191
+ },
192
+ '/iam': {
193
+ target: 'http://localhost:3000',
194
+ changeOrigin: true,
195
+ },
196
+ },
197
+ },
161
198
  },
162
199
  });