better-auth-studio 1.1.2-beta.15 → 1.1.2-beta.16
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 +36 -23
- package/data/default-geo.json +1 -1
- package/dist/adapters/astro.d.ts +1 -1
- package/dist/adapters/astro.js +13 -13
- package/dist/adapters/elysia.d.ts +2 -2
- package/dist/adapters/elysia.js +13 -13
- package/dist/adapters/express.d.ts +2 -2
- package/dist/adapters/express.js +4 -4
- package/dist/adapters/hono.d.ts +2 -2
- package/dist/adapters/hono.js +12 -12
- package/dist/adapters/nextjs.d.ts +1 -1
- package/dist/adapters/nextjs.js +10 -10
- package/dist/adapters/nuxt.d.ts +1 -1
- package/dist/adapters/nuxt.js +22 -22
- package/dist/adapters/remix.d.ts +1 -1
- package/dist/adapters/remix.js +13 -13
- package/dist/adapters/solid-start.d.ts +1 -1
- package/dist/adapters/solid-start.js +13 -13
- package/dist/adapters/svelte-kit.d.ts +2 -2
- package/dist/adapters/svelte-kit.js +13 -13
- package/dist/adapters/tanstack-start.d.ts +1 -1
- package/dist/adapters/tanstack-start.js +13 -13
- package/dist/add-svelte-kit-env-modules.js +11 -11
- package/dist/auth-adapter.d.ts +1 -1
- package/dist/auth-adapter.js +96 -96
- package/dist/cli/commands/init.js +57 -57
- package/dist/cli.js +75 -75
- package/dist/config.d.ts +5 -5
- package/dist/config.js +37 -37
- package/dist/core/handler.d.ts +1 -1
- package/dist/core/handler.js +115 -115
- package/dist/data.d.ts +2 -2
- package/dist/data.js +60 -60
- package/dist/geo-service.js +78 -78
- package/dist/get-tsconfig-info.js +4 -4
- package/dist/index.d.ts +8 -8
- package/dist/index.js +6 -6
- package/dist/providers/events/helpers.d.ts +2 -2
- package/dist/providers/events/helpers.js +156 -156
- package/dist/routes/api-router.d.ts +2 -2
- package/dist/routes/api-router.js +3 -3
- package/dist/routes.d.ts +4 -4
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +1272 -1272
- package/dist/routes.js.map +1 -1
- package/dist/studio.d.ts +3 -3
- package/dist/studio.js +64 -64
- package/dist/types/events.d.ts +7 -7
- package/dist/types/events.js +165 -165
- package/dist/types/handler.d.ts +5 -5
- package/dist/utils/auth-callbacks-injector.d.ts +2 -2
- package/dist/utils/auth-callbacks-injector.js +27 -27
- package/dist/utils/auth-callbacks-wrapper.d.ts +3 -3
- package/dist/utils/auth-callbacks-wrapper.js +117 -107
- package/dist/utils/database-detection.d.ts +1 -1
- package/dist/utils/database-detection.js +44 -44
- package/dist/utils/database-hook-injector.d.ts +3 -3
- package/dist/utils/database-hook-injector.js +135 -131
- package/dist/utils/email-otp-hooks-injector.d.ts +28 -12
- package/dist/utils/email-otp-hooks-injector.js +104 -97
- package/dist/utils/event-ingestion.d.ts +5 -5
- package/dist/utils/event-ingestion.d.ts.map +1 -1
- package/dist/utils/event-ingestion.js +14 -16
- package/dist/utils/event-ingestion.js.map +1 -1
- package/dist/utils/hook-injector.d.ts +2 -2
- package/dist/utils/hook-injector.js +199 -199
- package/dist/utils/html-injector.d.ts +3 -3
- package/dist/utils/html-injector.js +37 -37
- package/dist/utils/org-hooks-injector.d.ts +3 -3
- package/dist/utils/org-hooks-injector.js +63 -63
- package/dist/utils/org-hooks-wrapper.d.ts +41 -35
- package/dist/utils/org-hooks-wrapper.js +778 -658
- package/dist/utils/organization-hooks-wrapper.d.ts +23 -17
- package/dist/utils/organization-hooks-wrapper.js +325 -277
- package/dist/utils/package-json.js +11 -11
- package/dist/utils/paths.js +1 -1
- package/dist/utils/server-init.d.ts +1 -1
- package/dist/utils/server-init.js +25 -25
- package/dist/utils/session.js +12 -12
- package/dist/utils.js +24 -24
- package/package.json +26 -26
- package/scripts/download-geolite2.js +8 -8
- package/scripts/generate-default-db.js +324 -324
- package/scripts/postinstall.js +25 -25
package/README.md
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
# Better Auth Studio
|
|
1
|
+
# Better Auth Studio
|
|
2
2
|
|
|
3
3
|
> ⚠️ **Beta Version Notice**
|
|
4
|
-
>
|
|
4
|
+
>
|
|
5
5
|
> Better Auth Studio is currently in **beta** and in early development. You may encounter bugs or incomplete features. Please report any issues you find on our GitHub repository to help us improve the project. Your feedback is greatly appreciated!
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
A web-based studio interface for managing Better Auth applications. Better Auth Studio provides a comprehensive dashboard for managing users, organizations, teams, and more.
|
|
9
8
|
|
|
10
9
|
## ✨ Try Better Auth Studio Demo
|
|
@@ -18,8 +17,6 @@ You can try a live, demo version of Better Auth Studio here:
|
|
|
18
17
|
|
|
19
18
|
This online demo lets you explore the admin studio UI. Please note this is a test environment.
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
20
|
## 🚀 Quick Start
|
|
24
21
|
|
|
25
22
|
### Hosted Version
|
|
@@ -45,24 +42,27 @@ pnpm add -g better-auth-studio
|
|
|
45
42
|
Or use pnpx to run it without installation:
|
|
46
43
|
|
|
47
44
|
```bash
|
|
48
|
-
pnpx better-auth-studio [cmd]
|
|
45
|
+
pnpx better-auth-studio [cmd]
|
|
49
46
|
```
|
|
50
47
|
|
|
51
48
|
### Basic Usage
|
|
52
49
|
|
|
53
50
|
1. **Navigate to your Better Auth project directory**
|
|
51
|
+
|
|
54
52
|
```bash
|
|
55
53
|
cd your-better-auth-project
|
|
56
54
|
```
|
|
57
55
|
|
|
58
56
|
2. **Start the studio**
|
|
59
|
-
|
|
57
|
+
|
|
60
58
|
If installed as dev dependency:
|
|
59
|
+
|
|
61
60
|
```bash
|
|
62
61
|
pnpm better-auth-studio start
|
|
63
62
|
```
|
|
64
|
-
|
|
63
|
+
|
|
65
64
|
Or with pnpx:
|
|
65
|
+
|
|
66
66
|
```bash
|
|
67
67
|
pnpx better-auth-studio start
|
|
68
68
|
```
|
|
@@ -86,7 +86,7 @@ Before using Better Auth Studio, ensure you have:
|
|
|
86
86
|
Better Auth Studio automatically detects and works with:
|
|
87
87
|
|
|
88
88
|
- **Prisma** (`prismaAdapter`)
|
|
89
|
-
- **Drizzle** (`drizzleAdapter`)
|
|
89
|
+
- **Drizzle** (`drizzleAdapter`)
|
|
90
90
|
- **SQLite** (`new Database()` from better-sqlite3)
|
|
91
91
|
- **PostgreSQL** (via Prisma or Drizzle)
|
|
92
92
|
- **MySQL** (via Prisma or Drizzle)
|
|
@@ -94,6 +94,7 @@ Better Auth Studio automatically detects and works with:
|
|
|
94
94
|
### Example Configuration Files
|
|
95
95
|
|
|
96
96
|
#### Prisma Setup
|
|
97
|
+
|
|
97
98
|
```typescript
|
|
98
99
|
// auth.ts
|
|
99
100
|
import { betterAuth } from "better-auth";
|
|
@@ -111,6 +112,7 @@ export const auth = betterAuth({
|
|
|
111
112
|
```
|
|
112
113
|
|
|
113
114
|
#### Drizzle Setup
|
|
115
|
+
|
|
114
116
|
```typescript
|
|
115
117
|
// auth.ts
|
|
116
118
|
import { betterAuth } from "better-auth";
|
|
@@ -126,6 +128,7 @@ export const auth = betterAuth({
|
|
|
126
128
|
```
|
|
127
129
|
|
|
128
130
|
#### SQLite Setup
|
|
131
|
+
|
|
129
132
|
```typescript
|
|
130
133
|
// auth.ts
|
|
131
134
|
import { betterAuth } from "better-auth";
|
|
@@ -140,9 +143,11 @@ export const auth = betterAuth({
|
|
|
140
143
|
## 🎯 Features
|
|
141
144
|
|
|
142
145
|
### 📊 Dashboard
|
|
146
|
+
|
|
143
147
|
- **Overview statistics** - User, teams and organization counts data
|
|
144
148
|
|
|
145
149
|
### 👥 User Management
|
|
150
|
+
|
|
146
151
|
- **View all users** - Paginated list with search and filtering
|
|
147
152
|
- **Create users** - Add new users with email/password
|
|
148
153
|
- **Edit users** - Update user information, email verification status
|
|
@@ -151,6 +156,7 @@ export const auth = betterAuth({
|
|
|
151
156
|
- **User details** - View user profiles, and accounts
|
|
152
157
|
|
|
153
158
|
### 🏢 Organization Management
|
|
159
|
+
|
|
154
160
|
- **View organizations** - List all organizations with pagination
|
|
155
161
|
- **Create organizations** - Add new organizations with custom slugs
|
|
156
162
|
- **Edit organizations** - Update organization details
|
|
@@ -160,6 +166,7 @@ export const auth = betterAuth({
|
|
|
160
166
|
- **Bulk seeding** - Generate test organizations and teams
|
|
161
167
|
|
|
162
168
|
### ⚙️ Settings & Configuration
|
|
169
|
+
|
|
163
170
|
- **Plugin status** - Check which Better Auth plugins are enabled
|
|
164
171
|
- **Database configuration** - View current database adapter and settings
|
|
165
172
|
- **Social providers** - Configure OAuth providers (GitHub, Google, etc.)
|
|
@@ -168,11 +175,13 @@ export const auth = betterAuth({
|
|
|
168
175
|
## 🛠️ Command Line Options
|
|
169
176
|
|
|
170
177
|
### Start Studio
|
|
178
|
+
|
|
171
179
|
```bash
|
|
172
180
|
pnpx better-auth-studio start [options]
|
|
173
181
|
```
|
|
174
182
|
|
|
175
183
|
**Options:**
|
|
184
|
+
|
|
176
185
|
- `--port <number>` - Specify port (default: 3000)
|
|
177
186
|
- `--host <string>` - Specify host (default: localhost)
|
|
178
187
|
- `--no-open` - Don't automatically open browser
|
|
@@ -180,6 +189,7 @@ pnpx better-auth-studio start [options]
|
|
|
180
189
|
- `--watch` - Watch for changes in auth config file and reload server automatically
|
|
181
190
|
|
|
182
191
|
**Examples:**
|
|
192
|
+
|
|
183
193
|
```bash
|
|
184
194
|
# Start on custom port (if installed as dev dependency)
|
|
185
195
|
pnpm better-auth-studio start --port 3001
|
|
@@ -205,6 +215,7 @@ pnpx better-auth-studio start --port 3001 --watch --config ./src/auth.ts
|
|
|
205
215
|
Specify a custom path to your auth config file when it's in a non-standard location or auto-detection fails.
|
|
206
216
|
|
|
207
217
|
**Example:**
|
|
218
|
+
|
|
208
219
|
```bash
|
|
209
220
|
# With relative path
|
|
210
221
|
pnpm better-auth-studio start --config ./src/lib/auth.ts
|
|
@@ -220,6 +231,7 @@ pnpm better-auth-studio start --config /path/to/project/auth.ts
|
|
|
220
231
|
Automatically reload the server when your `auth.ts` file changes. Perfect for development when iterating on your auth configuration.
|
|
221
232
|
|
|
222
233
|
**Example:**
|
|
234
|
+
|
|
223
235
|
```bash
|
|
224
236
|
# Start with watch mode enabled
|
|
225
237
|
pnpx better-auth-studio start --watch
|
|
@@ -228,6 +240,7 @@ pnpx better-auth-studio start --watch
|
|
|
228
240
|
**How it works:** Monitors your auth config file for changes, automatically restarts the server, and updates the browser UI via WebSocket - no manual refresh needed.
|
|
229
241
|
|
|
230
242
|
### Other Commands
|
|
243
|
+
|
|
231
244
|
```bash
|
|
232
245
|
# Check version
|
|
233
246
|
pnpx better-auth-studio --version
|
|
@@ -255,11 +268,13 @@ pnpm add better-auth-studio
|
|
|
255
268
|
### Setup
|
|
256
269
|
|
|
257
270
|
**Step 1: Initialize configuration**
|
|
271
|
+
|
|
258
272
|
```bash
|
|
259
273
|
pnpx better-auth-studio init
|
|
260
274
|
```
|
|
261
275
|
|
|
262
276
|
This creates a `studio.config.ts` file:
|
|
277
|
+
|
|
263
278
|
```typescript
|
|
264
279
|
import type { StudioConfig } from "better-auth-studio";
|
|
265
280
|
import { auth } from "./lib/auth";
|
|
@@ -283,19 +298,14 @@ export default config;
|
|
|
283
298
|
### Next.js (App Router)
|
|
284
299
|
|
|
285
300
|
The init command automatically creates `app/api/studio/[[...path]]/route.ts`:
|
|
301
|
+
|
|
286
302
|
```typescript
|
|
287
303
|
import { betterAuthStudio } from "better-auth-studio/nextjs";
|
|
288
304
|
import studioConfig from "@/studio.config";
|
|
289
305
|
|
|
290
306
|
const handler = betterAuthStudio(studioConfig);
|
|
291
307
|
|
|
292
|
-
export {
|
|
293
|
-
handler as GET,
|
|
294
|
-
handler as POST,
|
|
295
|
-
handler as PUT,
|
|
296
|
-
handler as DELETE,
|
|
297
|
-
handler as PATCH,
|
|
298
|
-
};
|
|
308
|
+
export { handler as GET, handler as POST, handler as PUT, handler as DELETE, handler as PATCH };
|
|
299
309
|
```
|
|
300
310
|
|
|
301
311
|
Access at `http://localhost:3000/api/studio`
|
|
@@ -303,6 +313,7 @@ Access at `http://localhost:3000/api/studio`
|
|
|
303
313
|
### Express
|
|
304
314
|
|
|
305
315
|
Add the studio handler to your server:
|
|
316
|
+
|
|
306
317
|
```typescript
|
|
307
318
|
import express from "express";
|
|
308
319
|
import { toNodeHandler } from "better-auth/node";
|
|
@@ -323,17 +334,18 @@ Access at `http://localhost:3000/api/studio`
|
|
|
323
334
|
|
|
324
335
|
### Configuration Options
|
|
325
336
|
|
|
326
|
-
| Option
|
|
327
|
-
|
|
328
|
-
| `auth`
|
|
329
|
-
| `basePath`
|
|
330
|
-
| `access.allowEmails` | No
|
|
331
|
-
| `access.roles`
|
|
332
|
-
| `metadata`
|
|
337
|
+
| Option | Required | Description |
|
|
338
|
+
| -------------------- | -------- | -------------------------------- |
|
|
339
|
+
| `auth` | Yes | Your Better Auth instance |
|
|
340
|
+
| `basePath` | Yes | URL path where studio is mounted |
|
|
341
|
+
| `access.allowEmails` | No | Array of admin email addresses |
|
|
342
|
+
| `access.roles` | No | Array of allowed user roles |
|
|
343
|
+
| `metadata` | No | Custom branding (title, theme) |
|
|
333
344
|
|
|
334
345
|
## 📝 Development
|
|
335
346
|
|
|
336
347
|
### Running from Source
|
|
348
|
+
|
|
337
349
|
```bash
|
|
338
350
|
# Clone the repository
|
|
339
351
|
git clone https://github.com/Kinfe123/better-auth-studio.git
|
|
@@ -350,6 +362,7 @@ pnpm dev
|
|
|
350
362
|
```
|
|
351
363
|
|
|
352
364
|
### Contributing
|
|
365
|
+
|
|
353
366
|
1. Fork the repository
|
|
354
367
|
2. Create a feature branch
|
|
355
368
|
3. Make your changes
|
package/data/default-geo.json
CHANGED
package/dist/adapters/astro.d.ts
CHANGED
package/dist/adapters/astro.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { handleStudioRequest } from
|
|
2
|
-
import { injectEventHooks } from
|
|
1
|
+
import { handleStudioRequest } from "../core/handler.js";
|
|
2
|
+
import { injectEventHooks } from "../utils/hook-injector.js";
|
|
3
3
|
/**
|
|
4
4
|
* Astro adapter for Better Auth Studio
|
|
5
5
|
*
|
|
@@ -28,10 +28,10 @@ export function betterAuthStudio(config) {
|
|
|
28
28
|
return universalToResponse(universalRes);
|
|
29
29
|
}
|
|
30
30
|
catch (error) {
|
|
31
|
-
console.error(
|
|
32
|
-
return new Response(JSON.stringify({ error:
|
|
31
|
+
console.error("Studio handler error:", error);
|
|
32
|
+
return new Response(JSON.stringify({ error: "Internal server error" }), {
|
|
33
33
|
status: 500,
|
|
34
|
-
headers: {
|
|
34
|
+
headers: { "Content-Type": "application/json" },
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
};
|
|
@@ -40,16 +40,16 @@ async function convertAstroToUniversal(ctx, config) {
|
|
|
40
40
|
const request = ctx.request;
|
|
41
41
|
let body;
|
|
42
42
|
const method = request.method;
|
|
43
|
-
if (method !==
|
|
44
|
-
const contentType = request.headers.get(
|
|
45
|
-
if (contentType.includes(
|
|
43
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
44
|
+
const contentType = request.headers.get("content-type") || "";
|
|
45
|
+
if (contentType.includes("application/json")) {
|
|
46
46
|
try {
|
|
47
47
|
body = await request.json();
|
|
48
48
|
}
|
|
49
49
|
catch { }
|
|
50
50
|
}
|
|
51
|
-
else if (contentType.includes(
|
|
52
|
-
contentType.includes(
|
|
51
|
+
else if (contentType.includes("application/x-www-form-urlencoded") ||
|
|
52
|
+
contentType.includes("multipart/form-data")) {
|
|
53
53
|
try {
|
|
54
54
|
const formData = await request.formData();
|
|
55
55
|
body = Object.fromEntries(formData.entries());
|
|
@@ -75,12 +75,12 @@ async function convertAstroToUniversal(ctx, config) {
|
|
|
75
75
|
request.headers.forEach((value, key) => {
|
|
76
76
|
headers[key] = value;
|
|
77
77
|
});
|
|
78
|
-
const basePath = config.basePath ||
|
|
79
|
-
const normalizedBasePath = basePath.endsWith(
|
|
78
|
+
const basePath = config.basePath || "/api/studio";
|
|
79
|
+
const normalizedBasePath = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
|
|
80
80
|
const url = new URL(request.url);
|
|
81
81
|
let path = url.pathname;
|
|
82
82
|
if (path.startsWith(normalizedBasePath)) {
|
|
83
|
-
path = path.slice(normalizedBasePath.length) ||
|
|
83
|
+
path = path.slice(normalizedBasePath.length) || "/";
|
|
84
84
|
}
|
|
85
85
|
const pathWithQuery = path + url.search;
|
|
86
86
|
return {
|
package/dist/adapters/elysia.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { handleStudioRequest } from
|
|
2
|
-
import { injectEventHooks } from
|
|
1
|
+
import { handleStudioRequest } from "../core/handler.js";
|
|
2
|
+
import { injectEventHooks } from "../utils/hook-injector.js";
|
|
3
3
|
/**
|
|
4
4
|
* Elysia adapter for Better Auth Studio
|
|
5
5
|
*/
|
|
@@ -14,28 +14,28 @@ export function betterAuthStudio(config) {
|
|
|
14
14
|
return sendElysiaResponse(context, universalRes);
|
|
15
15
|
}
|
|
16
16
|
catch (error) {
|
|
17
|
-
console.error(
|
|
17
|
+
console.error("Studio handler error:", error);
|
|
18
18
|
context.set.status = 500;
|
|
19
|
-
return { error:
|
|
19
|
+
return { error: "Internal server error" };
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
async function convertElysiaToUniversal(context) {
|
|
24
24
|
let body;
|
|
25
25
|
const method = context.request.method;
|
|
26
|
-
if (method !==
|
|
26
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
27
27
|
const elysiaBody = context.body ?? context.query ?? undefined;
|
|
28
28
|
if (elysiaBody !== undefined) {
|
|
29
29
|
body = elysiaBody;
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
|
-
const contentType = context.request.headers.get(
|
|
32
|
+
const contentType = context.request.headers.get("content-type") || "";
|
|
33
33
|
try {
|
|
34
|
-
if (contentType.includes(
|
|
34
|
+
if (contentType.includes("application/json")) {
|
|
35
35
|
body = await context.request.json();
|
|
36
36
|
}
|
|
37
|
-
else if (contentType.includes(
|
|
38
|
-
contentType.includes(
|
|
37
|
+
else if (contentType.includes("application/x-www-form-urlencoded") ||
|
|
38
|
+
contentType.includes("multipart/form-data")) {
|
|
39
39
|
const formData = await context.request.formData();
|
|
40
40
|
body = Object.fromEntries(formData.entries());
|
|
41
41
|
}
|
|
@@ -78,9 +78,9 @@ function sendElysiaResponse(context, universal) {
|
|
|
78
78
|
headers: universal.headers,
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
|
-
else if (typeof universal.body ===
|
|
82
|
-
const contentType = universal.headers[
|
|
83
|
-
if (contentType.includes(
|
|
81
|
+
else if (typeof universal.body === "string") {
|
|
82
|
+
const contentType = universal.headers["content-type"] || universal.headers["Content-Type"] || "";
|
|
83
|
+
if (contentType.includes("application/json")) {
|
|
84
84
|
try {
|
|
85
85
|
return JSON.parse(universal.body);
|
|
86
86
|
}
|
|
@@ -88,7 +88,7 @@ function sendElysiaResponse(context, universal) {
|
|
|
88
88
|
return universal.body;
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
else if (contentType.includes(
|
|
91
|
+
else if (contentType.includes("text/html")) {
|
|
92
92
|
return new Response(universal.body, {
|
|
93
93
|
status: universal.status,
|
|
94
94
|
headers: universal.headers,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Router as ExpressRouter } from
|
|
2
|
-
import type { StudioConfig } from
|
|
1
|
+
import type { Router as ExpressRouter } from "express";
|
|
2
|
+
import type { StudioConfig } from "../types/handler.js";
|
|
3
3
|
/**
|
|
4
4
|
* Express adapter for Better Auth Studio
|
|
5
5
|
*/
|
package/dist/adapters/express.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Router } from
|
|
2
|
-
import { handleStudioRequest } from
|
|
3
|
-
import { injectEventHooks } from
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { handleStudioRequest } from "../core/handler.js";
|
|
3
|
+
import { injectEventHooks } from "../utils/hook-injector.js";
|
|
4
4
|
/**
|
|
5
5
|
* Express adapter for Better Auth Studio
|
|
6
6
|
*/
|
|
@@ -9,7 +9,7 @@ export function betterAuthStudio(config) {
|
|
|
9
9
|
injectEventHooks(config.auth, config.events);
|
|
10
10
|
}
|
|
11
11
|
const router = Router();
|
|
12
|
-
router.all(
|
|
12
|
+
router.all("*", async (req, res, next) => {
|
|
13
13
|
try {
|
|
14
14
|
const universalReq = convertExpressToUniversal(req);
|
|
15
15
|
const universalRes = await handleStudioRequest(universalReq, config);
|
package/dist/adapters/hono.d.ts
CHANGED
package/dist/adapters/hono.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { handleStudioRequest } from
|
|
2
|
-
import { injectEventHooks } from
|
|
1
|
+
import { handleStudioRequest } from "../core/handler.js";
|
|
2
|
+
import { injectEventHooks } from "../utils/hook-injector.js";
|
|
3
3
|
/**
|
|
4
4
|
* Hono adapter for Better Auth Studio
|
|
5
5
|
*/
|
|
@@ -14,23 +14,23 @@ export function betterAuthStudio(config) {
|
|
|
14
14
|
return sendHonoResponse(c, universalRes);
|
|
15
15
|
}
|
|
16
16
|
catch (error) {
|
|
17
|
-
console.error(
|
|
18
|
-
return c.json({ error:
|
|
17
|
+
console.error("Studio handler error:", error);
|
|
18
|
+
return c.json({ error: "Internal server error" }, 500);
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
async function convertHonoToUniversal(c) {
|
|
23
23
|
let body;
|
|
24
24
|
const method = c.req.method;
|
|
25
|
-
if (method !==
|
|
26
|
-
const contentType = c.req.header(
|
|
27
|
-
if (contentType.includes(
|
|
25
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
26
|
+
const contentType = c.req.header("content-type") || "";
|
|
27
|
+
if (contentType.includes("application/json")) {
|
|
28
28
|
try {
|
|
29
29
|
body = await c.req.json();
|
|
30
30
|
}
|
|
31
31
|
catch { }
|
|
32
32
|
}
|
|
33
|
-
else if (contentType.includes(
|
|
33
|
+
else if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
34
34
|
try {
|
|
35
35
|
body = await c.req.parseBody();
|
|
36
36
|
}
|
|
@@ -58,9 +58,9 @@ function sendHonoResponse(c, universal) {
|
|
|
58
58
|
if (Buffer.isBuffer(universal.body)) {
|
|
59
59
|
return c.body(universal.body);
|
|
60
60
|
}
|
|
61
|
-
else if (typeof universal.body ===
|
|
62
|
-
const contentType = universal.headers[
|
|
63
|
-
if (contentType.includes(
|
|
61
|
+
else if (typeof universal.body === "string") {
|
|
62
|
+
const contentType = universal.headers["content-type"] || universal.headers["Content-Type"] || "";
|
|
63
|
+
if (contentType.includes("application/json")) {
|
|
64
64
|
try {
|
|
65
65
|
return c.json(JSON.parse(universal.body));
|
|
66
66
|
}
|
|
@@ -68,7 +68,7 @@ function sendHonoResponse(c, universal) {
|
|
|
68
68
|
return c.text(universal.body);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
else if (contentType.includes(
|
|
71
|
+
else if (contentType.includes("text/html")) {
|
|
72
72
|
return c.html(universal.body);
|
|
73
73
|
}
|
|
74
74
|
else {
|
package/dist/adapters/nextjs.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { handleStudioRequest } from
|
|
2
|
-
import { injectEventHooks } from
|
|
1
|
+
import { handleStudioRequest } from "../core/handler.js";
|
|
2
|
+
import { injectEventHooks } from "../utils/hook-injector.js";
|
|
3
3
|
function getUrlFromRequest(req) {
|
|
4
4
|
const nextUrl = req.nextUrl;
|
|
5
|
-
if (nextUrl && typeof nextUrl.pathname ===
|
|
6
|
-
return nextUrl.pathname + (nextUrl.search ||
|
|
5
|
+
if (nextUrl && typeof nextUrl.pathname === "string") {
|
|
6
|
+
return nextUrl.pathname + (nextUrl.search || "");
|
|
7
7
|
}
|
|
8
8
|
const url = new URL(req.url);
|
|
9
9
|
return url.pathname + url.search;
|
|
@@ -19,19 +19,19 @@ export function betterAuthStudio(config) {
|
|
|
19
19
|
return universalToResponse(universalResponse);
|
|
20
20
|
}
|
|
21
21
|
catch (error) {
|
|
22
|
-
console.error(
|
|
23
|
-
return new Response(JSON.stringify({ error:
|
|
22
|
+
console.error("Studio handler error:", error);
|
|
23
|
+
return new Response(JSON.stringify({ error: "Internal server error" }), {
|
|
24
24
|
status: 500,
|
|
25
|
-
headers: {
|
|
25
|
+
headers: { "Content-Type": "application/json" },
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
async function requestToUniversal(req) {
|
|
31
31
|
let body;
|
|
32
|
-
if (req.method !==
|
|
33
|
-
const contentType = req.headers.get(
|
|
34
|
-
if (contentType.includes(
|
|
32
|
+
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
33
|
+
const contentType = req.headers.get("content-type") || "";
|
|
34
|
+
if (contentType.includes("application/json")) {
|
|
35
35
|
try {
|
|
36
36
|
body = await req.json();
|
|
37
37
|
}
|
package/dist/adapters/nuxt.d.ts
CHANGED
package/dist/adapters/nuxt.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { handleStudioRequest } from
|
|
2
|
-
import { injectEventHooks } from
|
|
1
|
+
import { handleStudioRequest } from "../core/handler.js";
|
|
2
|
+
import { injectEventHooks } from "../utils/hook-injector.js";
|
|
3
3
|
/**
|
|
4
4
|
* Nuxt adapter for Better Auth Studio
|
|
5
5
|
*
|
|
@@ -28,17 +28,17 @@ export function betterAuthStudio(config) {
|
|
|
28
28
|
}
|
|
29
29
|
catch (error) {
|
|
30
30
|
// Handle client disconnection gracefully
|
|
31
|
-
if (error?.code ===
|
|
32
|
-
error?.code ===
|
|
33
|
-
error?.message?.includes(
|
|
34
|
-
error?.message?.includes(
|
|
31
|
+
if (error?.code === "EPIPE" ||
|
|
32
|
+
error?.code === "ECONNRESET" ||
|
|
33
|
+
error?.message?.includes("aborted") ||
|
|
34
|
+
error?.message?.includes("destroyed")) {
|
|
35
35
|
// Client disconnected, return empty response
|
|
36
36
|
return new Response(null, { status: 499 });
|
|
37
37
|
}
|
|
38
|
-
console.error(
|
|
39
|
-
return new Response(JSON.stringify({ error:
|
|
38
|
+
console.error("Studio handler error:", error);
|
|
39
|
+
return new Response(JSON.stringify({ error: "Internal server error" }), {
|
|
40
40
|
status: 500,
|
|
41
|
-
headers: {
|
|
41
|
+
headers: { "Content-Type": "application/json" },
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
44
|
};
|
|
@@ -46,7 +46,7 @@ export function betterAuthStudio(config) {
|
|
|
46
46
|
async function convertNuxtToUniversal(event, config) {
|
|
47
47
|
let body;
|
|
48
48
|
const method = event.method;
|
|
49
|
-
if (method !==
|
|
49
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
50
50
|
// First check if body was already read by h3/Nuxt and stored on event
|
|
51
51
|
if (event.body !== undefined) {
|
|
52
52
|
body = event.body;
|
|
@@ -57,15 +57,15 @@ async function convertNuxtToUniversal(event, config) {
|
|
|
57
57
|
try {
|
|
58
58
|
// Check if readBody is available globally (Nuxt auto-imports it)
|
|
59
59
|
const readBodyFn = globalThis.readBody;
|
|
60
|
-
if (typeof readBodyFn ===
|
|
60
|
+
if (typeof readBodyFn === "function") {
|
|
61
61
|
body = await readBodyFn(event);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
catch (error) {
|
|
65
65
|
// Only rethrow connection errors
|
|
66
|
-
if (error?.code ===
|
|
67
|
-
error?.code ===
|
|
68
|
-
error?.message?.includes(
|
|
66
|
+
if (error?.code === "EPIPE" ||
|
|
67
|
+
error?.code === "ECONNRESET" ||
|
|
68
|
+
error?.message?.includes("aborted")) {
|
|
69
69
|
throw error;
|
|
70
70
|
}
|
|
71
71
|
// For other errors (like readBody not found), silently continue
|
|
@@ -77,21 +77,21 @@ async function convertNuxtToUniversal(event, config) {
|
|
|
77
77
|
const headers = {};
|
|
78
78
|
if (event.headers) {
|
|
79
79
|
Object.entries(event.headers).forEach(([key, value]) => {
|
|
80
|
-
if (typeof value ===
|
|
80
|
+
if (typeof value === "string") {
|
|
81
81
|
headers[key] = value;
|
|
82
82
|
}
|
|
83
83
|
else if (Array.isArray(value)) {
|
|
84
|
-
headers[key] = value.join(
|
|
84
|
+
headers[key] = value.join(", ");
|
|
85
85
|
}
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
88
|
// Extract path and query
|
|
89
|
-
const basePath = config.basePath ||
|
|
90
|
-
const normalizedBasePath = basePath.endsWith(
|
|
89
|
+
const basePath = config.basePath || "/api/studio";
|
|
90
|
+
const normalizedBasePath = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
|
|
91
91
|
const url = getRequestURL(event);
|
|
92
92
|
let path = url.pathname;
|
|
93
93
|
if (path.startsWith(normalizedBasePath)) {
|
|
94
|
-
path = path.slice(normalizedBasePath.length) ||
|
|
94
|
+
path = path.slice(normalizedBasePath.length) || "/";
|
|
95
95
|
}
|
|
96
96
|
const pathWithQuery = path + url.search;
|
|
97
97
|
return {
|
|
@@ -102,9 +102,9 @@ async function convertNuxtToUniversal(event, config) {
|
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
104
|
function getRequestURL(event) {
|
|
105
|
-
const protocol = event.node.req.socket?.encrypted ?
|
|
106
|
-
const host = event.headers.host || event.headers[
|
|
107
|
-
const path = (event.node.req.url ||
|
|
105
|
+
const protocol = event.node.req.socket?.encrypted ? "https" : "http";
|
|
106
|
+
const host = event.headers.host || event.headers[":authority"] || "localhost";
|
|
107
|
+
const path = (event.node.req.url || "/").replace(/[/\\]{2,}/g, "/");
|
|
108
108
|
return new URL(path, `${protocol}://${host}`);
|
|
109
109
|
}
|
|
110
110
|
function universalToResponse(res) {
|
package/dist/adapters/remix.d.ts
CHANGED