better-auth-studio 1.1.3-beta.8 → 1.1.3
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 +145 -16
- package/dist/adapters/astro.d.ts +0 -1
- package/dist/adapters/astro.js +5 -2
- package/dist/adapters/cloudflare-workers.d.ts +101 -0
- package/dist/adapters/cloudflare-workers.js +494 -0
- package/dist/adapters/elysia.d.ts +0 -1
- package/dist/adapters/elysia.js +7 -33
- package/dist/adapters/express.d.ts +0 -1
- package/dist/adapters/express.js +4 -1
- package/dist/adapters/hono.d.ts +0 -1
- package/dist/adapters/hono.js +7 -27
- package/dist/adapters/nextjs.d.ts +0 -1
- package/dist/adapters/nextjs.js +5 -2
- package/dist/adapters/nuxt.d.ts +0 -1
- package/dist/adapters/nuxt.js +5 -2
- package/dist/adapters/remix.d.ts +0 -1
- package/dist/adapters/remix.js +5 -2
- package/dist/adapters/solid-start.d.ts +0 -1
- package/dist/adapters/solid-start.js +5 -2
- package/dist/adapters/svelte-kit.d.ts +0 -1
- package/dist/adapters/svelte-kit.js +5 -2
- package/dist/adapters/tanstack-start.d.ts +0 -1
- package/dist/adapters/tanstack-start.js +36 -8
- package/dist/add-svelte-kit-env-modules.d.ts +0 -1
- package/dist/add-svelte-kit-env-modules.js +0 -1
- package/dist/auth-adapter.d.ts +5 -2
- package/dist/auth-adapter.js +39 -4
- package/dist/cli/commands/init.d.ts +0 -1
- package/dist/cli/commands/init.js +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +6 -1
- package/dist/config.d.ts +0 -1
- package/dist/config.js +0 -1
- package/dist/core/handler.d.ts +0 -1
- package/dist/core/handler.js +36 -5
- package/dist/data.d.ts +10 -4
- package/dist/data.js +109 -19
- package/dist/geo-service.d.ts +0 -1
- package/dist/geo-service.js +0 -1
- package/dist/get-tsconfig-info.d.ts +0 -1
- package/dist/get-tsconfig-info.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/providers/events/helpers.d.ts +3 -2
- package/dist/providers/events/helpers.js +303 -93
- package/dist/public/assets/main-C-R_HO98.css +1 -0
- package/dist/public/assets/main-DDypFItU.js +1302 -0
- package/dist/public/index.html +2 -2
- package/dist/public/shaders.png +0 -0
- package/dist/routes/api-router.d.ts +2 -3
- package/dist/routes/api-router.js +0 -1
- package/dist/routes.d.ts +2 -3
- package/dist/routes.js +813 -172
- package/dist/studio.d.ts +0 -1
- package/dist/studio.js +6 -4
- package/dist/types/events.d.ts +0 -1
- package/dist/types/events.js +0 -1
- package/dist/types/handler.d.ts +13 -3
- package/dist/types/handler.js +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.js +0 -1
- package/dist/utils/access-rules.d.ts +19 -0
- package/dist/utils/access-rules.js +126 -0
- package/dist/utils/auth-callbacks-injector.d.ts +0 -1
- package/dist/utils/auth-callbacks-injector.js +0 -1
- package/dist/utils/database-detection.d.ts +0 -1
- package/dist/utils/database-detection.js +33 -4
- package/dist/utils/event-ingestion.d.ts +0 -1
- package/dist/utils/event-ingestion.js +1 -1
- package/dist/utils/hook-injector.d.ts +0 -1
- package/dist/utils/hook-injector.js +2 -2
- package/dist/utils/html-injector.d.ts +1 -7
- package/dist/utils/html-injector.js +15 -1
- package/dist/utils/org-hooks-injector.d.ts +0 -1
- package/dist/utils/org-hooks-injector.js +0 -1
- package/dist/utils/package-json.d.ts +1 -1
- package/dist/utils/package-json.js +21 -1
- package/dist/utils/paths.d.ts +0 -1
- package/dist/utils/paths.js +0 -1
- package/dist/utils/reason-messages.d.ts +0 -1
- package/dist/utils/reason-messages.js +0 -1
- package/dist/utils/session.d.ts +0 -1
- package/dist/utils/session.js +0 -1
- package/dist/utils.d.ts +0 -1
- package/dist/utils.js +0 -1
- package/package.json +4 -4
- package/dist/adapters/astro.d.ts.map +0 -1
- package/dist/adapters/astro.js.map +0 -1
- package/dist/adapters/elysia.d.ts.map +0 -1
- package/dist/adapters/elysia.js.map +0 -1
- package/dist/adapters/express.d.ts.map +0 -1
- package/dist/adapters/express.js.map +0 -1
- package/dist/adapters/hono.d.ts.map +0 -1
- package/dist/adapters/hono.js.map +0 -1
- package/dist/adapters/nextjs.d.ts.map +0 -1
- package/dist/adapters/nextjs.js.map +0 -1
- package/dist/adapters/nuxt.d.ts.map +0 -1
- package/dist/adapters/nuxt.js.map +0 -1
- package/dist/adapters/remix.d.ts.map +0 -1
- package/dist/adapters/remix.js.map +0 -1
- package/dist/adapters/solid-start.d.ts.map +0 -1
- package/dist/adapters/solid-start.js.map +0 -1
- package/dist/adapters/svelte-kit.d.ts.map +0 -1
- package/dist/adapters/svelte-kit.js.map +0 -1
- package/dist/adapters/tanstack-start.d.ts.map +0 -1
- package/dist/adapters/tanstack-start.js.map +0 -1
- package/dist/add-svelte-kit-env-modules.d.ts.map +0 -1
- package/dist/add-svelte-kit-env-modules.js.map +0 -1
- package/dist/auth-adapter.d.ts.map +0 -1
- package/dist/auth-adapter.js.map +0 -1
- package/dist/cli/commands/init.d.ts.map +0 -1
- package/dist/cli/commands/init.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/core/handler.d.ts.map +0 -1
- package/dist/core/handler.js.map +0 -1
- package/dist/data.d.ts.map +0 -1
- package/dist/data.js.map +0 -1
- package/dist/geo-service.d.ts.map +0 -1
- package/dist/geo-service.js.map +0 -1
- package/dist/get-tsconfig-info.d.ts.map +0 -1
- package/dist/get-tsconfig-info.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/providers/events/helpers.d.ts.map +0 -1
- package/dist/providers/events/helpers.js.map +0 -1
- package/dist/public/assets/main-Bi83bOQp.js +0 -1216
- package/dist/public/assets/main-Dx_SZlEy.css +0 -1
- package/dist/routes/api-router.d.ts.map +0 -1
- package/dist/routes/api-router.js.map +0 -1
- package/dist/routes.d.ts.map +0 -1
- package/dist/routes.js.map +0 -1
- package/dist/studio.d.ts.map +0 -1
- package/dist/studio.js.map +0 -1
- package/dist/types/events.d.ts.map +0 -1
- package/dist/types/events.js.map +0 -1
- package/dist/types/handler.d.ts.map +0 -1
- package/dist/types/handler.js.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/utils/auth-callbacks-injector.d.ts.map +0 -1
- package/dist/utils/auth-callbacks-injector.js.map +0 -1
- package/dist/utils/auth-callbacks-wrapper.d.ts +0 -7
- package/dist/utils/auth-callbacks-wrapper.d.ts.map +0 -1
- package/dist/utils/auth-callbacks-wrapper.js +0 -133
- package/dist/utils/auth-callbacks-wrapper.js.map +0 -1
- package/dist/utils/database-detection.d.ts.map +0 -1
- package/dist/utils/database-detection.js.map +0 -1
- package/dist/utils/database-hook-injector.d.ts +0 -3
- package/dist/utils/database-hook-injector.d.ts.map +0 -1
- package/dist/utils/database-hook-injector.js +0 -145
- package/dist/utils/database-hook-injector.js.map +0 -1
- package/dist/utils/email-otp-hooks-injector.d.ts +0 -45
- package/dist/utils/email-otp-hooks-injector.d.ts.map +0 -1
- package/dist/utils/email-otp-hooks-injector.js +0 -141
- package/dist/utils/email-otp-hooks-injector.js.map +0 -1
- package/dist/utils/event-ingestion.d.ts.map +0 -1
- package/dist/utils/event-ingestion.js.map +0 -1
- package/dist/utils/hook-injector.d.ts.map +0 -1
- package/dist/utils/hook-injector.js.map +0 -1
- package/dist/utils/html-injector.d.ts.map +0 -1
- package/dist/utils/html-injector.js.map +0 -1
- package/dist/utils/org-hooks-injector.d.ts.map +0 -1
- package/dist/utils/org-hooks-injector.js.map +0 -1
- package/dist/utils/org-hooks-wrapper.d.ts +0 -80
- package/dist/utils/org-hooks-wrapper.d.ts.map +0 -1
- package/dist/utils/org-hooks-wrapper.js +0 -807
- package/dist/utils/org-hooks-wrapper.js.map +0 -1
- package/dist/utils/organization-hooks-wrapper.d.ts +0 -44
- package/dist/utils/organization-hooks-wrapper.d.ts.map +0 -1
- package/dist/utils/organization-hooks-wrapper.js +0 -345
- package/dist/utils/organization-hooks-wrapper.js.map +0 -1
- package/dist/utils/package-json.d.ts.map +0 -1
- package/dist/utils/package-json.js.map +0 -1
- package/dist/utils/paths.d.ts.map +0 -1
- package/dist/utils/paths.js.map +0 -1
- package/dist/utils/reason-messages.d.ts.map +0 -1
- package/dist/utils/reason-messages.js.map +0 -1
- package/dist/utils/server-init.d.ts +0 -10
- package/dist/utils/server-init.d.ts.map +0 -1
- package/dist/utils/server-init.js +0 -40
- package/dist/utils/server-init.js.map +0 -1
- package/dist/utils/session.d.ts.map +0 -1
- package/dist/utils/session.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- package/public/assets/main-Bi83bOQp.js +0 -1216
- package/public/assets/main-Dx_SZlEy.css +0 -1
- package/public/favicon.svg +0 -6
- package/public/index.html +0 -14
- package/public/logo.png +0 -0
- package/public/vite.svg +0 -5
- package/scripts/download-geolite2.js +0 -42
- package/scripts/generate-default-db.js +0 -462
|
@@ -94,9 +94,12 @@ async function convertSolidStartToUniversal(event, config) {
|
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
96
|
function universalToResponse(res) {
|
|
97
|
+
const headers = new Headers(res.headers);
|
|
98
|
+
res.setCookies?.forEach((cookie) => {
|
|
99
|
+
headers.append("Set-Cookie", cookie);
|
|
100
|
+
});
|
|
97
101
|
return new Response(res.body, {
|
|
98
102
|
status: res.status,
|
|
99
|
-
headers
|
|
103
|
+
headers,
|
|
100
104
|
});
|
|
101
105
|
}
|
|
102
|
-
//# sourceMappingURL=solid-start.js.map
|
|
@@ -106,9 +106,12 @@ async function convertSvelteKitToUniversal(event, config) {
|
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
108
|
function universalToResponse(res) {
|
|
109
|
+
const headers = new Headers(res.headers);
|
|
110
|
+
res.setCookies?.forEach((cookie) => {
|
|
111
|
+
headers.append("Set-Cookie", cookie);
|
|
112
|
+
});
|
|
109
113
|
return new Response(res.body, {
|
|
110
114
|
status: res.status,
|
|
111
|
-
headers
|
|
115
|
+
headers,
|
|
112
116
|
});
|
|
113
117
|
}
|
|
114
|
-
//# sourceMappingURL=svelte-kit.js.map
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { handleStudioRequest } from "../core/handler.js";
|
|
2
2
|
import { injectEventHooks, injectLastSeenAtHooks } from "../utils/hook-injector.js";
|
|
3
|
+
const STATIC_ASSET_QUERY_PARAM = "__better_auth_studio_asset";
|
|
4
|
+
const STATIC_ASSET_PATH_PATTERN = /^\/(?:assets\/[^/?#]+|vite\.svg|favicon\.svg|logo\.png)$/;
|
|
3
5
|
/**
|
|
4
6
|
* TanStack Start adapter for Better Auth Studio
|
|
5
7
|
*
|
|
@@ -35,7 +37,7 @@ export function betterAuthStudio(config) {
|
|
|
35
37
|
try {
|
|
36
38
|
const universalReq = await convertTanStackStartToUniversal(request, config);
|
|
37
39
|
const universalRes = await handleStudioRequest(universalReq, config);
|
|
38
|
-
return universalToResponse(universalRes);
|
|
40
|
+
return universalToResponse(universalRes, config);
|
|
39
41
|
}
|
|
40
42
|
catch (error) {
|
|
41
43
|
console.error("Studio handler error:", error);
|
|
@@ -87,11 +89,15 @@ async function convertTanStackStartToUniversal(request, config) {
|
|
|
87
89
|
const basePath = config.basePath || "/api/studio";
|
|
88
90
|
const normalizedBasePath = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
|
|
89
91
|
const url = new URL(request.url);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
+
const queryAssetPath = url.searchParams.get(STATIC_ASSET_QUERY_PARAM);
|
|
93
|
+
const acceptedQueryAssetPath = queryAssetPath && STATIC_ASSET_PATH_PATTERN.test(queryAssetPath) ? queryAssetPath : null;
|
|
94
|
+
let path = acceptedQueryAssetPath || url.pathname;
|
|
95
|
+
if (!acceptedQueryAssetPath && path.startsWith(normalizedBasePath)) {
|
|
92
96
|
path = path.slice(normalizedBasePath.length) || "/";
|
|
93
97
|
}
|
|
94
|
-
|
|
98
|
+
url.searchParams.delete(STATIC_ASSET_QUERY_PARAM);
|
|
99
|
+
const query = url.searchParams.toString();
|
|
100
|
+
const pathWithQuery = path + (query ? `?${query}` : "");
|
|
95
101
|
return {
|
|
96
102
|
url: pathWithQuery,
|
|
97
103
|
method: method,
|
|
@@ -99,10 +105,32 @@ async function convertTanStackStartToUniversal(request, config) {
|
|
|
99
105
|
body,
|
|
100
106
|
};
|
|
101
107
|
}
|
|
102
|
-
function universalToResponse(res) {
|
|
103
|
-
|
|
108
|
+
function universalToResponse(res, config) {
|
|
109
|
+
const headers = new Headers(res.headers);
|
|
110
|
+
res.setCookies?.forEach((cookie) => {
|
|
111
|
+
headers.append("Set-Cookie", cookie);
|
|
112
|
+
});
|
|
113
|
+
let body = res.body;
|
|
114
|
+
if (typeof body === "string" &&
|
|
115
|
+
headers.get("Content-Type")?.toLowerCase().includes("text/html")) {
|
|
116
|
+
body = rewriteStaticAssetUrls(body, config.basePath || "/api/studio");
|
|
117
|
+
}
|
|
118
|
+
return new Response(body, {
|
|
104
119
|
status: res.status,
|
|
105
|
-
headers
|
|
120
|
+
headers,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Nitro can treat nested URLs ending in .js/.css as public files before a
|
|
125
|
+
* TanStack Start splat route gets a chance to handle them. Keep Studio assets
|
|
126
|
+
* on the exact server-route URL and carry the requested file in the query.
|
|
127
|
+
*/
|
|
128
|
+
function rewriteStaticAssetUrls(html, basePath) {
|
|
129
|
+
const normalizedBasePath = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
|
|
130
|
+
const escapedBasePath = normalizedBasePath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
131
|
+
const assetUrlPattern = new RegExp(`((?:href|src)=["'])${escapedBasePath}(/(?:assets/[^"'?#]+|vite\\.svg|favicon\\.svg|logo\\.png))(["'])`, "g");
|
|
132
|
+
return html.replace(assetUrlPattern, (_match, prefix, assetPath, suffix) => {
|
|
133
|
+
const query = new URLSearchParams({ [STATIC_ASSET_QUERY_PARAM]: assetPath });
|
|
134
|
+
return `${prefix}${normalizedBasePath}?${query.toString()}${suffix}`;
|
|
106
135
|
});
|
|
107
136
|
}
|
|
108
|
-
//# sourceMappingURL=tanstack-start.js.map
|
package/dist/auth-adapter.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type InternalAdapter } from "better-auth";
|
|
2
2
|
type OptionalFields<T> = {
|
|
3
3
|
[K in keyof T]?: T[K];
|
|
4
4
|
};
|
|
@@ -8,6 +8,10 @@ export interface AuthAdapter extends UserInternalAdapter {
|
|
|
8
8
|
createAccount: (data: any) => Promise<any>;
|
|
9
9
|
createVerification: (data: any) => Promise<any>;
|
|
10
10
|
createOrganization: (data: any) => Promise<any>;
|
|
11
|
+
count?: (options: {
|
|
12
|
+
model: string;
|
|
13
|
+
where?: any;
|
|
14
|
+
}) => Promise<number>;
|
|
11
15
|
create?: (...args: any[]) => Promise<any>;
|
|
12
16
|
update?: (...args: any[]) => Promise<any>;
|
|
13
17
|
delete?: (...args: any[]) => Promise<any>;
|
|
@@ -34,4 +38,3 @@ export declare function createMockSession(adapter: AuthAdapter, userId: string,
|
|
|
34
38
|
export declare function createMockAccount(adapter: AuthAdapter, userId: string, index: number, providerId?: string): Promise<any>;
|
|
35
39
|
export declare function createMockVerification(adapter: AuthAdapter, _userId: string, index: number): Promise<any>;
|
|
36
40
|
export {};
|
|
37
|
-
//# sourceMappingURL=auth-adapter.d.ts.map
|
package/dist/auth-adapter.js
CHANGED
|
@@ -102,8 +102,14 @@ export async function getAuthAdapter(configPath) {
|
|
|
102
102
|
image: data.image || `https://api.dicebear.com/7.x/avataaars/svg?seed=${data.email}`,
|
|
103
103
|
},
|
|
104
104
|
});
|
|
105
|
-
const hashedPassword = await hashPassword(data.password);
|
|
106
105
|
if (data.password) {
|
|
106
|
+
let hashedPassword = data.password;
|
|
107
|
+
try {
|
|
108
|
+
hashedPassword = await hashPassword(data.password);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
console.log({ err });
|
|
112
|
+
}
|
|
107
113
|
try {
|
|
108
114
|
await adapter.create({
|
|
109
115
|
model: "account",
|
|
@@ -117,7 +123,9 @@ export async function getAuthAdapter(configPath) {
|
|
|
117
123
|
},
|
|
118
124
|
});
|
|
119
125
|
}
|
|
120
|
-
catch (_accountError) {
|
|
126
|
+
catch (_accountError) {
|
|
127
|
+
console.log({ _accountError });
|
|
128
|
+
}
|
|
121
129
|
}
|
|
122
130
|
return user;
|
|
123
131
|
},
|
|
@@ -193,6 +201,25 @@ export async function getAuthAdapter(configPath) {
|
|
|
193
201
|
return [];
|
|
194
202
|
}
|
|
195
203
|
},
|
|
204
|
+
count: async (options) => {
|
|
205
|
+
try {
|
|
206
|
+
if (typeof adapter.count === "function") {
|
|
207
|
+
return await adapter.count(options);
|
|
208
|
+
}
|
|
209
|
+
if (typeof adapter.findMany === "function") {
|
|
210
|
+
const rows = await adapter.findMany({
|
|
211
|
+
model: options.model,
|
|
212
|
+
where: options.where,
|
|
213
|
+
limit: 100000,
|
|
214
|
+
});
|
|
215
|
+
return Array.isArray(rows) ? rows.length : 0;
|
|
216
|
+
}
|
|
217
|
+
return 0;
|
|
218
|
+
}
|
|
219
|
+
catch (_error) {
|
|
220
|
+
return 0;
|
|
221
|
+
}
|
|
222
|
+
},
|
|
196
223
|
findMany: async (options) => {
|
|
197
224
|
try {
|
|
198
225
|
if (typeof adapter.findMany === "function") {
|
|
@@ -416,15 +443,24 @@ function generateRandomIP() {
|
|
|
416
443
|
const fourthOctet = Math.floor(Math.random() * 255) + 1;
|
|
417
444
|
return `${range.min.split(".")[0]}.${secondOctet}.${thirdOctet}.${fourthOctet}`;
|
|
418
445
|
}
|
|
446
|
+
const SESSION_SEED_USER_AGENTS = [
|
|
447
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Mobile/15E148 Safari/604.1",
|
|
448
|
+
"Mozilla/5.0 (Linux; Android 15; Pixel 9 Pro Build/AP3A.241205.015) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Mobile Safari/537.36",
|
|
449
|
+
"Mozilla/5.0 (iPad; CPU OS 18_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Mobile/15E148 Safari/604.1",
|
|
450
|
+
"Mozilla/5.0 (Linux; Android 14; SM-X910 Build/UP1A.231005.007) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36",
|
|
451
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0",
|
|
452
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
|
|
453
|
+
];
|
|
419
454
|
export async function createMockSession(adapter, userId, index) {
|
|
420
455
|
// Generate a random IP address
|
|
421
456
|
const ipAddress = generateRandomIP();
|
|
457
|
+
const userAgent = SESSION_SEED_USER_AGENTS[(index - 1) % SESSION_SEED_USER_AGENTS.length];
|
|
422
458
|
const sessionData = {
|
|
423
459
|
userId: userId,
|
|
424
460
|
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days from now
|
|
425
461
|
token: `session_token_${index}_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`,
|
|
426
462
|
ipAddress: ipAddress,
|
|
427
|
-
userAgent
|
|
463
|
+
userAgent,
|
|
428
464
|
createdAt: new Date(),
|
|
429
465
|
updatedAt: new Date(),
|
|
430
466
|
};
|
|
@@ -488,4 +524,3 @@ export async function createMockVerification(adapter, _userId, index) {
|
|
|
488
524
|
};
|
|
489
525
|
return await adapter.createVerification(verificationData);
|
|
490
526
|
}
|
|
491
|
-
//# sourceMappingURL=auth-adapter.js.map
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -281,6 +281,12 @@ program
|
|
|
281
281
|
else if (content.includes("prismaAdapter")) {
|
|
282
282
|
databaseInfo = "Prisma";
|
|
283
283
|
}
|
|
284
|
+
else if (content.includes("kyselyAdapter") ||
|
|
285
|
+
content.includes("Kysely") ||
|
|
286
|
+
content.includes('from "kysely"') ||
|
|
287
|
+
content.includes("from 'kysely'")) {
|
|
288
|
+
databaseInfo = "Kysely";
|
|
289
|
+
}
|
|
284
290
|
else if (authConfig.database.adapter && authConfig.database.provider) {
|
|
285
291
|
const adapter = authConfig.database.adapter;
|
|
286
292
|
const adapterName = adapter.charAt(0).toUpperCase() + adapter.slice(1);
|
|
@@ -364,4 +370,3 @@ program
|
|
|
364
370
|
}
|
|
365
371
|
});
|
|
366
372
|
program.parse();
|
|
367
|
-
//# sourceMappingURL=cli.js.map
|
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
package/dist/core/handler.d.ts
CHANGED
|
@@ -9,4 +9,3 @@ export declare function initializeEventIngestionAndHooks(config: StudioConfig):
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function handleStudioRequest(request: UniversalRequest, config: StudioConfig): Promise<UniversalResponse>;
|
|
11
11
|
export declare function getAuthAdapter(auth: any): Promise<any>;
|
|
12
|
-
//# sourceMappingURL=handler.d.ts.map
|
package/dist/core/handler.js
CHANGED
|
@@ -5,6 +5,7 @@ import { createClickHouseProvider, createHttpProvider, createNodeSqliteProvider,
|
|
|
5
5
|
import { initializeEventIngestion, isEventIngestionInitialized } from "../utils/event-ingestion.js";
|
|
6
6
|
import { injectEventHooks, injectLastSeenAtHooks } from "../utils/hook-injector.js";
|
|
7
7
|
import { serveIndexHtml as getIndexHtml } from "../utils/html-injector.js";
|
|
8
|
+
import { evaluateRequestAccess } from "../utils/access-rules.js";
|
|
8
9
|
import { decryptSession, isSessionValid, STUDIO_COOKIE_NAME } from "../utils/session.js";
|
|
9
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
11
|
const __dirname = dirname(__filename);
|
|
@@ -32,6 +33,7 @@ export async function initializeEventIngestionAndHooks(config) {
|
|
|
32
33
|
case "postgres":
|
|
33
34
|
case "prisma":
|
|
34
35
|
case "drizzle":
|
|
36
|
+
case "kysely":
|
|
35
37
|
try {
|
|
36
38
|
provider = createPostgresProvider({
|
|
37
39
|
client: config.events.client,
|
|
@@ -132,10 +134,28 @@ export async function handleStudioRequest(request, config) {
|
|
|
132
134
|
if (path === "" || path === "/") {
|
|
133
135
|
path = "/";
|
|
134
136
|
}
|
|
137
|
+
if (isSelfHosted) {
|
|
138
|
+
const accessDecision = evaluateRequestAccess({
|
|
139
|
+
accessConfig: config.access,
|
|
140
|
+
path,
|
|
141
|
+
method: request.method,
|
|
142
|
+
headers: request.headers,
|
|
143
|
+
ip: request.ip,
|
|
144
|
+
});
|
|
145
|
+
if (!accessDecision.allowed) {
|
|
146
|
+
return jsonResponse(403, {
|
|
147
|
+
success: false,
|
|
148
|
+
message: accessDecision.message,
|
|
149
|
+
reason: accessDecision.reason,
|
|
150
|
+
...(accessDecision.ipAddress ? { ipAddress: accessDecision.ipAddress } : {}),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
135
154
|
if (path.startsWith("/assets/") ||
|
|
136
155
|
path === "/vite.svg" ||
|
|
137
156
|
path === "/favicon.svg" ||
|
|
138
|
-
path === "/logo.png"
|
|
157
|
+
path === "/logo.png" ||
|
|
158
|
+
path === "/shaders.png") {
|
|
139
159
|
return handleStaticFile(path, config);
|
|
140
160
|
}
|
|
141
161
|
if (path === "/") {
|
|
@@ -154,6 +174,16 @@ export async function handleStudioRequest(request, config) {
|
|
|
154
174
|
}
|
|
155
175
|
return await handleApiRoute(request, path, config);
|
|
156
176
|
}
|
|
177
|
+
if (isSelfHosted && (path === "/auth" || path.startsWith("/auth/"))) {
|
|
178
|
+
const apiPath = "/api" + path;
|
|
179
|
+
if (isProtectedApiPath(apiPath)) {
|
|
180
|
+
const sessionResult = verifyStudioSession(request, config);
|
|
181
|
+
if (!sessionResult.valid) {
|
|
182
|
+
return jsonResponse(401, { error: "Unauthorized", message: sessionResult.error });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return await handleApiRoute(request, apiPath, config);
|
|
186
|
+
}
|
|
157
187
|
if (isSelfHosted) {
|
|
158
188
|
const acceptHeader = request.headers["accept"] || request.headers["Accept"] || "";
|
|
159
189
|
const wantsJson = acceptHeader.includes("application/json") ||
|
|
@@ -251,6 +281,7 @@ async function handleApiRoute(request, path, config) {
|
|
|
251
281
|
path: path,
|
|
252
282
|
method: request.method,
|
|
253
283
|
headers: request.headers,
|
|
284
|
+
ip: request.ip,
|
|
254
285
|
body: request.body,
|
|
255
286
|
auth: config.auth,
|
|
256
287
|
basePath: config.basePath || "/api/studio",
|
|
@@ -258,8 +289,9 @@ async function handleApiRoute(request, path, config) {
|
|
|
258
289
|
studioConfig: config,
|
|
259
290
|
});
|
|
260
291
|
const headers = { "Content-Type": "application/json" };
|
|
292
|
+
const setCookies = [];
|
|
261
293
|
if (result.cookies && result.cookies.length > 0) {
|
|
262
|
-
|
|
294
|
+
setCookies.push(...result.cookies.map((c) => {
|
|
263
295
|
let cookie = `${c.name}=${c.value}`;
|
|
264
296
|
if (c.options.httpOnly)
|
|
265
297
|
cookie += "; HttpOnly";
|
|
@@ -272,12 +304,12 @@ async function handleApiRoute(request, path, config) {
|
|
|
272
304
|
if (c.options.path)
|
|
273
305
|
cookie += `; Path=${c.options.path}`;
|
|
274
306
|
return cookie;
|
|
275
|
-
});
|
|
276
|
-
headers["Set-Cookie"] = cookieStrings.join(", ");
|
|
307
|
+
}));
|
|
277
308
|
}
|
|
278
309
|
return {
|
|
279
310
|
status: result.status,
|
|
280
311
|
headers,
|
|
312
|
+
...(setCookies.length > 0 ? { setCookies } : {}),
|
|
281
313
|
body: JSON.stringify(result.data),
|
|
282
314
|
};
|
|
283
315
|
}
|
|
@@ -600,4 +632,3 @@ function getCacheControl(path) {
|
|
|
600
632
|
}
|
|
601
633
|
return "no-cache";
|
|
602
634
|
}
|
|
603
|
-
//# sourceMappingURL=handler.js.map
|
package/dist/data.d.ts
CHANGED
|
@@ -13,10 +13,17 @@ export interface User {
|
|
|
13
13
|
export interface Session {
|
|
14
14
|
id: string;
|
|
15
15
|
userId: string;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
token?: string;
|
|
17
|
+
expiresAt?: Date | string;
|
|
18
|
+
expires?: Date | string;
|
|
19
|
+
createdAt: Date | string;
|
|
20
|
+
updatedAt?: Date | string;
|
|
21
|
+
userAgent?: string | null;
|
|
22
|
+
ipAddress?: string | null;
|
|
19
23
|
ip?: string;
|
|
24
|
+
activeOrganizationId?: string;
|
|
25
|
+
activeTeamId?: string;
|
|
26
|
+
[key: string]: unknown;
|
|
20
27
|
}
|
|
21
28
|
export interface AuthStats {
|
|
22
29
|
totalUsers: number;
|
|
@@ -35,4 +42,3 @@ export interface PaginatedResult<T> {
|
|
|
35
42
|
totalPages: number;
|
|
36
43
|
}
|
|
37
44
|
export declare function getAuthData(_authConfig: AuthConfig, type?: "stats" | "users" | "sessions" | "providers" | "deleteUser" | "updateUser" | "analytics", options?: any, configPath?: string, preloadedAdapter?: any): Promise<any>;
|
|
38
|
-
//# sourceMappingURL=data.d.ts.map
|
package/dist/data.js
CHANGED
|
@@ -126,17 +126,36 @@ async function getRealUsers(adapter, options) {
|
|
|
126
126
|
async function getRealSessions(adapter, options) {
|
|
127
127
|
const { page, limit } = options;
|
|
128
128
|
try {
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
let allSessions = null;
|
|
130
|
+
let getSessionsError;
|
|
131
|
+
if (typeof adapter?.getSessions === "function") {
|
|
132
|
+
try {
|
|
133
|
+
const result = await adapter.getSessions();
|
|
134
|
+
if (Array.isArray(result)) {
|
|
135
|
+
allSessions = result;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
getSessionsError = error;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (allSessions === null && typeof adapter?.findMany === "function") {
|
|
143
|
+
allSessions = await adapter.findMany({ model: "session", limit: 100000 });
|
|
144
|
+
}
|
|
145
|
+
if (allSessions === null && getSessionsError) {
|
|
146
|
+
throw getSessionsError;
|
|
147
|
+
}
|
|
148
|
+
if (Array.isArray(allSessions)) {
|
|
149
|
+
const normalizedSessions = allSessions.map(normalizeSession);
|
|
131
150
|
const startIndex = (page - 1) * limit;
|
|
132
151
|
const endIndex = startIndex + limit;
|
|
133
|
-
const paginatedSessions =
|
|
152
|
+
const paginatedSessions = normalizedSessions.slice(startIndex, endIndex);
|
|
134
153
|
return {
|
|
135
154
|
data: paginatedSessions,
|
|
136
|
-
total:
|
|
155
|
+
total: normalizedSessions.length,
|
|
137
156
|
page,
|
|
138
157
|
limit,
|
|
139
|
-
totalPages: Math.ceil(
|
|
158
|
+
totalPages: Math.ceil(normalizedSessions.length / limit),
|
|
140
159
|
};
|
|
141
160
|
}
|
|
142
161
|
return {
|
|
@@ -151,6 +170,22 @@ async function getRealSessions(adapter, options) {
|
|
|
151
170
|
throw new Error(`Failed to get auth data: ${_error}`);
|
|
152
171
|
}
|
|
153
172
|
}
|
|
173
|
+
function normalizeSession(rawSession) {
|
|
174
|
+
const session = rawSession && typeof rawSession === "object" ? rawSession : {};
|
|
175
|
+
return {
|
|
176
|
+
...session,
|
|
177
|
+
id: session.id ?? session.session_id,
|
|
178
|
+
userId: session.userId ?? session.user_id,
|
|
179
|
+
token: session.token ?? session.session_token,
|
|
180
|
+
expiresAt: session.expiresAt ?? session.expires_at ?? session.expires,
|
|
181
|
+
createdAt: session.createdAt ?? session.created_at,
|
|
182
|
+
updatedAt: session.updatedAt ?? session.updated_at,
|
|
183
|
+
userAgent: session.userAgent ?? session.user_agent,
|
|
184
|
+
ipAddress: session.ipAddress ?? session.ip_address ?? session.ip,
|
|
185
|
+
activeOrganizationId: session.activeOrganizationId ?? session.active_organization_id ?? session.active_organization,
|
|
186
|
+
activeTeamId: session.activeTeamId ?? session.active_team_id ?? session.active_team,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
154
189
|
async function getRealProviderStats(_adapter) {
|
|
155
190
|
try {
|
|
156
191
|
return [
|
|
@@ -466,7 +501,7 @@ async function getRealAnalytics(adapter, options) {
|
|
|
466
501
|
data = buckets.map((bucket) => {
|
|
467
502
|
return users.filter((user) => {
|
|
468
503
|
const createdAt = new Date(user.createdAt);
|
|
469
|
-
return createdAt >= bucket.start && createdAt
|
|
504
|
+
return createdAt >= bucket.start && createdAt <= bucket.end;
|
|
470
505
|
}).length;
|
|
471
506
|
});
|
|
472
507
|
}
|
|
@@ -475,21 +510,26 @@ async function getRealAnalytics(adapter, options) {
|
|
|
475
510
|
data = buckets.map((bucket) => {
|
|
476
511
|
return users.filter((user) => {
|
|
477
512
|
const createdAt = new Date(user.createdAt);
|
|
478
|
-
return createdAt >= bucket.start && createdAt
|
|
513
|
+
return createdAt >= bucket.start && createdAt <= bucket.end;
|
|
479
514
|
}).length;
|
|
480
515
|
});
|
|
481
516
|
}
|
|
482
517
|
else if (type === "activeUsers") {
|
|
483
|
-
//
|
|
518
|
+
// Logins = count of sessions (login events) created in each bucket
|
|
484
519
|
data = buckets.map((bucket) => {
|
|
485
|
-
|
|
520
|
+
return sessions.filter((session) => {
|
|
486
521
|
const sessionCreated = new Date(session.createdAt);
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
522
|
+
return sessionCreated >= bucket.start && sessionCreated <= bucket.end;
|
|
523
|
+
}).length;
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
else if (type === "sessions") {
|
|
527
|
+
// Sessions = count of sessions created in each bucket
|
|
528
|
+
data = buckets.map((bucket) => {
|
|
529
|
+
return sessions.filter((session) => {
|
|
530
|
+
const sessionCreated = new Date(session.createdAt);
|
|
531
|
+
return sessionCreated >= bucket.start && sessionCreated <= bucket.end;
|
|
532
|
+
}).length;
|
|
493
533
|
});
|
|
494
534
|
}
|
|
495
535
|
else if (type === "organizations") {
|
|
@@ -497,7 +537,7 @@ async function getRealAnalytics(adapter, options) {
|
|
|
497
537
|
data = buckets.map((bucket) => {
|
|
498
538
|
return organizations.filter((org) => {
|
|
499
539
|
const createdAt = new Date(org.createdAt);
|
|
500
|
-
return createdAt >= bucket.start && createdAt
|
|
540
|
+
return createdAt >= bucket.start && createdAt <= bucket.end;
|
|
501
541
|
}).length;
|
|
502
542
|
});
|
|
503
543
|
}
|
|
@@ -506,24 +546,74 @@ async function getRealAnalytics(adapter, options) {
|
|
|
506
546
|
data = buckets.map((bucket) => {
|
|
507
547
|
return teams.filter((team) => {
|
|
508
548
|
const createdAt = new Date(team.createdAt);
|
|
509
|
-
return createdAt >= bucket.start && createdAt
|
|
549
|
+
return createdAt >= bucket.start && createdAt <= bucket.end;
|
|
510
550
|
}).length;
|
|
511
551
|
});
|
|
512
552
|
}
|
|
513
|
-
// Calculate
|
|
553
|
+
// Calculate total
|
|
514
554
|
const total = data.reduce((sum, val) => sum + val, 0);
|
|
515
555
|
const average = total / data.length;
|
|
556
|
+
// For activeUsers (logins), also compute unique users per bucket for tooltips
|
|
557
|
+
let uniqueUsers;
|
|
558
|
+
if (type === "activeUsers") {
|
|
559
|
+
uniqueUsers = buckets.map((bucket) => {
|
|
560
|
+
const bucketSessions = sessions.filter((session) => {
|
|
561
|
+
const sessionCreated = new Date(session.createdAt);
|
|
562
|
+
return sessionCreated >= bucket.start && sessionCreated <= bucket.end;
|
|
563
|
+
});
|
|
564
|
+
return new Set(bucketSessions.map((s) => s.userId)).size;
|
|
565
|
+
});
|
|
566
|
+
}
|
|
516
567
|
const lastValue = data[data.length - 1] || 0;
|
|
517
568
|
const previousValue = data[data.length - 2] || average;
|
|
518
569
|
const percentageChange = previousValue > 0 ? ((lastValue - previousValue) / previousValue) * 100 : 0;
|
|
570
|
+
// Calculate previous period total for comparison
|
|
571
|
+
let previousTotal = 0;
|
|
572
|
+
const getPreviousPeriodTotal = (prevStart, prevEnd) => {
|
|
573
|
+
if (type === "users" || type === "newUsers") {
|
|
574
|
+
return users.filter((user) => {
|
|
575
|
+
const createdAt = new Date(user.createdAt);
|
|
576
|
+
return createdAt >= prevStart && createdAt <= prevEnd;
|
|
577
|
+
}).length;
|
|
578
|
+
}
|
|
579
|
+
else if (type === "activeUsers" || type === "sessions") {
|
|
580
|
+
return sessions.filter((session) => {
|
|
581
|
+
const sessionCreated = new Date(session.createdAt);
|
|
582
|
+
return sessionCreated >= prevStart && sessionCreated <= prevEnd;
|
|
583
|
+
}).length;
|
|
584
|
+
}
|
|
585
|
+
else if (type === "organizations") {
|
|
586
|
+
return organizations.filter((org) => {
|
|
587
|
+
const createdAt = new Date(org.createdAt);
|
|
588
|
+
return createdAt >= prevStart && createdAt <= prevEnd;
|
|
589
|
+
}).length;
|
|
590
|
+
}
|
|
591
|
+
else if (type === "teams") {
|
|
592
|
+
return teams.filter((team) => {
|
|
593
|
+
const createdAt = new Date(team.createdAt);
|
|
594
|
+
return createdAt >= prevStart && createdAt <= prevEnd;
|
|
595
|
+
}).length;
|
|
596
|
+
}
|
|
597
|
+
return 0;
|
|
598
|
+
};
|
|
599
|
+
if (period === "1D") {
|
|
600
|
+
const prevStart = new Date(startDate.getTime() - 24 * 60 * 60 * 1000);
|
|
601
|
+
previousTotal = getPreviousPeriodTotal(prevStart, startDate);
|
|
602
|
+
}
|
|
603
|
+
else if (period === "1W") {
|
|
604
|
+
const prevStart = new Date(startDate.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
605
|
+
previousTotal = getPreviousPeriodTotal(prevStart, startDate);
|
|
606
|
+
}
|
|
519
607
|
return {
|
|
520
608
|
data,
|
|
521
609
|
labels: buckets.map((b) => b.label),
|
|
522
610
|
total,
|
|
611
|
+
previousTotal,
|
|
523
612
|
average: Math.round(average),
|
|
524
613
|
percentageChange: Math.round(percentageChange * 10) / 10,
|
|
525
614
|
period,
|
|
526
615
|
type,
|
|
616
|
+
...(uniqueUsers ? { uniqueUsers } : {}),
|
|
527
617
|
};
|
|
528
618
|
}
|
|
529
619
|
catch (_error) {
|
|
@@ -531,6 +621,7 @@ async function getRealAnalytics(adapter, options) {
|
|
|
531
621
|
data: [],
|
|
532
622
|
labels: [],
|
|
533
623
|
total: 0,
|
|
624
|
+
previousTotal: 0,
|
|
534
625
|
average: 0,
|
|
535
626
|
percentageChange: 0,
|
|
536
627
|
period: options.period,
|
|
@@ -538,4 +629,3 @@ async function getRealAnalytics(adapter, options) {
|
|
|
538
629
|
};
|
|
539
630
|
}
|
|
540
631
|
}
|
|
541
|
-
//# sourceMappingURL=data.js.map
|
package/dist/geo-service.d.ts
CHANGED
|
@@ -26,4 +26,3 @@ export declare function initializeGeoService(): Promise<void>;
|
|
|
26
26
|
*/
|
|
27
27
|
export declare function resolveIPLocationAsync(ipAddress: string, ipConfig?: IpAddressProviderConfig | null): Promise<LocationData | null>;
|
|
28
28
|
export declare function resolveIPLocation(ipAddress: string): LocationData | null;
|
|
29
|
-
//# sourceMappingURL=geo-service.d.ts.map
|
package/dist/geo-service.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -7,4 +7,3 @@ export { defineStudioConfig, STUDIO_TOOL_IDS } from "./types/handler.js";
|
|
|
7
7
|
export { injectLastSeenAtHooks } from "./utils/hook-injector.js";
|
|
8
8
|
export { checkEventIngestionHealth, emitEvent, getEventIngestionProvider, getEventQueueSize, initializeEventIngestion, isEventIngestionInitialized, shutdownEventIngestion, } from "./utils/event-ingestion.js";
|
|
9
9
|
import "./utils/server-init.js";
|
|
10
|
-
//# sourceMappingURL=index.d.ts.map
|