@opensaas/stack-auth 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.
- package/.turbo/turbo-build.log +4 -0
- package/INTEGRATION_SUMMARY.md +425 -0
- package/README.md +445 -0
- package/dist/client/index.d.ts +38 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +23 -0
- package/dist/client/index.js.map +1 -0
- package/dist/config/index.d.ts +50 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +115 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +160 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/lists/index.d.ts +46 -0
- package/dist/lists/index.d.ts.map +1 -0
- package/dist/lists/index.js +227 -0
- package/dist/lists/index.js.map +1 -0
- package/dist/server/index.d.ts +27 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +90 -0
- package/dist/server/index.js.map +1 -0
- package/dist/ui/components/ForgotPasswordForm.d.ts +36 -0
- package/dist/ui/components/ForgotPasswordForm.d.ts.map +1 -0
- package/dist/ui/components/ForgotPasswordForm.js +50 -0
- package/dist/ui/components/ForgotPasswordForm.js.map +1 -0
- package/dist/ui/components/SignInForm.d.ts +52 -0
- package/dist/ui/components/SignInForm.d.ts.map +1 -0
- package/dist/ui/components/SignInForm.js +66 -0
- package/dist/ui/components/SignInForm.js.map +1 -0
- package/dist/ui/components/SignUpForm.d.ts +56 -0
- package/dist/ui/components/SignUpForm.d.ts.map +1 -0
- package/dist/ui/components/SignUpForm.js +74 -0
- package/dist/ui/components/SignUpForm.js.map +1 -0
- package/dist/ui/index.d.ts +7 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +4 -0
- package/dist/ui/index.js.map +1 -0
- package/package.json +55 -0
- package/src/client/index.ts +44 -0
- package/src/config/index.ts +140 -0
- package/src/config/types.ts +166 -0
- package/src/index.ts +44 -0
- package/src/lists/index.ts +245 -0
- package/src/server/index.ts +120 -0
- package/src/ui/components/ForgotPasswordForm.tsx +120 -0
- package/src/ui/components/SignInForm.tsx +191 -0
- package/src/ui/components/SignUpForm.tsx +238 -0
- package/src/ui/index.ts +7 -0
- package/tsconfig.json +14 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React, { useState } from 'react'
|
|
4
|
+
import type { createAuthClient } from 'better-auth/react'
|
|
5
|
+
|
|
6
|
+
export type SignInFormProps = {
|
|
7
|
+
/**
|
|
8
|
+
* Better-auth client instance
|
|
9
|
+
* Created with createAuthClient from better-auth/react
|
|
10
|
+
* Pass your client from lib/auth-client.ts
|
|
11
|
+
*/
|
|
12
|
+
authClient: ReturnType<typeof createAuthClient>
|
|
13
|
+
/**
|
|
14
|
+
* URL to redirect to after successful sign in
|
|
15
|
+
* @default '/'
|
|
16
|
+
*/
|
|
17
|
+
redirectTo?: string
|
|
18
|
+
/**
|
|
19
|
+
* Show OAuth provider buttons
|
|
20
|
+
* @default true
|
|
21
|
+
*/
|
|
22
|
+
showSocialProviders?: boolean
|
|
23
|
+
/**
|
|
24
|
+
* Which OAuth providers to show
|
|
25
|
+
* @default ['github', 'google']
|
|
26
|
+
*/
|
|
27
|
+
socialProviders?: string[]
|
|
28
|
+
/**
|
|
29
|
+
* Custom CSS class for the form container
|
|
30
|
+
*/
|
|
31
|
+
className?: string
|
|
32
|
+
/**
|
|
33
|
+
* Callback when sign in is successful
|
|
34
|
+
*/
|
|
35
|
+
onSuccess?: () => void
|
|
36
|
+
/**
|
|
37
|
+
* Callback when sign in fails
|
|
38
|
+
*/
|
|
39
|
+
onError?: (error: Error) => void
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Sign in form component
|
|
44
|
+
* Provides email/password sign in and OAuth provider buttons
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* import { SignInForm } from '@opensaas/stack-auth/ui'
|
|
49
|
+
* import { authClient } from '@/lib/auth-client'
|
|
50
|
+
*
|
|
51
|
+
* export default function SignInPage() {
|
|
52
|
+
* return <SignInForm authClient={authClient} redirectTo="/admin" />
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export function SignInForm({
|
|
57
|
+
authClient,
|
|
58
|
+
redirectTo = '/',
|
|
59
|
+
showSocialProviders = true,
|
|
60
|
+
socialProviders = ['github', 'google'],
|
|
61
|
+
className = '',
|
|
62
|
+
onSuccess,
|
|
63
|
+
onError,
|
|
64
|
+
}: SignInFormProps) {
|
|
65
|
+
const [email, setEmail] = useState('')
|
|
66
|
+
const [password, setPassword] = useState('')
|
|
67
|
+
const [error, setError] = useState('')
|
|
68
|
+
const [loading, setLoading] = useState(false)
|
|
69
|
+
|
|
70
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
71
|
+
e.preventDefault()
|
|
72
|
+
setError('')
|
|
73
|
+
setLoading(true)
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
const result = await authClient.signIn.email({
|
|
77
|
+
email,
|
|
78
|
+
password,
|
|
79
|
+
callbackURL: redirectTo,
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
if (result.error) {
|
|
83
|
+
throw new Error(result.error.message)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
onSuccess?.()
|
|
87
|
+
} catch (err) {
|
|
88
|
+
const message = err instanceof Error ? err.message : 'Sign in failed'
|
|
89
|
+
setError(message)
|
|
90
|
+
onError?.(err instanceof Error ? err : new Error(message))
|
|
91
|
+
} finally {
|
|
92
|
+
setLoading(false)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const handleSocialSignIn = async (provider: string) => {
|
|
97
|
+
setError('')
|
|
98
|
+
setLoading(true)
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
await authClient.signIn.social({
|
|
102
|
+
provider,
|
|
103
|
+
callbackURL: redirectTo,
|
|
104
|
+
})
|
|
105
|
+
onSuccess?.()
|
|
106
|
+
} catch (err) {
|
|
107
|
+
const message = err instanceof Error ? err.message : 'Sign in failed'
|
|
108
|
+
setError(message)
|
|
109
|
+
onError?.(err instanceof Error ? err : new Error(message))
|
|
110
|
+
setLoading(false)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<div className={`w-full max-w-md mx-auto p-6 ${className}`}>
|
|
116
|
+
<h2 className="text-2xl font-bold mb-6">Sign In</h2>
|
|
117
|
+
|
|
118
|
+
{error && (
|
|
119
|
+
<div className="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded mb-4">
|
|
120
|
+
{error}
|
|
121
|
+
</div>
|
|
122
|
+
)}
|
|
123
|
+
|
|
124
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
125
|
+
<div>
|
|
126
|
+
<label htmlFor="email" className="block text-sm font-medium mb-2">
|
|
127
|
+
Email
|
|
128
|
+
</label>
|
|
129
|
+
<input
|
|
130
|
+
id="email"
|
|
131
|
+
type="email"
|
|
132
|
+
value={email}
|
|
133
|
+
onChange={(e) => setEmail((e.target as HTMLInputElement).value)}
|
|
134
|
+
required
|
|
135
|
+
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
136
|
+
disabled={loading}
|
|
137
|
+
/>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<div>
|
|
141
|
+
<label htmlFor="password" className="block text-sm font-medium mb-2">
|
|
142
|
+
Password
|
|
143
|
+
</label>
|
|
144
|
+
<input
|
|
145
|
+
id="password"
|
|
146
|
+
type="password"
|
|
147
|
+
value={password}
|
|
148
|
+
onChange={(e) => setPassword((e.target as HTMLInputElement).value)}
|
|
149
|
+
required
|
|
150
|
+
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
151
|
+
disabled={loading}
|
|
152
|
+
/>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<button
|
|
156
|
+
type="submit"
|
|
157
|
+
disabled={loading}
|
|
158
|
+
className="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
|
159
|
+
>
|
|
160
|
+
{loading ? 'Signing in...' : 'Sign In'}
|
|
161
|
+
</button>
|
|
162
|
+
</form>
|
|
163
|
+
|
|
164
|
+
{showSocialProviders && socialProviders.length > 0 && (
|
|
165
|
+
<>
|
|
166
|
+
<div className="relative my-6">
|
|
167
|
+
<div className="absolute inset-0 flex items-center">
|
|
168
|
+
<div className="w-full border-t border-gray-300"></div>
|
|
169
|
+
</div>
|
|
170
|
+
<div className="relative flex justify-center text-sm">
|
|
171
|
+
<span className="px-2 bg-white text-gray-500">Or continue with</span>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
<div className="space-y-2">
|
|
176
|
+
{socialProviders.map((provider) => (
|
|
177
|
+
<button
|
|
178
|
+
key={provider}
|
|
179
|
+
onClick={() => handleSocialSignIn(provider)}
|
|
180
|
+
disabled={loading}
|
|
181
|
+
className="w-full bg-white border border-gray-300 text-gray-700 py-2 px-4 rounded-md hover:bg-gray-50 disabled:bg-gray-100 disabled:cursor-not-allowed"
|
|
182
|
+
>
|
|
183
|
+
Sign in with {provider.charAt(0).toUpperCase() + provider.slice(1)}
|
|
184
|
+
</button>
|
|
185
|
+
))}
|
|
186
|
+
</div>
|
|
187
|
+
</>
|
|
188
|
+
)}
|
|
189
|
+
</div>
|
|
190
|
+
)
|
|
191
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React, { useState } from 'react'
|
|
4
|
+
import type { createAuthClient } from 'better-auth/react'
|
|
5
|
+
|
|
6
|
+
export type SignUpFormProps = {
|
|
7
|
+
/**
|
|
8
|
+
* Better-auth client instance
|
|
9
|
+
* Created with createAuthClient from better-auth/react
|
|
10
|
+
*/
|
|
11
|
+
authClient: ReturnType<typeof createAuthClient>
|
|
12
|
+
/**
|
|
13
|
+
* URL to redirect to after successful sign up
|
|
14
|
+
* @default '/'
|
|
15
|
+
*/
|
|
16
|
+
redirectTo?: string
|
|
17
|
+
/**
|
|
18
|
+
* Show OAuth provider buttons
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
showSocialProviders?: boolean
|
|
22
|
+
/**
|
|
23
|
+
* Which OAuth providers to show
|
|
24
|
+
* @default ['github', 'google']
|
|
25
|
+
*/
|
|
26
|
+
socialProviders?: string[]
|
|
27
|
+
/**
|
|
28
|
+
* Require password confirmation
|
|
29
|
+
* @default true
|
|
30
|
+
*/
|
|
31
|
+
requirePasswordConfirmation?: boolean
|
|
32
|
+
/**
|
|
33
|
+
* Custom CSS class for the form container
|
|
34
|
+
*/
|
|
35
|
+
className?: string
|
|
36
|
+
/**
|
|
37
|
+
* Callback when sign up is successful
|
|
38
|
+
*/
|
|
39
|
+
onSuccess?: () => void
|
|
40
|
+
/**
|
|
41
|
+
* Callback when sign up fails
|
|
42
|
+
*/
|
|
43
|
+
onError?: (error: Error) => void
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Sign up form component
|
|
48
|
+
* Provides email/password registration and OAuth provider buttons
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* import { SignUpForm } from '@opensaas/stack-auth/ui'
|
|
53
|
+
* import { authClient } from '@/lib/auth-client'
|
|
54
|
+
*
|
|
55
|
+
* export default function SignUpPage() {
|
|
56
|
+
* return <SignUpForm authClient={authClient} redirectTo="/admin" />
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function SignUpForm({
|
|
61
|
+
authClient,
|
|
62
|
+
redirectTo = '/',
|
|
63
|
+
showSocialProviders = true,
|
|
64
|
+
socialProviders = ['github', 'google'],
|
|
65
|
+
requirePasswordConfirmation = true,
|
|
66
|
+
className = '',
|
|
67
|
+
onSuccess,
|
|
68
|
+
onError,
|
|
69
|
+
}: SignUpFormProps) {
|
|
70
|
+
const [name, setName] = useState('')
|
|
71
|
+
const [email, setEmail] = useState('')
|
|
72
|
+
const [password, setPassword] = useState('')
|
|
73
|
+
const [confirmPassword, setConfirmPassword] = useState('')
|
|
74
|
+
const [error, setError] = useState('')
|
|
75
|
+
const [loading, setLoading] = useState(false)
|
|
76
|
+
|
|
77
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
78
|
+
e.preventDefault()
|
|
79
|
+
setError('')
|
|
80
|
+
|
|
81
|
+
// Validate password confirmation
|
|
82
|
+
if (requirePasswordConfirmation && password !== confirmPassword) {
|
|
83
|
+
setError('Passwords do not match')
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
setLoading(true)
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const result = await authClient.signUp.email({
|
|
91
|
+
email,
|
|
92
|
+
password,
|
|
93
|
+
name,
|
|
94
|
+
callbackURL: redirectTo,
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
if (result.error) {
|
|
98
|
+
throw new Error(result.error.message)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
onSuccess?.()
|
|
102
|
+
} catch (err) {
|
|
103
|
+
const message = err instanceof Error ? err.message : 'Sign up failed'
|
|
104
|
+
setError(message)
|
|
105
|
+
onError?.(err instanceof Error ? err : new Error(message))
|
|
106
|
+
} finally {
|
|
107
|
+
setLoading(false)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const handleSocialSignUp = async (provider: string) => {
|
|
112
|
+
setError('')
|
|
113
|
+
setLoading(true)
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
await authClient.signIn.social({
|
|
117
|
+
provider,
|
|
118
|
+
callbackURL: redirectTo,
|
|
119
|
+
})
|
|
120
|
+
onSuccess?.()
|
|
121
|
+
} catch (err) {
|
|
122
|
+
const message = err instanceof Error ? err.message : 'Sign up failed'
|
|
123
|
+
setError(message)
|
|
124
|
+
onError?.(err instanceof Error ? err : new Error(message))
|
|
125
|
+
setLoading(false)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<div className={`w-full max-w-md mx-auto p-6 ${className}`}>
|
|
131
|
+
<h2 className="text-2xl font-bold mb-6">Sign Up</h2>
|
|
132
|
+
|
|
133
|
+
{error && (
|
|
134
|
+
<div className="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded mb-4">
|
|
135
|
+
{error}
|
|
136
|
+
</div>
|
|
137
|
+
)}
|
|
138
|
+
|
|
139
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
140
|
+
<div>
|
|
141
|
+
<label htmlFor="name" className="block text-sm font-medium mb-2">
|
|
142
|
+
Name
|
|
143
|
+
</label>
|
|
144
|
+
<input
|
|
145
|
+
id="name"
|
|
146
|
+
type="text"
|
|
147
|
+
value={name}
|
|
148
|
+
onChange={(e) => setName((e.target as HTMLInputElement).value)}
|
|
149
|
+
required
|
|
150
|
+
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
151
|
+
disabled={loading}
|
|
152
|
+
/>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<div>
|
|
156
|
+
<label htmlFor="email" className="block text-sm font-medium mb-2">
|
|
157
|
+
Email
|
|
158
|
+
</label>
|
|
159
|
+
<input
|
|
160
|
+
id="email"
|
|
161
|
+
type="email"
|
|
162
|
+
value={email}
|
|
163
|
+
onChange={(e) => setEmail((e.target as HTMLInputElement).value)}
|
|
164
|
+
required
|
|
165
|
+
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
166
|
+
disabled={loading}
|
|
167
|
+
/>
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
<div>
|
|
171
|
+
<label htmlFor="password" className="block text-sm font-medium mb-2">
|
|
172
|
+
Password
|
|
173
|
+
</label>
|
|
174
|
+
<input
|
|
175
|
+
id="password"
|
|
176
|
+
type="password"
|
|
177
|
+
value={password}
|
|
178
|
+
onChange={(e) => setPassword((e.target as HTMLInputElement).value)}
|
|
179
|
+
required
|
|
180
|
+
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
181
|
+
disabled={loading}
|
|
182
|
+
/>
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
{requirePasswordConfirmation && (
|
|
186
|
+
<div>
|
|
187
|
+
<label htmlFor="confirmPassword" className="block text-sm font-medium mb-2">
|
|
188
|
+
Confirm Password
|
|
189
|
+
</label>
|
|
190
|
+
<input
|
|
191
|
+
id="confirmPassword"
|
|
192
|
+
type="password"
|
|
193
|
+
value={confirmPassword}
|
|
194
|
+
onChange={(e) => setConfirmPassword((e.target as HTMLInputElement).value)}
|
|
195
|
+
required
|
|
196
|
+
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
197
|
+
disabled={loading}
|
|
198
|
+
/>
|
|
199
|
+
</div>
|
|
200
|
+
)}
|
|
201
|
+
|
|
202
|
+
<button
|
|
203
|
+
type="submit"
|
|
204
|
+
disabled={loading}
|
|
205
|
+
className="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
|
206
|
+
>
|
|
207
|
+
{loading ? 'Creating account...' : 'Sign Up'}
|
|
208
|
+
</button>
|
|
209
|
+
</form>
|
|
210
|
+
|
|
211
|
+
{showSocialProviders && socialProviders.length > 0 && (
|
|
212
|
+
<>
|
|
213
|
+
<div className="relative my-6">
|
|
214
|
+
<div className="absolute inset-0 flex items-center">
|
|
215
|
+
<div className="w-full border-t border-gray-300"></div>
|
|
216
|
+
</div>
|
|
217
|
+
<div className="relative flex justify-center text-sm">
|
|
218
|
+
<span className="px-2 bg-white text-gray-500">Or continue with</span>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
|
|
222
|
+
<div className="space-y-2">
|
|
223
|
+
{socialProviders.map((provider) => (
|
|
224
|
+
<button
|
|
225
|
+
key={provider}
|
|
226
|
+
onClick={() => handleSocialSignUp(provider)}
|
|
227
|
+
disabled={loading}
|
|
228
|
+
className="w-full bg-white border border-gray-300 text-gray-700 py-2 px-4 rounded-md hover:bg-gray-50 disabled:bg-gray-100 disabled:cursor-not-allowed"
|
|
229
|
+
>
|
|
230
|
+
Sign up with {provider.charAt(0).toUpperCase() + provider.slice(1)}
|
|
231
|
+
</button>
|
|
232
|
+
))}
|
|
233
|
+
</div>
|
|
234
|
+
</>
|
|
235
|
+
)}
|
|
236
|
+
</div>
|
|
237
|
+
)
|
|
238
|
+
}
|
package/src/ui/index.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { SignInForm } from './components/SignInForm.js'
|
|
2
|
+
export { SignUpForm } from './components/SignUpForm.js'
|
|
3
|
+
export { ForgotPasswordForm } from './components/ForgotPasswordForm.js'
|
|
4
|
+
|
|
5
|
+
export type { SignInFormProps } from './components/SignInForm.js'
|
|
6
|
+
export type { SignUpFormProps } from './components/SignUpForm.js'
|
|
7
|
+
export type { ForgotPasswordFormProps } from './components/ForgotPasswordForm.js'
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "./dist",
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"composite": true,
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"declarationMap": true,
|
|
9
|
+
"jsx": "react-jsx",
|
|
10
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"]
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*"],
|
|
13
|
+
"exclude": ["node_modules", "dist"]
|
|
14
|
+
}
|