create-nuxt-base 0.3.17 → 1.0.2

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 (41) hide show
  1. package/.github/workflows/publish.yml +4 -2
  2. package/.oxfmtrc.jsonc +7 -0
  3. package/CHANGELOG.md +20 -8
  4. package/nuxt-base-template/.dockerignore +44 -0
  5. package/nuxt-base-template/.nuxtrc +1 -0
  6. package/nuxt-base-template/.oxfmtrc.jsonc +8 -0
  7. package/nuxt-base-template/Dockerfile.dev +23 -0
  8. package/nuxt-base-template/app/components/Modal/ModalBackupCodes.vue +117 -0
  9. package/nuxt-base-template/app/components/Upload/TusFileUpload.vue +302 -0
  10. package/nuxt-base-template/app/composables/use-better-auth.ts +25 -0
  11. package/nuxt-base-template/app/composables/use-file.ts +39 -4
  12. package/nuxt-base-template/app/composables/use-share.ts +1 -1
  13. package/nuxt-base-template/app/composables/use-tus-upload.ts +278 -0
  14. package/nuxt-base-template/app/interfaces/upload.interface.ts +58 -0
  15. package/nuxt-base-template/app/interfaces/user.interface.ts +12 -0
  16. package/nuxt-base-template/app/lib/auth-client.ts +135 -0
  17. package/nuxt-base-template/app/middleware/admin.global.ts +23 -0
  18. package/nuxt-base-template/app/middleware/auth.global.ts +18 -0
  19. package/nuxt-base-template/app/middleware/guest.global.ts +18 -0
  20. package/nuxt-base-template/app/pages/app/settings/security.vue +409 -0
  21. package/nuxt-base-template/app/pages/auth/2fa.vue +120 -0
  22. package/nuxt-base-template/app/pages/auth/forgot-password.vue +72 -21
  23. package/nuxt-base-template/app/pages/auth/login.vue +75 -11
  24. package/nuxt-base-template/app/pages/auth/register.vue +184 -0
  25. package/nuxt-base-template/app/pages/auth/reset-password.vue +153 -0
  26. package/nuxt-base-template/app/utils/crypto.ts +13 -0
  27. package/nuxt-base-template/docker-entrypoint.sh +21 -0
  28. package/nuxt-base-template/nuxt.config.ts +4 -1
  29. package/nuxt-base-template/oxlint.json +14 -0
  30. package/nuxt-base-template/package-lock.json +11582 -10675
  31. package/nuxt-base-template/package.json +35 -32
  32. package/nuxt-base-template/tests/iam.spec.ts +247 -0
  33. package/package.json +14 -11
  34. package/.eslintignore +0 -14
  35. package/.eslintrc +0 -3
  36. package/.prettierignore +0 -5
  37. package/.prettierrc +0 -6
  38. package/nuxt-base-template/CLAUDE.md +0 -361
  39. package/nuxt-base-template/app/pages/auth/reset-password/[token].vue +0 -110
  40. package/nuxt-base-template/app/public/favicon.ico +0 -0
  41. package/nuxt-base-template/eslint.config.mjs +0 -4
@@ -2,9 +2,12 @@
2
2
  "name": "nuxt-base-template",
3
3
  "private": true,
4
4
  "type": "module",
5
- "engines": {
6
- "node": ">=22",
7
- "npm": ">=10"
5
+ "exports": {
6
+ ".": {
7
+ "import": {
8
+ "node": "./tslib.es6.mjs"
9
+ }
10
+ }
8
11
  },
9
12
  "scripts": {
10
13
  "init": "npm install",
@@ -27,47 +30,47 @@
27
30
  "postinstall": "nuxt prepare",
28
31
  "test": "npm run test:e2e",
29
32
  "test:e2e": "playwright test",
30
- "lint": "eslint 'app/**/*.{ts,js,vue}'",
31
- "lint:fix": "eslint 'app/**/*.{ts,js,vue}' --fix",
32
- "format": "prettier --write .",
33
- "format:check": "prettier --check .",
33
+ "lint": "oxlint app/",
34
+ "lint:fix": "oxlint --fix app/",
35
+ "format": "oxfmt",
36
+ "format:check": "oxfmt --check",
34
37
  "check": "npm run lint && npm run format:check",
35
38
  "fix": "npm run lint:fix && npm run format"
36
39
  },
37
40
  "dependencies": {
41
+ "@better-auth/passkey": "1.4.10",
38
42
  "@hey-api/client-fetch": "0.13.1",
39
43
  "@lenne.tech/bug.lt": "latest",
40
- "@nuxt/image": "1.11.0",
41
- "@nuxt/ui": "4.0.1",
42
- "@pinia/nuxt": "0.11.2",
43
- "@vueuse/nuxt": "13.9.0",
44
- "valibot": "1.1.0"
44
+ "@nuxt/image": "2.0.0",
45
+ "@nuxt/ui": "4.3.0",
46
+ "@pinia/nuxt": "0.11.3",
47
+ "@vueuse/nuxt": "14.1.0",
48
+ "better-auth": "1.4.10",
49
+ "tus-js-client": "4.3.1",
50
+ "valibot": "1.2.0"
45
51
  },
46
52
  "devDependencies": {
47
- "@hey-api/openapi-ts": "0.85.2",
48
- "@lenne.tech/eslint-config-vue": "2.1.4",
49
- "@nuxt/devtools": "2.6.5",
50
- "@nuxt/test-utils": "3.19.2",
51
- "@nuxtjs/color-mode": "3.5.2",
53
+ "@hey-api/openapi-ts": "0.90.3",
54
+ "@nuxt/devtools": "3.1.1",
55
+ "@nuxt/test-utils": "3.23.0",
56
+ "@nuxtjs/color-mode": "4.0.0",
52
57
  "@nuxtjs/plausible": "2.0.1",
53
- "@nuxtjs/seo": "3.2.2",
54
- "@playwright/test": "1.56.1",
58
+ "@nuxtjs/seo": "3.3.0",
59
+ "@playwright/test": "1.57.0",
55
60
  "@tailwindcss/typography": "0.5.19",
56
- "@tailwindcss/vite": "4.1.14",
57
- "@types/node": "24.8.1",
61
+ "@tailwindcss/vite": "4.1.18",
62
+ "@types/node": "25.0.6",
58
63
  "dayjs-nuxt": "2.1.11",
59
- "eslint": "9.37.0",
60
- "jsdom": "26.1.0",
61
- "nuxt": "4.1.3",
62
- "rimraf": "6.0.1",
63
- "tailwindcss": "4.1.14",
64
+ "jsdom": "27.4.0",
65
+ "nuxt": "4.2.2",
66
+ "oxfmt": "latest",
67
+ "oxlint": "latest",
68
+ "rimraf": "6.1.2",
69
+ "tailwindcss": "4.1.18",
64
70
  "typescript": "5.9.3"
65
71
  },
66
- "exports": {
67
- ".": {
68
- "import": {
69
- "node": "./tslib.es6.mjs"
70
- }
71
- }
72
+ "engines": {
73
+ "node": ">=22",
74
+ "npm": ">=10"
72
75
  }
73
76
  }
@@ -0,0 +1,247 @@
1
+ import { expect, test } from '@nuxt/test-utils/playwright';
2
+
3
+ import { authClient, type AuthResponse } from '../app/lib/auth-client';
4
+
5
+ /**
6
+ * IAM E2E Tests using Better-Auth Client
7
+ *
8
+ * These tests use the Better-Auth client library directly to communicate
9
+ * with the /iam API endpoints on the running API server.
10
+ *
11
+ * Test flow: Test Runner → Better-Auth Client → API Server (/iam endpoints)
12
+ *
13
+ * Prerequisites:
14
+ * - API server running on http://localhost:3000
15
+ *
16
+ * NOTE: These tests are for DEMO purposes only. If the API server is not
17
+ * running, tests will be skipped with a warning (not treated as failure).
18
+ */
19
+
20
+ // Flag to track API availability - checked once in beforeAll
21
+ let apiAvailable = false;
22
+
23
+ test.describe.serial('IAM Better-Auth Client Tests', () => {
24
+ // Shared test user credentials - created once in the first test
25
+ const testId = Date.now();
26
+ const testEmail = `playwright-${testId}@iam-test.com`;
27
+ const testPassword = `TestPass${testId}!`;
28
+ const testName = 'Playwright Test User';
29
+
30
+ test.beforeAll(async ({ request }) => {
31
+ // Check if the API server is running
32
+ try {
33
+ const response = await request.get('http://localhost:3000/');
34
+ if (response.ok()) {
35
+ apiAvailable = true;
36
+ console.info('✓ API Server is running at http://localhost:3000');
37
+ }
38
+ } catch (_error) {
39
+ // API is not available - will be handled below
40
+ }
41
+
42
+ if (!apiAvailable) {
43
+ console.warn('');
44
+ console.warn('⚠️ ═══════════════════════════════════════════════════════════');
45
+ console.warn('⚠️ WARNING: API Server is not running!');
46
+ console.warn('⚠️');
47
+ console.warn('⚠️ IAM tests will be SKIPPED (demo tests only)');
48
+ console.warn('⚠️');
49
+ console.warn('⚠️ To run these tests, start the API server first:');
50
+ console.warn('⚠️ cd projects/api && npm start');
51
+ console.warn('⚠️');
52
+ console.warn('⚠️ Then run the tests:');
53
+ console.warn('⚠️ cd projects/app && npm run test:e2e');
54
+ console.warn('⚠️ ═══════════════════════════════════════════════════════════');
55
+ console.warn('');
56
+ }
57
+ });
58
+
59
+ // =========================================================================
60
+ // Sign-Up Tests
61
+ // =========================================================================
62
+
63
+ test('1. should sign up a new user via Better-Auth client', async () => {
64
+ test.skip(!apiAvailable, 'API server not running - skipping demo test');
65
+
66
+ const response = (await authClient.signUp.email({
67
+ email: testEmail,
68
+ name: testName,
69
+ password: testPassword,
70
+ })) as AuthResponse;
71
+
72
+ expect(response.error).toBeNull();
73
+ expect(response.data?.user?.email).toBe(testEmail);
74
+ console.info(` ✓ User registered: ${testEmail}`);
75
+ });
76
+
77
+ test('2. should fail sign-up with existing email', async () => {
78
+ test.skip(!apiAvailable, 'API server not running - skipping demo test');
79
+
80
+ const response = (await authClient.signUp.email({
81
+ email: testEmail,
82
+ name: testName,
83
+ password: testPassword,
84
+ })) as AuthResponse;
85
+
86
+ // Better-Auth returns error in response for duplicate email
87
+ expect(response.error).not.toBeNull();
88
+ console.info(' ✓ Duplicate registration correctly rejected');
89
+ });
90
+
91
+ // =========================================================================
92
+ // Sign-In Tests
93
+ // =========================================================================
94
+
95
+ test('3. should sign in with valid credentials', async () => {
96
+ test.skip(!apiAvailable, 'API server not running - skipping demo test');
97
+
98
+ const response = (await authClient.signIn.email({
99
+ email: testEmail,
100
+ password: testPassword,
101
+ })) as AuthResponse;
102
+
103
+ expect(response.error).toBeNull();
104
+ expect(response.data?.user?.email).toBe(testEmail);
105
+ expect(response.data?.user).toBeDefined();
106
+ expect(response.data?.token).toBeDefined(); // JWT token - presence indicates success
107
+ console.info(` ✓ User signed in: ${testEmail}`);
108
+ });
109
+
110
+ test('4. should fail sign-in with wrong password', async () => {
111
+ test.skip(!apiAvailable, 'API server not running - skipping demo test');
112
+
113
+ const response = (await authClient.signIn.email({
114
+ email: testEmail,
115
+ password: 'WrongPassword123!',
116
+ })) as AuthResponse;
117
+
118
+ expect(response.error).not.toBeNull();
119
+ console.info(' ✓ Wrong password correctly rejected');
120
+ });
121
+
122
+ test('5. should fail sign-in with non-existent email', async () => {
123
+ test.skip(!apiAvailable, 'API server not running - skipping demo test');
124
+
125
+ const response = (await authClient.signIn.email({
126
+ email: 'nonexistent@iam-test.com',
127
+ password: 'SomePassword123!',
128
+ })) as AuthResponse;
129
+
130
+ expect(response.error).not.toBeNull();
131
+ console.info(' ✓ Non-existent user correctly rejected');
132
+ });
133
+
134
+ // =========================================================================
135
+ // Session Tests
136
+ // =========================================================================
137
+
138
+ test('6. should get session after sign-in', async () => {
139
+ test.skip(!apiAvailable, 'API server not running - skipping demo test');
140
+
141
+ // First sign in
142
+ const signInResponse = (await authClient.signIn.email({
143
+ email: testEmail,
144
+ password: testPassword,
145
+ })) as AuthResponse;
146
+ expect(signInResponse.error).toBeNull();
147
+
148
+ // Verify user data is returned (session details depend on JWT/cookie mode)
149
+ expect(signInResponse.data?.user).toBeDefined();
150
+ expect(signInResponse.data?.user?.email).toBe(testEmail);
151
+
152
+ console.info(' ✓ Sign-in successful, user data received');
153
+ });
154
+
155
+ // =========================================================================
156
+ // Sign-Out Tests
157
+ // =========================================================================
158
+
159
+ test('7. should sign out successfully', async () => {
160
+ test.skip(!apiAvailable, 'API server not running - skipping demo test');
161
+
162
+ // First sign in
163
+ const signInResponse = (await authClient.signIn.email({
164
+ email: testEmail,
165
+ password: testPassword,
166
+ })) as AuthResponse;
167
+ expect(signInResponse.error).toBeNull();
168
+
169
+ // Then sign out - a Better-Auth client handles cookies internally
170
+ await authClient.signOut();
171
+
172
+ // Sign-out should succeed
173
+ console.info(' ✓ Sign-out completed');
174
+ });
175
+
176
+ // =========================================================================
177
+ // Full Authentication Flow
178
+ // =========================================================================
179
+
180
+ test('8. should complete full auth flow: sign-up -> sign-in -> sign-out', async () => {
181
+ test.skip(!apiAvailable, 'API server not running - skipping demo test');
182
+
183
+ const flowEmail = `flow-${Date.now()}@iam-test.com`;
184
+ const flowPassword = `FlowPass${Date.now()}!`;
185
+ const flowName = 'Flow Test User';
186
+
187
+ // Step 1: Sign Up
188
+ const signUpRes = (await authClient.signUp.email({
189
+ email: flowEmail,
190
+ name: flowName,
191
+ password: flowPassword,
192
+ })) as AuthResponse;
193
+ expect(signUpRes.error).toBeNull();
194
+ expect(signUpRes.data?.user?.email).toBe(flowEmail);
195
+ console.info(' ✓ Step 1: Sign-up successful');
196
+
197
+ // Step 2: Sign In
198
+ const signInRes = (await authClient.signIn.email({
199
+ email: flowEmail,
200
+ password: flowPassword,
201
+ })) as AuthResponse;
202
+ expect(signInRes.error).toBeNull();
203
+ expect(signInRes.data?.user?.email).toBe(flowEmail);
204
+ expect(signInRes.data?.user).toBeDefined();
205
+ console.info(' ✓ Step 2: Sign-in successful');
206
+
207
+ // Step 3: Sign Out
208
+ await authClient.signOut();
209
+ console.info(' ✓ Step 3: Sign-out successful');
210
+ });
211
+
212
+ // =========================================================================
213
+ // Response Structure Tests
214
+ // =========================================================================
215
+
216
+ test('9. sign-in response should have correct structure', async () => {
217
+ test.skip(!apiAvailable, 'API server not running - skipping demo test');
218
+
219
+ const response = (await authClient.signIn.email({
220
+ email: testEmail,
221
+ password: testPassword,
222
+ })) as AuthResponse;
223
+
224
+ expect(response.error).toBeNull();
225
+ expect(response.data).toBeDefined();
226
+ expect(response.data?.user).toBeDefined();
227
+ expect(response.data?.user?.id).toBeDefined();
228
+ expect(response.data?.user?.email).toBe(testEmail);
229
+ // User object should have core fields
230
+ expect(response.data?.user?.name).toBeDefined();
231
+ console.info(' ✓ Response structure validated');
232
+ });
233
+
234
+ test('10. error response should have correct structure', async () => {
235
+ test.skip(!apiAvailable, 'API server not running - skipping demo test');
236
+
237
+ const response = (await authClient.signIn.email({
238
+ email: 'invalid@iam-test.com',
239
+ password: 'wrongPassword',
240
+ })) as AuthResponse;
241
+
242
+ expect(response.error).not.toBeNull();
243
+ expect(response.error?.message).toBeDefined();
244
+ expect(response.error?.status).toBeDefined();
245
+ console.info(' ✓ Error response structure validated');
246
+ });
247
+ });
package/package.json CHANGED
@@ -1,30 +1,33 @@
1
1
  {
2
2
  "name": "create-nuxt-base",
3
- "version": "0.3.17",
3
+ "version": "1.0.2",
4
4
  "description": "Starter to generate a configured environment with VueJS, Nuxt, Tailwind, Eslint, Unit Tests, Playwright etc.",
5
- "main": "index.js",
6
- "engines": {
7
- "node": ">=22",
8
- "npm": ">=10"
5
+ "license": "MIT",
6
+ "repository": {
7
+ "url": "https://github.com/lenneTech/nuxt-base-starter"
9
8
  },
9
+ "author": "lenne.Tech GmbH",
10
10
  "bin": {
11
11
  "create-nuxt-base": "./index.js"
12
12
  },
13
+ "main": "index.js",
13
14
  "scripts": {
14
- "prettier": "prettier \"*.{js,json,yml,md,html,ts}\" .",
15
- "format": "npm run prettier -- --write",
15
+ "format": "oxfmt",
16
+ "format:check": "oxfmt --check",
16
17
  "release": "standard-version && git push --follow-tags origin main",
17
18
  "release:minor": "standard-version --release-as minor && git push --follow-tags origin main",
18
19
  "release:major": "standard-version --release-as major && git push --follow-tags origin main"
19
20
  },
20
- "author": "lenne.Tech GmbH",
21
- "license": "MIT",
22
21
  "dependencies": {
23
22
  "cross-spawn": "7.0.6",
24
- "fs-extra": "11.3.2"
23
+ "fs-extra": "11.3.3"
25
24
  },
26
25
  "devDependencies": {
27
- "prettier": "3.6.2",
26
+ "oxfmt": "latest",
28
27
  "standard-version": "9.5.0"
28
+ },
29
+ "engines": {
30
+ "node": ">=22",
31
+ "npm": ">=10"
29
32
  }
30
33
  }
package/.eslintignore DELETED
@@ -1,14 +0,0 @@
1
- *.md
2
- .gitignore
3
- .eslintrc
4
- package.json
5
- package-lock.json
6
- README.md
7
- vitest.config.js
8
- tailwind.config.js
9
- .lintstagedrc
10
- .husky
11
- yarn.lock
12
- .gitlab-ci.yml
13
- lerna.json
14
- assets/**
package/.eslintrc DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "extends": "@lenne.tech/vue"
3
- }
package/.prettierignore DELETED
@@ -1,5 +0,0 @@
1
- .nuxt
2
- .output
3
- node_modules
4
- dist
5
- .env
package/.prettierrc DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "arrowParens": "always",
3
- "printWidth": 180,
4
- "semi": true,
5
- "singleQuote": true
6
- }