feat: migrate auth and state flows to better-auth and convex
This commit is contained in:
@@ -31,11 +31,33 @@ function listFromEnv(name, fallback = []) {
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function boolFromEnv(name, fallback) {
|
||||
const raw = process.env[name];
|
||||
if (!raw) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
const normalized = String(raw).trim().toLowerCase();
|
||||
if (["1", "true", "yes", "on"].includes(normalized)) {
|
||||
return true;
|
||||
}
|
||||
if (["0", "false", "no", "off"].includes(normalized)) {
|
||||
return false;
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
const parsed = {
|
||||
port: intFromEnv("PORT", 3000),
|
||||
stateFilePath: strFromEnv("STATE_FILE_PATH", "./data/state.json"),
|
||||
logLevel: strFromEnv("LOG_LEVEL", "info"),
|
||||
appBaseUrl: strFromEnv("APP_BASE_URL", "http://localhost:3000"),
|
||||
betterAuthSecret: strFromEnv("BETTER_AUTH_SECRET", "dev-better-auth-secret"),
|
||||
betterAuthBasePath: strFromEnv("BETTER_AUTH_BASE_PATH", "/api/auth"),
|
||||
betterAuthDevPassword: strFromEnv("BETTER_AUTH_DEV_PASSWORD", "xartaudio-dev-password"),
|
||||
convexDeploymentUrl: strFromEnv("CONVEX_DEPLOYMENT_URL", ""),
|
||||
convexAuthToken: strFromEnv("CONVEX_AUTH_TOKEN", ""),
|
||||
convexStateQuery: strFromEnv("CONVEX_STATE_QUERY", "state:getLatestSnapshot"),
|
||||
convexStateMutation: strFromEnv("CONVEX_STATE_MUTATION", "state:saveSnapshot"),
|
||||
xWebhookSecret: process.env.X_WEBHOOK_SECRET || "dev-x-secret",
|
||||
xBearerToken: strFromEnv("X_BEARER_TOKEN", ""),
|
||||
xBotUserId: strFromEnv("X_BOT_USER_ID", ""),
|
||||
@@ -43,16 +65,19 @@ const parsed = {
|
||||
polarAccessToken: strFromEnv("POLAR_ACCESS_TOKEN", ""),
|
||||
polarServer: strFromEnv("POLAR_SERVER", "production"),
|
||||
polarProductIds: listFromEnv("POLAR_PRODUCT_IDS", []),
|
||||
ttsApiKey: strFromEnv("TTS_API_KEY", ""),
|
||||
ttsBaseUrl: strFromEnv("TTS_BASE_URL", ""),
|
||||
ttsModel: strFromEnv("TTS_MODEL", "gpt-4o-mini-tts"),
|
||||
ttsVoice: strFromEnv("TTS_VOICE", "alloy"),
|
||||
s3Bucket: strFromEnv("S3_BUCKET", ""),
|
||||
s3Region: strFromEnv("S3_REGION", ""),
|
||||
s3Endpoint: strFromEnv("S3_ENDPOINT", ""),
|
||||
s3AccessKeyId: strFromEnv("S3_ACCESS_KEY_ID", ""),
|
||||
s3SecretAccessKey: strFromEnv("S3_SECRET_ACCESS_KEY", ""),
|
||||
s3SignedUrlTtlSec: intFromEnv("S3_SIGNED_URL_TTL_SEC", 3600),
|
||||
qwenTtsApiKey: strFromEnv("QWEN_TTS_API_KEY", ""),
|
||||
qwenTtsBaseUrl: strFromEnv("QWEN_TTS_BASE_URL", "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"),
|
||||
qwenTtsModel: strFromEnv("QWEN_TTS_MODEL", "qwen-tts-latest"),
|
||||
qwenTtsVoice: strFromEnv("QWEN_TTS_VOICE", "Cherry"),
|
||||
qwenTtsFormat: strFromEnv("QWEN_TTS_FORMAT", "mp3"),
|
||||
minioEndPoint: strFromEnv("MINIO_ENDPOINT", ""),
|
||||
minioPort: intFromEnv("MINIO_PORT", 443),
|
||||
minioUseSSL: boolFromEnv("MINIO_USE_SSL", true),
|
||||
minioBucket: strFromEnv("MINIO_BUCKET", ""),
|
||||
minioRegion: strFromEnv("MINIO_REGION", "us-east-1"),
|
||||
minioAccessKey: strFromEnv("MINIO_ACCESS_KEY", ""),
|
||||
minioSecretKey: strFromEnv("MINIO_SECRET_KEY", ""),
|
||||
minioSignedUrlTtlSec: intFromEnv("MINIO_SIGNED_URL_TTL_SEC", 3600),
|
||||
rateLimits: {
|
||||
webhookPerMinute: intFromEnv("WEBHOOK_RPM", 120),
|
||||
authPerMinute: intFromEnv("AUTH_RPM", 30),
|
||||
@@ -69,9 +94,15 @@ const parsed = {
|
||||
|
||||
const ConfigSchema = z.object({
|
||||
port: z.number().int().positive(),
|
||||
stateFilePath: z.string().min(1),
|
||||
logLevel: z.enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"]),
|
||||
appBaseUrl: z.string().min(1),
|
||||
betterAuthSecret: z.string().min(1),
|
||||
betterAuthBasePath: z.string().min(1),
|
||||
betterAuthDevPassword: z.string().min(8),
|
||||
convexDeploymentUrl: z.string(),
|
||||
convexAuthToken: z.string(),
|
||||
convexStateQuery: z.string().min(1),
|
||||
convexStateMutation: z.string().min(1),
|
||||
xWebhookSecret: z.string().min(1),
|
||||
xBearerToken: z.string(),
|
||||
xBotUserId: z.string(),
|
||||
@@ -79,16 +110,19 @@ const ConfigSchema = z.object({
|
||||
polarAccessToken: z.string(),
|
||||
polarServer: z.enum(["production", "sandbox"]),
|
||||
polarProductIds: z.array(z.string().min(1)),
|
||||
ttsApiKey: z.string(),
|
||||
ttsBaseUrl: z.string(),
|
||||
ttsModel: z.string().min(1),
|
||||
ttsVoice: z.string().min(1),
|
||||
s3Bucket: z.string(),
|
||||
s3Region: z.string(),
|
||||
s3Endpoint: z.string(),
|
||||
s3AccessKeyId: z.string(),
|
||||
s3SecretAccessKey: z.string(),
|
||||
s3SignedUrlTtlSec: z.number().int().positive(),
|
||||
qwenTtsApiKey: z.string(),
|
||||
qwenTtsBaseUrl: z.string().min(1),
|
||||
qwenTtsModel: z.string().min(1),
|
||||
qwenTtsVoice: z.string().min(1),
|
||||
qwenTtsFormat: z.string().min(1),
|
||||
minioEndPoint: z.string(),
|
||||
minioPort: z.number().int().positive(),
|
||||
minioUseSSL: z.boolean(),
|
||||
minioBucket: z.string(),
|
||||
minioRegion: z.string(),
|
||||
minioAccessKey: z.string(),
|
||||
minioSecretKey: z.string(),
|
||||
minioSignedUrlTtlSec: z.number().int().positive(),
|
||||
rateLimits: z.object({
|
||||
webhookPerMinute: z.number().int().positive(),
|
||||
authPerMinute: z.number().int().positive(),
|
||||
|
||||
Reference in New Issue
Block a user