flnxi-Wu/license-server/scripts/init-project.ts
2026-06-02 19:25:48 +08:00

116 lines
3.2 KiB
TypeScript

import { PrismaClient } from '.prisma/main-client';
import * as crypto from 'crypto';
const prisma = new PrismaClient();
function getEnv(name: string, fallback = ''): string {
return (process.env[name] || fallback).trim();
}
function getRequiredEnv(name: string): string {
const value = getEnv(name);
if (!value) {
throw new Error(`缺少环境变量:${name}`);
}
return value;
}
function getEncryptionKey(): string {
const key = getRequiredEnv('MAIN_DB_ENCRYPTION_KEY');
if (key.length < 32) {
throw new Error('MAIN_DB_ENCRYPTION_KEY 长度不足 32 字节');
}
return key.substring(0, 32);
}
function encryptPassword(password: string): string {
const key = getEncryptionKey();
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update(password, 'utf8', 'hex');
encrypted += cipher.final('hex');
return `${iv.toString('hex')}:${encrypted}`;
}
function getProjectCode(): string {
const fromArg = process.argv[2]?.trim();
return fromArg || getEnv('LICENSE_PROJECT_CODE', 'flnxi-sucai');
}
function getProjectConfig() {
const postgresUser = getRequiredEnv('POSTGRES_USER');
const postgresPassword = getRequiredEnv('POSTGRES_PASSWORD');
const postgresDb = getRequiredEnv('POSTGRES_DB');
return {
code: getProjectCode(),
name: getEnv('LICENSE_PROJECT_NAME', 'FLNXI素材库'),
description: getEnv('LICENSE_PROJECT_DESCRIPTION', 'FLNXI素材库商业授权项目'),
dbHost: getEnv('PROJECT_DB_HOST', 'postgres'),
dbPort: Number.parseInt(getEnv('PROJECT_DB_PORT', '5432'), 10),
dbName: getEnv('PROJECT_DB_NAME', postgresDb),
dbUser: getEnv('PROJECT_DB_USER', postgresUser),
dbPassword: getEnv('PROJECT_DB_PASSWORD', postgresPassword),
dbSchema: getEnv('PROJECT_DB_SCHEMA', 'public'),
};
}
async function main() {
const config = getProjectConfig();
if (!Number.isFinite(config.dbPort) || config.dbPort <= 0) {
throw new Error('PROJECT_DB_PORT 必须是有效端口号');
}
const encryptedPassword = encryptPassword(config.dbPassword);
const existing = await prisma.project.findUnique({
where: { code: config.code },
});
if (existing) {
await prisma.project.update({
where: { code: config.code },
data: {
name: config.name,
description: config.description,
dbHost: config.dbHost,
dbPort: config.dbPort,
dbName: config.dbName,
dbUser: config.dbUser,
dbPassword: encryptedPassword,
dbSchema: config.dbSchema,
isActive: true,
},
});
console.log(`项目 "${config.code}" 已存在,连接配置已更新。`);
return;
}
await prisma.project.create({
data: {
code: config.code,
name: config.name,
description: config.description,
dbHost: config.dbHost,
dbPort: config.dbPort,
dbName: config.dbName,
dbUser: config.dbUser,
dbPassword: encryptedPassword,
dbSchema: config.dbSchema,
isActive: true,
},
});
console.log(`项目 "${config.code}" 创建成功。`);
}
main()
.catch((error) => {
console.error('初始化项目失败:', error);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});