next-lite-auth 0.1.2 → 0.2.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/README.md +21 -16
- package/dist/client.js +214 -55
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +215 -56
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +33 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +31 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +22 -22
package/README.md
CHANGED
|
@@ -14,14 +14,13 @@ Lightweight JWT auth for Next.js using static JSON users — no database require
|
|
|
14
14
|
- Next.js >= 13
|
|
15
15
|
- React >= 18
|
|
16
16
|
- TypeScript
|
|
17
|
-
- Tailwind CSS + shadcn/ui (for built-in login UI)
|
|
18
17
|
|
|
19
18
|
---
|
|
20
19
|
|
|
21
20
|
## Installation
|
|
22
21
|
|
|
23
22
|
```bash
|
|
24
|
-
pnpm add next-lite-auth
|
|
23
|
+
pnpm add next-lite-auth
|
|
25
24
|
```
|
|
26
25
|
|
|
27
26
|
---
|
|
@@ -31,21 +30,24 @@ pnpm add next-lite-auth jose
|
|
|
31
30
|
### 1. Create `auth.ts` at your project root
|
|
32
31
|
|
|
33
32
|
```ts
|
|
34
|
-
import { createLiteAuth } from "next-lite-auth";
|
|
33
|
+
import { createLiteAuth, usersFromEnv } from "next-lite-auth";
|
|
35
34
|
|
|
36
35
|
export const { handlers, middleware, getUserFromCookies } = createLiteAuth({
|
|
37
|
-
users:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
jwtSecret: process.env.JWT_SECRET!,
|
|
36
|
+
users: usersFromEnv(),
|
|
37
|
+
jwtSecret: process.env.LITE_AUTH_SECRET!,
|
|
38
|
+
enabled: process.env.LITE_AUTH_ENABLED !== "false",
|
|
41
39
|
});
|
|
42
40
|
```
|
|
43
41
|
|
|
44
42
|
```bash
|
|
45
43
|
# .env.local
|
|
46
|
-
|
|
44
|
+
LITE_AUTH_SECRET=your-random-secret-here
|
|
45
|
+
LITE_AUTH_ENABLED=true
|
|
46
|
+
LITE_AUTH_USERS=[{"email":"admin@example.com","password":"secret","role":"admin","name":"Admin"}]
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
`auth.ts` is safe to commit — credentials live only in `.env.local`.
|
|
50
|
+
|
|
49
51
|
### 2. Add one route file
|
|
50
52
|
|
|
51
53
|
```ts
|
|
@@ -77,16 +79,18 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
|
|
77
79
|
|
|
78
80
|
---
|
|
79
81
|
|
|
80
|
-
##
|
|
82
|
+
## OSS-friendly: toggle auth via env
|
|
81
83
|
|
|
82
|
-
|
|
84
|
+
If you ship an OSS project using next-lite-auth, your users can enable or disable auth with a single env variable — no code changes needed:
|
|
83
85
|
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
```bash
|
|
87
|
+
# Disable auth (open access)
|
|
88
|
+
LITE_AUTH_ENABLED=false
|
|
89
|
+
|
|
90
|
+
# Enable auth
|
|
91
|
+
LITE_AUTH_ENABLED=true
|
|
92
|
+
LITE_AUTH_USERS=[{"email":"admin@example.com","password":"secret"}]
|
|
93
|
+
LITE_AUTH_SECRET=your-secret
|
|
90
94
|
```
|
|
91
95
|
|
|
92
96
|
---
|
|
@@ -138,6 +142,7 @@ const user = await getUserFromCookies(cookies());
|
|
|
138
142
|
| Export | Description |
|
|
139
143
|
|---|---|
|
|
140
144
|
| `createLiteAuth(config)` | Factory — returns `handlers`, `middleware`, `getUserFromCookies` |
|
|
145
|
+
| `usersFromEnv()` | Reads `LITE_AUTH_USERS` env var and returns `User[]` |
|
|
141
146
|
| `handlers.GET / POST` | Catch-all route handlers |
|
|
142
147
|
| `middleware(options)` | Edge middleware for server-side route protection |
|
|
143
148
|
| `getUserFromCookies(cookies)` | Server-side session helper |
|
package/dist/client.js
CHANGED
|
@@ -33,6 +33,144 @@ var import_navigation = require("next/navigation");
|
|
|
33
33
|
// src/client/LiteLoginPage.tsx
|
|
34
34
|
var import_react = require("react");
|
|
35
35
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
36
|
+
var styles = {
|
|
37
|
+
page: {
|
|
38
|
+
minHeight: "100vh",
|
|
39
|
+
display: "flex",
|
|
40
|
+
alignItems: "center",
|
|
41
|
+
justifyContent: "center",
|
|
42
|
+
backgroundColor: "#f9fafb",
|
|
43
|
+
padding: "0 16px",
|
|
44
|
+
fontFamily: "system-ui, -apple-system, sans-serif"
|
|
45
|
+
},
|
|
46
|
+
container: {
|
|
47
|
+
width: "100%",
|
|
48
|
+
maxWidth: "360px",
|
|
49
|
+
display: "flex",
|
|
50
|
+
flexDirection: "column",
|
|
51
|
+
gap: "24px"
|
|
52
|
+
},
|
|
53
|
+
header: {
|
|
54
|
+
textAlign: "center"
|
|
55
|
+
},
|
|
56
|
+
title: {
|
|
57
|
+
margin: "0 0 4px",
|
|
58
|
+
fontSize: "22px",
|
|
59
|
+
fontWeight: 600,
|
|
60
|
+
color: "#111827",
|
|
61
|
+
letterSpacing: "-0.01em"
|
|
62
|
+
},
|
|
63
|
+
description: {
|
|
64
|
+
margin: 0,
|
|
65
|
+
fontSize: "14px",
|
|
66
|
+
color: "#6b7280"
|
|
67
|
+
},
|
|
68
|
+
card: {
|
|
69
|
+
backgroundColor: "#ffffff",
|
|
70
|
+
border: "1px solid #e5e7eb",
|
|
71
|
+
borderRadius: "12px",
|
|
72
|
+
padding: "24px",
|
|
73
|
+
display: "flex",
|
|
74
|
+
flexDirection: "column",
|
|
75
|
+
gap: "16px",
|
|
76
|
+
boxShadow: "0 1px 3px rgba(0,0,0,0.07)"
|
|
77
|
+
},
|
|
78
|
+
error: {
|
|
79
|
+
backgroundColor: "#fef2f2",
|
|
80
|
+
border: "1px solid #fecaca",
|
|
81
|
+
borderRadius: "6px",
|
|
82
|
+
padding: "8px 12px",
|
|
83
|
+
fontSize: "13px",
|
|
84
|
+
color: "#dc2626"
|
|
85
|
+
},
|
|
86
|
+
field: {
|
|
87
|
+
display: "flex",
|
|
88
|
+
flexDirection: "column",
|
|
89
|
+
gap: "6px"
|
|
90
|
+
},
|
|
91
|
+
label: {
|
|
92
|
+
fontSize: "13px",
|
|
93
|
+
fontWeight: 500,
|
|
94
|
+
color: "#374151"
|
|
95
|
+
},
|
|
96
|
+
input: {
|
|
97
|
+
height: "36px",
|
|
98
|
+
width: "100%",
|
|
99
|
+
borderRadius: "6px",
|
|
100
|
+
border: "1px solid #d1d5db",
|
|
101
|
+
padding: "0 12px",
|
|
102
|
+
fontSize: "14px",
|
|
103
|
+
color: "#111827",
|
|
104
|
+
backgroundColor: "#fff",
|
|
105
|
+
outline: "none",
|
|
106
|
+
boxSizing: "border-box",
|
|
107
|
+
transition: "border-color 0.15s"
|
|
108
|
+
},
|
|
109
|
+
inputFocus: {
|
|
110
|
+
borderColor: "#6366f1",
|
|
111
|
+
boxShadow: "0 0 0 3px rgba(99,102,241,0.15)"
|
|
112
|
+
},
|
|
113
|
+
button: {
|
|
114
|
+
height: "36px",
|
|
115
|
+
width: "100%",
|
|
116
|
+
borderRadius: "6px",
|
|
117
|
+
border: "none",
|
|
118
|
+
backgroundColor: "#111827",
|
|
119
|
+
color: "#ffffff",
|
|
120
|
+
fontSize: "14px",
|
|
121
|
+
fontWeight: 500,
|
|
122
|
+
cursor: "pointer",
|
|
123
|
+
transition: "opacity 0.15s"
|
|
124
|
+
},
|
|
125
|
+
buttonDisabled: {
|
|
126
|
+
opacity: 0.5,
|
|
127
|
+
pointerEvents: "none"
|
|
128
|
+
},
|
|
129
|
+
footer: {
|
|
130
|
+
textAlign: "center",
|
|
131
|
+
fontSize: "12px",
|
|
132
|
+
color: "#9ca3af"
|
|
133
|
+
},
|
|
134
|
+
link: {
|
|
135
|
+
color: "#6b7280",
|
|
136
|
+
textDecoration: "underline",
|
|
137
|
+
textUnderlineOffset: "3px"
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var darkModeCSS = `
|
|
141
|
+
@media (prefers-color-scheme: dark) {
|
|
142
|
+
.lite-auth-page { background-color: #09090b !important; }
|
|
143
|
+
.lite-auth-title { color: #fafafa !important; }
|
|
144
|
+
.lite-auth-desc { color: #a1a1aa !important; }
|
|
145
|
+
.lite-auth-card {
|
|
146
|
+
background-color: #18181b !important;
|
|
147
|
+
border-color: #27272a !important;
|
|
148
|
+
box-shadow: none !important;
|
|
149
|
+
}
|
|
150
|
+
.lite-auth-error {
|
|
151
|
+
background-color: rgba(239,68,68,0.1) !important;
|
|
152
|
+
border-color: rgba(239,68,68,0.3) !important;
|
|
153
|
+
color: #f87171 !important;
|
|
154
|
+
}
|
|
155
|
+
.lite-auth-label { color: #e4e4e7 !important; }
|
|
156
|
+
.lite-auth-input {
|
|
157
|
+
background-color: transparent !important;
|
|
158
|
+
border-color: #3f3f46 !important;
|
|
159
|
+
color: #fafafa !important;
|
|
160
|
+
}
|
|
161
|
+
.lite-auth-input::placeholder { color: #52525b !important; }
|
|
162
|
+
.lite-auth-input:focus {
|
|
163
|
+
border-color: #6366f1 !important;
|
|
164
|
+
box-shadow: 0 0 0 3px rgba(99,102,241,0.2) !important;
|
|
165
|
+
}
|
|
166
|
+
.lite-auth-btn {
|
|
167
|
+
background-color: #fafafa !important;
|
|
168
|
+
color: #09090b !important;
|
|
169
|
+
}
|
|
170
|
+
.lite-auth-footer { color: #52525b !important; }
|
|
171
|
+
.lite-auth-link { color: #71717a !important; }
|
|
172
|
+
}
|
|
173
|
+
`;
|
|
36
174
|
function LiteLoginPage({
|
|
37
175
|
title = "Sign in",
|
|
38
176
|
description = "Enter your credentials to continue"
|
|
@@ -40,6 +178,7 @@ function LiteLoginPage({
|
|
|
40
178
|
const { login } = useLiteAuth();
|
|
41
179
|
const [error, setError] = (0, import_react.useState)("");
|
|
42
180
|
const [loading, setLoading] = (0, import_react.useState)(false);
|
|
181
|
+
const [focusedField, setFocusedField] = (0, import_react.useState)(null);
|
|
43
182
|
async function handleSubmit(e) {
|
|
44
183
|
e.preventDefault();
|
|
45
184
|
setError("");
|
|
@@ -54,70 +193,90 @@ function LiteLoginPage({
|
|
|
54
193
|
setError(result.error);
|
|
55
194
|
}
|
|
56
195
|
}
|
|
57
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.
|
|
58
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
59
|
-
|
|
60
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("
|
|
65
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
66
|
-
|
|
67
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
196
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
197
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: darkModeCSS }),
|
|
198
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "lite-auth-page", style: styles.page, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.container, children: [
|
|
199
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.header, children: [
|
|
200
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "lite-auth-title", style: styles.title, children: title }),
|
|
201
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "lite-auth-desc", style: styles.description, children: description })
|
|
202
|
+
] }),
|
|
203
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "lite-auth-card", style: styles.card, children: [
|
|
204
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "lite-auth-error", style: styles.error, children: error }),
|
|
205
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: handleSubmit, style: { display: "flex", flexDirection: "column", gap: "16px" }, children: [
|
|
206
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
|
|
207
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "email", className: "lite-auth-label", style: styles.label, children: "Email" }),
|
|
208
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
209
|
+
"input",
|
|
210
|
+
{
|
|
211
|
+
id: "email",
|
|
212
|
+
name: "email",
|
|
213
|
+
type: "email",
|
|
214
|
+
required: true,
|
|
215
|
+
autoComplete: "email",
|
|
216
|
+
placeholder: "you@example.com",
|
|
217
|
+
className: "lite-auth-input",
|
|
218
|
+
style: {
|
|
219
|
+
...styles.input,
|
|
220
|
+
...focusedField === "email" ? styles.inputFocus : {}
|
|
221
|
+
},
|
|
222
|
+
onFocus: () => setFocusedField("email"),
|
|
223
|
+
onBlur: () => setFocusedField(null)
|
|
224
|
+
}
|
|
225
|
+
)
|
|
226
|
+
] }),
|
|
227
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
|
|
228
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "password", className: "lite-auth-label", style: styles.label, children: "Password" }),
|
|
229
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
230
|
+
"input",
|
|
231
|
+
{
|
|
232
|
+
id: "password",
|
|
233
|
+
name: "password",
|
|
234
|
+
type: "password",
|
|
235
|
+
required: true,
|
|
236
|
+
autoComplete: "current-password",
|
|
237
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
238
|
+
className: "lite-auth-input",
|
|
239
|
+
style: {
|
|
240
|
+
...styles.input,
|
|
241
|
+
...focusedField === "password" ? styles.inputFocus : {}
|
|
242
|
+
},
|
|
243
|
+
onFocus: () => setFocusedField("password"),
|
|
244
|
+
onBlur: () => setFocusedField(null)
|
|
245
|
+
}
|
|
246
|
+
)
|
|
247
|
+
] }),
|
|
82
248
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
83
|
-
"
|
|
249
|
+
"button",
|
|
84
250
|
{
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
251
|
+
type: "submit",
|
|
252
|
+
disabled: loading,
|
|
253
|
+
className: "lite-auth-btn",
|
|
254
|
+
style: {
|
|
255
|
+
...styles.button,
|
|
256
|
+
...loading ? styles.buttonDisabled : {}
|
|
257
|
+
},
|
|
258
|
+
children: loading ? "Signing in\u2026" : "Sign in"
|
|
92
259
|
}
|
|
93
260
|
)
|
|
94
|
-
] })
|
|
261
|
+
] })
|
|
262
|
+
] }),
|
|
263
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "lite-auth-footer", style: styles.footer, children: [
|
|
264
|
+
"Powered by",
|
|
265
|
+
" ",
|
|
95
266
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
96
|
-
"
|
|
267
|
+
"a",
|
|
97
268
|
{
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
269
|
+
href: "https://github.com/amide-init/next-lite-auth",
|
|
270
|
+
target: "_blank",
|
|
271
|
+
rel: "noopener noreferrer",
|
|
272
|
+
className: "lite-auth-link",
|
|
273
|
+
style: styles.link,
|
|
274
|
+
children: "next-lite-auth"
|
|
102
275
|
}
|
|
103
276
|
)
|
|
104
277
|
] })
|
|
105
|
-
] })
|
|
106
|
-
|
|
107
|
-
"Powered by",
|
|
108
|
-
" ",
|
|
109
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
110
|
-
"a",
|
|
111
|
-
{
|
|
112
|
-
href: "https://github.com/amide-init/next-lite-auth",
|
|
113
|
-
target: "_blank",
|
|
114
|
-
rel: "noopener noreferrer",
|
|
115
|
-
className: "underline underline-offset-4 hover:text-primary transition-colors",
|
|
116
|
-
children: "next-lite-auth"
|
|
117
|
-
}
|
|
118
|
-
)
|
|
119
|
-
] })
|
|
120
|
-
] }) });
|
|
278
|
+
] }) })
|
|
279
|
+
] });
|
|
121
280
|
}
|
|
122
281
|
|
|
123
282
|
// src/client/LiteAuthProvider.tsx
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/index.ts","../src/client/LiteAuthProvider.tsx","../src/client/LiteLoginPage.tsx"],"sourcesContent":["export { LiteAuthProvider, useLiteAuth } from \"./LiteAuthProvider\";\nexport { LiteLoginPage } from \"./LiteLoginPage\";\n","\"use client\";\n\nimport { createContext, useContext, useState, useEffect, useCallback, ReactNode } from \"react\";\nimport { usePathname } from \"next/navigation\";\nimport { PublicUser } from \"../core/types\";\nimport { LiteLoginPage } from \"./LiteLoginPage\";\n\ntype LiteAuthContextValue = {\n user: PublicUser | null;\n loading: boolean;\n login: (creds: { email: string; password: string }) => Promise<{ error?: string }>;\n logout: () => Promise<void>;\n};\n\nconst LiteAuthContext = createContext<LiteAuthContextValue | null>(null);\n\ntype LiteAuthProviderProps = {\n children: ReactNode;\n protect?: string[];\n loginPath?: string;\n logoutPath?: string;\n mePath?: string;\n};\n\nexport function LiteAuthProvider({\n children,\n protect = [],\n loginPath = \"/api/auth/login\",\n logoutPath = \"/api/auth/logout\",\n mePath = \"/api/auth/me\",\n}: LiteAuthProviderProps) {\n const [user, setUser] = useState<PublicUser | null>(null);\n const [loading, setLoading] = useState(true);\n const pathname = usePathname();\n\n useEffect(() => {\n fetch(mePath)\n .then((r) => r.json())\n .then(({ user }) => setUser(user ?? null))\n .catch(() => setUser(null))\n .finally(() => setLoading(false));\n }, [mePath]);\n\n const login = useCallback(\n async ({ email, password }: { email: string; password: string }) => {\n const res = await fetch(loginPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email, password }),\n });\n const data = await res.json();\n if (!res.ok) return { error: data.error ?? \"Login failed\" };\n setUser(data.user);\n return {};\n },\n [loginPath]\n );\n\n const logout = useCallback(async () => {\n await fetch(logoutPath, { method: \"POST\" });\n setUser(null);\n }, [logoutPath]);\n\n const value = { user, loading, login, logout };\n\n const isProtected = protect.some(\n (p) => pathname === p || pathname.startsWith(p + \"/\")\n );\n\n if (loading) {\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n }\n\n if (!user && isProtected) {\n return (\n <LiteAuthContext.Provider value={value}>\n <LiteLoginPage />\n </LiteAuthContext.Provider>\n );\n }\n\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n}\n\nexport function useLiteAuth(): LiteAuthContextValue {\n const ctx = useContext(LiteAuthContext);\n if (!ctx) throw new Error(\"useLiteAuth must be used inside <LiteAuthProvider>\");\n return ctx;\n}\n","\"use client\";\n\nimport { FormEvent, useState } from \"react\";\nimport { useLiteAuth } from \"./LiteAuthProvider\";\n\ntype LiteLoginPageProps = {\n title?: string;\n description?: string;\n};\n\nexport function LiteLoginPage({\n title = \"Sign in\",\n description = \"Enter your credentials to continue\",\n}: LiteLoginPageProps) {\n const { login } = useLiteAuth();\n const [error, setError] = useState(\"\");\n const [loading, setLoading] = useState(false);\n\n async function handleSubmit(e: FormEvent<HTMLFormElement>) {\n e.preventDefault();\n setError(\"\");\n setLoading(true);\n\n const form = e.currentTarget;\n const result = await login({\n email: (form.elements.namedItem(\"email\") as HTMLInputElement).value,\n password: (form.elements.namedItem(\"password\") as HTMLInputElement).value,\n });\n\n setLoading(false);\n\n if (result.error) {\n setError(result.error);\n }\n // no redirect needed — login() sets user in context,\n // LiteAuthProvider re-renders children automatically\n }\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-background px-4\">\n <div className=\"w-full max-w-sm space-y-6\">\n\n <div className=\"space-y-1 text-center\">\n <h1 className=\"text-2xl font-semibold tracking-tight\">{title}</h1>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n\n <div className=\"rounded-xl border bg-card text-card-foreground shadow-sm p-6 space-y-4\">\n {error && (\n <div className=\"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n {error}\n </div>\n )}\n\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <div className=\"space-y-1.5\">\n <label htmlFor=\"email\" className=\"text-sm font-medium leading-none\">\n Email\n </label>\n <input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n required\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label htmlFor=\"password\" className=\"text-sm font-medium leading-none\">\n Password\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required\n autoComplete=\"current-password\"\n placeholder=\"••••••••\"\n className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n </div>\n\n <button\n type=\"submit\"\n disabled={loading}\n className=\"inline-flex h-9 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 transition-colors\"\n >\n {loading ? \"Signing in…\" : \"Sign in\"}\n </button>\n </form>\n </div>\n\n <p className=\"text-center text-xs text-muted-foreground\">\n Powered by{\" \"}\n <a\n href=\"https://github.com/amide-init/next-lite-auth\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline underline-offset-4 hover:text-primary transition-colors\"\n >\n next-lite-auth\n </a>\n </p>\n\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","user"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/index.ts","../src/client/LiteAuthProvider.tsx","../src/client/LiteLoginPage.tsx"],"sourcesContent":["export { LiteAuthProvider, useLiteAuth } from \"./LiteAuthProvider\";\nexport { LiteLoginPage } from \"./LiteLoginPage\";\n","\"use client\";\n\nimport { createContext, useContext, useState, useEffect, useCallback, ReactNode } from \"react\";\nimport { usePathname } from \"next/navigation\";\nimport { PublicUser } from \"../core/types\";\nimport { LiteLoginPage } from \"./LiteLoginPage\";\n\ntype LiteAuthContextValue = {\n user: PublicUser | null;\n loading: boolean;\n login: (creds: { email: string; password: string }) => Promise<{ error?: string }>;\n logout: () => Promise<void>;\n};\n\nconst LiteAuthContext = createContext<LiteAuthContextValue | null>(null);\n\ntype LiteAuthProviderProps = {\n children: ReactNode;\n protect?: string[];\n loginPath?: string;\n logoutPath?: string;\n mePath?: string;\n};\n\nexport function LiteAuthProvider({\n children,\n protect = [],\n loginPath = \"/api/auth/login\",\n logoutPath = \"/api/auth/logout\",\n mePath = \"/api/auth/me\",\n}: LiteAuthProviderProps) {\n const [user, setUser] = useState<PublicUser | null>(null);\n const [loading, setLoading] = useState(true);\n const pathname = usePathname();\n\n useEffect(() => {\n fetch(mePath)\n .then((r) => r.json())\n .then(({ user }) => setUser(user ?? null))\n .catch(() => setUser(null))\n .finally(() => setLoading(false));\n }, [mePath]);\n\n const login = useCallback(\n async ({ email, password }: { email: string; password: string }) => {\n const res = await fetch(loginPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email, password }),\n });\n const data = await res.json();\n if (!res.ok) return { error: data.error ?? \"Login failed\" };\n setUser(data.user);\n return {};\n },\n [loginPath]\n );\n\n const logout = useCallback(async () => {\n await fetch(logoutPath, { method: \"POST\" });\n setUser(null);\n }, [logoutPath]);\n\n const value = { user, loading, login, logout };\n\n const isProtected = protect.some(\n (p) => pathname === p || pathname.startsWith(p + \"/\")\n );\n\n if (loading) {\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n }\n\n if (!user && isProtected) {\n return (\n <LiteAuthContext.Provider value={value}>\n <LiteLoginPage />\n </LiteAuthContext.Provider>\n );\n }\n\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n}\n\nexport function useLiteAuth(): LiteAuthContextValue {\n const ctx = useContext(LiteAuthContext);\n if (!ctx) throw new Error(\"useLiteAuth must be used inside <LiteAuthProvider>\");\n return ctx;\n}\n","\"use client\";\n\nimport { CSSProperties, FormEvent, useState } from \"react\";\nimport { useLiteAuth } from \"./LiteAuthProvider\";\n\ntype LiteLoginPageProps = {\n title?: string;\n description?: string;\n};\n\nconst styles: Record<string, CSSProperties> = {\n page: {\n minHeight: \"100vh\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"#f9fafb\",\n padding: \"0 16px\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n },\n container: {\n width: \"100%\",\n maxWidth: \"360px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"24px\",\n },\n header: {\n textAlign: \"center\",\n },\n title: {\n margin: \"0 0 4px\",\n fontSize: \"22px\",\n fontWeight: 600,\n color: \"#111827\",\n letterSpacing: \"-0.01em\",\n },\n description: {\n margin: 0,\n fontSize: \"14px\",\n color: \"#6b7280\",\n },\n card: {\n backgroundColor: \"#ffffff\",\n border: \"1px solid #e5e7eb\",\n borderRadius: \"12px\",\n padding: \"24px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"16px\",\n boxShadow: \"0 1px 3px rgba(0,0,0,0.07)\",\n },\n error: {\n backgroundColor: \"#fef2f2\",\n border: \"1px solid #fecaca\",\n borderRadius: \"6px\",\n padding: \"8px 12px\",\n fontSize: \"13px\",\n color: \"#dc2626\",\n },\n field: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"6px\",\n },\n label: {\n fontSize: \"13px\",\n fontWeight: 500,\n color: \"#374151\",\n },\n input: {\n height: \"36px\",\n width: \"100%\",\n borderRadius: \"6px\",\n border: \"1px solid #d1d5db\",\n padding: \"0 12px\",\n fontSize: \"14px\",\n color: \"#111827\",\n backgroundColor: \"#fff\",\n outline: \"none\",\n boxSizing: \"border-box\",\n transition: \"border-color 0.15s\",\n },\n inputFocus: {\n borderColor: \"#6366f1\",\n boxShadow: \"0 0 0 3px rgba(99,102,241,0.15)\",\n },\n button: {\n height: \"36px\",\n width: \"100%\",\n borderRadius: \"6px\",\n border: \"none\",\n backgroundColor: \"#111827\",\n color: \"#ffffff\",\n fontSize: \"14px\",\n fontWeight: 500,\n cursor: \"pointer\",\n transition: \"opacity 0.15s\",\n },\n buttonDisabled: {\n opacity: 0.5,\n pointerEvents: \"none\",\n },\n footer: {\n textAlign: \"center\",\n fontSize: \"12px\",\n color: \"#9ca3af\",\n },\n link: {\n color: \"#6b7280\",\n textDecoration: \"underline\",\n textUnderlineOffset: \"3px\",\n },\n};\n\nconst darkModeCSS = `\n @media (prefers-color-scheme: dark) {\n .lite-auth-page { background-color: #09090b !important; }\n .lite-auth-title { color: #fafafa !important; }\n .lite-auth-desc { color: #a1a1aa !important; }\n .lite-auth-card {\n background-color: #18181b !important;\n border-color: #27272a !important;\n box-shadow: none !important;\n }\n .lite-auth-error {\n background-color: rgba(239,68,68,0.1) !important;\n border-color: rgba(239,68,68,0.3) !important;\n color: #f87171 !important;\n }\n .lite-auth-label { color: #e4e4e7 !important; }\n .lite-auth-input {\n background-color: transparent !important;\n border-color: #3f3f46 !important;\n color: #fafafa !important;\n }\n .lite-auth-input::placeholder { color: #52525b !important; }\n .lite-auth-input:focus {\n border-color: #6366f1 !important;\n box-shadow: 0 0 0 3px rgba(99,102,241,0.2) !important;\n }\n .lite-auth-btn {\n background-color: #fafafa !important;\n color: #09090b !important;\n }\n .lite-auth-footer { color: #52525b !important; }\n .lite-auth-link { color: #71717a !important; }\n }\n`;\n\nexport function LiteLoginPage({\n title = \"Sign in\",\n description = \"Enter your credentials to continue\",\n}: LiteLoginPageProps) {\n const { login } = useLiteAuth();\n const [error, setError] = useState(\"\");\n const [loading, setLoading] = useState(false);\n const [focusedField, setFocusedField] = useState<string | null>(null);\n\n async function handleSubmit(e: FormEvent<HTMLFormElement>) {\n e.preventDefault();\n setError(\"\");\n setLoading(true);\n\n const form = e.currentTarget;\n const result = await login({\n email: (form.elements.namedItem(\"email\") as HTMLInputElement).value,\n password: (form.elements.namedItem(\"password\") as HTMLInputElement).value,\n });\n\n setLoading(false);\n\n if (result.error) {\n setError(result.error);\n }\n }\n\n return (\n <>\n <style>{darkModeCSS}</style>\n <div className=\"lite-auth-page\" style={styles.page}>\n <div style={styles.container}>\n <div style={styles.header}>\n <h1 className=\"lite-auth-title\" style={styles.title}>{title}</h1>\n <p className=\"lite-auth-desc\" style={styles.description}>{description}</p>\n </div>\n\n <div className=\"lite-auth-card\" style={styles.card}>\n {error && (\n <div className=\"lite-auth-error\" style={styles.error}>{error}</div>\n )}\n\n <form onSubmit={handleSubmit} style={{ display: \"flex\", flexDirection: \"column\", gap: \"16px\" }}>\n <div style={styles.field}>\n <label htmlFor=\"email\" className=\"lite-auth-label\" style={styles.label}>Email</label>\n <input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n required\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n className=\"lite-auth-input\"\n style={{\n ...styles.input,\n ...(focusedField === \"email\" ? styles.inputFocus : {}),\n }}\n onFocus={() => setFocusedField(\"email\")}\n onBlur={() => setFocusedField(null)}\n />\n </div>\n\n <div style={styles.field}>\n <label htmlFor=\"password\" className=\"lite-auth-label\" style={styles.label}>Password</label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required\n autoComplete=\"current-password\"\n placeholder=\"••••••••\"\n className=\"lite-auth-input\"\n style={{\n ...styles.input,\n ...(focusedField === \"password\" ? styles.inputFocus : {}),\n }}\n onFocus={() => setFocusedField(\"password\")}\n onBlur={() => setFocusedField(null)}\n />\n </div>\n\n <button\n type=\"submit\"\n disabled={loading}\n className=\"lite-auth-btn\"\n style={{\n ...styles.button,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n >\n {loading ? \"Signing in…\" : \"Sign in\"}\n </button>\n </form>\n </div>\n\n <p className=\"lite-auth-footer\" style={styles.footer}>\n Powered by{\" \"}\n <a\n href=\"https://github.com/amide-init/next-lite-auth\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"lite-auth-link\"\n style={styles.link}\n >\n next-lite-auth\n </a>\n </p>\n </div>\n </div>\n </>\n );\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","user"]}
|
package/dist/client.mjs
CHANGED
|
@@ -4,7 +4,145 @@ import { usePathname } from "next/navigation";
|
|
|
4
4
|
|
|
5
5
|
// src/client/LiteLoginPage.tsx
|
|
6
6
|
import { useState } from "react";
|
|
7
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var styles = {
|
|
9
|
+
page: {
|
|
10
|
+
minHeight: "100vh",
|
|
11
|
+
display: "flex",
|
|
12
|
+
alignItems: "center",
|
|
13
|
+
justifyContent: "center",
|
|
14
|
+
backgroundColor: "#f9fafb",
|
|
15
|
+
padding: "0 16px",
|
|
16
|
+
fontFamily: "system-ui, -apple-system, sans-serif"
|
|
17
|
+
},
|
|
18
|
+
container: {
|
|
19
|
+
width: "100%",
|
|
20
|
+
maxWidth: "360px",
|
|
21
|
+
display: "flex",
|
|
22
|
+
flexDirection: "column",
|
|
23
|
+
gap: "24px"
|
|
24
|
+
},
|
|
25
|
+
header: {
|
|
26
|
+
textAlign: "center"
|
|
27
|
+
},
|
|
28
|
+
title: {
|
|
29
|
+
margin: "0 0 4px",
|
|
30
|
+
fontSize: "22px",
|
|
31
|
+
fontWeight: 600,
|
|
32
|
+
color: "#111827",
|
|
33
|
+
letterSpacing: "-0.01em"
|
|
34
|
+
},
|
|
35
|
+
description: {
|
|
36
|
+
margin: 0,
|
|
37
|
+
fontSize: "14px",
|
|
38
|
+
color: "#6b7280"
|
|
39
|
+
},
|
|
40
|
+
card: {
|
|
41
|
+
backgroundColor: "#ffffff",
|
|
42
|
+
border: "1px solid #e5e7eb",
|
|
43
|
+
borderRadius: "12px",
|
|
44
|
+
padding: "24px",
|
|
45
|
+
display: "flex",
|
|
46
|
+
flexDirection: "column",
|
|
47
|
+
gap: "16px",
|
|
48
|
+
boxShadow: "0 1px 3px rgba(0,0,0,0.07)"
|
|
49
|
+
},
|
|
50
|
+
error: {
|
|
51
|
+
backgroundColor: "#fef2f2",
|
|
52
|
+
border: "1px solid #fecaca",
|
|
53
|
+
borderRadius: "6px",
|
|
54
|
+
padding: "8px 12px",
|
|
55
|
+
fontSize: "13px",
|
|
56
|
+
color: "#dc2626"
|
|
57
|
+
},
|
|
58
|
+
field: {
|
|
59
|
+
display: "flex",
|
|
60
|
+
flexDirection: "column",
|
|
61
|
+
gap: "6px"
|
|
62
|
+
},
|
|
63
|
+
label: {
|
|
64
|
+
fontSize: "13px",
|
|
65
|
+
fontWeight: 500,
|
|
66
|
+
color: "#374151"
|
|
67
|
+
},
|
|
68
|
+
input: {
|
|
69
|
+
height: "36px",
|
|
70
|
+
width: "100%",
|
|
71
|
+
borderRadius: "6px",
|
|
72
|
+
border: "1px solid #d1d5db",
|
|
73
|
+
padding: "0 12px",
|
|
74
|
+
fontSize: "14px",
|
|
75
|
+
color: "#111827",
|
|
76
|
+
backgroundColor: "#fff",
|
|
77
|
+
outline: "none",
|
|
78
|
+
boxSizing: "border-box",
|
|
79
|
+
transition: "border-color 0.15s"
|
|
80
|
+
},
|
|
81
|
+
inputFocus: {
|
|
82
|
+
borderColor: "#6366f1",
|
|
83
|
+
boxShadow: "0 0 0 3px rgba(99,102,241,0.15)"
|
|
84
|
+
},
|
|
85
|
+
button: {
|
|
86
|
+
height: "36px",
|
|
87
|
+
width: "100%",
|
|
88
|
+
borderRadius: "6px",
|
|
89
|
+
border: "none",
|
|
90
|
+
backgroundColor: "#111827",
|
|
91
|
+
color: "#ffffff",
|
|
92
|
+
fontSize: "14px",
|
|
93
|
+
fontWeight: 500,
|
|
94
|
+
cursor: "pointer",
|
|
95
|
+
transition: "opacity 0.15s"
|
|
96
|
+
},
|
|
97
|
+
buttonDisabled: {
|
|
98
|
+
opacity: 0.5,
|
|
99
|
+
pointerEvents: "none"
|
|
100
|
+
},
|
|
101
|
+
footer: {
|
|
102
|
+
textAlign: "center",
|
|
103
|
+
fontSize: "12px",
|
|
104
|
+
color: "#9ca3af"
|
|
105
|
+
},
|
|
106
|
+
link: {
|
|
107
|
+
color: "#6b7280",
|
|
108
|
+
textDecoration: "underline",
|
|
109
|
+
textUnderlineOffset: "3px"
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
var darkModeCSS = `
|
|
113
|
+
@media (prefers-color-scheme: dark) {
|
|
114
|
+
.lite-auth-page { background-color: #09090b !important; }
|
|
115
|
+
.lite-auth-title { color: #fafafa !important; }
|
|
116
|
+
.lite-auth-desc { color: #a1a1aa !important; }
|
|
117
|
+
.lite-auth-card {
|
|
118
|
+
background-color: #18181b !important;
|
|
119
|
+
border-color: #27272a !important;
|
|
120
|
+
box-shadow: none !important;
|
|
121
|
+
}
|
|
122
|
+
.lite-auth-error {
|
|
123
|
+
background-color: rgba(239,68,68,0.1) !important;
|
|
124
|
+
border-color: rgba(239,68,68,0.3) !important;
|
|
125
|
+
color: #f87171 !important;
|
|
126
|
+
}
|
|
127
|
+
.lite-auth-label { color: #e4e4e7 !important; }
|
|
128
|
+
.lite-auth-input {
|
|
129
|
+
background-color: transparent !important;
|
|
130
|
+
border-color: #3f3f46 !important;
|
|
131
|
+
color: #fafafa !important;
|
|
132
|
+
}
|
|
133
|
+
.lite-auth-input::placeholder { color: #52525b !important; }
|
|
134
|
+
.lite-auth-input:focus {
|
|
135
|
+
border-color: #6366f1 !important;
|
|
136
|
+
box-shadow: 0 0 0 3px rgba(99,102,241,0.2) !important;
|
|
137
|
+
}
|
|
138
|
+
.lite-auth-btn {
|
|
139
|
+
background-color: #fafafa !important;
|
|
140
|
+
color: #09090b !important;
|
|
141
|
+
}
|
|
142
|
+
.lite-auth-footer { color: #52525b !important; }
|
|
143
|
+
.lite-auth-link { color: #71717a !important; }
|
|
144
|
+
}
|
|
145
|
+
`;
|
|
8
146
|
function LiteLoginPage({
|
|
9
147
|
title = "Sign in",
|
|
10
148
|
description = "Enter your credentials to continue"
|
|
@@ -12,6 +150,7 @@ function LiteLoginPage({
|
|
|
12
150
|
const { login } = useLiteAuth();
|
|
13
151
|
const [error, setError] = useState("");
|
|
14
152
|
const [loading, setLoading] = useState(false);
|
|
153
|
+
const [focusedField, setFocusedField] = useState(null);
|
|
15
154
|
async function handleSubmit(e) {
|
|
16
155
|
e.preventDefault();
|
|
17
156
|
setError("");
|
|
@@ -26,70 +165,90 @@ function LiteLoginPage({
|
|
|
26
165
|
setError(result.error);
|
|
27
166
|
}
|
|
28
167
|
}
|
|
29
|
-
return /* @__PURE__ */
|
|
30
|
-
/* @__PURE__ */
|
|
31
|
-
|
|
32
|
-
/* @__PURE__ */
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
/* @__PURE__ */ jsxs("
|
|
37
|
-
/* @__PURE__ */
|
|
38
|
-
|
|
39
|
-
/* @__PURE__ */
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
168
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
169
|
+
/* @__PURE__ */ jsx("style", { children: darkModeCSS }),
|
|
170
|
+
/* @__PURE__ */ jsx("div", { className: "lite-auth-page", style: styles.page, children: /* @__PURE__ */ jsxs("div", { style: styles.container, children: [
|
|
171
|
+
/* @__PURE__ */ jsxs("div", { style: styles.header, children: [
|
|
172
|
+
/* @__PURE__ */ jsx("h1", { className: "lite-auth-title", style: styles.title, children: title }),
|
|
173
|
+
/* @__PURE__ */ jsx("p", { className: "lite-auth-desc", style: styles.description, children: description })
|
|
174
|
+
] }),
|
|
175
|
+
/* @__PURE__ */ jsxs("div", { className: "lite-auth-card", style: styles.card, children: [
|
|
176
|
+
error && /* @__PURE__ */ jsx("div", { className: "lite-auth-error", style: styles.error, children: error }),
|
|
177
|
+
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, style: { display: "flex", flexDirection: "column", gap: "16px" }, children: [
|
|
178
|
+
/* @__PURE__ */ jsxs("div", { style: styles.field, children: [
|
|
179
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "email", className: "lite-auth-label", style: styles.label, children: "Email" }),
|
|
180
|
+
/* @__PURE__ */ jsx(
|
|
181
|
+
"input",
|
|
182
|
+
{
|
|
183
|
+
id: "email",
|
|
184
|
+
name: "email",
|
|
185
|
+
type: "email",
|
|
186
|
+
required: true,
|
|
187
|
+
autoComplete: "email",
|
|
188
|
+
placeholder: "you@example.com",
|
|
189
|
+
className: "lite-auth-input",
|
|
190
|
+
style: {
|
|
191
|
+
...styles.input,
|
|
192
|
+
...focusedField === "email" ? styles.inputFocus : {}
|
|
193
|
+
},
|
|
194
|
+
onFocus: () => setFocusedField("email"),
|
|
195
|
+
onBlur: () => setFocusedField(null)
|
|
196
|
+
}
|
|
197
|
+
)
|
|
198
|
+
] }),
|
|
199
|
+
/* @__PURE__ */ jsxs("div", { style: styles.field, children: [
|
|
200
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "password", className: "lite-auth-label", style: styles.label, children: "Password" }),
|
|
201
|
+
/* @__PURE__ */ jsx(
|
|
202
|
+
"input",
|
|
203
|
+
{
|
|
204
|
+
id: "password",
|
|
205
|
+
name: "password",
|
|
206
|
+
type: "password",
|
|
207
|
+
required: true,
|
|
208
|
+
autoComplete: "current-password",
|
|
209
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
210
|
+
className: "lite-auth-input",
|
|
211
|
+
style: {
|
|
212
|
+
...styles.input,
|
|
213
|
+
...focusedField === "password" ? styles.inputFocus : {}
|
|
214
|
+
},
|
|
215
|
+
onFocus: () => setFocusedField("password"),
|
|
216
|
+
onBlur: () => setFocusedField(null)
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
] }),
|
|
54
220
|
/* @__PURE__ */ jsx(
|
|
55
|
-
"
|
|
221
|
+
"button",
|
|
56
222
|
{
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
223
|
+
type: "submit",
|
|
224
|
+
disabled: loading,
|
|
225
|
+
className: "lite-auth-btn",
|
|
226
|
+
style: {
|
|
227
|
+
...styles.button,
|
|
228
|
+
...loading ? styles.buttonDisabled : {}
|
|
229
|
+
},
|
|
230
|
+
children: loading ? "Signing in\u2026" : "Sign in"
|
|
64
231
|
}
|
|
65
232
|
)
|
|
66
|
-
] })
|
|
233
|
+
] })
|
|
234
|
+
] }),
|
|
235
|
+
/* @__PURE__ */ jsxs("p", { className: "lite-auth-footer", style: styles.footer, children: [
|
|
236
|
+
"Powered by",
|
|
237
|
+
" ",
|
|
67
238
|
/* @__PURE__ */ jsx(
|
|
68
|
-
"
|
|
239
|
+
"a",
|
|
69
240
|
{
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
241
|
+
href: "https://github.com/amide-init/next-lite-auth",
|
|
242
|
+
target: "_blank",
|
|
243
|
+
rel: "noopener noreferrer",
|
|
244
|
+
className: "lite-auth-link",
|
|
245
|
+
style: styles.link,
|
|
246
|
+
children: "next-lite-auth"
|
|
74
247
|
}
|
|
75
248
|
)
|
|
76
249
|
] })
|
|
77
|
-
] })
|
|
78
|
-
|
|
79
|
-
"Powered by",
|
|
80
|
-
" ",
|
|
81
|
-
/* @__PURE__ */ jsx(
|
|
82
|
-
"a",
|
|
83
|
-
{
|
|
84
|
-
href: "https://github.com/amide-init/next-lite-auth",
|
|
85
|
-
target: "_blank",
|
|
86
|
-
rel: "noopener noreferrer",
|
|
87
|
-
className: "underline underline-offset-4 hover:text-primary transition-colors",
|
|
88
|
-
children: "next-lite-auth"
|
|
89
|
-
}
|
|
90
|
-
)
|
|
91
|
-
] })
|
|
92
|
-
] }) });
|
|
250
|
+
] }) })
|
|
251
|
+
] });
|
|
93
252
|
}
|
|
94
253
|
|
|
95
254
|
// src/client/LiteAuthProvider.tsx
|
package/dist/client.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/LiteAuthProvider.tsx","../src/client/LiteLoginPage.tsx"],"sourcesContent":["\"use client\";\n\nimport { createContext, useContext, useState, useEffect, useCallback, ReactNode } from \"react\";\nimport { usePathname } from \"next/navigation\";\nimport { PublicUser } from \"../core/types\";\nimport { LiteLoginPage } from \"./LiteLoginPage\";\n\ntype LiteAuthContextValue = {\n user: PublicUser | null;\n loading: boolean;\n login: (creds: { email: string; password: string }) => Promise<{ error?: string }>;\n logout: () => Promise<void>;\n};\n\nconst LiteAuthContext = createContext<LiteAuthContextValue | null>(null);\n\ntype LiteAuthProviderProps = {\n children: ReactNode;\n protect?: string[];\n loginPath?: string;\n logoutPath?: string;\n mePath?: string;\n};\n\nexport function LiteAuthProvider({\n children,\n protect = [],\n loginPath = \"/api/auth/login\",\n logoutPath = \"/api/auth/logout\",\n mePath = \"/api/auth/me\",\n}: LiteAuthProviderProps) {\n const [user, setUser] = useState<PublicUser | null>(null);\n const [loading, setLoading] = useState(true);\n const pathname = usePathname();\n\n useEffect(() => {\n fetch(mePath)\n .then((r) => r.json())\n .then(({ user }) => setUser(user ?? null))\n .catch(() => setUser(null))\n .finally(() => setLoading(false));\n }, [mePath]);\n\n const login = useCallback(\n async ({ email, password }: { email: string; password: string }) => {\n const res = await fetch(loginPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email, password }),\n });\n const data = await res.json();\n if (!res.ok) return { error: data.error ?? \"Login failed\" };\n setUser(data.user);\n return {};\n },\n [loginPath]\n );\n\n const logout = useCallback(async () => {\n await fetch(logoutPath, { method: \"POST\" });\n setUser(null);\n }, [logoutPath]);\n\n const value = { user, loading, login, logout };\n\n const isProtected = protect.some(\n (p) => pathname === p || pathname.startsWith(p + \"/\")\n );\n\n if (loading) {\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n }\n\n if (!user && isProtected) {\n return (\n <LiteAuthContext.Provider value={value}>\n <LiteLoginPage />\n </LiteAuthContext.Provider>\n );\n }\n\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n}\n\nexport function useLiteAuth(): LiteAuthContextValue {\n const ctx = useContext(LiteAuthContext);\n if (!ctx) throw new Error(\"useLiteAuth must be used inside <LiteAuthProvider>\");\n return ctx;\n}\n","\"use client\";\n\nimport { FormEvent, useState } from \"react\";\nimport { useLiteAuth } from \"./LiteAuthProvider\";\n\ntype LiteLoginPageProps = {\n title?: string;\n description?: string;\n};\n\nexport function LiteLoginPage({\n title = \"Sign in\",\n description = \"Enter your credentials to continue\",\n}: LiteLoginPageProps) {\n const { login } = useLiteAuth();\n const [error, setError] = useState(\"\");\n const [loading, setLoading] = useState(false);\n\n async function handleSubmit(e: FormEvent<HTMLFormElement>) {\n e.preventDefault();\n setError(\"\");\n setLoading(true);\n\n const form = e.currentTarget;\n const result = await login({\n email: (form.elements.namedItem(\"email\") as HTMLInputElement).value,\n password: (form.elements.namedItem(\"password\") as HTMLInputElement).value,\n });\n\n setLoading(false);\n\n if (result.error) {\n setError(result.error);\n }\n // no redirect needed — login() sets user in context,\n // LiteAuthProvider re-renders children automatically\n }\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-background px-4\">\n <div className=\"w-full max-w-sm space-y-6\">\n\n <div className=\"space-y-1 text-center\">\n <h1 className=\"text-2xl font-semibold tracking-tight\">{title}</h1>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n\n <div className=\"rounded-xl border bg-card text-card-foreground shadow-sm p-6 space-y-4\">\n {error && (\n <div className=\"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n {error}\n </div>\n )}\n\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <div className=\"space-y-1.5\">\n <label htmlFor=\"email\" className=\"text-sm font-medium leading-none\">\n Email\n </label>\n <input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n required\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label htmlFor=\"password\" className=\"text-sm font-medium leading-none\">\n Password\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required\n autoComplete=\"current-password\"\n placeholder=\"••••••••\"\n className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n </div>\n\n <button\n type=\"submit\"\n disabled={loading}\n className=\"inline-flex h-9 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 transition-colors\"\n >\n {loading ? \"Signing in…\" : \"Sign in\"}\n </button>\n </form>\n </div>\n\n <p className=\"text-center text-xs text-muted-foreground\">\n Powered by{\" \"}\n <a\n href=\"https://github.com/amide-init/next-lite-auth\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline underline-offset-4 hover:text-primary transition-colors\"\n >\n next-lite-auth\n </a>\n </p>\n\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["useState","jsx","useState","user"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/LiteAuthProvider.tsx","../src/client/LiteLoginPage.tsx"],"sourcesContent":["\"use client\";\n\nimport { createContext, useContext, useState, useEffect, useCallback, ReactNode } from \"react\";\nimport { usePathname } from \"next/navigation\";\nimport { PublicUser } from \"../core/types\";\nimport { LiteLoginPage } from \"./LiteLoginPage\";\n\ntype LiteAuthContextValue = {\n user: PublicUser | null;\n loading: boolean;\n login: (creds: { email: string; password: string }) => Promise<{ error?: string }>;\n logout: () => Promise<void>;\n};\n\nconst LiteAuthContext = createContext<LiteAuthContextValue | null>(null);\n\ntype LiteAuthProviderProps = {\n children: ReactNode;\n protect?: string[];\n loginPath?: string;\n logoutPath?: string;\n mePath?: string;\n};\n\nexport function LiteAuthProvider({\n children,\n protect = [],\n loginPath = \"/api/auth/login\",\n logoutPath = \"/api/auth/logout\",\n mePath = \"/api/auth/me\",\n}: LiteAuthProviderProps) {\n const [user, setUser] = useState<PublicUser | null>(null);\n const [loading, setLoading] = useState(true);\n const pathname = usePathname();\n\n useEffect(() => {\n fetch(mePath)\n .then((r) => r.json())\n .then(({ user }) => setUser(user ?? null))\n .catch(() => setUser(null))\n .finally(() => setLoading(false));\n }, [mePath]);\n\n const login = useCallback(\n async ({ email, password }: { email: string; password: string }) => {\n const res = await fetch(loginPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email, password }),\n });\n const data = await res.json();\n if (!res.ok) return { error: data.error ?? \"Login failed\" };\n setUser(data.user);\n return {};\n },\n [loginPath]\n );\n\n const logout = useCallback(async () => {\n await fetch(logoutPath, { method: \"POST\" });\n setUser(null);\n }, [logoutPath]);\n\n const value = { user, loading, login, logout };\n\n const isProtected = protect.some(\n (p) => pathname === p || pathname.startsWith(p + \"/\")\n );\n\n if (loading) {\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n }\n\n if (!user && isProtected) {\n return (\n <LiteAuthContext.Provider value={value}>\n <LiteLoginPage />\n </LiteAuthContext.Provider>\n );\n }\n\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n}\n\nexport function useLiteAuth(): LiteAuthContextValue {\n const ctx = useContext(LiteAuthContext);\n if (!ctx) throw new Error(\"useLiteAuth must be used inside <LiteAuthProvider>\");\n return ctx;\n}\n","\"use client\";\n\nimport { CSSProperties, FormEvent, useState } from \"react\";\nimport { useLiteAuth } from \"./LiteAuthProvider\";\n\ntype LiteLoginPageProps = {\n title?: string;\n description?: string;\n};\n\nconst styles: Record<string, CSSProperties> = {\n page: {\n minHeight: \"100vh\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"#f9fafb\",\n padding: \"0 16px\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n },\n container: {\n width: \"100%\",\n maxWidth: \"360px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"24px\",\n },\n header: {\n textAlign: \"center\",\n },\n title: {\n margin: \"0 0 4px\",\n fontSize: \"22px\",\n fontWeight: 600,\n color: \"#111827\",\n letterSpacing: \"-0.01em\",\n },\n description: {\n margin: 0,\n fontSize: \"14px\",\n color: \"#6b7280\",\n },\n card: {\n backgroundColor: \"#ffffff\",\n border: \"1px solid #e5e7eb\",\n borderRadius: \"12px\",\n padding: \"24px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"16px\",\n boxShadow: \"0 1px 3px rgba(0,0,0,0.07)\",\n },\n error: {\n backgroundColor: \"#fef2f2\",\n border: \"1px solid #fecaca\",\n borderRadius: \"6px\",\n padding: \"8px 12px\",\n fontSize: \"13px\",\n color: \"#dc2626\",\n },\n field: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"6px\",\n },\n label: {\n fontSize: \"13px\",\n fontWeight: 500,\n color: \"#374151\",\n },\n input: {\n height: \"36px\",\n width: \"100%\",\n borderRadius: \"6px\",\n border: \"1px solid #d1d5db\",\n padding: \"0 12px\",\n fontSize: \"14px\",\n color: \"#111827\",\n backgroundColor: \"#fff\",\n outline: \"none\",\n boxSizing: \"border-box\",\n transition: \"border-color 0.15s\",\n },\n inputFocus: {\n borderColor: \"#6366f1\",\n boxShadow: \"0 0 0 3px rgba(99,102,241,0.15)\",\n },\n button: {\n height: \"36px\",\n width: \"100%\",\n borderRadius: \"6px\",\n border: \"none\",\n backgroundColor: \"#111827\",\n color: \"#ffffff\",\n fontSize: \"14px\",\n fontWeight: 500,\n cursor: \"pointer\",\n transition: \"opacity 0.15s\",\n },\n buttonDisabled: {\n opacity: 0.5,\n pointerEvents: \"none\",\n },\n footer: {\n textAlign: \"center\",\n fontSize: \"12px\",\n color: \"#9ca3af\",\n },\n link: {\n color: \"#6b7280\",\n textDecoration: \"underline\",\n textUnderlineOffset: \"3px\",\n },\n};\n\nconst darkModeCSS = `\n @media (prefers-color-scheme: dark) {\n .lite-auth-page { background-color: #09090b !important; }\n .lite-auth-title { color: #fafafa !important; }\n .lite-auth-desc { color: #a1a1aa !important; }\n .lite-auth-card {\n background-color: #18181b !important;\n border-color: #27272a !important;\n box-shadow: none !important;\n }\n .lite-auth-error {\n background-color: rgba(239,68,68,0.1) !important;\n border-color: rgba(239,68,68,0.3) !important;\n color: #f87171 !important;\n }\n .lite-auth-label { color: #e4e4e7 !important; }\n .lite-auth-input {\n background-color: transparent !important;\n border-color: #3f3f46 !important;\n color: #fafafa !important;\n }\n .lite-auth-input::placeholder { color: #52525b !important; }\n .lite-auth-input:focus {\n border-color: #6366f1 !important;\n box-shadow: 0 0 0 3px rgba(99,102,241,0.2) !important;\n }\n .lite-auth-btn {\n background-color: #fafafa !important;\n color: #09090b !important;\n }\n .lite-auth-footer { color: #52525b !important; }\n .lite-auth-link { color: #71717a !important; }\n }\n`;\n\nexport function LiteLoginPage({\n title = \"Sign in\",\n description = \"Enter your credentials to continue\",\n}: LiteLoginPageProps) {\n const { login } = useLiteAuth();\n const [error, setError] = useState(\"\");\n const [loading, setLoading] = useState(false);\n const [focusedField, setFocusedField] = useState<string | null>(null);\n\n async function handleSubmit(e: FormEvent<HTMLFormElement>) {\n e.preventDefault();\n setError(\"\");\n setLoading(true);\n\n const form = e.currentTarget;\n const result = await login({\n email: (form.elements.namedItem(\"email\") as HTMLInputElement).value,\n password: (form.elements.namedItem(\"password\") as HTMLInputElement).value,\n });\n\n setLoading(false);\n\n if (result.error) {\n setError(result.error);\n }\n }\n\n return (\n <>\n <style>{darkModeCSS}</style>\n <div className=\"lite-auth-page\" style={styles.page}>\n <div style={styles.container}>\n <div style={styles.header}>\n <h1 className=\"lite-auth-title\" style={styles.title}>{title}</h1>\n <p className=\"lite-auth-desc\" style={styles.description}>{description}</p>\n </div>\n\n <div className=\"lite-auth-card\" style={styles.card}>\n {error && (\n <div className=\"lite-auth-error\" style={styles.error}>{error}</div>\n )}\n\n <form onSubmit={handleSubmit} style={{ display: \"flex\", flexDirection: \"column\", gap: \"16px\" }}>\n <div style={styles.field}>\n <label htmlFor=\"email\" className=\"lite-auth-label\" style={styles.label}>Email</label>\n <input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n required\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n className=\"lite-auth-input\"\n style={{\n ...styles.input,\n ...(focusedField === \"email\" ? styles.inputFocus : {}),\n }}\n onFocus={() => setFocusedField(\"email\")}\n onBlur={() => setFocusedField(null)}\n />\n </div>\n\n <div style={styles.field}>\n <label htmlFor=\"password\" className=\"lite-auth-label\" style={styles.label}>Password</label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required\n autoComplete=\"current-password\"\n placeholder=\"••••••••\"\n className=\"lite-auth-input\"\n style={{\n ...styles.input,\n ...(focusedField === \"password\" ? styles.inputFocus : {}),\n }}\n onFocus={() => setFocusedField(\"password\")}\n onBlur={() => setFocusedField(null)}\n />\n </div>\n\n <button\n type=\"submit\"\n disabled={loading}\n className=\"lite-auth-btn\"\n style={{\n ...styles.button,\n ...(loading ? styles.buttonDisabled : {}),\n }}\n >\n {loading ? \"Signing in…\" : \"Sign in\"}\n </button>\n </form>\n </div>\n\n <p className=\"lite-auth-footer\" style={styles.footer}>\n Powered by{\" \"}\n <a\n href=\"https://github.com/amide-init/next-lite-auth\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"lite-auth-link\"\n style={styles.link}\n >\n next-lite-auth\n </a>\n </p>\n </div>\n </div>\n </>\n );\n}\n"],"mappings":"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","names":["useState","jsx","useState","user"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -12,6 +12,7 @@ type LiteAuthConfig = {
|
|
|
12
12
|
users: User[];
|
|
13
13
|
jwtSecret: string;
|
|
14
14
|
cookieName?: string;
|
|
15
|
+
enabled?: boolean;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
declare function createLiteAuth(config: LiteAuthConfig): {
|
|
@@ -26,4 +27,6 @@ declare function createLiteAuth(config: LiteAuthConfig): {
|
|
|
26
27
|
getUserFromCookies: (cookies: next_dist_server_web_spec_extension_adapters_request_cookies.ReadonlyRequestCookies) => Promise<PublicUser | null>;
|
|
27
28
|
};
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
declare function usersFromEnv(): User[];
|
|
31
|
+
|
|
32
|
+
export { type LiteAuthConfig, type PublicUser, type User, createLiteAuth, usersFromEnv };
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ type LiteAuthConfig = {
|
|
|
12
12
|
users: User[];
|
|
13
13
|
jwtSecret: string;
|
|
14
14
|
cookieName?: string;
|
|
15
|
+
enabled?: boolean;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
declare function createLiteAuth(config: LiteAuthConfig): {
|
|
@@ -26,4 +27,6 @@ declare function createLiteAuth(config: LiteAuthConfig): {
|
|
|
26
27
|
getUserFromCookies: (cookies: next_dist_server_web_spec_extension_adapters_request_cookies.ReadonlyRequestCookies) => Promise<PublicUser | null>;
|
|
27
28
|
};
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
declare function usersFromEnv(): User[];
|
|
31
|
+
|
|
32
|
+
export { type LiteAuthConfig, type PublicUser, type User, createLiteAuth, usersFromEnv };
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
|
-
createLiteAuth: () => createLiteAuth
|
|
23
|
+
createLiteAuth: () => createLiteAuth,
|
|
24
|
+
usersFromEnv: () => usersFromEnv
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(src_exports);
|
|
26
27
|
|
|
@@ -86,11 +87,13 @@ function makeHandlers(ctx) {
|
|
|
86
87
|
return import_server.NextResponse.json({ user });
|
|
87
88
|
}
|
|
88
89
|
async function GET(req) {
|
|
90
|
+
if (!ctx.enabled) return import_server.NextResponse.json({ user: null });
|
|
89
91
|
const action = req.nextUrl.pathname.split("/").pop();
|
|
90
92
|
if (action === "me") return me(req);
|
|
91
93
|
return import_server.NextResponse.json({ error: "Not found" }, { status: 404 });
|
|
92
94
|
}
|
|
93
95
|
async function POST(req) {
|
|
96
|
+
if (!ctx.enabled) return import_server.NextResponse.json({ ok: true });
|
|
94
97
|
const action = req.nextUrl.pathname.split("/").pop();
|
|
95
98
|
if (action === "login") return login(req);
|
|
96
99
|
if (action === "logout") return logout(req);
|
|
@@ -113,6 +116,7 @@ var import_server2 = require("next/server");
|
|
|
113
116
|
function makeMiddleware(ctx) {
|
|
114
117
|
return function middleware(options) {
|
|
115
118
|
return async function(req) {
|
|
119
|
+
if (!ctx.enabled) return import_server2.NextResponse.next();
|
|
116
120
|
const { protect, redirectTo = "/login" } = options;
|
|
117
121
|
const { pathname } = req.nextUrl;
|
|
118
122
|
const isProtected = protect.some(
|
|
@@ -138,7 +142,8 @@ function createLiteAuth(config) {
|
|
|
138
142
|
const ctx = {
|
|
139
143
|
users: config.users,
|
|
140
144
|
jwtSecret: config.jwtSecret,
|
|
141
|
-
cookieName: config.cookieName ?? "lite-auth-token"
|
|
145
|
+
cookieName: config.cookieName ?? "lite-auth-token",
|
|
146
|
+
enabled: config.enabled ?? true
|
|
142
147
|
};
|
|
143
148
|
return {
|
|
144
149
|
handlers: makeHandlers(ctx),
|
|
@@ -146,8 +151,33 @@ function createLiteAuth(config) {
|
|
|
146
151
|
getUserFromCookies: getUserFromCookies(ctx)
|
|
147
152
|
};
|
|
148
153
|
}
|
|
154
|
+
|
|
155
|
+
// src/core/usersFromEnv.ts
|
|
156
|
+
function usersFromEnv() {
|
|
157
|
+
const raw = process.env.LITE_AUTH_USERS;
|
|
158
|
+
if (!raw) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`[next-lite-auth] LITE_AUTH_USERS environment variable is not set. Set it to a JSON array of users, e.g.: LITE_AUTH_USERS='[{"email":"admin@example.com","password":"secret"}]'`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
let parsed;
|
|
164
|
+
try {
|
|
165
|
+
parsed = JSON.parse(raw);
|
|
166
|
+
} catch {
|
|
167
|
+
throw new Error(
|
|
168
|
+
"[next-lite-auth] LITE_AUTH_USERS is not valid JSON. Expected a JSON array of users."
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
if (!Array.isArray(parsed)) {
|
|
172
|
+
throw new Error(
|
|
173
|
+
'[next-lite-auth] LITE_AUTH_USERS must be a JSON array, e.g.: [{"email":"admin@example.com","password":"secret"}]'
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
return parsed;
|
|
177
|
+
}
|
|
149
178
|
// Annotate the CommonJS export names for ESM import in node:
|
|
150
179
|
0 && (module.exports = {
|
|
151
|
-
createLiteAuth
|
|
180
|
+
createLiteAuth,
|
|
181
|
+
usersFromEnv
|
|
152
182
|
});
|
|
153
183
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/server/handlers.ts","../src/server/jwt.ts","../src/server/getUserFromCookies.ts","../src/middleware/index.ts","../src/core/createLiteAuth.ts"],"sourcesContent":["export { createLiteAuth } from \"./core/createLiteAuth\";\nexport type { User, PublicUser, LiteAuthConfig } from \"./core/types\";\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { signToken, verifyToken } from \"./jwt\";\n\nexport function makeHandlers(ctx: LiteAuthContext) {\n async function login(req: NextRequest): Promise<NextResponse> {\n let body: { email?: string; password?: string };\n try {\n body = await req.json();\n } catch {\n return NextResponse.json({ error: \"Invalid JSON\" }, { status: 400 });\n }\n\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: \"Email and password are required\" }, { status: 400 });\n }\n\n const user = ctx.users.find((u) => u.email === email && u.password === password);\n if (!user) {\n return NextResponse.json({ error: \"Invalid credentials\" }, { status: 401 });\n }\n\n const { password: _, ...publicUser } = user;\n const token = await signToken(publicUser, ctx.jwtSecret);\n\n const res = NextResponse.json({ user: publicUser });\n res.cookies.set(ctx.cookieName, token, {\n httpOnly: true,\n path: \"/\",\n sameSite: \"lax\",\n secure: process.env.NODE_ENV === \"production\",\n maxAge: 60 * 60 * 24 * 7,\n });\n return res;\n }\n\n async function logout(_req: NextRequest): Promise<NextResponse> {\n const res = NextResponse.json({ ok: true });\n res.cookies.set(ctx.cookieName, \"\", { httpOnly: true, path: \"/\", maxAge: 0 });\n return res;\n }\n\n async function me(req: NextRequest): Promise<NextResponse> {\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (!token) return NextResponse.json({ user: null }, { status: 401 });\n const user = await verifyToken(token, ctx.jwtSecret);\n if (!user) return NextResponse.json({ user: null }, { status: 401 });\n return NextResponse.json({ user });\n }\n\n async function GET(req: NextRequest): Promise<NextResponse> {\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"me\") return me(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n async function POST(req: NextRequest): Promise<NextResponse> {\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"login\") return login(req);\n if (action === \"logout\") return logout(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n return { GET, POST };\n}\n","import { SignJWT, jwtVerify } from \"jose\";\nimport { PublicUser } from \"../core/types\";\n\nfunction getSecret(secret: string) {\n return new TextEncoder().encode(secret);\n}\n\nexport async function signToken(user: PublicUser, secret: string): Promise<string> {\n return new SignJWT({ ...user })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuedAt()\n .setExpirationTime(\"7d\")\n .sign(getSecret(secret));\n}\n\nexport async function verifyToken(token: string, secret: string): Promise<PublicUser | null> {\n try {\n const { payload } = await jwtVerify(token, getSecret(secret));\n return payload as unknown as PublicUser;\n } catch {\n return null;\n }\n}\n","import { ReadonlyRequestCookies } from \"next/dist/server/web/spec-extension/adapters/request-cookies\";\nimport { LiteAuthContext, PublicUser } from \"../core/types\";\nimport { verifyToken } from \"./jwt\";\n\nexport function getUserFromCookies(ctx: LiteAuthContext) {\n return async function (cookies: ReadonlyRequestCookies): Promise<PublicUser | null> {\n const token = cookies.get(ctx.cookieName)?.value;\n if (!token) return null;\n return verifyToken(token, ctx.jwtSecret);\n };\n}\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { verifyToken } from \"../server/jwt\";\n\ntype MiddlewareOptions = {\n protect: string[];\n redirectTo?: string;\n};\n\nexport function makeMiddleware(ctx: LiteAuthContext) {\n return function middleware(options: MiddlewareOptions) {\n return async function (req: NextRequest): Promise<NextResponse> {\n const { protect, redirectTo = \"/login\" } = options;\n const { pathname } = req.nextUrl;\n\n const isProtected = protect.some(\n (pattern) => pathname === pattern || pathname.startsWith(pattern + \"/\")\n );\n\n if (!isProtected) {\n return NextResponse.next();\n }\n\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (token) {\n const user = await verifyToken(token, ctx.jwtSecret);\n if (user) return NextResponse.next();\n }\n\n const loginUrl = new URL(redirectTo, req.url);\n loginUrl.searchParams.set(\"from\", pathname);\n return NextResponse.redirect(loginUrl);\n };\n };\n}\n","import { LiteAuthConfig, LiteAuthContext } from \"./types\";\nimport { makeHandlers, getUserFromCookies } from \"../server\";\nimport { makeMiddleware } from \"../middleware\";\n\nexport function createLiteAuth(config: LiteAuthConfig) {\n const ctx: LiteAuthContext = {\n users: config.users,\n jwtSecret: config.jwtSecret,\n cookieName: config.cookieName ?? \"lite-auth-token\",\n };\n\n return {\n handlers: makeHandlers(ctx),\n middleware: makeMiddleware(ctx),\n getUserFromCookies: getUserFromCookies(ctx),\n };\n}\n"],"mappings":"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","names":["import_server"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server/handlers.ts","../src/server/jwt.ts","../src/server/getUserFromCookies.ts","../src/middleware/index.ts","../src/core/createLiteAuth.ts","../src/core/usersFromEnv.ts"],"sourcesContent":["export { createLiteAuth } from \"./core/createLiteAuth\";\nexport { usersFromEnv } from \"./core/usersFromEnv\";\nexport type { User, PublicUser, LiteAuthConfig } from \"./core/types\";\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { signToken, verifyToken } from \"./jwt\";\n\nexport function makeHandlers(ctx: LiteAuthContext) {\n async function login(req: NextRequest): Promise<NextResponse> {\n let body: { email?: string; password?: string };\n try {\n body = await req.json();\n } catch {\n return NextResponse.json({ error: \"Invalid JSON\" }, { status: 400 });\n }\n\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: \"Email and password are required\" }, { status: 400 });\n }\n\n const user = ctx.users.find((u) => u.email === email && u.password === password);\n if (!user) {\n return NextResponse.json({ error: \"Invalid credentials\" }, { status: 401 });\n }\n\n const { password: _, ...publicUser } = user;\n const token = await signToken(publicUser, ctx.jwtSecret);\n\n const res = NextResponse.json({ user: publicUser });\n res.cookies.set(ctx.cookieName, token, {\n httpOnly: true,\n path: \"/\",\n sameSite: \"lax\",\n secure: process.env.NODE_ENV === \"production\",\n maxAge: 60 * 60 * 24 * 7,\n });\n return res;\n }\n\n async function logout(_req: NextRequest): Promise<NextResponse> {\n const res = NextResponse.json({ ok: true });\n res.cookies.set(ctx.cookieName, \"\", { httpOnly: true, path: \"/\", maxAge: 0 });\n return res;\n }\n\n async function me(req: NextRequest): Promise<NextResponse> {\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (!token) return NextResponse.json({ user: null }, { status: 401 });\n const user = await verifyToken(token, ctx.jwtSecret);\n if (!user) return NextResponse.json({ user: null }, { status: 401 });\n return NextResponse.json({ user });\n }\n\n async function GET(req: NextRequest): Promise<NextResponse> {\n if (!ctx.enabled) return NextResponse.json({ user: null });\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"me\") return me(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n async function POST(req: NextRequest): Promise<NextResponse> {\n if (!ctx.enabled) return NextResponse.json({ ok: true });\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"login\") return login(req);\n if (action === \"logout\") return logout(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n return { GET, POST };\n}\n","import { SignJWT, jwtVerify } from \"jose\";\nimport { PublicUser } from \"../core/types\";\n\nfunction getSecret(secret: string) {\n return new TextEncoder().encode(secret);\n}\n\nexport async function signToken(user: PublicUser, secret: string): Promise<string> {\n return new SignJWT({ ...user })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuedAt()\n .setExpirationTime(\"7d\")\n .sign(getSecret(secret));\n}\n\nexport async function verifyToken(token: string, secret: string): Promise<PublicUser | null> {\n try {\n const { payload } = await jwtVerify(token, getSecret(secret));\n return payload as unknown as PublicUser;\n } catch {\n return null;\n }\n}\n","import { ReadonlyRequestCookies } from \"next/dist/server/web/spec-extension/adapters/request-cookies\";\nimport { LiteAuthContext, PublicUser } from \"../core/types\";\nimport { verifyToken } from \"./jwt\";\n\nexport function getUserFromCookies(ctx: LiteAuthContext) {\n return async function (cookies: ReadonlyRequestCookies): Promise<PublicUser | null> {\n const token = cookies.get(ctx.cookieName)?.value;\n if (!token) return null;\n return verifyToken(token, ctx.jwtSecret);\n };\n}\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { verifyToken } from \"../server/jwt\";\n\ntype MiddlewareOptions = {\n protect: string[];\n redirectTo?: string;\n};\n\nexport function makeMiddleware(ctx: LiteAuthContext) {\n return function middleware(options: MiddlewareOptions) {\n return async function (req: NextRequest): Promise<NextResponse> {\n if (!ctx.enabled) return NextResponse.next();\n const { protect, redirectTo = \"/login\" } = options;\n const { pathname } = req.nextUrl;\n\n const isProtected = protect.some(\n (pattern) => pathname === pattern || pathname.startsWith(pattern + \"/\")\n );\n\n if (!isProtected) {\n return NextResponse.next();\n }\n\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (token) {\n const user = await verifyToken(token, ctx.jwtSecret);\n if (user) return NextResponse.next();\n }\n\n const loginUrl = new URL(redirectTo, req.url);\n loginUrl.searchParams.set(\"from\", pathname);\n return NextResponse.redirect(loginUrl);\n };\n };\n}\n","import { LiteAuthConfig, LiteAuthContext } from \"./types\";\nimport { makeHandlers, getUserFromCookies } from \"../server\";\nimport { makeMiddleware } from \"../middleware\";\n\nexport function createLiteAuth(config: LiteAuthConfig) {\n const ctx: LiteAuthContext = {\n users: config.users,\n jwtSecret: config.jwtSecret,\n cookieName: config.cookieName ?? \"lite-auth-token\",\n enabled: config.enabled ?? true,\n };\n\n return {\n handlers: makeHandlers(ctx),\n middleware: makeMiddleware(ctx),\n getUserFromCookies: getUserFromCookies(ctx),\n };\n}\n","import { User } from \"./types\";\n\nexport function usersFromEnv(): User[] {\n const raw = process.env.LITE_AUTH_USERS;\n\n if (!raw) {\n throw new Error(\n \"[next-lite-auth] LITE_AUTH_USERS environment variable is not set. \" +\n \"Set it to a JSON array of users, e.g.: \" +\n 'LITE_AUTH_USERS=\\'[{\"email\":\"admin@example.com\",\"password\":\"secret\"}]\\''\n );\n }\n\n let parsed: unknown;\n\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new Error(\n \"[next-lite-auth] LITE_AUTH_USERS is not valid JSON. \" +\n \"Expected a JSON array of users.\"\n );\n }\n\n if (!Array.isArray(parsed)) {\n throw new Error(\n \"[next-lite-auth] LITE_AUTH_USERS must be a JSON array, e.g.: \" +\n '[{\"email\":\"admin@example.com\",\"password\":\"secret\"}]'\n );\n }\n\n return parsed as User[];\n}\n"],"mappings":"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","names":["import_server"]}
|
package/dist/index.mjs
CHANGED
|
@@ -60,11 +60,13 @@ function makeHandlers(ctx) {
|
|
|
60
60
|
return NextResponse.json({ user });
|
|
61
61
|
}
|
|
62
62
|
async function GET(req) {
|
|
63
|
+
if (!ctx.enabled) return NextResponse.json({ user: null });
|
|
63
64
|
const action = req.nextUrl.pathname.split("/").pop();
|
|
64
65
|
if (action === "me") return me(req);
|
|
65
66
|
return NextResponse.json({ error: "Not found" }, { status: 404 });
|
|
66
67
|
}
|
|
67
68
|
async function POST(req) {
|
|
69
|
+
if (!ctx.enabled) return NextResponse.json({ ok: true });
|
|
68
70
|
const action = req.nextUrl.pathname.split("/").pop();
|
|
69
71
|
if (action === "login") return login(req);
|
|
70
72
|
if (action === "logout") return logout(req);
|
|
@@ -87,6 +89,7 @@ import { NextResponse as NextResponse2 } from "next/server";
|
|
|
87
89
|
function makeMiddleware(ctx) {
|
|
88
90
|
return function middleware(options) {
|
|
89
91
|
return async function(req) {
|
|
92
|
+
if (!ctx.enabled) return NextResponse2.next();
|
|
90
93
|
const { protect, redirectTo = "/login" } = options;
|
|
91
94
|
const { pathname } = req.nextUrl;
|
|
92
95
|
const isProtected = protect.some(
|
|
@@ -112,7 +115,8 @@ function createLiteAuth(config) {
|
|
|
112
115
|
const ctx = {
|
|
113
116
|
users: config.users,
|
|
114
117
|
jwtSecret: config.jwtSecret,
|
|
115
|
-
cookieName: config.cookieName ?? "lite-auth-token"
|
|
118
|
+
cookieName: config.cookieName ?? "lite-auth-token",
|
|
119
|
+
enabled: config.enabled ?? true
|
|
116
120
|
};
|
|
117
121
|
return {
|
|
118
122
|
handlers: makeHandlers(ctx),
|
|
@@ -120,7 +124,32 @@ function createLiteAuth(config) {
|
|
|
120
124
|
getUserFromCookies: getUserFromCookies(ctx)
|
|
121
125
|
};
|
|
122
126
|
}
|
|
127
|
+
|
|
128
|
+
// src/core/usersFromEnv.ts
|
|
129
|
+
function usersFromEnv() {
|
|
130
|
+
const raw = process.env.LITE_AUTH_USERS;
|
|
131
|
+
if (!raw) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`[next-lite-auth] LITE_AUTH_USERS environment variable is not set. Set it to a JSON array of users, e.g.: LITE_AUTH_USERS='[{"email":"admin@example.com","password":"secret"}]'`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
let parsed;
|
|
137
|
+
try {
|
|
138
|
+
parsed = JSON.parse(raw);
|
|
139
|
+
} catch {
|
|
140
|
+
throw new Error(
|
|
141
|
+
"[next-lite-auth] LITE_AUTH_USERS is not valid JSON. Expected a JSON array of users."
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
if (!Array.isArray(parsed)) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
'[next-lite-auth] LITE_AUTH_USERS must be a JSON array, e.g.: [{"email":"admin@example.com","password":"secret"}]'
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return parsed;
|
|
150
|
+
}
|
|
123
151
|
export {
|
|
124
|
-
createLiteAuth
|
|
152
|
+
createLiteAuth,
|
|
153
|
+
usersFromEnv
|
|
125
154
|
};
|
|
126
155
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/handlers.ts","../src/server/jwt.ts","../src/server/getUserFromCookies.ts","../src/middleware/index.ts","../src/core/createLiteAuth.ts"],"sourcesContent":["import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { signToken, verifyToken } from \"./jwt\";\n\nexport function makeHandlers(ctx: LiteAuthContext) {\n async function login(req: NextRequest): Promise<NextResponse> {\n let body: { email?: string; password?: string };\n try {\n body = await req.json();\n } catch {\n return NextResponse.json({ error: \"Invalid JSON\" }, { status: 400 });\n }\n\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: \"Email and password are required\" }, { status: 400 });\n }\n\n const user = ctx.users.find((u) => u.email === email && u.password === password);\n if (!user) {\n return NextResponse.json({ error: \"Invalid credentials\" }, { status: 401 });\n }\n\n const { password: _, ...publicUser } = user;\n const token = await signToken(publicUser, ctx.jwtSecret);\n\n const res = NextResponse.json({ user: publicUser });\n res.cookies.set(ctx.cookieName, token, {\n httpOnly: true,\n path: \"/\",\n sameSite: \"lax\",\n secure: process.env.NODE_ENV === \"production\",\n maxAge: 60 * 60 * 24 * 7,\n });\n return res;\n }\n\n async function logout(_req: NextRequest): Promise<NextResponse> {\n const res = NextResponse.json({ ok: true });\n res.cookies.set(ctx.cookieName, \"\", { httpOnly: true, path: \"/\", maxAge: 0 });\n return res;\n }\n\n async function me(req: NextRequest): Promise<NextResponse> {\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (!token) return NextResponse.json({ user: null }, { status: 401 });\n const user = await verifyToken(token, ctx.jwtSecret);\n if (!user) return NextResponse.json({ user: null }, { status: 401 });\n return NextResponse.json({ user });\n }\n\n async function GET(req: NextRequest): Promise<NextResponse> {\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"me\") return me(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n async function POST(req: NextRequest): Promise<NextResponse> {\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"login\") return login(req);\n if (action === \"logout\") return logout(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n return { GET, POST };\n}\n","import { SignJWT, jwtVerify } from \"jose\";\nimport { PublicUser } from \"../core/types\";\n\nfunction getSecret(secret: string) {\n return new TextEncoder().encode(secret);\n}\n\nexport async function signToken(user: PublicUser, secret: string): Promise<string> {\n return new SignJWT({ ...user })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuedAt()\n .setExpirationTime(\"7d\")\n .sign(getSecret(secret));\n}\n\nexport async function verifyToken(token: string, secret: string): Promise<PublicUser | null> {\n try {\n const { payload } = await jwtVerify(token, getSecret(secret));\n return payload as unknown as PublicUser;\n } catch {\n return null;\n }\n}\n","import { ReadonlyRequestCookies } from \"next/dist/server/web/spec-extension/adapters/request-cookies\";\nimport { LiteAuthContext, PublicUser } from \"../core/types\";\nimport { verifyToken } from \"./jwt\";\n\nexport function getUserFromCookies(ctx: LiteAuthContext) {\n return async function (cookies: ReadonlyRequestCookies): Promise<PublicUser | null> {\n const token = cookies.get(ctx.cookieName)?.value;\n if (!token) return null;\n return verifyToken(token, ctx.jwtSecret);\n };\n}\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { verifyToken } from \"../server/jwt\";\n\ntype MiddlewareOptions = {\n protect: string[];\n redirectTo?: string;\n};\n\nexport function makeMiddleware(ctx: LiteAuthContext) {\n return function middleware(options: MiddlewareOptions) {\n return async function (req: NextRequest): Promise<NextResponse> {\n const { protect, redirectTo = \"/login\" } = options;\n const { pathname } = req.nextUrl;\n\n const isProtected = protect.some(\n (pattern) => pathname === pattern || pathname.startsWith(pattern + \"/\")\n );\n\n if (!isProtected) {\n return NextResponse.next();\n }\n\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (token) {\n const user = await verifyToken(token, ctx.jwtSecret);\n if (user) return NextResponse.next();\n }\n\n const loginUrl = new URL(redirectTo, req.url);\n loginUrl.searchParams.set(\"from\", pathname);\n return NextResponse.redirect(loginUrl);\n };\n };\n}\n","import { LiteAuthConfig, LiteAuthContext } from \"./types\";\nimport { makeHandlers, getUserFromCookies } from \"../server\";\nimport { makeMiddleware } from \"../middleware\";\n\nexport function createLiteAuth(config: LiteAuthConfig) {\n const ctx: LiteAuthContext = {\n users: config.users,\n jwtSecret: config.jwtSecret,\n cookieName: config.cookieName ?? \"lite-auth-token\",\n };\n\n return {\n handlers: makeHandlers(ctx),\n middleware: makeMiddleware(ctx),\n getUserFromCookies: getUserFromCookies(ctx),\n };\n}\n"],"mappings":"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","names":["NextResponse","NextResponse"]}
|
|
1
|
+
{"version":3,"sources":["../src/server/handlers.ts","../src/server/jwt.ts","../src/server/getUserFromCookies.ts","../src/middleware/index.ts","../src/core/createLiteAuth.ts","../src/core/usersFromEnv.ts"],"sourcesContent":["import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { signToken, verifyToken } from \"./jwt\";\n\nexport function makeHandlers(ctx: LiteAuthContext) {\n async function login(req: NextRequest): Promise<NextResponse> {\n let body: { email?: string; password?: string };\n try {\n body = await req.json();\n } catch {\n return NextResponse.json({ error: \"Invalid JSON\" }, { status: 400 });\n }\n\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: \"Email and password are required\" }, { status: 400 });\n }\n\n const user = ctx.users.find((u) => u.email === email && u.password === password);\n if (!user) {\n return NextResponse.json({ error: \"Invalid credentials\" }, { status: 401 });\n }\n\n const { password: _, ...publicUser } = user;\n const token = await signToken(publicUser, ctx.jwtSecret);\n\n const res = NextResponse.json({ user: publicUser });\n res.cookies.set(ctx.cookieName, token, {\n httpOnly: true,\n path: \"/\",\n sameSite: \"lax\",\n secure: process.env.NODE_ENV === \"production\",\n maxAge: 60 * 60 * 24 * 7,\n });\n return res;\n }\n\n async function logout(_req: NextRequest): Promise<NextResponse> {\n const res = NextResponse.json({ ok: true });\n res.cookies.set(ctx.cookieName, \"\", { httpOnly: true, path: \"/\", maxAge: 0 });\n return res;\n }\n\n async function me(req: NextRequest): Promise<NextResponse> {\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (!token) return NextResponse.json({ user: null }, { status: 401 });\n const user = await verifyToken(token, ctx.jwtSecret);\n if (!user) return NextResponse.json({ user: null }, { status: 401 });\n return NextResponse.json({ user });\n }\n\n async function GET(req: NextRequest): Promise<NextResponse> {\n if (!ctx.enabled) return NextResponse.json({ user: null });\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"me\") return me(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n async function POST(req: NextRequest): Promise<NextResponse> {\n if (!ctx.enabled) return NextResponse.json({ ok: true });\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"login\") return login(req);\n if (action === \"logout\") return logout(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n return { GET, POST };\n}\n","import { SignJWT, jwtVerify } from \"jose\";\nimport { PublicUser } from \"../core/types\";\n\nfunction getSecret(secret: string) {\n return new TextEncoder().encode(secret);\n}\n\nexport async function signToken(user: PublicUser, secret: string): Promise<string> {\n return new SignJWT({ ...user })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuedAt()\n .setExpirationTime(\"7d\")\n .sign(getSecret(secret));\n}\n\nexport async function verifyToken(token: string, secret: string): Promise<PublicUser | null> {\n try {\n const { payload } = await jwtVerify(token, getSecret(secret));\n return payload as unknown as PublicUser;\n } catch {\n return null;\n }\n}\n","import { ReadonlyRequestCookies } from \"next/dist/server/web/spec-extension/adapters/request-cookies\";\nimport { LiteAuthContext, PublicUser } from \"../core/types\";\nimport { verifyToken } from \"./jwt\";\n\nexport function getUserFromCookies(ctx: LiteAuthContext) {\n return async function (cookies: ReadonlyRequestCookies): Promise<PublicUser | null> {\n const token = cookies.get(ctx.cookieName)?.value;\n if (!token) return null;\n return verifyToken(token, ctx.jwtSecret);\n };\n}\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { verifyToken } from \"../server/jwt\";\n\ntype MiddlewareOptions = {\n protect: string[];\n redirectTo?: string;\n};\n\nexport function makeMiddleware(ctx: LiteAuthContext) {\n return function middleware(options: MiddlewareOptions) {\n return async function (req: NextRequest): Promise<NextResponse> {\n if (!ctx.enabled) return NextResponse.next();\n const { protect, redirectTo = \"/login\" } = options;\n const { pathname } = req.nextUrl;\n\n const isProtected = protect.some(\n (pattern) => pathname === pattern || pathname.startsWith(pattern + \"/\")\n );\n\n if (!isProtected) {\n return NextResponse.next();\n }\n\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (token) {\n const user = await verifyToken(token, ctx.jwtSecret);\n if (user) return NextResponse.next();\n }\n\n const loginUrl = new URL(redirectTo, req.url);\n loginUrl.searchParams.set(\"from\", pathname);\n return NextResponse.redirect(loginUrl);\n };\n };\n}\n","import { LiteAuthConfig, LiteAuthContext } from \"./types\";\nimport { makeHandlers, getUserFromCookies } from \"../server\";\nimport { makeMiddleware } from \"../middleware\";\n\nexport function createLiteAuth(config: LiteAuthConfig) {\n const ctx: LiteAuthContext = {\n users: config.users,\n jwtSecret: config.jwtSecret,\n cookieName: config.cookieName ?? \"lite-auth-token\",\n enabled: config.enabled ?? true,\n };\n\n return {\n handlers: makeHandlers(ctx),\n middleware: makeMiddleware(ctx),\n getUserFromCookies: getUserFromCookies(ctx),\n };\n}\n","import { User } from \"./types\";\n\nexport function usersFromEnv(): User[] {\n const raw = process.env.LITE_AUTH_USERS;\n\n if (!raw) {\n throw new Error(\n \"[next-lite-auth] LITE_AUTH_USERS environment variable is not set. \" +\n \"Set it to a JSON array of users, e.g.: \" +\n 'LITE_AUTH_USERS=\\'[{\"email\":\"admin@example.com\",\"password\":\"secret\"}]\\''\n );\n }\n\n let parsed: unknown;\n\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new Error(\n \"[next-lite-auth] LITE_AUTH_USERS is not valid JSON. \" +\n \"Expected a JSON array of users.\"\n );\n }\n\n if (!Array.isArray(parsed)) {\n throw new Error(\n \"[next-lite-auth] LITE_AUTH_USERS must be a JSON array, e.g.: \" +\n '[{\"email\":\"admin@example.com\",\"password\":\"secret\"}]'\n );\n }\n\n return parsed as User[];\n}\n"],"mappings":"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","names":["NextResponse","NextResponse"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-lite-auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Lightweight JWT auth for Next.js using static JSON users (no database)",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -17,30 +17,18 @@
|
|
|
17
17
|
"require": "./dist/client.js"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
|
-
"files": [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"dev": "tsup --watch",
|
|
24
|
-
"typecheck": "tsc --noEmit",
|
|
25
|
-
"prepublishOnly": "pnpm build",
|
|
26
|
-
"docs:dev": "vitepress dev docs",
|
|
27
|
-
"docs:build": "vitepress build docs",
|
|
28
|
-
"docs:preview": "vitepress preview docs"
|
|
29
|
-
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
30
23
|
"peerDependencies": {
|
|
31
24
|
"next": ">=13.0.0",
|
|
32
|
-
"react": ">=18.0.0"
|
|
33
|
-
"tailwindcss": ">=3.0.0"
|
|
34
|
-
},
|
|
35
|
-
"peerDependenciesMeta": {
|
|
36
|
-
"tailwindcss": {
|
|
37
|
-
"optional": true
|
|
38
|
-
}
|
|
25
|
+
"react": ">=18.0.0"
|
|
39
26
|
},
|
|
40
27
|
"dependencies": {
|
|
41
28
|
"jose": "^5.0.0"
|
|
42
29
|
},
|
|
43
30
|
"devDependencies": {
|
|
31
|
+
"@types/node": "^25.5.2",
|
|
44
32
|
"@types/react": "^18.0.0",
|
|
45
33
|
"next": "^14.0.0",
|
|
46
34
|
"react": "^18.0.0",
|
|
@@ -52,7 +40,6 @@
|
|
|
52
40
|
"node": ">=20.0.0",
|
|
53
41
|
"pnpm": ">=9.0.0"
|
|
54
42
|
},
|
|
55
|
-
"packageManager": "pnpm@9.0.0",
|
|
56
43
|
"author": "amide-init",
|
|
57
44
|
"repository": {
|
|
58
45
|
"type": "git",
|
|
@@ -62,6 +49,19 @@
|
|
|
62
49
|
"bugs": {
|
|
63
50
|
"url": "https://github.com/amide-init/next-lite-auth/issues"
|
|
64
51
|
},
|
|
65
|
-
"keywords": [
|
|
66
|
-
|
|
67
|
-
|
|
52
|
+
"keywords": [
|
|
53
|
+
"nextjs",
|
|
54
|
+
"auth",
|
|
55
|
+
"jwt",
|
|
56
|
+
"lightweight"
|
|
57
|
+
],
|
|
58
|
+
"license": "MIT",
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "tsup",
|
|
61
|
+
"dev": "tsup --watch",
|
|
62
|
+
"typecheck": "tsc --noEmit",
|
|
63
|
+
"docs:dev": "vitepress dev docs",
|
|
64
|
+
"docs:build": "vitepress build docs",
|
|
65
|
+
"docs:preview": "vitepress preview docs"
|
|
66
|
+
}
|
|
67
|
+
}
|