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.
- package/CHANGELOG.md +33 -0
- package/nuxt-base-template/app/components/Modal/ModalBackupCodes.vue +2 -1
- package/nuxt-base-template/app/components/Upload/TusFileUpload.vue +7 -7
- package/nuxt-base-template/app/interfaces/user.interface.ts +5 -12
- package/nuxt-base-template/app/layouts/default.vue +1 -1
- package/nuxt-base-template/app/middleware/admin.global.ts +2 -2
- package/nuxt-base-template/app/middleware/auth.global.ts +2 -2
- package/nuxt-base-template/app/middleware/guest.global.ts +2 -2
- package/nuxt-base-template/app/pages/app/index.vue +1 -1
- package/nuxt-base-template/app/pages/app/settings/security.vue +2 -2
- package/nuxt-base-template/app/pages/auth/2fa.vue +2 -3
- package/nuxt-base-template/app/pages/auth/forgot-password.vue +2 -1
- package/nuxt-base-template/app/pages/auth/login.vue +2 -2
- package/nuxt-base-template/app/pages/auth/register.vue +1 -1
- package/nuxt-base-template/app/pages/auth/reset-password.vue +2 -1
- package/nuxt-base-template/docs/pages/docs.vue +1 -1
- package/nuxt-base-template/nuxt.config.ts +38 -1
- package/nuxt-base-template/package-lock.json +136 -2905
- package/nuxt-base-template/package.json +1 -0
- package/package.json +1 -1
- package/nuxt-base-template/app/components/Transition/TransitionFade.vue +0 -27
- package/nuxt-base-template/app/components/Transition/TransitionFadeScale.vue +0 -27
- package/nuxt-base-template/app/components/Transition/TransitionSlide.vue +0 -12
- package/nuxt-base-template/app/components/Transition/TransitionSlideBottom.vue +0 -12
- package/nuxt-base-template/app/components/Transition/TransitionSlideRevert.vue +0 -12
- package/nuxt-base-template/app/composables/use-better-auth.ts +0 -597
- package/nuxt-base-template/app/composables/use-file.ts +0 -71
- package/nuxt-base-template/app/composables/use-share.ts +0 -38
- package/nuxt-base-template/app/composables/use-tus-upload.ts +0 -278
- package/nuxt-base-template/app/composables/use-tw.ts +0 -1
- package/nuxt-base-template/app/interfaces/upload.interface.ts +0 -58
- package/nuxt-base-template/app/lib/auth-client.ts +0 -229
- package/nuxt-base-template/app/lib/auth-state.ts +0 -206
- package/nuxt-base-template/app/plugins/auth-interceptor.client.ts +0 -151
- 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
|
-
|
|
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 {
|
|
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:
|
|
48
|
+
complete: [items: LtUploadItem[]];
|
|
49
49
|
/** Upload-Fehler */
|
|
50
|
-
error: [item:
|
|
50
|
+
error: [item: LtUploadItem, error: Error];
|
|
51
51
|
/** Ein Upload abgeschlossen */
|
|
52
|
-
success: [item:
|
|
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 } =
|
|
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 } =
|
|
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 |
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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';
|
|
@@ -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 } =
|
|
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 } =
|
|
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 } =
|
|
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
|
-
|
|
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 } =
|
|
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
|
|
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 } =
|
|
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
|
-
|
|
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 } =
|
|
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
|
});
|