- 新增 storage 抽象:local 与 s3: 前缀兼容(不改 schema) - invoice-pool 上传/预览/ocr 读取适配 S3/MinIO - trialrun compose 增加 minio profile + env 示例与 runbook 指引 - 更新 README 与 v3 CSV 状态推进
105 行
4.0 KiB
JavaScript
105 行
4.0 KiB
JavaScript
const path = require("node:path");
|
|
|
|
const ONE_DAY_SECONDS = 24 * 60 * 60;
|
|
const ONE_MINUTE_SECONDS = 60;
|
|
|
|
function requiredEnv(name) {
|
|
const value = process.env[name];
|
|
if (!value) {
|
|
throw new Error(`Missing required env: ${name}`);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function getConfig() {
|
|
const nodeEnv = process.env.NODE_ENV ?? "development";
|
|
const serverRoot = path.resolve(__dirname, "..");
|
|
const storageDir = process.env.STORAGE_DIR ?? "generated/storage";
|
|
const clientDistDir = process.env.CLIENT_DIST_DIR ?? "../client/dist";
|
|
|
|
return {
|
|
nodeEnv,
|
|
port: Number(process.env.PORT ?? 3000),
|
|
host: process.env.HOST ?? "0.0.0.0",
|
|
|
|
metricsEnabled: process.env.METRICS_ENABLED !== "false",
|
|
|
|
appOrigin: process.env.APP_ORIGIN ?? "",
|
|
jwtSecret: requiredEnv("JWT_SECRET"),
|
|
|
|
accessTokenTtl: "15m",
|
|
refreshTtlSeconds: 7 * ONE_DAY_SECONDS,
|
|
|
|
refreshCookieName: "refresh_token",
|
|
cookieSecure:
|
|
process.env.COOKIE_SECURE != null
|
|
? process.env.COOKIE_SECURE === "true"
|
|
: nodeEnv === "production",
|
|
|
|
passwordResetCodeTtlSeconds: Number(
|
|
process.env.PASSWORD_RESET_CODE_TTL_SECONDS ?? 10 * 60,
|
|
),
|
|
|
|
devShowPasswordResetCode: process.env.DEV_SHOW_PASSWORD_RESET_CODE === "true",
|
|
|
|
loginFailWindowSeconds: Number(
|
|
process.env.AUTH_LOGIN_FAIL_WINDOW_SECONDS ?? 15 * ONE_MINUTE_SECONDS,
|
|
),
|
|
loginFailMaxAttempts: Number(process.env.AUTH_LOGIN_FAIL_MAX_ATTEMPTS ?? 5),
|
|
loginLockSeconds: Number(process.env.AUTH_LOGIN_LOCK_SECONDS ?? 30 * ONE_MINUTE_SECONDS),
|
|
|
|
appTimezone: process.env.APP_TIMEZONE ?? "Asia/Shanghai",
|
|
storageDir: path.resolve(serverRoot, storageDir),
|
|
storageDriver: process.env.STORAGE_DRIVER ?? "local",
|
|
s3Endpoint: process.env.S3_ENDPOINT ?? "",
|
|
s3Region: process.env.S3_REGION ?? "us-east-1",
|
|
s3Bucket: process.env.S3_BUCKET ?? "",
|
|
s3AccessKeyId: process.env.S3_ACCESS_KEY_ID ?? "",
|
|
s3SecretAccessKey: process.env.S3_SECRET_ACCESS_KEY ?? "",
|
|
s3ForcePathStyle: process.env.S3_FORCE_PATH_STYLE === "true",
|
|
serveClientDist: process.env.SERVE_CLIENT_DIST === "true",
|
|
clientDistDir: path.resolve(serverRoot, clientDistDir),
|
|
signedUrlTtlSeconds: Number(process.env.SIGNED_URL_TTL_SECONDS ?? 600),
|
|
maxUploadSizeBytes: Number(process.env.MAX_UPLOAD_SIZE_BYTES ?? 10 * 1024 * 1024),
|
|
|
|
rateLimitEnabled:
|
|
process.env.RATE_LIMIT_ENABLED != null
|
|
? process.env.RATE_LIMIT_ENABLED === "true"
|
|
: nodeEnv === "production",
|
|
rateLimitLoginMax: Number(process.env.RATE_LIMIT_LOGIN_MAX ?? 10),
|
|
rateLimitLoginWindow: process.env.RATE_LIMIT_LOGIN_WINDOW ?? "1 minute",
|
|
|
|
delegationRevokeCron: process.env.DELEGATION_REVOKE_CRON ?? "0 * * * *",
|
|
|
|
jobDriver: process.env.JOB_DRIVER ?? "cron",
|
|
jobsEnabled: process.env.JOBS_ENABLED !== "false",
|
|
pgBossSchema: process.env.PG_BOSS_SCHEMA ?? "pgboss",
|
|
|
|
ocrProvider: process.env.OCR_PROVIDER ?? "off",
|
|
ocrBatchSize: Number(process.env.OCR_BATCH_SIZE ?? 10),
|
|
ocrLockTtlSeconds: Number(process.env.OCR_LOCK_TTL_SECONDS ?? 300),
|
|
ocrPollCron: process.env.OCR_POLL_CRON ?? "* * * * *",
|
|
ocrMaxAttempts: Number(process.env.OCR_MAX_ATTEMPTS ?? 3),
|
|
ocrTimeoutMs: Number(process.env.OCR_TIMEOUT_MS ?? 5000),
|
|
|
|
invoiceArchiveCron: process.env.INVOICE_ARCHIVE_CRON ?? "30 2 * * *",
|
|
invoiceArchiveUnusedDays: Number(process.env.INVOICE_ARCHIVE_UNUSED_DAYS ?? 90),
|
|
invoiceArchiveBatchSize: Number(process.env.INVOICE_ARCHIVE_BATCH_SIZE ?? 200),
|
|
|
|
tencentSecretId: process.env.TENCENT_SECRET_ID ?? "",
|
|
tencentSecretKey: process.env.TENCENT_SECRET_KEY ?? "",
|
|
tencentOcrRegion: process.env.TENCENT_OCR_REGION ?? "ap-beijing",
|
|
|
|
emailEnabled: process.env.EMAIL_ENABLED === "true",
|
|
emailFrom: process.env.EMAIL_FROM ?? "[email protected]",
|
|
emailBaseUrl: process.env.EMAIL_BASE_URL ?? "",
|
|
smtpHost: process.env.SMTP_HOST ?? "",
|
|
smtpPort: Number(process.env.SMTP_PORT ?? 587),
|
|
smtpSecure: process.env.SMTP_SECURE === "true",
|
|
smtpUser: process.env.SMTP_USER ?? "",
|
|
smtpPass: process.env.SMTP_PASS ?? "",
|
|
};
|
|
}
|
|
|
|
module.exports = { getConfig };
|