@main12/auth-login 0.1.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 (59) hide show
  1. package/README.md +218 -0
  2. package/dist/auth/application/hooks/useForgotPasswordFlow.d.ts +10 -0
  3. package/dist/auth/application/hooks/useForgotPasswordFlow.js +45 -0
  4. package/dist/auth/application/hooks/useLoginFlow.d.ts +30 -0
  5. package/dist/auth/application/hooks/useLoginFlow.js +105 -0
  6. package/dist/auth/application/hooks/useSetPasswordFlow.d.ts +18 -0
  7. package/dist/auth/application/hooks/useSetPasswordFlow.js +59 -0
  8. package/dist/auth/application/hooks/useVerifyOtpFlow.d.ts +18 -0
  9. package/dist/auth/application/hooks/useVerifyOtpFlow.js +84 -0
  10. package/dist/auth/application/services/authService.d.ts +26 -0
  11. package/dist/auth/application/services/authService.js +90 -0
  12. package/dist/auth/domain/otp.d.ts +25 -0
  13. package/dist/auth/domain/otp.js +41 -0
  14. package/dist/auth/domain/passwordRules.d.ts +12 -0
  15. package/dist/auth/domain/passwordRules.js +34 -0
  16. package/dist/auth/domain/types.d.ts +35 -0
  17. package/dist/auth/domain/types.js +2 -0
  18. package/dist/components/AuthLayout.d.ts +20 -0
  19. package/dist/components/AuthLayout.js +49 -0
  20. package/dist/components/PoweredBy.d.ts +10 -0
  21. package/dist/components/PoweredBy.js +50 -0
  22. package/dist/components/email/baseTemplate.d.ts +13 -0
  23. package/dist/components/email/baseTemplate.js +69 -0
  24. package/dist/components/email/constants.d.ts +26 -0
  25. package/dist/components/email/constants.js +30 -0
  26. package/dist/components/email/index.d.ts +7 -0
  27. package/dist/components/email/index.js +7 -0
  28. package/dist/components/email/templates/otp.d.ts +16 -0
  29. package/dist/components/email/templates/otp.js +38 -0
  30. package/dist/components/email/templates/passwordChanged.d.ts +15 -0
  31. package/dist/components/email/templates/passwordChanged.js +33 -0
  32. package/dist/components/email/templates/passwordReset.d.ts +15 -0
  33. package/dist/components/email/templates/passwordReset.js +36 -0
  34. package/dist/components/email/templates/welcome.d.ts +16 -0
  35. package/dist/components/email/templates/welcome.js +38 -0
  36. package/dist/components/email/translations.d.ts +45 -0
  37. package/dist/components/email/translations.js +88 -0
  38. package/dist/components/pages/ForgotPasswordPage.d.ts +5 -0
  39. package/dist/components/pages/ForgotPasswordPage.js +45 -0
  40. package/dist/components/pages/LoginPage.d.ts +11 -0
  41. package/dist/components/pages/LoginPage.js +222 -0
  42. package/dist/components/pages/SetPasswordPage.d.ts +5 -0
  43. package/dist/components/pages/SetPasswordPage.js +74 -0
  44. package/dist/components/pages/SignupPage.d.ts +10 -0
  45. package/dist/components/pages/SignupPage.js +129 -0
  46. package/dist/components/pages/VerifyOtpPage.d.ts +5 -0
  47. package/dist/components/pages/VerifyOtpPage.js +87 -0
  48. package/dist/components/ui/index.d.ts +57 -0
  49. package/dist/components/ui/index.js +121 -0
  50. package/dist/css.d.js +0 -0
  51. package/dist/endpoints/authEndpoints.d.ts +22 -0
  52. package/dist/endpoints/authEndpoints.js +422 -0
  53. package/dist/exports/client.d.ts +24 -0
  54. package/dist/exports/client.js +22 -0
  55. package/dist/exports/rsc.d.ts +6 -0
  56. package/dist/exports/rsc.js +5 -0
  57. package/dist/index.d.ts +12 -0
  58. package/dist/index.js +16 -0
  59. package/package.json +115 -0
@@ -0,0 +1,422 @@
1
+ import { generateOtp, hashOtp, verifyOtp, getOtpExpiry, isOtpExpired } from '../auth/domain/otp.js';
2
+ import { generateWelcomeEmail, generateOtpEmail } from '../components/email/index.js';
3
+ /**
4
+ * POST /api/auth/check-email — Check if user exists and has password
5
+ */ export const checkEmailEndpoint = {
6
+ path: '/api/auth/check-email',
7
+ method: 'post',
8
+ handler: async (req)=>{
9
+ const { email } = req.json ? await req.json() : req.body || {};
10
+ if (!email) return Response.json({
11
+ error: 'Email is required'
12
+ }, {
13
+ status: 400
14
+ });
15
+ try {
16
+ const users = await req.payload.find({
17
+ collection: 'users',
18
+ where: {
19
+ email: {
20
+ equals: email.toLowerCase().trim()
21
+ }
22
+ },
23
+ limit: 1
24
+ });
25
+ if (!users.docs?.length) {
26
+ return Response.json({
27
+ exists: false,
28
+ hasPassword: false,
29
+ authProvider: null
30
+ });
31
+ }
32
+ const user = users.docs[0];
33
+ return Response.json({
34
+ exists: true,
35
+ hasPassword: !!user.password,
36
+ authProvider: user.authProvider || null
37
+ });
38
+ } catch (err) {
39
+ return Response.json({
40
+ error: 'Failed to check email'
41
+ }, {
42
+ status: 500
43
+ });
44
+ }
45
+ }
46
+ };
47
+ /**
48
+ * POST /api/auth/otp/send — Generate OTP, store it, send email via Payload
49
+ */ export const sendOtpEndpoint = {
50
+ path: '/api/auth/otp/send',
51
+ method: 'post',
52
+ handler: async (req)=>{
53
+ const body = req.json ? await req.json() : req.body || {};
54
+ const { email, purpose = 'login' } = body;
55
+ if (!email) return Response.json({
56
+ success: false,
57
+ message: 'Email is required'
58
+ }, {
59
+ status: 400
60
+ });
61
+ try {
62
+ // Check user exists
63
+ const users = await req.payload.find({
64
+ collection: 'users',
65
+ where: {
66
+ email: {
67
+ equals: email.toLowerCase().trim()
68
+ }
69
+ },
70
+ limit: 1
71
+ });
72
+ if (!users.docs?.length) {
73
+ return Response.json({
74
+ success: false,
75
+ message: 'No account found with this email'
76
+ }, {
77
+ status: 404
78
+ });
79
+ }
80
+ const user = users.docs[0];
81
+ const otp = generateOtp();
82
+ const hashed = hashOtp(otp);
83
+ const expiresAt = getOtpExpiry(10);
84
+ // Store OTP in a custom collection or users doc
85
+ // For simplicity, we'll use the users collection with an otp field
86
+ // In production, use a dedicated `otps` collection
87
+ try {
88
+ await req.payload.update({
89
+ collection: 'users',
90
+ id: user.id,
91
+ data: {
92
+ otpHash: hashed,
93
+ otpPurpose: purpose,
94
+ otpAttempts: 0,
95
+ otpExpiresAt: expiresAt.toISOString()
96
+ }
97
+ });
98
+ } catch {
99
+ // If the users collection doesn't have OTP fields, create a dedicated otps doc
100
+ await req.payload.create({
101
+ collection: 'otps',
102
+ data: {
103
+ email: email.toLowerCase().trim(),
104
+ hash: hashed,
105
+ purpose,
106
+ attempts: 0,
107
+ expiresAt: expiresAt.toISOString()
108
+ }
109
+ });
110
+ }
111
+ // Send email via Payload's configured adapter
112
+ const emailResult = purpose === 'signup' ? generateOtpEmail({
113
+ userName: user.name || user.email,
114
+ otp,
115
+ purpose: 'login'
116
+ }) : generateOtpEmail({
117
+ userName: user.name || user.email,
118
+ otp,
119
+ purpose: purpose
120
+ });
121
+ await req.payload.sendEmail({
122
+ to: email,
123
+ subject: emailResult.subject,
124
+ html: emailResult.html
125
+ });
126
+ return Response.json({
127
+ success: true
128
+ });
129
+ } catch (err) {
130
+ console.error('OTP send error:', err);
131
+ return Response.json({
132
+ success: false,
133
+ message: err.message || 'Failed to send OTP'
134
+ }, {
135
+ status: 500
136
+ });
137
+ }
138
+ }
139
+ };
140
+ /**
141
+ * POST /api/auth/otp/verify — Verify OTP and login the user
142
+ */ export const verifyOtpEndpoint = {
143
+ path: '/api/auth/otp/verify',
144
+ method: 'post',
145
+ handler: async (req)=>{
146
+ const body = req.json ? await req.json() : req.body || {};
147
+ const { email, otp } = body;
148
+ if (!email || !otp) return Response.json({
149
+ success: false,
150
+ error: 'Email and OTP are required'
151
+ }, {
152
+ status: 400
153
+ });
154
+ try {
155
+ // Find OTP record — try users collection first
156
+ const users = await req.payload.find({
157
+ collection: 'users',
158
+ where: {
159
+ email: {
160
+ equals: email.toLowerCase().trim()
161
+ }
162
+ },
163
+ limit: 1
164
+ });
165
+ let otpHash;
166
+ let otpAttempts = 0;
167
+ let otpExpiresAt;
168
+ const user = users.docs?.[0];
169
+ if (user?.otpHash) {
170
+ otpHash = user.otpHash;
171
+ otpAttempts = user.otpAttempts || 0;
172
+ otpExpiresAt = user.otpExpiresAt;
173
+ } else {
174
+ // Try dedicated otps collection
175
+ const otpDocs = await req.payload.find({
176
+ collection: 'otps',
177
+ where: {
178
+ email: {
179
+ equals: email.toLowerCase().trim()
180
+ }
181
+ },
182
+ sort: '-createdAt',
183
+ limit: 1
184
+ });
185
+ const otpDoc = otpDocs.docs?.[0];
186
+ if (otpDoc) {
187
+ otpHash = otpDoc.hash;
188
+ otpAttempts = otpDoc.attempts || 0;
189
+ otpExpiresAt = otpDoc.expiresAt;
190
+ }
191
+ }
192
+ if (!otpHash) {
193
+ return Response.json({
194
+ success: false,
195
+ error: 'No OTP found. Please request a new code.'
196
+ }, {
197
+ status: 400
198
+ });
199
+ }
200
+ if (isOtpExpired(otpExpiresAt)) {
201
+ return Response.json({
202
+ success: false,
203
+ error: 'Code has expired. Please request a new one.'
204
+ }, {
205
+ status: 400
206
+ });
207
+ }
208
+ if (otpAttempts >= 3) {
209
+ return Response.json({
210
+ success: false,
211
+ error: 'Too many attempts. Please request a new code.'
212
+ }, {
213
+ status: 400
214
+ });
215
+ }
216
+ // Increment attempts
217
+ if (user?.otpHash) {
218
+ await req.payload.update({
219
+ collection: 'users',
220
+ id: user.id,
221
+ data: {
222
+ otpAttempts: otpAttempts + 1
223
+ }
224
+ });
225
+ }
226
+ if (!verifyOtp(otp, otpHash)) {
227
+ return Response.json({
228
+ success: false,
229
+ error: 'Invalid code. Please try again.'
230
+ }, {
231
+ status: 400
232
+ });
233
+ }
234
+ // OTP is valid — log the user in
235
+ // Payload requires password for login. We use the stored password
236
+ // (auto-generated during signup or previously set by user).
237
+ const userData = users.docs?.[0];
238
+ const result = await req.payload.login({
239
+ collection: 'users',
240
+ data: {
241
+ email: email.toLowerCase().trim(),
242
+ password: userData?.password || ''
243
+ },
244
+ req: req
245
+ });
246
+ // Clean up OTP
247
+ if (user?.otpHash) {
248
+ await req.payload.update({
249
+ collection: 'users',
250
+ id: user.id,
251
+ data: {
252
+ otpHash: null,
253
+ otpPurpose: null,
254
+ otpAttempts: null,
255
+ otpExpiresAt: null
256
+ }
257
+ });
258
+ }
259
+ return Response.json({
260
+ success: true,
261
+ token: result.token,
262
+ isNewUser: !user?.password
263
+ });
264
+ } catch (err) {
265
+ console.error('OTP verify error:', err);
266
+ return Response.json({
267
+ success: false,
268
+ error: err.message || 'Verification failed'
269
+ }, {
270
+ status: 500
271
+ });
272
+ }
273
+ }
274
+ };
275
+ /**
276
+ * POST /api/auth/set-password — Set/update password for authenticated user
277
+ */ export const setPasswordEndpoint = {
278
+ path: '/api/auth/set-password',
279
+ method: 'post',
280
+ handler: async (req)=>{
281
+ const body = req.json ? await req.json() : req.body || {};
282
+ const { password, confirmPassword } = body;
283
+ if (!password || !confirmPassword) {
284
+ return Response.json({
285
+ success: false,
286
+ message: 'Password and confirmation are required'
287
+ }, {
288
+ status: 400
289
+ });
290
+ }
291
+ if (password !== confirmPassword) {
292
+ return Response.json({
293
+ success: false,
294
+ message: 'Passwords do not match'
295
+ }, {
296
+ status: 400
297
+ });
298
+ }
299
+ if (password.length < 8) {
300
+ return Response.json({
301
+ success: false,
302
+ message: 'Password must be at least 8 characters'
303
+ }, {
304
+ status: 400
305
+ });
306
+ }
307
+ try {
308
+ const user = req.user;
309
+ if (!user) {
310
+ return Response.json({
311
+ success: false,
312
+ message: 'Not authenticated'
313
+ }, {
314
+ status: 401
315
+ });
316
+ }
317
+ await req.payload.update({
318
+ collection: 'users',
319
+ id: user.id,
320
+ data: {
321
+ password,
322
+ confirmPassword
323
+ }
324
+ });
325
+ return Response.json({
326
+ success: true,
327
+ message: 'Password set successfully'
328
+ });
329
+ } catch (err) {
330
+ return Response.json({
331
+ success: false,
332
+ message: err.message || 'Failed to set password'
333
+ }, {
334
+ status: 500
335
+ });
336
+ }
337
+ }
338
+ };
339
+ /**
340
+ * POST /api/auth/signup — Create new user + send welcome email
341
+ */ export const signupEndpoint = {
342
+ path: '/api/auth/signup',
343
+ method: 'post',
344
+ handler: async (req)=>{
345
+ const body = req.json ? await req.json() : req.body || {};
346
+ const { name, email } = body;
347
+ if (!email) {
348
+ return Response.json({
349
+ success: false,
350
+ message: 'Email is required'
351
+ }, {
352
+ status: 400
353
+ });
354
+ }
355
+ try {
356
+ // Check if user already exists
357
+ const existing = await req.payload.find({
358
+ collection: 'users',
359
+ where: {
360
+ email: {
361
+ equals: email.toLowerCase().trim()
362
+ }
363
+ },
364
+ limit: 1
365
+ });
366
+ if (existing.docs?.length) {
367
+ return Response.json({
368
+ success: false,
369
+ message: 'An account with this email already exists'
370
+ }, {
371
+ status: 409
372
+ });
373
+ }
374
+ // Auto-generate a random password (user sets their own via OTP flow)
375
+ const tempPassword = `tmp_${Math.random().toString(36).slice(2)}_${Date.now()}`;
376
+ const user = await req.payload.create({
377
+ collection: 'users',
378
+ data: {
379
+ email: email.toLowerCase().trim(),
380
+ password: tempPassword,
381
+ name: name?.trim() || email.split('@')[0],
382
+ role: 'user'
383
+ }
384
+ });
385
+ // Send welcome email
386
+ try {
387
+ const welcomeEmail = generateWelcomeEmail({
388
+ userName: name?.trim() || email.split('@')[0],
389
+ userEmail: email.toLowerCase().trim()
390
+ });
391
+ await req.payload.sendEmail({
392
+ to: email,
393
+ subject: welcomeEmail.subject,
394
+ html: welcomeEmail.html
395
+ });
396
+ } catch (emailErr) {
397
+ console.error('Welcome email failed:', emailErr);
398
+ // Don't fail signup if email fails
399
+ }
400
+ return Response.json({
401
+ success: true,
402
+ message: 'Account created',
403
+ userId: user.id
404
+ });
405
+ } catch (err) {
406
+ console.error('Signup error:', err);
407
+ return Response.json({
408
+ success: false,
409
+ message: err.message || 'Signup failed'
410
+ }, {
411
+ status: 500
412
+ });
413
+ }
414
+ }
415
+ };
416
+ export const authEndpoints = [
417
+ checkEmailEndpoint,
418
+ sendOtpEndpoint,
419
+ verifyOtpEndpoint,
420
+ setPasswordEndpoint,
421
+ signupEndpoint
422
+ ];
@@ -0,0 +1,24 @@
1
+ export { useLoginFlow } from '../auth/application/hooks/useLoginFlow.js';
2
+ export { useVerifyOtpFlow } from '../auth/application/hooks/useVerifyOtpFlow.js';
3
+ export { useForgotPasswordFlow } from '../auth/application/hooks/useForgotPasswordFlow.js';
4
+ export { useSetPasswordFlow } from '../auth/application/hooks/useSetPasswordFlow.js';
5
+ export { checkEmail, sendOtp, verifyOtp, setUserPassword, signup, initiateGoogleLogin, } from '../auth/application/services/authService.js';
6
+ export { evaluatePasswordStrength, isPasswordValid, MIN_PASSWORD_LENGTH } from '../auth/domain/passwordRules.js';
7
+ export { default as LoginPage } from '../components/pages/LoginPage.js';
8
+ export { default as SignupPage } from '../components/pages/SignupPage.js';
9
+ export { default as ForgotPasswordPage } from '../components/pages/ForgotPasswordPage.js';
10
+ export { default as VerifyOtpPage } from '../components/pages/VerifyOtpPage.js';
11
+ export { default as SetPasswordPage } from '../components/pages/SetPasswordPage.js';
12
+ export { AuthLayout } from '../components/AuthLayout.js';
13
+ export { PoweredBy } from '../components/PoweredBy.js';
14
+ export type { LoginStep, OTPPurpose, CheckEmailResponse, SendOtpResponse, VerifyOtpResponse, SetPasswordResponse, SignupResponse, PasswordStrengthResult, } from '../auth/domain/types.js';
15
+ export type { UseLoginFlowOptions } from '../auth/application/hooks/useLoginFlow.js';
16
+ export type { UseVerifyOtpFlowOptions } from '../auth/application/hooks/useVerifyOtpFlow.js';
17
+ export type { UseSetPasswordFlowOptions } from '../auth/application/hooks/useSetPasswordFlow.js';
18
+ export type { LoginPageProps } from '../components/pages/LoginPage.js';
19
+ export type { SignupPageProps } from '../components/pages/SignupPage.js';
20
+ export type { ForgotPasswordPageProps } from '../components/pages/ForgotPasswordPage.js';
21
+ export type { VerifyOtpPageProps } from '../components/pages/VerifyOtpPage.js';
22
+ export type { SetPasswordPageProps } from '../components/pages/SetPasswordPage.js';
23
+ export type { AuthLayoutConfig, AuthLayoutProps } from '../components/AuthLayout.js';
24
+ export type { PoweredByProps } from '../components/PoweredBy.js';
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+ // ============================================================
3
+ // Client-side exports for @main12/auth-login/client
4
+ // ============================================================
5
+ // Auth hooks
6
+ export { useLoginFlow } from '../auth/application/hooks/useLoginFlow.js';
7
+ export { useVerifyOtpFlow } from '../auth/application/hooks/useVerifyOtpFlow.js';
8
+ export { useForgotPasswordFlow } from '../auth/application/hooks/useForgotPasswordFlow.js';
9
+ export { useSetPasswordFlow } from '../auth/application/hooks/useSetPasswordFlow.js';
10
+ // Auth service functions (client-side fetch wrappers)
11
+ export { checkEmail, sendOtp, verifyOtp, setUserPassword, signup, initiateGoogleLogin } from '../auth/application/services/authService.js';
12
+ // Domain utilities
13
+ export { evaluatePasswordStrength, isPasswordValid, MIN_PASSWORD_LENGTH } from '../auth/domain/passwordRules.js';
14
+ // Page components
15
+ export { default as LoginPage } from '../components/pages/LoginPage.js';
16
+ export { default as SignupPage } from '../components/pages/SignupPage.js';
17
+ export { default as ForgotPasswordPage } from '../components/pages/ForgotPasswordPage.js';
18
+ export { default as VerifyOtpPage } from '../components/pages/VerifyOtpPage.js';
19
+ export { default as SetPasswordPage } from '../components/pages/SetPasswordPage.js';
20
+ // Layout & shared components
21
+ export { AuthLayout } from '../components/AuthLayout.js';
22
+ export { PoweredBy } from '../components/PoweredBy.js';
@@ -0,0 +1,6 @@
1
+ export { wrapInBaseTemplate, DEFAULT_COLORS, SOCIAL_ICONS, getBaseUrl, getSenderEmail, getEmailTranslations, generateOtpEmail, generateWelcomeEmail, generatePasswordResetEmail, generatePasswordChangedEmail, } from '../components/email/index.js';
2
+ export type { BaseTemplateOptions, } from '../components/email/baseTemplate.js';
3
+ export type { EmailColors, SocialLink, SocialPlatform, } from '../components/email/constants.js';
4
+ export type { SupportedLanguage, EmailTranslations, } from '../components/email/translations.js';
5
+ export type { OtpEmailParams, OtpEmailResult, WelcomeEmailParams, WelcomeEmailResult, PasswordResetEmailParams, PasswordResetEmailResult, PasswordChangedEmailParams, PasswordChangedEmailResult, } from '../components/email/index.js';
6
+ export type { AuthLoginPluginOptions } from '../index.js';
@@ -0,0 +1,5 @@
1
+ // ============================================================
2
+ // RSC (React Server Components) exports for @main12/auth-login/rsc
3
+ // ============================================================
4
+ // Email template system (server-only — uses Node APIs)
5
+ export { wrapInBaseTemplate, DEFAULT_COLORS, SOCIAL_ICONS, getBaseUrl, getSenderEmail, getEmailTranslations, generateOtpEmail, generateWelcomeEmail, generatePasswordResetEmail, generatePasswordChangedEmail } from '../components/email/index.js';
@@ -0,0 +1,12 @@
1
+ import type { Config } from 'payload';
2
+ export interface AuthLoginPluginOptions {
3
+ /** Enable/disable the plugin */
4
+ enabled?: boolean;
5
+ /** Project name used in emails */
6
+ projectName?: string;
7
+ /** Contact email used in email footers */
8
+ contactEmail?: string;
9
+ /** Domain for links in emails */
10
+ domain?: string;
11
+ }
12
+ export declare const authLoginPlugin: (options?: AuthLoginPluginOptions) => (config: Config) => Config;
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ import { authEndpoints } from './endpoints/authEndpoints.js';
2
+ export const authLoginPlugin = (options = {})=>(config)=>{
3
+ if (options.enabled === false) return config;
4
+ // Register auth API endpoints
5
+ config.endpoints = [
6
+ ...config.endpoints || [],
7
+ ...authEndpoints
8
+ ];
9
+ // Chain onInit
10
+ const incomingOnInit = config.onInit;
11
+ config.onInit = async (payload)=>{
12
+ if (incomingOnInit) await incomingOnInit(payload);
13
+ payload.logger.info(`[auth-login] Plugin initialized for ${options.projectName || 'project'}`);
14
+ };
15
+ return config;
16
+ };
package/package.json ADDED
@@ -0,0 +1,115 @@
1
+ {
2
+ "name": "@main12/auth-login",
3
+ "version": "0.1.0",
4
+ "description": "Reusable Payload CMS auth plugin — login, signup, OTP, forgot password, branded emails, Powered by Main12",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./src/index.ts",
10
+ "types": "./src/index.ts",
11
+ "default": "./src/index.ts"
12
+ },
13
+ "./client": {
14
+ "import": "./src/exports/client.ts",
15
+ "types": "./src/exports/client.ts",
16
+ "default": "./src/exports/client.ts"
17
+ },
18
+ "./rsc": {
19
+ "import": "./src/exports/rsc.ts",
20
+ "types": "./src/exports/rsc.ts",
21
+ "default": "./src/exports/rsc.ts"
22
+ }
23
+ },
24
+ "main": "./src/index.ts",
25
+ "types": "./src/index.ts",
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "scripts": {
30
+ "build": "pnpm copyfiles && pnpm build:types && pnpm build:swc",
31
+ "build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
32
+ "build:types": "tsc --outDir dist",
33
+ "clean": "rimraf {dist,*.tsbuildinfo}",
34
+ "copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
35
+ "dev": "next dev dev --turbo",
36
+ "dev:generate-importmap": "pnpm dev:payload generate:importmap",
37
+ "dev:generate-types": "pnpm dev:payload generate:types",
38
+ "dev:payload": "cross-env PAYLOAD_CONFIG_PATH=./dev/payload.config.ts payload",
39
+ "lint": "eslint",
40
+ "lint:fix": "eslint ./src --fix",
41
+ "test": "vitest"
42
+ },
43
+ "devDependencies": {
44
+ "@eslint/eslintrc": "^3.2.0",
45
+ "@payloadcms/db-sqlite": "3.82.1",
46
+ "@payloadcms/next": "3.82.1",
47
+ "@payloadcms/richtext-lexical": "3.82.1",
48
+ "@payloadcms/ui": "3.82.1",
49
+ "@swc/cli": "0.6.0",
50
+ "@tailwindcss/postcss": "^4.3.3",
51
+ "@types/node": "24.12.3",
52
+ "@types/react": "19.2.14",
53
+ "@types/react-dom": "19.2.3",
54
+ "copyfiles": "2.4.1",
55
+ "cross-env": "10.1.0",
56
+ "eslint": "^9.23.0",
57
+ "next": "16.2.7",
58
+ "payload": "3.82.1",
59
+ "react": "19.2.6",
60
+ "react-dom": "19.2.6",
61
+ "rimraf": "3.0.2",
62
+ "sharp": "0.34.2",
63
+ "tailwindcss": "^4.3.3",
64
+ "typescript": "6.0.3",
65
+ "vitest": "4.1.6"
66
+ },
67
+ "peerDependencies": {
68
+ "next": "^16.0.0",
69
+ "payload": "^3.82.0",
70
+ "react": "^19.0.0"
71
+ },
72
+ "peerDependenciesMeta": {
73
+ "@heroui/react": {
74
+ "optional": true
75
+ },
76
+ "framer-motion": {
77
+ "optional": true
78
+ },
79
+ "next-intl": {
80
+ "optional": true
81
+ }
82
+ },
83
+ "engines": {
84
+ "node": ">=18.20.2"
85
+ },
86
+ "publishConfig": {
87
+ "exports": {
88
+ ".": {
89
+ "import": "./dist/index.js",
90
+ "types": "./dist/index.d.ts",
91
+ "default": "./dist/index.js"
92
+ },
93
+ "./client": {
94
+ "import": "./dist/exports/client.js",
95
+ "types": "./dist/exports/client.d.ts",
96
+ "default": "./dist/exports/client.js"
97
+ },
98
+ "./rsc": {
99
+ "import": "./dist/exports/rsc.js",
100
+ "types": "./dist/exports/rsc.d.ts",
101
+ "default": "./dist/exports/rsc.js"
102
+ }
103
+ },
104
+ "main": "./dist/index.js",
105
+ "types": "./dist/index.d.ts"
106
+ },
107
+ "pnpm": {
108
+ "onlyBuiltDependencies": [
109
+ "@swc/core",
110
+ "sharp",
111
+ "esbuild"
112
+ ]
113
+ },
114
+ "registry": "https://registry.npmjs.org/"
115
+ }