116 lines
3.2 KiB
TypeScript
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();
|
|
});
|