Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@mertdogar/better-auth-do-sqlite

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mertdogar/better-auth-do-sqlite - npm Package Compare versions

Comparing version
0.0.20
to
0.0.22
+265
-43
dist/index.cjs

@@ -8,7 +8,153 @@ 'use strict';

var kyselyPluginSerialize = require('kysely-plugin-serialize');
var factory = require('hono/factory');
var hono = require('hono');
var cors = require('hono/cors');
var zod = require('zod');
// lib/auth-do.ts
// lib/logger.ts
var LogLevelSeverity = {
debug: 0,
info: 1,
success: 2,
warn: 3,
error: 4
};
var colors = {
reset: "\x1B[0m",
bright: "\x1B[1m",
dim: "\x1B[2m",
red: "\x1B[31m",
green: "\x1B[32m",
yellow: "\x1B[33m",
blue: "\x1B[34m",
cyan: "\x1B[36m",
gray: "\x1B[90m"
};
var levelColors = {
debug: colors.gray,
info: colors.blue,
success: colors.green,
warn: colors.yellow,
error: colors.red
};
var levelEmojis = {
debug: "\u{1F50D}",
info: "\u2139\uFE0F ",
success: "\u2705",
warn: "\u26A0\uFE0F ",
error: "\u274C"
};
var Logger = class _Logger {
name;
format;
level;
severity;
enabled;
constructor({ name, format = "text", level = "info", enabled = true }) {
this.name = name;
this.format = format;
this.level = level;
this.severity = LogLevelSeverity[level];
this.enabled = enabled;
}
shouldLog(level) {
return this.enabled && LogLevelSeverity[level] >= this.severity;
}
formatTimestamp() {
return (/* @__PURE__ */ new Date()).toISOString();
}
formatError(error) {
if (error instanceof Error) {
return {
name: error.name,
message: error.message,
stack: error.stack
};
}
return { message: String(error) };
}
log(level, message, data) {
if (!this.shouldLog(level)) return;
if (this.format === "json") {
const log = {
timestamp: this.formatTimestamp(),
name: this.name,
level,
message,
data
};
console.log(JSON.stringify(log));
} else if (this.format === "pretty") {
const color = levelColors[level];
const emoji = levelEmojis[level];
const timestamp = colors.gray + this.formatTimestamp() + colors.reset;
const nameStr = colors.cyan + `[${this.name}]` + colors.reset;
const levelStr = color + colors.bright + level.toUpperCase() + colors.reset;
const dataStr = data ? colors.dim + ` ${JSON.stringify(data)}` + colors.reset : "";
console.log(`${timestamp} ${emoji} ${nameStr} ${levelStr} ${message}${dataStr}`);
} else {
const timestamp = this.formatTimestamp();
const dataStr = data ? ` ${JSON.stringify(data)}` : "";
console.log(`[${timestamp}] [${this.name}] ${level.toUpperCase()}: ${message}${dataStr}`);
}
}
debug(message, data) {
this.log("debug", message, data);
}
info(message, data) {
this.log("info", message, data);
}
success(message, data) {
this.log("success", message, data);
}
warn(message, data) {
this.log("warn", message, data);
}
error(message, error, data) {
const logData = { ...data };
if (error) {
if (this.format === "json") {
const errorLog = {
timestamp: this.formatTimestamp(),
name: this.name,
level: "error",
message,
data: logData,
error: this.formatError(error)
};
if (this.shouldLog("error")) {
console.error(JSON.stringify(errorLog));
}
return;
} else {
if (error instanceof Error) {
logData.error = error.message;
logData.stack = error.stack;
} else {
logData.error = String(error);
}
}
}
this.log("error", message, logData);
}
child(name) {
return new _Logger({
name: `${this.name}:${name}`,
format: this.format,
level: this.level,
enabled: this.enabled
});
}
setLevel(level) {
this.level = level;
this.severity = LogLevelSeverity[level];
}
setEnabled(enabled) {
this.enabled = enabled;
}
};
var createLogger = (options) => new Logger(options);
// lib/libsql-http-server.ts

@@ -23,4 +169,12 @@ var LibSQLHttpServer = class {

// Track protocol version for current request
constructor(sql) {
logger;
constructor(sql, loggerOptions) {
this.sql = sql;
this.logger = new Logger({
name: "LibSQLHttpServer",
format: loggerOptions?.format || "text",
level: loggerOptions?.level || "info",
enabled: loggerOptions?.enabled ?? true,
...loggerOptions
});
}

@@ -108,3 +262,3 @@ /**

} catch (error) {
console.error("LibSQL HTTP Server error:", error);
this.logger.error("LibSQL HTTP Server error", error);
return new Response(JSON.stringify({ error: error.message || "Internal server error" }), {

@@ -165,4 +319,4 @@ status: 500,

} catch (parseError) {
console.error("[LibSQL HTTP] Failed to parse request body:", parseError.message);
return new Response(JSON.stringify({ error: "Invalid JSON in request body" }), {
this.logger.error("Failed to parse request body", parseError);
return new Response(JSON.stringify({ error: "Invalid JSON request body" }), {
status: 400,

@@ -209,6 +363,8 @@ headers: { "Content-Type": "application/json" }

} catch (error) {
console.error(`[LibSQL HTTP] Request ${i + 1} failed:`, error.message);
this.logger.error(`Request ${i + 1} failed`, error);
results.push({
type: "error",
error: { message: error.message || "Request failed" }
error: {
message: error.message || "Query execution failed"
}
});

@@ -228,10 +384,8 @@ }

} catch (error) {
console.error("[LibSQL HTTP] V2 Pipeline error:", error);
console.error("[LibSQL HTTP] Error details:", {
this.logger.error("V2 Pipeline error", error, {
message: error.message,
stack: error.stack,
name: error.name
stack: error.stack
});
return new Response(JSON.stringify({ error: error.message || "Pipeline execution failed" }), {
status: 400,
status: 500,
headers: { "Content-Type": "application/json" }

@@ -654,4 +808,12 @@ });

libsqlServer;
logger;
constructor(ctx, env) {
super(ctx, env);
this.logger = new Logger({
name: "AuthDO",
format: env.loggerOptions?.format || "text",
level: env.loggerOptions?.level || "info",
enabled: env.loggerOptions?.enabled ?? true,
...env.loggerOptions
});
this.db = new kysely.Kysely({

@@ -664,5 +826,8 @@ dialect: new DODialect({ ctx }),

this.ctx.blockConcurrencyWhile(async () => {
this.logger.debug("Initializing Better Auth tables");
await this.initBetterAuthTables();
this.logger.success("Better Auth tables initialized");
});
this.auth = betterAuth.betterAuth({
logger: env.logger ? env.logger : void 0,
database: {

@@ -696,3 +861,3 @@ db: this.db,

after: plugins.createAuthMiddleware(async (ctx2) => {
if (ctx2.path.includes("/sign-up")) {
if (ctx2.path.includes("/sign-up") || ctx2.path.includes("/callback/:id")) {
const newSession = ctx2.context.newSession;

@@ -710,3 +875,3 @@ if (newSession) {

if (!apiKeyResponse) {
console.error("Failed to create API key:", apiKeyResponse);
this.logger.error("Failed to create API key", null, { response: apiKeyResponse });
return;

@@ -725,3 +890,3 @@ }

});
this.libsqlServer = new LibSQLHttpServer(this.ctx.storage.sql);
this.libsqlServer = new LibSQLHttpServer(this.ctx.storage.sql, env.loggerOptions);
}

@@ -804,2 +969,28 @@ getDB() {

sqlUrl.pathname = sqlPath;
if (!this.env.libsqlToken) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "Content-Type": "application/json" }
});
}
const authorizationHeader = request.headers.get("Authorization");
if (!authorizationHeader || !authorizationHeader.startsWith("Bearer ")) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "Content-Type": "application/json" }
});
}
const token = authorizationHeader.split(" ")[1];
if (!token) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "Content-Type": "application/json" }
});
}
if (token !== this.env.libsqlToken) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "Content-Type": "application/json" }
});
}
return await this.libsqlServer.handleRequest(new Request(sqlUrl, request));

@@ -810,3 +1001,3 @@ }

} catch (error) {
console.error("Auth error:", error);
this.logger.error("Authentication error occurred", error);
return new Response(JSON.stringify({ error: "Authentication error" }), {

@@ -860,3 +1051,8 @@ status: 500,

}
var SqlServerRouterEnvSchema = zod.z.object({
APP_DO_ID: zod.z.string().optional().default("app"),
prefixRegex: zod.z.string().optional().default(/^\/api\/sqld/.source)
});
function sqlServerRouter() {
const factory$1 = factory.createFactory();
const router = new hono.Hono();

@@ -893,5 +1089,5 @@ router.use(

);
router.get("/v2", async (c) => {
console.log("v2", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const v2Handler = factory$1.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);

@@ -902,5 +1098,5 @@ url.pathname = "/sql/v2";

});
router.get("/v3", async (c) => {
console.log("v3", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const v3Handler = factory$1.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);

@@ -911,5 +1107,5 @@ url.pathname = "/sql/v3";

});
router.get("/v3-protobuf", async (c) => {
console.log("v3-protobuf", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const v3ProtobufHandler = factory$1.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);

@@ -920,43 +1116,67 @@ url.pathname = "/sql/v3-protobuf";

});
router.all("/v2/*", async (c) => {
console.log("v2/*", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const v2AllHandler = factory$1.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);
url.pathname = url.pathname.replace(c.env.prefixRegex || /^\/api\/sqld/, "/sql");
url.pathname = url.pathname.replace(
env.prefixRegex ? new RegExp(env.prefixRegex) : /^\/api\/sqld/,
"/sql"
);
const modifiedRequest = new Request(url, c.req.raw);
return appDO.fetch(modifiedRequest);
});
router.all("/v3/*", async (c) => {
console.log("v3/*", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const v3AllHandler = factory$1.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);
url.pathname = url.pathname.replace(c.env.prefixRegex || /^\/api\/sqld/, "/sql");
console.log("modified url", url.pathname);
url.pathname = url.pathname.replace(
env.prefixRegex ? new RegExp(env.prefixRegex) : /^\/api\/sqld/,
"/sql"
);
const modifiedRequest = new Request(url, c.req.raw);
return appDO.fetch(modifiedRequest);
});
router.all("/sql/*", async (c) => {
console.log("sql/*", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const sqlAllHandler = factory$1.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);
url.pathname = url.pathname.replace(c.env.prefixRegex || /^\/api\/sqld/, "");
url.pathname = url.pathname.replace(
env.prefixRegex ? new RegExp(env.prefixRegex) : /^\/api\/sqld/,
""
);
const modifiedRequest = new Request(url, c.req.raw);
return appDO.fetch(modifiedRequest);
});
router.all("/sql", async (c) => {
console.log("sql", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const sqlHandler = factory$1.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);
url.pathname = url.pathname.replace(c.env.prefixRegex || /^\/api\/sqld/, "");
url.pathname = url.pathname.replace(
env.prefixRegex ? new RegExp(env.prefixRegex) : /^\/api\/sqld/,
""
);
const modifiedRequest = new Request(url, c.req.raw);
return appDO.fetch(modifiedRequest);
});
router.get("/v2", ...v2Handler);
router.get("/v3", ...v3Handler);
router.get("/v3-protobuf", ...v3ProtobufHandler);
router.all("/v2/*", ...v2AllHandler);
router.all("/v3/*", ...v3AllHandler);
router.all("/sql/*", ...sqlAllHandler);
router.all("/sql", ...sqlHandler);
return router;
}
var BetterAuthRouterEnvSchema = zod.z.object({
APP_DO_ID: zod.z.string().optional().default("app")
});
function betterAuthRouter() {
const factory$1 = factory.createFactory();
const router = new hono.Hono();
router.all("/*", (c) => {
const authDO = getDO(c, c.env.APP_DO_ID || "app");
const handler = factory$1.createHandlers((c) => {
const env = BetterAuthRouterEnvSchema.parse(c.env);
const authDO = getDO(c, env.APP_DO_ID);
return authDO.fetch(c.req.raw);
});
router.all("/*", ...handler);
return router;

@@ -967,4 +1187,6 @@ }

exports.LibSQLHttpServer = LibSQLHttpServer;
exports.Logger = Logger;
exports.authMiddleware = authMiddleware;
exports.betterAuthRouter = betterAuthRouter;
exports.createLogger = createLogger;
exports.getBearerToken = getBearerToken;

@@ -971,0 +1193,0 @@ exports.getDO = getDO;

@@ -6,7 +6,153 @@ import { DurableObject } from 'cloudflare:workers';

import { SerializePlugin } from 'kysely-plugin-serialize';
import { createFactory } from 'hono/factory';
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { z } from 'zod';
// lib/auth-do.ts
// lib/logger.ts
var LogLevelSeverity = {
debug: 0,
info: 1,
success: 2,
warn: 3,
error: 4
};
var colors = {
reset: "\x1B[0m",
bright: "\x1B[1m",
dim: "\x1B[2m",
red: "\x1B[31m",
green: "\x1B[32m",
yellow: "\x1B[33m",
blue: "\x1B[34m",
cyan: "\x1B[36m",
gray: "\x1B[90m"
};
var levelColors = {
debug: colors.gray,
info: colors.blue,
success: colors.green,
warn: colors.yellow,
error: colors.red
};
var levelEmojis = {
debug: "\u{1F50D}",
info: "\u2139\uFE0F ",
success: "\u2705",
warn: "\u26A0\uFE0F ",
error: "\u274C"
};
var Logger = class _Logger {
name;
format;
level;
severity;
enabled;
constructor({ name, format = "text", level = "info", enabled = true }) {
this.name = name;
this.format = format;
this.level = level;
this.severity = LogLevelSeverity[level];
this.enabled = enabled;
}
shouldLog(level) {
return this.enabled && LogLevelSeverity[level] >= this.severity;
}
formatTimestamp() {
return (/* @__PURE__ */ new Date()).toISOString();
}
formatError(error) {
if (error instanceof Error) {
return {
name: error.name,
message: error.message,
stack: error.stack
};
}
return { message: String(error) };
}
log(level, message, data) {
if (!this.shouldLog(level)) return;
if (this.format === "json") {
const log = {
timestamp: this.formatTimestamp(),
name: this.name,
level,
message,
data
};
console.log(JSON.stringify(log));
} else if (this.format === "pretty") {
const color = levelColors[level];
const emoji = levelEmojis[level];
const timestamp = colors.gray + this.formatTimestamp() + colors.reset;
const nameStr = colors.cyan + `[${this.name}]` + colors.reset;
const levelStr = color + colors.bright + level.toUpperCase() + colors.reset;
const dataStr = data ? colors.dim + ` ${JSON.stringify(data)}` + colors.reset : "";
console.log(`${timestamp} ${emoji} ${nameStr} ${levelStr} ${message}${dataStr}`);
} else {
const timestamp = this.formatTimestamp();
const dataStr = data ? ` ${JSON.stringify(data)}` : "";
console.log(`[${timestamp}] [${this.name}] ${level.toUpperCase()}: ${message}${dataStr}`);
}
}
debug(message, data) {
this.log("debug", message, data);
}
info(message, data) {
this.log("info", message, data);
}
success(message, data) {
this.log("success", message, data);
}
warn(message, data) {
this.log("warn", message, data);
}
error(message, error, data) {
const logData = { ...data };
if (error) {
if (this.format === "json") {
const errorLog = {
timestamp: this.formatTimestamp(),
name: this.name,
level: "error",
message,
data: logData,
error: this.formatError(error)
};
if (this.shouldLog("error")) {
console.error(JSON.stringify(errorLog));
}
return;
} else {
if (error instanceof Error) {
logData.error = error.message;
logData.stack = error.stack;
} else {
logData.error = String(error);
}
}
}
this.log("error", message, logData);
}
child(name) {
return new _Logger({
name: `${this.name}:${name}`,
format: this.format,
level: this.level,
enabled: this.enabled
});
}
setLevel(level) {
this.level = level;
this.severity = LogLevelSeverity[level];
}
setEnabled(enabled) {
this.enabled = enabled;
}
};
var createLogger = (options) => new Logger(options);
// lib/libsql-http-server.ts

@@ -21,4 +167,12 @@ var LibSQLHttpServer = class {

// Track protocol version for current request
constructor(sql) {
logger;
constructor(sql, loggerOptions) {
this.sql = sql;
this.logger = new Logger({
name: "LibSQLHttpServer",
format: loggerOptions?.format || "text",
level: loggerOptions?.level || "info",
enabled: loggerOptions?.enabled ?? true,
...loggerOptions
});
}

@@ -106,3 +260,3 @@ /**

} catch (error) {
console.error("LibSQL HTTP Server error:", error);
this.logger.error("LibSQL HTTP Server error", error);
return new Response(JSON.stringify({ error: error.message || "Internal server error" }), {

@@ -163,4 +317,4 @@ status: 500,

} catch (parseError) {
console.error("[LibSQL HTTP] Failed to parse request body:", parseError.message);
return new Response(JSON.stringify({ error: "Invalid JSON in request body" }), {
this.logger.error("Failed to parse request body", parseError);
return new Response(JSON.stringify({ error: "Invalid JSON request body" }), {
status: 400,

@@ -207,6 +361,8 @@ headers: { "Content-Type": "application/json" }

} catch (error) {
console.error(`[LibSQL HTTP] Request ${i + 1} failed:`, error.message);
this.logger.error(`Request ${i + 1} failed`, error);
results.push({
type: "error",
error: { message: error.message || "Request failed" }
error: {
message: error.message || "Query execution failed"
}
});

@@ -226,10 +382,8 @@ }

} catch (error) {
console.error("[LibSQL HTTP] V2 Pipeline error:", error);
console.error("[LibSQL HTTP] Error details:", {
this.logger.error("V2 Pipeline error", error, {
message: error.message,
stack: error.stack,
name: error.name
stack: error.stack
});
return new Response(JSON.stringify({ error: error.message || "Pipeline execution failed" }), {
status: 400,
status: 500,
headers: { "Content-Type": "application/json" }

@@ -652,4 +806,12 @@ });

libsqlServer;
logger;
constructor(ctx, env) {
super(ctx, env);
this.logger = new Logger({
name: "AuthDO",
format: env.loggerOptions?.format || "text",
level: env.loggerOptions?.level || "info",
enabled: env.loggerOptions?.enabled ?? true,
...env.loggerOptions
});
this.db = new Kysely({

@@ -662,5 +824,8 @@ dialect: new DODialect({ ctx }),

this.ctx.blockConcurrencyWhile(async () => {
this.logger.debug("Initializing Better Auth tables");
await this.initBetterAuthTables();
this.logger.success("Better Auth tables initialized");
});
this.auth = betterAuth({
logger: env.logger ? env.logger : void 0,
database: {

@@ -694,3 +859,3 @@ db: this.db,

after: createAuthMiddleware(async (ctx2) => {
if (ctx2.path.includes("/sign-up")) {
if (ctx2.path.includes("/sign-up") || ctx2.path.includes("/callback/:id")) {
const newSession = ctx2.context.newSession;

@@ -708,3 +873,3 @@ if (newSession) {

if (!apiKeyResponse) {
console.error("Failed to create API key:", apiKeyResponse);
this.logger.error("Failed to create API key", null, { response: apiKeyResponse });
return;

@@ -723,3 +888,3 @@ }

});
this.libsqlServer = new LibSQLHttpServer(this.ctx.storage.sql);
this.libsqlServer = new LibSQLHttpServer(this.ctx.storage.sql, env.loggerOptions);
}

@@ -802,2 +967,28 @@ getDB() {

sqlUrl.pathname = sqlPath;
if (!this.env.libsqlToken) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "Content-Type": "application/json" }
});
}
const authorizationHeader = request.headers.get("Authorization");
if (!authorizationHeader || !authorizationHeader.startsWith("Bearer ")) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "Content-Type": "application/json" }
});
}
const token = authorizationHeader.split(" ")[1];
if (!token) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "Content-Type": "application/json" }
});
}
if (token !== this.env.libsqlToken) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "Content-Type": "application/json" }
});
}
return await this.libsqlServer.handleRequest(new Request(sqlUrl, request));

@@ -808,3 +999,3 @@ }

} catch (error) {
console.error("Auth error:", error);
this.logger.error("Authentication error occurred", error);
return new Response(JSON.stringify({ error: "Authentication error" }), {

@@ -858,3 +1049,8 @@ status: 500,

}
var SqlServerRouterEnvSchema = z.object({
APP_DO_ID: z.string().optional().default("app"),
prefixRegex: z.string().optional().default(/^\/api\/sqld/.source)
});
function sqlServerRouter() {
const factory = createFactory();
const router = new Hono();

@@ -891,5 +1087,5 @@ router.use(

);
router.get("/v2", async (c) => {
console.log("v2", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const v2Handler = factory.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);

@@ -900,5 +1096,5 @@ url.pathname = "/sql/v2";

});
router.get("/v3", async (c) => {
console.log("v3", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const v3Handler = factory.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);

@@ -909,5 +1105,5 @@ url.pathname = "/sql/v3";

});
router.get("/v3-protobuf", async (c) => {
console.log("v3-protobuf", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const v3ProtobufHandler = factory.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);

@@ -918,46 +1114,70 @@ url.pathname = "/sql/v3-protobuf";

});
router.all("/v2/*", async (c) => {
console.log("v2/*", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const v2AllHandler = factory.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);
url.pathname = url.pathname.replace(c.env.prefixRegex || /^\/api\/sqld/, "/sql");
url.pathname = url.pathname.replace(
env.prefixRegex ? new RegExp(env.prefixRegex) : /^\/api\/sqld/,
"/sql"
);
const modifiedRequest = new Request(url, c.req.raw);
return appDO.fetch(modifiedRequest);
});
router.all("/v3/*", async (c) => {
console.log("v3/*", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const v3AllHandler = factory.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);
url.pathname = url.pathname.replace(c.env.prefixRegex || /^\/api\/sqld/, "/sql");
console.log("modified url", url.pathname);
url.pathname = url.pathname.replace(
env.prefixRegex ? new RegExp(env.prefixRegex) : /^\/api\/sqld/,
"/sql"
);
const modifiedRequest = new Request(url, c.req.raw);
return appDO.fetch(modifiedRequest);
});
router.all("/sql/*", async (c) => {
console.log("sql/*", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const sqlAllHandler = factory.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);
url.pathname = url.pathname.replace(c.env.prefixRegex || /^\/api\/sqld/, "");
url.pathname = url.pathname.replace(
env.prefixRegex ? new RegExp(env.prefixRegex) : /^\/api\/sqld/,
""
);
const modifiedRequest = new Request(url, c.req.raw);
return appDO.fetch(modifiedRequest);
});
router.all("/sql", async (c) => {
console.log("sql", c.req.url);
const appDO = getDO(c, c.env.APP_DO_ID || "app");
const sqlHandler = factory.createHandlers(async (c) => {
const env = SqlServerRouterEnvSchema.parse(c.env);
const appDO = getDO(c, env.APP_DO_ID);
const url = new URL(c.req.url);
url.pathname = url.pathname.replace(c.env.prefixRegex || /^\/api\/sqld/, "");
url.pathname = url.pathname.replace(
env.prefixRegex ? new RegExp(env.prefixRegex) : /^\/api\/sqld/,
""
);
const modifiedRequest = new Request(url, c.req.raw);
return appDO.fetch(modifiedRequest);
});
router.get("/v2", ...v2Handler);
router.get("/v3", ...v3Handler);
router.get("/v3-protobuf", ...v3ProtobufHandler);
router.all("/v2/*", ...v2AllHandler);
router.all("/v3/*", ...v3AllHandler);
router.all("/sql/*", ...sqlAllHandler);
router.all("/sql", ...sqlHandler);
return router;
}
var BetterAuthRouterEnvSchema = z.object({
APP_DO_ID: z.string().optional().default("app")
});
function betterAuthRouter() {
const factory = createFactory();
const router = new Hono();
router.all("/*", (c) => {
const authDO = getDO(c, c.env.APP_DO_ID || "app");
const handler = factory.createHandlers((c) => {
const env = BetterAuthRouterEnvSchema.parse(c.env);
const authDO = getDO(c, env.APP_DO_ID);
return authDO.fetch(c.req.raw);
});
router.all("/*", ...handler);
return router;
}
export { AuthDO, LibSQLHttpServer, authMiddleware, betterAuthRouter, getBearerToken, getDO, requireAuth, sqlServerRouter };
export { AuthDO, LibSQLHttpServer, Logger, authMiddleware, betterAuthRouter, createLogger, getBearerToken, getDO, requireAuth, sqlServerRouter };
+19
-26
{
"name": "@mertdogar/better-auth-do-sqlite",
"libName": "better-auth-do-sqlite",
"version": "0.0.20",
"version": "0.0.22",
"description": "Complete authentication and database solution for Cloudflare Durable Objects with Better Auth and libSQL HTTP protocol support",

@@ -20,9 +20,5 @@ "main": "./dist/index.cjs",

"format": "eslint . --fix",
"build-types": "node --import tsx ./tools/fix-dts.mts",
"build-common": "tsup lib/index.ts --format cjs,esm --clean --treeshake --dts",
"build-all": "tsup lib/index.ts --format cjs,esm --treeshake --dts --onSuccess \"npm run build-types\"",
"build": "npm run build-common -- --onSuccess \"npm run build-types\"",
"dev": "npm run build-common -- --sourcemap --watch --onSuccess \"npm run build-types\"",
"dev-all": "npm run build-all -- --watch",
"prepublishOnly": "npm run build-all",
"build": "tsup lib/index.ts --format cjs,esm --clean --treeshake --dts",
"dev": "tsup lib/index.ts --format cjs,esm --clean --treeshake --dts --sourcemap --watch",
"prepublishOnly": "npm run build",
"update-jsr-version": "node --import tsx ./tools/update-jsr-version.mts",

@@ -32,5 +28,3 @@ "publish-package": "changeset publish",

"check-jsr": "npx jsr publish --allow-dirty --dry-run",
"change": "changeset",
"test": "vitest",
"test-coverage": "vitest --coverage"
"change": "changeset"
},

@@ -71,16 +65,15 @@ "repository": {

"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.25.1",
"@eslint/js": "^9.38.0",
"@libsql/client": "^0.15.15",
"@testing-library/dom": "^10.4.0",
"@types/node": "^22.15.3",
"@types/node": "^22.18.13",
"@types/tx2": "^1.0.3",
"@typescript-eslint/eslint-plugin": "^8.31.1",
"@typescript-eslint/parser": "^8.31.1",
"@typescript-eslint/utils": "^8.31.1",
"@vitest/coverage-v8": "^3.1.2",
"eslint": "^9.25.1",
"@typescript-eslint/eslint-plugin": "^8.46.2",
"@typescript-eslint/parser": "^8.46.2",
"@typescript-eslint/utils": "^8.46.2",
"eslint": "^9.38.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-prettier": "^5.2.3",
"globals": "^15.15.0",
"jsdom": "^26.1.0",
"globals": "^16.4.0",
"jsdom": "^27.0.1",
"prettier": "^3.5.0",

@@ -91,4 +84,3 @@ "tslib": "^2.8.1",

"typescript": "^5.8.3",
"typescript-eslint": "^8.46.0",
"vitest": "^3.1.2"
"typescript-eslint": "^8.46.2"
},

@@ -106,8 +98,9 @@ "files": [

"dependencies": {
"@cloudflare/workers-types": "4.20251004.0",
"better-auth": "1.3.26",
"hono": "4.9.10",
"@cloudflare/workers-types": "4.20251014.0",
"better-auth": "1.3.34",
"hono": "4.10.3",
"kysely": "0.28.8",
"kysely-plugin-serialize": "0.8.2"
"kysely-plugin-serialize": "0.8.2",
"zod": "^3.24.2"
}
}
+68
-20

@@ -72,2 +72,3 @@ # @mertdogar/better-auth-do-sqlite

APP_DO: DurableObjectNamespace
APP_DO_ID?: string // Optional: defaults to 'app'
}

@@ -92,6 +93,6 @@ ```

// Apply auth middleware globally
app.use('*', authMiddleware('app'))
app.use('*', authMiddleware())
// Mount Better Auth routes
app.route('/api/auth', betterAuthRouter('app'))
app.route('/api/auth', betterAuthRouter())

@@ -137,14 +138,26 @@ // Protected route example

### `authMiddleware(bindingPrefix: string)`
### `authMiddleware()`
Middleware that attaches authentication context to requests.
Hono middleware that injects session information into the context.
**Parameters:**
```typescript
app.use('*', authMiddleware())
```
- `bindingPrefix`: The prefix of your Durable Object binding (e.g., `'app'` for `APP_DO`)
The middleware reads `APP_DO_ID` from `c.env` (defaults to `'app'` if not set).
### `betterAuthRouter<E>()`
Hono router that handles all Better Auth endpoints. Generic type parameter allows type-safe integration with your app's environment.
```typescript
app.use('*', authMiddleware('app'))
// Basic usage
app.route('/api/auth', betterAuthRouter())
// With explicit types
app.route('/api/auth', betterAuthRouter<{ Bindings: Env }>())
```
The router reads `APP_DO_ID` from `c.env` (defaults to `'app'` if not set).
### `betterAuthRouter(bindingPrefix: string)`

@@ -170,3 +183,3 @@

### `getDO(context: HonoContext, bindingPrefix: string)`
### `getDO(context: HonoContext, doId: string)`

@@ -178,3 +191,3 @@ Helper function to get the Durable Object instance.

- `context`: Hono context object
- `bindingPrefix`: The prefix of your Durable Object binding
- `doId`: The Durable Object instance ID/name

@@ -185,2 +198,16 @@ ```typescript

### `sqlServerRouter<E>()`
Hono router that proxies libSQL HTTP protocol requests to the Durable Object. Generic type parameter allows type-safe integration.
```typescript
// Basic usage
app.route('/api/sqld', sqlServerRouter())
// With explicit types
app.route('/api/sqld', sqlServerRouter<{ Bindings: Env }>())
```
The router reads `APP_DO_ID` and optional `prefixRegex` from `c.env`.
## Configuration

@@ -202,7 +229,15 @@

The library expects a Durable Object binding with the pattern `{PREFIX}_DO`. For example:
The library expects a Durable Object binding named `APP_DO` in your `wrangler.jsonc`. The middleware and routers read `APP_DO_ID` from `c.env` to determine which Durable Object instance to use:
- If you use `authMiddleware('app')`, you need an `APP_DO` binding
- If you use `authMiddleware('auth')`, you need an `AUTH_DO` binding
```typescript
// Default behavior: uses instance ID 'app'
app.use('*', authMiddleware())
// Custom instance: set APP_DO_ID dynamically
app.use('/tenant/:id/*', async (c, next) => {
c.env.APP_DO_ID = c.req.param('id')
return authMiddleware()(c, next)
})
```
## Advanced Usage

@@ -232,3 +267,3 @@

You can use multiple Durable Object instances for different authentication domains:
You can use multiple Durable Object instances for different authentication domains by setting different `APP_DO_ID` values:

@@ -242,11 +277,24 @@ ```typescript

const app = new Hono()
interface Env {
JWT_SECRET: string
USER_AUTH_DO: DurableObjectNamespace
ADMIN_AUTH_DO: DurableObjectNamespace
APP_DO: DurableObjectNamespace
}
// User routes
app.use('/user/*', authMiddleware('userAuth'))
app.route('/user/auth', betterAuthRouter('userAuth'))
const app = new Hono<{ Bindings: Env }>()
// Admin routes
app.use('/admin/*', authMiddleware('adminAuth'))
app.route('/admin/auth', betterAuthRouter('adminAuth'))
// User routes - set APP_DO_ID to 'userAuth'
app.use('/user/*', async (c, next) => {
c.env.APP_DO_ID = 'userAuth'
return authMiddleware()(c, next)
})
app.route('/user/auth', betterAuthRouter())
// Admin routes - set APP_DO_ID to 'adminAuth'
app.use('/admin/*', async (c, next) => {
c.env.APP_DO_ID = 'adminAuth'
return authMiddleware()(c, next)
})
app.route('/admin/auth', betterAuthRouter())
```

@@ -253,0 +301,0 @@

# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.0.2] - 2025-10-06
### Fixed
- Fixed package entry points in `package.json`
- Corrected `types` path from `dist/lib/index.d.ts` to `dist/index.d.ts`
- Removed non-existent `browser` (UMD) export
- Updated `main` to point to CommonJS build (`dist/index.cjs`)
- Simplified `exports` configuration for better compatibility with Vite and other bundlers
## [0.0.1] - 2025-10-06
### Added
- Initial release
- Better Auth adapter for Cloudflare Durable Objects with SQLite storage
- `@Authenticatable()` decorator for easy integration
- `AuthenticatableDurableObject` base class
- Full Better Auth support with automatic schema initialization
- libSQL HTTP protocol server (v1, v2, v3)
- Direct SQLite database access via HTTP
- Compatible with official `@libsql/client`
- Email & password authentication
- Session management with configurable expiration
- RPC methods for user management
- Hono middleware for route protection
- Comprehensive TypeScript type definitions
- Debug logging support
- Data type transformations (JS ↔ SQLite)
- Complete documentation and examples
[unreleased]: https://github.com/mertdogar/better-auth-do-sqlite/compare/v0.0.2...HEAD
[0.0.2]: https://github.com/mertdogar/better-auth-do-sqlite/compare/v0.0.1...v0.0.2
[0.0.1]: https://github.com/mertdogar/better-auth-do-sqlite/releases/tag/v0.0.1

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display