init test

This commit is contained in:
2026-01-24 00:43:25 +08:00
parent 51aed643a0
commit 5657bffd39
22 changed files with 1182 additions and 18 deletions

7
.claude/settings.json Normal file
View File

@@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"Bash(bun run:*)"
]
}
}

View File

@@ -1,4 +1,5 @@
# docker compose exec backend ./generate_admin_key.sh
CONVEX_SELF_HOSTED_ADMIN_KEY=
CONVEX_SELF_HOSTED_URL=http://localhost:3210
# CONVEX_SELF_HOSTED_URL=https://convex.kevisual.cn
# CONVEX_SELF_HOSTED_URL=https://convex.kevisual.cn
CONVEX_SITE_URL=https://api-convex.kevisual.cn

View File

@@ -9,6 +9,9 @@
*/
import type * as abcv from "../abcv.js";
import type * as actions_jwt from "../actions/jwt.js";
import type * as actions_redis from "../actions/redis.js";
import type * as http from "../http.js";
import type {
ApiFromModules,
@@ -18,6 +21,9 @@ import type {
declare const fullApi: ApiFromModules<{
abcv: typeof abcv;
"actions/jwt": typeof actions_jwt;
"actions/redis": typeof actions_redis;
http: typeof http;
}>;
/**

View File

@@ -1,12 +1,14 @@
import { query, mutation, action } from "./_generated/server";
import { Kevisual } from '@kevisual/ai/browser'
import { v } from "convex/values";
import { } from "convex/server";
export const get = query({
args: {},
handler: async (ctx) => {
const auth = await ctx.auth.getUserIdentity();
console.log("Query abcv.get called", auth);
console.log("Query abcv.get called, auth:", auth);
if (auth) {
console.log("Authenticated user ID:", auth.subject);
}
return await ctx.db.query("abcv").collect();
},
});

83
convex/actions/jwt.ts Normal file
View File

@@ -0,0 +1,83 @@
'use node';
import * as jose from "jose";
import type { GenericId } from "convex/values";
// JWT 验证配置
const JWT_CONFIG = {
// jwksUri: "https://kevisual.cn/root/convex/jwks.json",
jwksUri: "http://convex.kevisual.cn:3211/root/convex/jwks.json",
issuer: "https://kevisual.cn",
audience: "test-convex-app",
algorithms: ["RS256"],
};
// 创建 JWKS 缓存
let jwksCache: jose.JWTVerifyGetKey | null = null;
function getJWKS() {
if (!jwksCache) {
jwksCache = jose.createRemoteJWKSet(new URL(JWT_CONFIG.jwksUri));
}
return jwksCache;
}
export const createJwt = async (payload: jose.JWTPayload): Promise<string> => {
const secret = new TextEncoder().encode("your-256-bit-secret");
const token = await new jose.SignJWT(payload)
.setProtectedHeader({ alg: "HS256", typ: "JWT" })
.setIssuedAt()
.setExpirationTime("2h")
.sign(secret);
return token;
}
// 验证 JWT token 并返回 payload
export async function verifyToken(token: string): Promise<jose.JWTPayload> {
const JWKS = getJWKS();
const { payload } = await jose.jwtVerify(token, JWKS, {
issuer: JWT_CONFIG.issuer,
audience: JWT_CONFIG.audience,
algorithms: JWT_CONFIG.algorithms,
});
return payload;
}
// 从请求 header 中提取 Bearer token
export function extractBearerToken(authHeader: string | null): string | null {
if (!authHeader) return null;
const match = authHeader.match(/^Bearer\s+(.+)$/i);
return match ? match[1] : null;
}
// 获取或创建用户(演示用)
export async function getOrCreateUser(
db: any,
tokenPayload: jose.JWTPayload
): Promise<GenericId<"users">> {
const externalId = tokenPayload.sub as string;
// 查找已存在的用户
const existingUser = await db
.query("users")
.withIndex("id", (q: any) => q.eq("id", externalId))
.first();
if (existingUser) {
// 更新最后登录时间
await db
.table("users")
.doc(existingUser._id)
.patch({ lastLoginAt: new Date().toISOString() });
return existingUser._id;
}
// 创建新用户
return await db
.table("users")
.insert({
id: externalId,
name: (tokenPayload.name as string) || "Unknown",
email: (tokenPayload.email as string) || "",
createdAt: new Date().toISOString(),
});
}

22
convex/actions/redis.ts Normal file
View File

@@ -0,0 +1,22 @@
'use node';
import { query, mutation, action } from "../_generated/server";
import { Kevisual } from '@kevisual/ai/browser'
import { v } from "convex/values";
import { Redis } from "ioredis";
const redisClient = new Redis({
host: process.env.REDIS_HOST,
password: process.env.REDIS_PASSWORD,
});
let time: any = null;
export const isConnected = action({
args: {},
handler: async (ctx) => {
const result = await redisClient.ping();
if (time === null) {
time = new Date();
}
console.log("Redis PING at", new Date().toISOString(), "since", time);
return result === "PONG";
},
});

13
convex/auth.config.ts Normal file
View File

@@ -0,0 +1,13 @@
import { AuthConfig } from "convex/server";
export default {
providers: [
{
type: "customJwt",
applicationID: "convex-app",
issuer: "https://convex.kevisual.cn",
jwks: "https://api-convex.kevisual.cn/root/convex/jwks.json",
algorithm: "RS256",
},
],
};

38
convex/http.ts Normal file
View File

@@ -0,0 +1,38 @@
import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";
const http = httpRouter();
http.route({
path: "/auth",
method: "POST",
handler: httpAction(async (ctx, request) => {
// 处理请求并返回响应
return new Response(JSON.stringify({ message: "Hello from custom endpoint!" }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
}),
})
http.route({
path: '/root/convex/jwks.json',
method: 'GET',
handler: httpAction(async (ctx, request) => {
// 返回 JWKS 数据
const jwks = {
"keys": [
{
"kty": "RSA",
"n": "km4cjJJOMFkl2G5qWMuFmWwF7rmeqRYzYdR8SddKeeMW0e9yIf5pv2Mfwv0aMJUpb-_j3j9M7whx_SEGc_2jx1vxCu1AlYURhnnLTWdsR-ZRPr2LK9UstMrgpWV425R2RliqXTDTYlSxUUlD9nPue_tqbfwN2aM9MCarm67xK_ZCcKRlW9o9L2-9UMfzRA7uiy4VQtOemP0PTXp-E9RxNiMPOQXIRls9wTW_EkDT3dGy7JCZhj7_qib3T8k9m84SwU7wI2R_3IH4DcHSMAn1BRRMXZ1_wPhbP39laNtdJgbDjGCqUccGhLUaoo2WGkZ52eb7NPqamp0K1Dh2jwTIJQ",
"e": "AQAB",
"kid": "kid-key-1"
}
]
};
return new Response(JSON.stringify(jwks), {
status: 200,
headers: { "Content-Type": "application/json" },
});
}),
})
export default http;

View File

@@ -1,9 +1,21 @@
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
import { authTables } from "@convex-dev/auth/server";
// Define a messages table with an index.
export default defineSchema({
abcv: defineTable({
title: v.string(),
})
}),
users: defineTable({
id: v.string(), // 外部系统的用户 ID
name: v.string(),
createdAt: v.string(),
lastLoginAt: v.optional(v.string()),
}).index("id", ["id"]),
sessions: defineTable({
userId: v.id("users"),
createdAt: v.string(),
expiresAt: v.optional(v.string()),
token: v.optional(v.string()),
}).index("token", ["token"]),
});

6
demos/auth.config.ts Normal file
View File

@@ -0,0 +1,6 @@
import { getAuthConfigProvider } from "@convex-dev/better-auth/auth-config";
import type { AuthConfig } from "convex/server";
export default {
providers: [getAuthConfigProvider()],
} satisfies AuthConfig;

7
demos/convex.config.ts Normal file
View File

@@ -0,0 +1,7 @@
import { defineApp } from "convex/server";
import betterAuth from "@convex-dev/better-auth/convex.config";
const app = defineApp();
app.use(betterAuth);
export default app;

40
generate-jwks.ts Normal file
View File

@@ -0,0 +1,40 @@
import * as jose from 'jose';
import fs from 'node:fs'
async function generateKeyPair() {
const { privateKey, publicKey } = await jose.generateKeyPair('RS256', {
modulusLength: 2048,
extractable: true,
});
return { privateKey, publicKey };
}
async function createJWKS(publicKey: CryptoKey) {
const jwk = await jose.exportJWK(publicKey);
// 添加 kid 字段
jwk.kid = 'kid-key-1';
const jwks = {
keys: [jwk]
};
return jwks;
}
async function main() {
const { privateKey, publicKey } = await generateKeyPair();
const jwks = await createJWKS(publicKey);
// 将私钥和 JWKS 保存到文件
const privateJWK = await jose.exportJWK(privateKey);
const privatePEM = await jose.exportPKCS8(privateKey);
const publicPEM = await jose.exportSPKI(publicKey);
fs.writeFileSync('jwt/publicKey.txt', publicPEM);
fs.writeFileSync('jwt/privateKey.txt', privatePEM);
fs.writeFileSync('jwt/privateKey.json', JSON.stringify(privateJWK, null, 2));
fs.writeFileSync('jwt/jwks.json', JSON.stringify(jwks, null, 2));
console.log('Private key and JWKS have been saved to files.');
}
main().catch(console.error);

3
html/index.html Normal file
View File

@@ -0,0 +1,3 @@
<!doctype html>
<!-- <script type="module" src="./src/index.ts"></script> -->
<script type="module" src="./src/b.ts"></script>

35
html/src/b.ts Normal file
View File

@@ -0,0 +1,35 @@
// const jwtToken = "...";
console.log("jose loaded:", Math.floor(Date.now() / 1000) + 3600);
import { api } from "../../convex/_generated/api.js";
import { ConvexClient, AuthTokenFetcher } from "convex/browser";
const CONVEX_URL = "https://convex.kevisual.cn";
const client = new ConvexClient(CONVEX_URL, {
});
// 生成 RS256 JWT
const jwtToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3Qta2V5LTEifQ.eyJpc3MiOiJodHRwczovL2NvbnZleC5rZXZpc3VhbC5jbiIsInN1YiI6InVzZXI6OGZhMmJlNzNjMjIyOWU4NSIsImF1ZCI6InRlc3QtY29udmV4LWFwcCIsImV4cCI6MTc2OTE4MDE1MSwibmFtZSI6IlRlc3QgVXNlciIsImVtYWlsIjoidGVzdEBleGFtcGxlLmNvbSJ9.Kqkzs9qvisOjo4QGvUgc1J9m0MFO2H2KKnghx00LMsBoMciOGggGYwnn1tuhHwNmxUBhUHl9M2nmA8L2ict24mV28iKaFbbDEVTMAFkNsHHrkEO1VCtBypwMfC8xwmWMfAb_lrz0u5DXv19xhAA6LZN55DGrP3SibWyrNejhd3o64VGr9NEP-Ko8c8fZZdtM6dMW8HN2jKC2RaO3wpD8DUfZA1UQrKeWRBoQ1g5zPA4zwfIREoVx7Iudnb-wVqXojj5BIfnS2mWB76Ukyb_OkpJDn2Oh-wBFqj8YRpUpH_-oh_rsS2gpO5aHzwmVEQ4JRG1YASlV5jKlPiwDz7xHFQ"
const main = async () => {
const res = await fetch("https://api-convex.kevisual.cn/abcv/get", {
headers: {
Authorization: `Bearer ${jwtToken}`,
},
}).then((r) => r.text());
console.log("Fetch response:", res);
}
// main();
const main2 = async () => {
client.setAuth(async ({ forceRefreshToken }: { forceRefreshToken: boolean }) => {
console.log("AuthTokenFetcher called, forceRefreshToken:", forceRefreshToken);
return jwtToken;
}, async (isAuthenticated) => {
console.log("Auth state isAuthenticated", isAuthenticated);
if (isAuthenticated) {
const list = await client.query(api.abcv.get, {});
console.log("Initial list:", list);
}
const isAuth = client.client.hasAuth();
console.log("Has auth:", isAuth);
});
}
main2();

24
html/src/index.ts Normal file
View File

@@ -0,0 +1,24 @@
import { ConvexClient, AuthTokenFetcher } from "convex/browser";
import { api } from "../../convex/_generated/api.js";
const CONVEX_URL = "https://convex.kevisual.cn";
const client = new ConvexClient(CONVEX_URL, {
unsavedChangesWarning: true,
});
client.setAuth(async ({ forceRefreshToken }: { forceRefreshToken: boolean }) => {
console.log("AuthTokenFetcher called, forceRefreshToken:", forceRefreshToken);
return null;
}, (isAuthenticated) => {
console.log("Auth state isAuthenticated", isAuthenticated);
});
client.onUpdate(api.abcv.get, {}, (tasks) =>
console.log('api.abcv.get', tasks),
);
const list = await client.query(api.abcv.get, {});
console.log("Initial list:", list);
// const list = await client.action(api.abcv.chat, { message: "Hello, 1+1=?" });
// console.log("Chat response:", list);

View File

@@ -1,28 +1,70 @@
import { ConvexClient, AuthTokenFetcher } from "convex/browser";
import { api } from "./convex/_generated/api.js";
import * as jose from "jose";
const url = process.env["CONVEX_URL"]
const client = new ConvexClient(url!);
console.log("Client created", url);
// 加载测试私钥
const keys = JSON.parse(await Bun.file("./jwt/privateKey.json").text());
const privateKey = await jose.importJWK(keys, "RS256");
// 生成 RS256 JWT
const payload = {
iss: "https://convex.kevisual.cn",
sub: "user:8fa2be73c2229e85",
aud: "convex-app",
exp: Math.floor(Date.now() / 1000) + 3600,
name: "Test User AA",
email: "test@example.com",
};
const token = await new jose.SignJWT(payload)
.setProtectedHeader({
"alg": "RS256",
"typ": "JWT",
"kid": "kid-key-1"
})
.setIssuedAt()
.sign(privateKey);
console.log("Generated RS256 token:", token);
const authTokenFetcher: AuthTokenFetcher = async ({ forceRefreshToken }: { forceRefreshToken: boolean }) => {
console.log("AuthTokenFetcher called, forceRefreshToken:", forceRefreshToken);
return null;
return token;
}
const _auth = await client.setAuth(authTokenFetcher, () => { })
const auth = client.getAuth();
console.log("Client auth", auth);
client.setAuth(authTokenFetcher, (isAuthenticated) => {
console.log("Auth isAuthenticated:", isAuthenticated);
});
// console.log("Auth set up", auth);
await Bun.sleep(1000);
// const auth = client.getAuth();
// console.log("Client auth", auth);
const unsubscribe = client.onUpdate(api.abcv.get, {}, async (tasks) => {
console.log(tasks);
});
// const list = await client.query(api.abcv.get, {});
// console.log("Initial list:", list);
const list = await client.query(api.abcv.get, {});
console.log("Initial list:", list);
// for (let i = 0; i < list.length; i++) {
// const a = list[i];
// console.log(`Item ${i}:`, a.title);
// }
const list = await client.action(api.abcv.chat, { message: "Hello, 1+1=?" });
console.log("Chat response:", list);
// const list = await client.action(api.abcv.chat, { message: "Hello, 1+1=?" });
// console.log("Chat response:", list);
// const redisIsConnected = await client.action(api.actions.redis.isConnected, {});
// console.log("Redis isConnected:", redisIsConnected);
// const sign = await api.auth.signIn({ provider: "convex" })
// const sign = await httpClient.action("/auth", { method: "POST" });
// console.log("Sign in result:", sign);
const res = await fetch("http://convex.kevisual.cn:3211/auth", {
method: "POST",
});
const data = await res.json();
console.log("Custom endpoint response:", data);
await Bun.sleep(1000);
unsubscribe();
await client.close();

10
jwt/jwks.json Normal file
View File

@@ -0,0 +1,10 @@
{
"keys": [
{
"kty": "RSA",
"n": "km4cjJJOMFkl2G5qWMuFmWwF7rmeqRYzYdR8SddKeeMW0e9yIf5pv2Mfwv0aMJUpb-_j3j9M7whx_SEGc_2jx1vxCu1AlYURhnnLTWdsR-ZRPr2LK9UstMrgpWV425R2RliqXTDTYlSxUUlD9nPue_tqbfwN2aM9MCarm67xK_ZCcKRlW9o9L2-9UMfzRA7uiy4VQtOemP0PTXp-E9RxNiMPOQXIRls9wTW_EkDT3dGy7JCZhj7_qib3T8k9m84SwU7wI2R_3IH4DcHSMAn1BRRMXZ1_wPhbP39laNtdJgbDjGCqUccGhLUaoo2WGkZ52eb7NPqamp0K1Dh2jwTIJQ",
"e": "AQAB",
"kid": "kid-key-1"
}
]
}

11
jwt/privateKey.json Normal file
View File

@@ -0,0 +1,11 @@
{
"kty": "RSA",
"n": "km4cjJJOMFkl2G5qWMuFmWwF7rmeqRYzYdR8SddKeeMW0e9yIf5pv2Mfwv0aMJUpb-_j3j9M7whx_SEGc_2jx1vxCu1AlYURhnnLTWdsR-ZRPr2LK9UstMrgpWV425R2RliqXTDTYlSxUUlD9nPue_tqbfwN2aM9MCarm67xK_ZCcKRlW9o9L2-9UMfzRA7uiy4VQtOemP0PTXp-E9RxNiMPOQXIRls9wTW_EkDT3dGy7JCZhj7_qib3T8k9m84SwU7wI2R_3IH4DcHSMAn1BRRMXZ1_wPhbP39laNtdJgbDjGCqUccGhLUaoo2WGkZ52eb7NPqamp0K1Dh2jwTIJQ",
"e": "AQAB",
"d": "Ewq7rrIV9eaZ68_MB5kL2hw4l0dPMSjgbK_vq8CSAFC-NnW_b1lA0jEnP7mfTsMO_O4CwXOU4x7DiAnj53CL_FBiA6w_slH4Kfcrr3isFZuHZDPM5dnWcvpRBWExOsjPKq28FdtUGdzupCX1bxa7ZCcZO41EFdHLErhsp5Wz6iXtNwkQUDSBnyCVbWh7Pn8M1TT5iw3hF9GBTrrN-Nfy6C_7G1W1QuotLoUEbyn0QH-9Xttt0wFgNkEBjDe4SrvRWzuUvucBAP8GXUKxEKsv3pQX5lZWxR85fJyLhJSeZK84lzydDkZuQWTCXQprsSzUNFaB5UC6ZqKzCARZPBFhMQ",
"p": "xaLneraHzmgkfeyr5I1cUpTbSy2thtiGJnu5StMWcNqYIJtTsdf4nIcIx97VUxhE3BRAxyaPa2aLQjo-o1sMMZu_b4iqEppNrSblueOUojOm8DJ6UwTUM8hZYp07T6ufq9MYPWEJF_lrJNH9zXRAlpAb7H2inixpWCoBXDEqTMk",
"q": "vawSZQcxEMj__EVl-gxQA6GPwmCAdUUFE38Z9PMJMcBPGjEdBT7ll9l2PrsyFnAm6KPAR3MKF7EqcIPwRC4ZsXmE3pgfV7x9GB0fOGnjWh_XxVGvJjPrH52JSHcQUiqO0ym5evTfYNwH7b2N0wYZbmelDV8l5JG76nRJDujZ-n0",
"dp": "PXiNxv0_AFQkBYa3cD8HmCf0jU2Hy4lNMGsLFtrRAAj9iCbHwWkLSqQ1dvU4JMBHqqwh-c9kjGM4rUCwet62zDdFM8uuGlskDdcrXMYMVOb75XnN0kSOPAz0wFdnO0CGSUs_Htgvm-VYDfvClUSzUiFAji4Fhm0J1wI5qhMgtQE",
"dq": "VY2dCnbw-cpANRE0i1IscUbZqmqO5taIEKA_HA7X8dn1lDHdDjWtqA3N2UPkttxFoJ_kJhZM0hz2sKPCp25H5paSiTkCwjdiEZNpNrAEfe1pDTboEwpOHweXGdmiwf0ySStD36M-ctkstl7O7wWMSRF1EI__bpcRtRJYteHwGJ0",
"qi": "sxCqC7NKEkPWyBSKiGfGrjLxf3OL2dOjyUBvdxQUiK0L4JJTXfPf2PAYCwY3J1CawDC8weEislOSo4Q4pcKkH3nkI2zVC7fnwRXWttmEXNr-Px5pJg8yoIcFjwVa-mBSgjCo_v72sRGBHGQZY1Y7Xh5P78LpsfGEaBK6g_fWfZs"
}

28
jwt/privateKey.txt Normal file
View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCSbhyMkk4wWSXY
bmpYy4WZbAXuuZ6pFjNh1HxJ10p54xbR73Ih/mm/Yx/C/RowlSlv7+PeP0zvCHH9
IQZz/aPHW/EK7UCVhRGGectNZ2xH5lE+vYsr1Sy0yuClZXjblHZGWKpdMNNiVLFR
SUP2c+57+2pt/A3Zoz0wJqubrvEr9kJwpGVb2j0vb71Qx/NEDu6LLhVC056Y/Q9N
en4T1HE2Iw85BchGWz3BNb8SQNPd0bLskJmGPv+qJvdPyT2bzhLBTvAjZH/cgfgN
wdIwCfUFFExdnX/A+Fs/f2Vo210mBsOMYKpRxwaEtRqijZYaRnnZ5vs0+pqanQrU
OHaPBMglAgMBAAECggEAEwq7rrIV9eaZ68/MB5kL2hw4l0dPMSjgbK/vq8CSAFC+
NnW/b1lA0jEnP7mfTsMO/O4CwXOU4x7DiAnj53CL/FBiA6w/slH4Kfcrr3isFZuH
ZDPM5dnWcvpRBWExOsjPKq28FdtUGdzupCX1bxa7ZCcZO41EFdHLErhsp5Wz6iXt
NwkQUDSBnyCVbWh7Pn8M1TT5iw3hF9GBTrrN+Nfy6C/7G1W1QuotLoUEbyn0QH+9
Xttt0wFgNkEBjDe4SrvRWzuUvucBAP8GXUKxEKsv3pQX5lZWxR85fJyLhJSeZK84
lzydDkZuQWTCXQprsSzUNFaB5UC6ZqKzCARZPBFhMQKBgQDFoud6tofOaCR97Kvk
jVxSlNtLLa2G2IYme7lK0xZw2pggm1Ox1/ichwjH3tVTGETcFEDHJo9rZotCOj6j
Wwwxm79viKoSmk2tJuW545SiM6bwMnpTBNQzyFlinTtPq5+r0xg9YQkX+Wsk0f3N
dECWkBvsfaKeLGlYKgFcMSpMyQKBgQC9rBJlBzEQyP/8RWX6DFADoY/CYIB1RQUT
fxn08wkxwE8aMR0FPuWX2XY+uzIWcCboo8BHcwoXsSpwg/BELhmxeYTemB9XvH0Y
HR84aeNaH9fFUa8mM+sfnYlIdxBSKo7TKbl69N9g3AftvY3TBhluZ6UNXyXkkbvq
dEkO6Nn6fQKBgD14jcb9PwBUJAWGt3A/B5gn9I1Nh8uJTTBrCxba0QAI/Ygmx8Fp
C0qkNXb1OCTAR6qsIfnPZIxjOK1AsHretsw3RTPLrhpbJA3XK1zGDFTm++V5zdJE
jjwM9MBXZztAhklLPx7YL5vlWA37wpVEs1IhQI4uBYZtCdcCOaoTILUBAoGAVY2d
Cnbw+cpANRE0i1IscUbZqmqO5taIEKA/HA7X8dn1lDHdDjWtqA3N2UPkttxFoJ/k
JhZM0hz2sKPCp25H5paSiTkCwjdiEZNpNrAEfe1pDTboEwpOHweXGdmiwf0ySStD
36M+ctkstl7O7wWMSRF1EI//bpcRtRJYteHwGJ0CgYEAsxCqC7NKEkPWyBSKiGfG
rjLxf3OL2dOjyUBvdxQUiK0L4JJTXfPf2PAYCwY3J1CawDC8weEislOSo4Q4pcKk
H3nkI2zVC7fnwRXWttmEXNr+Px5pJg8yoIcFjwVa+mBSgjCo/v72sRGBHGQZY1Y7
Xh5P78LpsfGEaBK6g/fWfZs=
-----END PRIVATE KEY-----

9
jwt/publicKey.txt Normal file
View File

@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkm4cjJJOMFkl2G5qWMuF
mWwF7rmeqRYzYdR8SddKeeMW0e9yIf5pv2Mfwv0aMJUpb+/j3j9M7whx/SEGc/2j
x1vxCu1AlYURhnnLTWdsR+ZRPr2LK9UstMrgpWV425R2RliqXTDTYlSxUUlD9nPu
e/tqbfwN2aM9MCarm67xK/ZCcKRlW9o9L2+9UMfzRA7uiy4VQtOemP0PTXp+E9Rx
NiMPOQXIRls9wTW/EkDT3dGy7JCZhj7/qib3T8k9m84SwU7wI2R/3IH4DcHSMAn1
BRRMXZ1/wPhbP39laNtdJgbDjGCqUccGhLUaoo2WGkZ52eb7NPqamp0K1Dh2jwTI
JQIDAQAB
-----END PUBLIC KEY-----

View File

@@ -13,13 +13,17 @@
"type": "module",
"private": true,
"devDependencies": {
"@convex-dev/better-auth": "^0.10.10",
"@kevisual/ai": "^0.0.21",
"@types/bun": "latest"
"@types/bun": "latest",
"ioredis": "^5.9.2"
},
"peerDependencies": {
"typescript": "^5"
},
"dependencies": {
"convex": "^1.31.6"
"@convex-dev/auth": "^0.0.90",
"convex": "^1.31.6",
"jose": "^6.1.3"
}
}

765
pnpm-lock.yaml generated
View File

@@ -8,22 +8,98 @@ importers:
.:
dependencies:
'@convex-dev/auth':
specifier: ^0.0.90
version: 0.0.90(@auth/core@0.37.4)(convex@1.31.6(react@19.2.3))(react@19.2.3)
convex:
specifier: ^1.31.6
version: 1.31.6
version: 1.31.6(react@19.2.3)
jose:
specifier: ^6.1.3
version: 6.1.3
typescript:
specifier: ^5
version: 5.9.3
devDependencies:
'@convex-dev/better-auth':
specifier: ^0.10.10
version: 0.10.10(@better-auth/core@1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.0)(@standard-schema/spec@1.1.0)(better-auth@1.4.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(better-call@1.1.7(zod@4.3.6))(convex@1.31.6(react@19.2.3))(nanostores@1.1.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)
'@kevisual/ai':
specifier: ^0.0.21
version: 0.0.21
'@types/bun':
specifier: latest
version: 1.3.6
ioredis:
specifier: ^5.9.2
version: 5.9.2
packages:
'@auth/core@0.37.4':
resolution: {integrity: sha512-HOXJwXWXQRhbBDHlMU0K/6FT1v+wjtzdKhsNg0ZN7/gne6XPsIrjZ4daMcFnbq0Z/vsAbYBinQhhua0d77v7qw==}
peerDependencies:
'@simplewebauthn/browser': ^9.0.1
'@simplewebauthn/server': ^9.0.2
nodemailer: ^6.8.0
peerDependenciesMeta:
'@simplewebauthn/browser':
optional: true
'@simplewebauthn/server':
optional: true
nodemailer:
optional: true
'@better-auth/core@1.4.9':
resolution: {integrity: sha512-JT2q4NDkQzN22KclUEoZ7qU6tl9HUTfK1ctg2oWlT87SEagkwJcnrUwS9VznL+u9ziOIfY27P0f7/jSnmvLcoQ==}
peerDependencies:
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
better-call: 1.1.7
jose: ^6.1.0
kysely: ^0.28.5
nanostores: ^1.0.1
'@better-auth/passkey@1.4.9':
resolution: {integrity: sha512-fPsV0LYbmPytxrTaltM2RXbJnmSttX9UWr4wkZtJYgCBGeFqN8+8ZzBTZXOymWDJTVQ0kVZrD7c7/HyxXEG1zA==}
peerDependencies:
'@better-auth/core': 1.4.9
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
better-auth: 1.4.9
better-call: 1.1.7
nanostores: ^1.0.1
'@better-auth/telemetry@1.4.9':
resolution: {integrity: sha512-Tthy1/Gmx+pYlbvRQPBTKfVei8+pJwvH1NZp+5SbhwA6K2EXIaoonx/K6N/AXYs2aKUpyR4/gzqDesDjL7zd6A==}
peerDependencies:
'@better-auth/core': 1.4.9
'@better-auth/utils@0.3.0':
resolution: {integrity: sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==}
'@better-fetch/fetch@1.1.21':
resolution: {integrity: sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A==}
'@convex-dev/auth@0.0.90':
resolution: {integrity: sha512-aqw88EB042HvnaF4wcf/f/wTocmT2Bus2VDQRuV79cM0+8kORM0ICK/ByZ6XsHgQ9qr6TmidNbXm6QAgndrdpQ==}
hasBin: true
peerDependencies:
'@auth/core': ^0.37.0
convex: ^1.17.0
react: ^18.2.0 || ^19.0.0-0
peerDependenciesMeta:
react:
optional: true
'@convex-dev/better-auth@0.10.10':
resolution: {integrity: sha512-BpwQ2kph43O7hmtGQAJ+ie3KrjONp83659QDjKDdH+X8yIdGevgehaqS5GHB0iJo7zQTtvs687GnAeLZ4Xx3/w==}
peerDependencies:
better-auth: 1.4.9
convex: ^1.25.0
react: ^18.3.1 || ^19.0.0
react-dom: ^18.3.1 || ^19.0.0
'@esbuild/aix-ppc64@0.27.0':
resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==}
engines: {node: '>=18'}
@@ -180,6 +256,12 @@ packages:
cpu: [x64]
os: [win32]
'@hexagon/base64@1.1.28':
resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==}
'@ioredis/commands@1.5.0':
resolution: {integrity: sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow==}
'@kevisual/ai@0.0.21':
resolution: {integrity: sha512-4YvnEDpgCje3jDZug95pXzmIS4jHHulDjXONXSWLScsSLiqIRZnZQ6K+2IbCnIDAFmGIBYR/xFt0fyJIKJmrDQ==}
@@ -192,15 +274,189 @@ packages:
'@kevisual/query@0.0.35':
resolution: {integrity: sha512-80dyy2LMCmEC72g+X4QWUKlZErhawQPgnGSBNR4yhrBcFgHIJQ14LR1Z+bS5S1I7db+1PDNpaxBTjIaoYoXunw==}
'@levischuck/tiny-cbor@0.2.11':
resolution: {integrity: sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==}
'@noble/ciphers@2.1.1':
resolution: {integrity: sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw==}
engines: {node: '>= 20.19.0'}
'@noble/hashes@2.0.1':
resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==}
engines: {node: '>= 20.19.0'}
'@oslojs/asn1@1.0.0':
resolution: {integrity: sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA==}
'@oslojs/binary@1.0.0':
resolution: {integrity: sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ==}
'@oslojs/crypto@1.0.1':
resolution: {integrity: sha512-7n08G8nWjAr/Yu3vu9zzrd0L9XnrJfpMioQcvCMxBIiF5orECHe5/3J0jmXRVvgfqMm/+4oxlQ+Sq39COYLcNQ==}
'@oslojs/encoding@1.1.0':
resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
'@panva/hkdf@1.2.1':
resolution: {integrity: sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==}
'@peculiar/asn1-android@2.6.0':
resolution: {integrity: sha512-cBRCKtYPF7vJGN76/yG8VbxRcHLPF3HnkoHhKOZeHpoVtbMYfY9ROKtH3DtYUY9m8uI1Mh47PRhHf2hSK3xcSQ==}
'@peculiar/asn1-cms@2.6.0':
resolution: {integrity: sha512-2uZqP+ggSncESeUF/9Su8rWqGclEfEiz1SyU02WX5fUONFfkjzS2Z/F1Li0ofSmf4JqYXIOdCAZqIXAIBAT1OA==}
'@peculiar/asn1-csr@2.6.0':
resolution: {integrity: sha512-BeWIu5VpTIhfRysfEp73SGbwjjoLL/JWXhJ/9mo4vXnz3tRGm+NGm3KNcRzQ9VMVqwYS2RHlolz21svzRXIHPQ==}
'@peculiar/asn1-ecc@2.6.0':
resolution: {integrity: sha512-FF3LMGq6SfAOwUG2sKpPXblibn6XnEIKa+SryvUl5Pik+WR9rmRA3OCiwz8R3lVXnYnyRkSZsSLdml8H3UiOcw==}
'@peculiar/asn1-pfx@2.6.0':
resolution: {integrity: sha512-rtUvtf+tyKGgokHHmZzeUojRZJYPxoD/jaN1+VAB4kKR7tXrnDCA/RAWXAIhMJJC+7W27IIRGe9djvxKgsldCQ==}
'@peculiar/asn1-pkcs8@2.6.0':
resolution: {integrity: sha512-KyQ4D8G/NrS7Fw3XCJrngxmjwO/3htnA0lL9gDICvEQ+GJ+EPFqldcJQTwPIdvx98Tua+WjkdKHSC0/Km7T+lA==}
'@peculiar/asn1-pkcs9@2.6.0':
resolution: {integrity: sha512-b78OQ6OciW0aqZxdzliXGYHASeCvvw5caqidbpQRYW2mBtXIX2WhofNXTEe7NyxTb0P6J62kAAWLwn0HuMF1Fw==}
'@peculiar/asn1-rsa@2.6.0':
resolution: {integrity: sha512-Nu4C19tsrTsCp9fDrH+sdcOKoVfdfoQQ7S3VqjJU6vedR7tY3RLkQ5oguOIB3zFW33USDUuYZnPEQYySlgha4w==}
'@peculiar/asn1-schema@2.6.0':
resolution: {integrity: sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg==}
'@peculiar/asn1-x509-attr@2.6.0':
resolution: {integrity: sha512-MuIAXFX3/dc8gmoZBkwJWxUWOSvG4MMDntXhrOZpJVMkYX+MYc/rUAU2uJOved9iJEoiUx7//3D8oG83a78UJA==}
'@peculiar/asn1-x509@2.6.0':
resolution: {integrity: sha512-uzYbPEpoQiBoTq0/+jZtpM6Gq6zADBx+JNFP3yqRgziWBxQ/Dt/HcuvRfm9zJTPdRcBqPNdaRHTVwpyiq6iNMA==}
'@peculiar/x509@1.14.3':
resolution: {integrity: sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==}
engines: {node: '>=20.0.0'}
'@simplewebauthn/browser@13.2.2':
resolution: {integrity: sha512-FNW1oLQpTJyqG5kkDg5ZsotvWgmBaC6jCHR7Ej0qUNep36Wl9tj2eZu7J5rP+uhXgHaLk+QQ3lqcw2vS5MX1IA==}
'@simplewebauthn/server@13.2.2':
resolution: {integrity: sha512-HcWLW28yTMGXpwE9VLx9J+N2KEUaELadLrkPEEI9tpI5la70xNEVEsu/C+m3u7uoq4FulLqZQhgBCzR9IZhFpA==}
engines: {node: '>=20.0.0'}
'@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
'@types/bun@1.3.6':
resolution: {integrity: sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA==}
'@types/node@25.0.10':
resolution: {integrity: sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==}
asn1js@3.0.7:
resolution: {integrity: sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==}
engines: {node: '>=12.0.0'}
better-auth@1.4.9:
resolution: {integrity: sha512-usSdjuyTzZwIvM8fjF8YGhPncxV3MAg3dHUO9uPUnf0yklXUSYISiH1+imk6/Z+UBqsscyyPRnbIyjyK97p7YA==}
peerDependencies:
'@lynx-js/react': '*'
'@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0
'@sveltejs/kit': ^2.0.0
'@tanstack/react-start': ^1.0.0
better-sqlite3: ^12.0.0
drizzle-kit: '>=0.31.4'
drizzle-orm: '>=0.41.0'
mongodb: ^6.0.0 || ^7.0.0
mysql2: ^3.0.0
next: ^14.0.0 || ^15.0.0 || ^16.0.0
pg: ^8.0.0
prisma: ^5.0.0 || ^6.0.0 || ^7.0.0
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
solid-js: ^1.0.0
svelte: ^4.0.0 || ^5.0.0
vitest: ^2.0.0 || ^3.0.0 || ^4.0.0
vue: ^3.0.0
peerDependenciesMeta:
'@lynx-js/react':
optional: true
'@prisma/client':
optional: true
'@sveltejs/kit':
optional: true
'@tanstack/react-start':
optional: true
better-sqlite3:
optional: true
drizzle-kit:
optional: true
drizzle-orm:
optional: true
mongodb:
optional: true
mysql2:
optional: true
next:
optional: true
pg:
optional: true
prisma:
optional: true
react:
optional: true
react-dom:
optional: true
solid-js:
optional: true
svelte:
optional: true
vitest:
optional: true
vue:
optional: true
better-call@1.1.7:
resolution: {integrity: sha512-6gaJe1bBIEgVebQu/7q9saahVzvBsGaByEnE8aDVncZEDiJO7sdNB28ot9I6iXSbR25egGmmZ6aIURXyQHRraQ==}
peerDependencies:
zod: ^4.0.0
peerDependenciesMeta:
zod:
optional: true
bun-types@1.3.6:
resolution: {integrity: sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ==}
cluster-key-slot@1.1.2:
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
engines: {node: '>=0.10.0'}
common-tags@1.8.2:
resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==}
engines: {node: '>=4.0.0'}
convex-helpers@0.1.111:
resolution: {integrity: sha512-0O59Ohi8HVc3+KULxSC6JHsw8cQJyc8gZ7OAfNRVX7T5Wy6LhPx3l8veYN9avKg7UiPlO7m1eBiQMHKclIyXyQ==}
hasBin: true
peerDependencies:
'@standard-schema/spec': ^1.0.0
convex: ^1.25.4
hono: ^4.0.5
react: ^17.0.2 || ^18.0.0 || ^19.0.0
typescript: ^5.5
zod: ^3.25.0 || ^4.0.0
peerDependenciesMeta:
'@standard-schema/spec':
optional: true
hono:
optional: true
react:
optional: true
typescript:
optional: true
zod:
optional: true
convex@1.31.6:
resolution: {integrity: sha512-9cIsOzepa3s9DURRF+fZHxbNuzLgilg9XGQCc45v0Xx4FemqeIezpPFSJF9WHC9ckk43TDUUXLecvLVt9djPkw==}
engines: {node: '>=18.0.0', npm: '>=7.0.0'}
@@ -217,19 +473,153 @@ packages:
react:
optional: true
cookie@1.1.1:
resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
engines: {node: '>=18'}
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
defu@6.1.4:
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
denque@2.1.0:
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
engines: {node: '>=0.10'}
esbuild@0.27.0:
resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==}
engines: {node: '>=18'}
hasBin: true
ioredis@5.9.2:
resolution: {integrity: sha512-tAAg/72/VxOUW7RQSX1pIxJVucYKcjFjfvj60L57jrZpYCHC3XN0WCQ3sNYL4Gmvv+7GPvTAjc+KSdeNuE8oWQ==}
engines: {node: '>=12.22.0'}
is-network-error@1.3.0:
resolution: {integrity: sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==}
engines: {node: '>=16'}
jose@5.10.0:
resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==}
jose@6.1.3:
resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==}
jwt-decode@4.0.0:
resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==}
engines: {node: '>=18'}
kysely@0.28.10:
resolution: {integrity: sha512-ksNxfzIW77OcZ+QWSAPC7yDqUSaIVwkTWnTPNiIy//vifNbwsSgQ57OkkncHxxpcBHM3LRfLAZVEh7kjq5twVA==}
engines: {node: '>=20.0.0'}
lodash.defaults@4.2.0:
resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
lodash.isarguments@3.1.0:
resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
lucia@3.2.2:
resolution: {integrity: sha512-P1FlFBGCMPMXu+EGdVD9W4Mjm0DqsusmKgO7Xc33mI5X1bklmsQb0hfzPhXomQr9waWIBDsiOjvr1e6BTaUqpA==}
deprecated: This package has been deprecated. Please see https://lucia-auth.com/lucia-v3/migrate.
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
nanostores@1.1.0:
resolution: {integrity: sha512-yJBmDJr18xy47dbNVlHcgdPrulSn1nhSE6Ns9vTG+Nx9VPT6iV1MD6aQFp/t52zpf82FhLLTXAXr30NuCnxvwA==}
engines: {node: ^20.0.0 || >=22.0.0}
oauth4webapi@3.8.3:
resolution: {integrity: sha512-pQ5BsX3QRTgnt5HxgHwgunIRaDXBdkT23tf8dfzmtTIL2LTpdmxgbpbBm0VgFWAIDlezQvQCTgnVIUmHupXHxw==}
path-to-regexp@6.3.0:
resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
preact-render-to-string@6.5.11:
resolution: {integrity: sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==}
peerDependencies:
preact: '>=10'
preact@10.24.3:
resolution: {integrity: sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==}
prettier@3.8.1:
resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==}
engines: {node: '>=14'}
hasBin: true
pvtsutils@1.3.6:
resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==}
pvutils@1.1.5:
resolution: {integrity: sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==}
engines: {node: '>=16.0.0'}
react-dom@19.2.3:
resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==}
peerDependencies:
react: ^19.2.3
react@19.2.3:
resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
engines: {node: '>=0.10.0'}
redis-errors@1.2.0:
resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==}
engines: {node: '>=4'}
redis-parser@3.0.0:
resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==}
engines: {node: '>=4'}
reflect-metadata@0.2.2:
resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
remeda@2.33.4:
resolution: {integrity: sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==}
rou3@0.7.12:
resolution: {integrity: sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg==}
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
semver@7.7.3:
resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
engines: {node: '>=10'}
hasBin: true
server-only@0.0.1:
resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
set-cookie-parser@2.7.2:
resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==}
standard-as-callback@2.1.0:
resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
tslib@1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
tsyringe@4.10.0:
resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==}
engines: {node: '>= 6.0.0'}
type-fest@4.41.0:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
@@ -238,8 +628,93 @@ packages:
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
zod@4.3.6:
resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==}
snapshots:
'@auth/core@0.37.4':
dependencies:
'@panva/hkdf': 1.2.1
jose: 5.10.0
oauth4webapi: 3.8.3
preact: 10.24.3
preact-render-to-string: 6.5.11(preact@10.24.3)
'@better-auth/core@1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)':
dependencies:
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
'@standard-schema/spec': 1.1.0
better-call: 1.1.7(zod@4.3.6)
jose: 6.1.3
kysely: 0.28.10
nanostores: 1.1.0
zod: 4.3.6
'@better-auth/passkey@1.4.9(@better-auth/core@1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-auth@1.4.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(better-call@1.1.7(zod@4.3.6))(nanostores@1.1.0)':
dependencies:
'@better-auth/core': 1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
'@simplewebauthn/browser': 13.2.2
'@simplewebauthn/server': 13.2.2
better-auth: 1.4.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
better-call: 1.1.7(zod@4.3.6)
nanostores: 1.1.0
zod: 4.3.6
'@better-auth/telemetry@1.4.9(@better-auth/core@1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))':
dependencies:
'@better-auth/core': 1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
'@better-auth/utils@0.3.0': {}
'@better-fetch/fetch@1.1.21': {}
'@convex-dev/auth@0.0.90(@auth/core@0.37.4)(convex@1.31.6(react@19.2.3))(react@19.2.3)':
dependencies:
'@auth/core': 0.37.4
'@oslojs/crypto': 1.0.1
'@oslojs/encoding': 1.1.0
convex: 1.31.6(react@19.2.3)
cookie: 1.1.1
is-network-error: 1.3.0
jose: 5.10.0
jwt-decode: 4.0.0
lucia: 3.2.2
oauth4webapi: 3.8.3
path-to-regexp: 6.3.0
server-only: 0.0.1
optionalDependencies:
react: 19.2.3
'@convex-dev/better-auth@0.10.10(@better-auth/core@1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.0)(@standard-schema/spec@1.1.0)(better-auth@1.4.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(better-call@1.1.7(zod@4.3.6))(convex@1.31.6(react@19.2.3))(nanostores@1.1.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)':
dependencies:
'@better-auth/passkey': 1.4.9(@better-auth/core@1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-auth@1.4.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(better-call@1.1.7(zod@4.3.6))(nanostores@1.1.0)
'@better-fetch/fetch': 1.1.21
better-auth: 1.4.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
common-tags: 1.8.2
convex: 1.31.6(react@19.2.3)
convex-helpers: 0.1.111(@standard-schema/spec@1.1.0)(convex@1.31.6(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(zod@4.3.6)
jose: 6.1.3
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
remeda: 2.33.4
semver: 7.7.3
type-fest: 4.41.0
zod: 4.3.6
transitivePeerDependencies:
- '@better-auth/core'
- '@better-auth/utils'
- '@standard-schema/spec'
- better-call
- hono
- nanostores
- typescript
'@esbuild/aix-ppc64@0.27.0':
optional: true
@@ -318,6 +793,10 @@ snapshots:
'@esbuild/win32-x64@0.27.0':
optional: true
'@hexagon/base64@1.1.28': {}
'@ioredis/commands@1.5.0': {}
'@kevisual/ai@0.0.21':
dependencies:
'@kevisual/logger': 0.0.4
@@ -332,6 +811,138 @@ snapshots:
dependencies:
tslib: 2.8.1
'@levischuck/tiny-cbor@0.2.11': {}
'@noble/ciphers@2.1.1': {}
'@noble/hashes@2.0.1': {}
'@oslojs/asn1@1.0.0':
dependencies:
'@oslojs/binary': 1.0.0
'@oslojs/binary@1.0.0': {}
'@oslojs/crypto@1.0.1':
dependencies:
'@oslojs/asn1': 1.0.0
'@oslojs/binary': 1.0.0
'@oslojs/encoding@1.1.0': {}
'@panva/hkdf@1.2.1': {}
'@peculiar/asn1-android@2.6.0':
dependencies:
'@peculiar/asn1-schema': 2.6.0
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-cms@2.6.0':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.0
'@peculiar/asn1-x509-attr': 2.6.0
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-csr@2.6.0':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.0
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-ecc@2.6.0':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.0
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-pfx@2.6.0':
dependencies:
'@peculiar/asn1-cms': 2.6.0
'@peculiar/asn1-pkcs8': 2.6.0
'@peculiar/asn1-rsa': 2.6.0
'@peculiar/asn1-schema': 2.6.0
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-pkcs8@2.6.0':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.0
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-pkcs9@2.6.0':
dependencies:
'@peculiar/asn1-cms': 2.6.0
'@peculiar/asn1-pfx': 2.6.0
'@peculiar/asn1-pkcs8': 2.6.0
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.0
'@peculiar/asn1-x509-attr': 2.6.0
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-rsa@2.6.0':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.0
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-schema@2.6.0':
dependencies:
asn1js: 3.0.7
pvtsutils: 1.3.6
tslib: 2.8.1
'@peculiar/asn1-x509-attr@2.6.0':
dependencies:
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.0
asn1js: 3.0.7
tslib: 2.8.1
'@peculiar/asn1-x509@2.6.0':
dependencies:
'@peculiar/asn1-schema': 2.6.0
asn1js: 3.0.7
pvtsutils: 1.3.6
tslib: 2.8.1
'@peculiar/x509@1.14.3':
dependencies:
'@peculiar/asn1-cms': 2.6.0
'@peculiar/asn1-csr': 2.6.0
'@peculiar/asn1-ecc': 2.6.0
'@peculiar/asn1-pkcs9': 2.6.0
'@peculiar/asn1-rsa': 2.6.0
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.0
pvtsutils: 1.3.6
reflect-metadata: 0.2.2
tslib: 2.8.1
tsyringe: 4.10.0
'@simplewebauthn/browser@13.2.2': {}
'@simplewebauthn/server@13.2.2':
dependencies:
'@hexagon/base64': 1.1.28
'@levischuck/tiny-cbor': 0.2.11
'@peculiar/asn1-android': 2.6.0
'@peculiar/asn1-ecc': 2.6.0
'@peculiar/asn1-rsa': 2.6.0
'@peculiar/asn1-schema': 2.6.0
'@peculiar/asn1-x509': 2.6.0
'@peculiar/x509': 1.14.3
'@standard-schema/spec@1.1.0': {}
'@types/bun@1.3.6':
dependencies:
bun-types: 1.3.6
@@ -340,14 +951,72 @@ snapshots:
dependencies:
undici-types: 7.16.0
asn1js@3.0.7:
dependencies:
pvtsutils: 1.3.6
pvutils: 1.1.5
tslib: 2.8.1
better-auth@1.4.9(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
'@better-auth/core': 1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)
'@better-auth/telemetry': 1.4.9(@better-auth/core@1.4.9(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.7(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
'@noble/ciphers': 2.1.1
'@noble/hashes': 2.0.1
better-call: 1.1.7(zod@4.3.6)
defu: 6.1.4
jose: 6.1.3
kysely: 0.28.10
nanostores: 1.1.0
zod: 4.3.6
optionalDependencies:
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
better-call@1.1.7(zod@4.3.6):
dependencies:
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
rou3: 0.7.12
set-cookie-parser: 2.7.2
optionalDependencies:
zod: 4.3.6
bun-types@1.3.6:
dependencies:
'@types/node': 25.0.10
convex@1.31.6:
cluster-key-slot@1.1.2: {}
common-tags@1.8.2: {}
convex-helpers@0.1.111(@standard-schema/spec@1.1.0)(convex@1.31.6(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(zod@4.3.6):
dependencies:
convex: 1.31.6(react@19.2.3)
optionalDependencies:
'@standard-schema/spec': 1.1.0
react: 19.2.3
typescript: 5.9.3
zod: 4.3.6
convex@1.31.6(react@19.2.3):
dependencies:
esbuild: 0.27.0
prettier: 3.8.1
optionalDependencies:
react: 19.2.3
cookie@1.1.1: {}
debug@4.4.3:
dependencies:
ms: 2.1.3
defu@6.1.4: {}
denque@2.1.0: {}
esbuild@0.27.0:
optionalDependencies:
@@ -378,10 +1047,102 @@ snapshots:
'@esbuild/win32-ia32': 0.27.0
'@esbuild/win32-x64': 0.27.0
ioredis@5.9.2:
dependencies:
'@ioredis/commands': 1.5.0
cluster-key-slot: 1.1.2
debug: 4.4.3
denque: 2.1.0
lodash.defaults: 4.2.0
lodash.isarguments: 3.1.0
redis-errors: 1.2.0
redis-parser: 3.0.0
standard-as-callback: 2.1.0
transitivePeerDependencies:
- supports-color
is-network-error@1.3.0: {}
jose@5.10.0: {}
jose@6.1.3: {}
jwt-decode@4.0.0: {}
kysely@0.28.10: {}
lodash.defaults@4.2.0: {}
lodash.isarguments@3.1.0: {}
lucia@3.2.2:
dependencies:
'@oslojs/crypto': 1.0.1
'@oslojs/encoding': 1.1.0
ms@2.1.3: {}
nanostores@1.1.0: {}
oauth4webapi@3.8.3: {}
path-to-regexp@6.3.0: {}
preact-render-to-string@6.5.11(preact@10.24.3):
dependencies:
preact: 10.24.3
preact@10.24.3: {}
prettier@3.8.1: {}
pvtsutils@1.3.6:
dependencies:
tslib: 2.8.1
pvutils@1.1.5: {}
react-dom@19.2.3(react@19.2.3):
dependencies:
react: 19.2.3
scheduler: 0.27.0
react@19.2.3: {}
redis-errors@1.2.0: {}
redis-parser@3.0.0:
dependencies:
redis-errors: 1.2.0
reflect-metadata@0.2.2: {}
remeda@2.33.4: {}
rou3@0.7.12: {}
scheduler@0.27.0: {}
semver@7.7.3: {}
server-only@0.0.1: {}
set-cookie-parser@2.7.2: {}
standard-as-callback@2.1.0: {}
tslib@1.14.1: {}
tslib@2.8.1: {}
tsyringe@4.10.0:
dependencies:
tslib: 1.14.1
type-fest@4.41.0: {}
typescript@5.9.3: {}
undici-types@7.16.0: {}
zod@4.3.6: {}