feat: clear app.config.json5
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
import { App } from '@kevisual/router';
|
||||
import { useConfig } from '@kevisual/use-config';
|
||||
import * as redisLib from './modules/redis.ts';
|
||||
import * as minioLib from './modules/minio.ts';
|
||||
import * as sequelizeLib from './modules/sequelize.ts';
|
||||
import { useContextKey, useContext } from '@kevisual/use-config/context';
|
||||
import { SimpleRouter } from '@kevisual/router/simple';
|
||||
import { OssBase } from '@kevisual/oss/services';
|
||||
useConfig();
|
||||
export const router = useContextKey('router', () => new SimpleRouter());
|
||||
export const oss = useContextKey(
|
||||
'oss',
|
||||
|
||||
10
src/index.ts
10
src/index.ts
@@ -1,13 +1,11 @@
|
||||
import { useConfig } from '@kevisual/use-config';
|
||||
import { config } from './modules/config.ts';
|
||||
import { app } from './app.ts';
|
||||
import './route.ts';
|
||||
const config = useConfig();
|
||||
import { uploadMiddleware } from './routes-simple/upload.ts';
|
||||
import { port } from './modules/config.ts';
|
||||
|
||||
// if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
app.listen(config.port, () => {
|
||||
console.log(`server is running at http://localhost:${config.port}`);
|
||||
app.listen(port, () => {
|
||||
console.log(`server is running at http://localhost:${port}`);
|
||||
});
|
||||
app.server.on(uploadMiddleware);
|
||||
|
||||
console.log(`run ${config.appName} done`);
|
||||
|
||||
@@ -1,292 +1,3 @@
|
||||
// import { useConfig } from '@kevisual/use-config';
|
||||
// import { DataTypes, Model, Op, Sequelize } from 'sequelize';
|
||||
// import { createToken, checkToken } from '@kevisual/auth';
|
||||
// import { cryptPwd } from '@kevisual/auth';
|
||||
// import { customRandom, nanoid, customAlphabet } from 'nanoid';
|
||||
// import { CustomError } from '@kevisual/router';
|
||||
// import { Org } from './org.ts';
|
||||
|
||||
// import { useContextKey } from '@kevisual/use-config/context';
|
||||
// import { Redis } from 'ioredis';
|
||||
// export const redis = useContextKey<Redis>('redis');
|
||||
// const sequelize = useContextKey<Sequelize>('sequelize');
|
||||
// const config = useConfig<{ tokenSecret: string }>();
|
||||
|
||||
// type UserData = {
|
||||
// orgs?: string[];
|
||||
// };
|
||||
// export class User extends Model {
|
||||
// declare id: string;
|
||||
// declare username: string;
|
||||
// declare nickname: string; // 昵称
|
||||
// declare alias: string; // 别名
|
||||
// declare password: string;
|
||||
// declare salt: string;
|
||||
// declare needChangePassword: boolean;
|
||||
// declare description: string;
|
||||
// declare data: UserData;
|
||||
// declare type: string; // user | org | visitor
|
||||
// declare owner: string;
|
||||
// declare orgId: string;
|
||||
// declare email: string;
|
||||
// declare avatar: string;
|
||||
// tokenUser: any;
|
||||
// setTokenUser(tokenUser: any) {
|
||||
// this.tokenUser = tokenUser;
|
||||
// }
|
||||
// /**
|
||||
// * uid 是用于 orgId 的用户id 真实用户的id
|
||||
// * @param uid
|
||||
// * @returns
|
||||
// */
|
||||
// async createToken(uid?: string, loginType?: 'default' | 'plugin' | 'month' | 'season' | 'year') {
|
||||
// const { id, username, type } = this;
|
||||
// let expireTime = 60 * 60 * 24 * 7; // 7 days
|
||||
// switch (loginType) {
|
||||
// case 'plugin':
|
||||
// expireTime = 60 * 60 * 24 * 30 * 12; // 365 days
|
||||
// break;
|
||||
// case 'month':
|
||||
// expireTime = 60 * 60 * 24 * 30; // 30 days
|
||||
// break;
|
||||
// case 'season':
|
||||
// expireTime = 60 * 60 * 24 * 30 * 3; // 90 days
|
||||
// break;
|
||||
// case 'year':
|
||||
// expireTime = 60 * 60 * 24 * 30 * 12; // 365 days
|
||||
// break;
|
||||
// }
|
||||
// const now = new Date().getTime();
|
||||
// const token = await createToken({ id, username, uid, type }, config.tokenSecret);
|
||||
// return { token, expireTime: now + expireTime };
|
||||
// }
|
||||
// static async verifyToken(token: string) {
|
||||
// const ct = await checkToken(token, config.tokenSecret);
|
||||
// const tokenUser = ct.payload;
|
||||
// return tokenUser;
|
||||
// }
|
||||
// static async createUser(username: string, password?: string, description?: string) {
|
||||
// const user = await User.findOne({ where: { username } });
|
||||
// if (user) {
|
||||
// throw new CustomError('User already exists');
|
||||
// }
|
||||
// const salt = nanoid(6);
|
||||
// let needChangePassword = !password;
|
||||
// password = password || '123456';
|
||||
// const cPassword = cryptPwd(password, salt);
|
||||
// return await User.create({ username, password: cPassword, description, salt, needChangePassword });
|
||||
// }
|
||||
// static async createOrg(username: string, owner: string, description?: string) {
|
||||
// const user = await User.findOne({ where: { username } });
|
||||
// if (user) {
|
||||
// throw new CustomError('User already exists');
|
||||
// }
|
||||
// const me = await User.findByPk(owner);
|
||||
// if (!me) {
|
||||
// throw new CustomError('Owner not found');
|
||||
// }
|
||||
// if (me.type !== 'user') {
|
||||
// throw new CustomError('Owner type is not user');
|
||||
// }
|
||||
// const org = await Org.create({ username, description, users: [{ uid: owner, role: 'owner' }] });
|
||||
// const newUser = await User.create({ username, password: '', description, type: 'org', owner, orgId: org.id });
|
||||
// // owner add
|
||||
// await redis.del(`user:${me.id}:orgs`);
|
||||
// return newUser;
|
||||
// }
|
||||
// createPassword(password: string) {
|
||||
// const salt = this.salt;
|
||||
// const cPassword = cryptPwd(password, salt);
|
||||
// this.password = cPassword;
|
||||
// return cPassword;
|
||||
// }
|
||||
// checkPassword(password: string) {
|
||||
// const salt = this.salt;
|
||||
// const cPassword = cryptPwd(password, salt);
|
||||
// return this.password === cPassword;
|
||||
// }
|
||||
// async getInfo() {
|
||||
// const orgs = await this.getOrgs();
|
||||
// return {
|
||||
// id: this.id,
|
||||
// username: this.username,
|
||||
// nickname: this.nickname,
|
||||
// description: this.description,
|
||||
// needChangePassword: this.needChangePassword,
|
||||
// type: this.type,
|
||||
// avatar: this.avatar,
|
||||
// orgs,
|
||||
// };
|
||||
// }
|
||||
// async getOrgs() {
|
||||
// let id = this.id;
|
||||
// if (this.type === 'org') {
|
||||
// if (this.tokenUser && this.tokenUser.uid) {
|
||||
// id = this.tokenUser.uid;
|
||||
// } else {
|
||||
// console.log('getOrgs', 'no uid', this.id, this.username);
|
||||
// throw new CustomError('Permission denied');
|
||||
// }
|
||||
// }
|
||||
// const cache = await redis.get(`user:${id}:orgs`);
|
||||
// if (cache) {
|
||||
// return JSON.parse(cache) as string[];
|
||||
// }
|
||||
// const orgs = await Org.findAll({
|
||||
// order: [['updatedAt', 'DESC']],
|
||||
// where: {
|
||||
// users: {
|
||||
// [Op.contains]: [
|
||||
// {
|
||||
// uid: id,
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// const orgNames = orgs.map((org) => org.username);
|
||||
// if (orgNames.length > 0) {
|
||||
// await redis.set(`user:${id}:orgs`, JSON.stringify(orgNames), 'EX', 60 * 60); // 1 hour
|
||||
// }
|
||||
// return orgNames;
|
||||
// }
|
||||
// async expireOrgs() {
|
||||
// await redis.del(`user:${this.id}:orgs`);
|
||||
// }
|
||||
// }
|
||||
// User.init(
|
||||
// {
|
||||
// id: {
|
||||
// type: DataTypes.UUID,
|
||||
// primaryKey: true,
|
||||
// defaultValue: DataTypes.UUIDV4,
|
||||
// },
|
||||
// username: {
|
||||
// type: DataTypes.STRING,
|
||||
// allowNull: false,
|
||||
// unique: true,
|
||||
// // 用户名或者手机号
|
||||
// // 创建后避免修改的字段,当注册用户后,用户名注册则默认不能用手机号
|
||||
// },
|
||||
// nickname: {
|
||||
// type: DataTypes.TEXT,
|
||||
// allowNull: true,
|
||||
// },
|
||||
// alias: {
|
||||
// type: DataTypes.TEXT,
|
||||
// allowNull: true, // 别名,网络请求的别名,需要唯一,不能和username重复
|
||||
// defaultValue: '',
|
||||
// },
|
||||
// password: {
|
||||
// type: DataTypes.STRING,
|
||||
// allowNull: true,
|
||||
// },
|
||||
// email: {
|
||||
// type: DataTypes.STRING,
|
||||
// allowNull: true,
|
||||
// },
|
||||
// avatar: {
|
||||
// type: DataTypes.TEXT,
|
||||
// allowNull: true,
|
||||
// },
|
||||
// salt: {
|
||||
// type: DataTypes.STRING,
|
||||
// allowNull: true,
|
||||
// },
|
||||
// description: {
|
||||
// type: DataTypes.TEXT,
|
||||
// },
|
||||
// type: {
|
||||
// type: DataTypes.STRING,
|
||||
// defaultValue: 'user',
|
||||
// },
|
||||
// owner: {
|
||||
// type: DataTypes.UUID,
|
||||
// },
|
||||
// orgId: {
|
||||
// type: DataTypes.UUID,
|
||||
// },
|
||||
// needChangePassword: {
|
||||
// type: DataTypes.BOOLEAN,
|
||||
// defaultValue: false,
|
||||
// },
|
||||
// data: {
|
||||
// type: DataTypes.JSONB,
|
||||
// defaultValue: {},
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// sequelize,
|
||||
// tableName: 'cf_user', // codeflow user
|
||||
// paranoid: true,
|
||||
// },
|
||||
// );
|
||||
// User.sync({ alter: true, logging: false })
|
||||
// .then((res) => {
|
||||
// initializeUser();
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// console.error('Sync User error', err);
|
||||
// });
|
||||
|
||||
// const letter = 'abcdefghijklmnopqrstuvwxyz';
|
||||
// const custom = customAlphabet(letter, 6);
|
||||
// export const initializeUser = async (pwd = custom()) => {
|
||||
// const w = await User.findOne({ where: { username: 'root' }, logging: false });
|
||||
// if (!w) {
|
||||
// const root = await User.createUser('root', pwd, '系统管理员');
|
||||
// const org = await User.createOrg('admin', root.id, '管理员');
|
||||
// console.info(' new Users name', root.username, org.username);
|
||||
// console.info('new Users root password', pwd);
|
||||
// console.info('new Users id', root.id, org.id);
|
||||
// const demo = await createDemoUser();
|
||||
// return {
|
||||
// code: 200,
|
||||
// data: { root, org, pwd: pwd, demo },
|
||||
// };
|
||||
// } else {
|
||||
// return {
|
||||
// code: 500,
|
||||
// message: 'Users has been created',
|
||||
// };
|
||||
// }
|
||||
// };
|
||||
// export const createDemoUser = async (username = 'demo', pwd = custom()) => {
|
||||
// const u = await User.findOne({ where: { username }, logging: false });
|
||||
// if (!u) {
|
||||
// const user = await User.createUser(username, pwd, 'demo');
|
||||
// console.info('new Users name', user.username, pwd);
|
||||
// return {
|
||||
// code: 200,
|
||||
// data: { user, pwd: pwd },
|
||||
// };
|
||||
// } else {
|
||||
// console.info('Users has been created', u.username);
|
||||
// return {
|
||||
// code: 500,
|
||||
// message: 'Users has been created',
|
||||
// };
|
||||
// }
|
||||
// };
|
||||
// // initializeUser();
|
||||
|
||||
// export class UserServices extends User {
|
||||
// static async loginByPhone(phone: string) {
|
||||
// let user = await User.findOne({ where: { username: phone } });
|
||||
// let isNew = false;
|
||||
// if (!user) {
|
||||
// user = await User.createUser(phone, phone.slice(-6));
|
||||
// isNew = true;
|
||||
// }
|
||||
// const token = await user.createToken(null, 'season');
|
||||
// return { ...token, isNew };
|
||||
// }
|
||||
// static initializeUser = initializeUser;
|
||||
// static createDemoUser = createDemoUser;
|
||||
// }
|
||||
|
||||
// useContextKey('UserModel', () => UserServices);
|
||||
|
||||
import { User, UserInit, UserServices } from '@kevisual/code-center-module/models';
|
||||
export { User, UserInit, UserServices };
|
||||
import { OrgInit } from '@kevisual/code-center-module/models';
|
||||
|
||||
13
src/modules/config.ts
Normal file
13
src/modules/config.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import path from 'path';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
const envFiles = [
|
||||
path.resolve(process.cwd(), '.env.dev'),
|
||||
path.resolve(process.cwd(), '.env'),
|
||||
];
|
||||
dotenv.config({
|
||||
path: envFiles,
|
||||
});
|
||||
|
||||
export const config = process.env;
|
||||
export const port = config.PORT || 4005;
|
||||
@@ -1,11 +1,5 @@
|
||||
import { useConfig } from '@kevisual/use-config';
|
||||
|
||||
type MinioConfig = {
|
||||
domain: string;
|
||||
};
|
||||
const config = useConfig<MinioConfig>();
|
||||
|
||||
/**
|
||||
* 用来放cookie的域名
|
||||
*/
|
||||
export const domain = config.domain || ''; // 请在这里填写你的域名
|
||||
export const domain = process.env.DOMAIN || ''; // 请在这里填写你的域名
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { Client, ClientOptions } from 'minio';
|
||||
import { useConfig } from '@kevisual/use-config';
|
||||
|
||||
type MinioConfig = {
|
||||
minio: ClientOptions & { bucketName: string };
|
||||
const minioConfig = {
|
||||
endPoint: process.env.MINIO_ENDPOINT || 'localhost',
|
||||
port: parseInt(process.env.MINIO_PORT || '9000'),
|
||||
useSSL: process.env.MINIO_USE_SSL === 'true',
|
||||
accessKey: process.env.MINIO_ACCESS_KEY,
|
||||
secretKey: process.env.MINIO_SECRET_KEY,
|
||||
};
|
||||
const config = useConfig<MinioConfig>();
|
||||
export const minioClient = new Client(minioConfig);
|
||||
|
||||
const { bucketName, ...minioRest } = config.minio;
|
||||
export const minioClient = new Client(minioRest);
|
||||
export { bucketName };
|
||||
export const bucketName = process.env.MINIO_BUCKET_NAME || 'resources';
|
||||
if (!minioClient) {
|
||||
throw new Error('Minio client not initialized');
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { Redis } from 'ioredis';
|
||||
import { useConfig } from '@kevisual/use-config';
|
||||
|
||||
const config = useConfig<{
|
||||
redis: ConstructorParameters<typeof Redis>;
|
||||
}>();
|
||||
// 配置 Redis 连接
|
||||
export const redis = new Redis({
|
||||
host: 'localhost', // Redis 服务器的主机名或 IP 地址
|
||||
@@ -16,7 +12,6 @@ export const redis = new Redis({
|
||||
return Math.min(times * 50, 2000); // 每次重试时延迟增加
|
||||
},
|
||||
maxRetriesPerRequest: null, // 允许请求重试的次数 (如果需要无限次重试)
|
||||
...config.redis,
|
||||
});
|
||||
|
||||
// 监听连接事件
|
||||
@@ -31,4 +26,3 @@ redis.on('error', (err) => {
|
||||
// 初始化 Redis 客户端
|
||||
export const redisPublisher = new Redis(); // 用于发布消息
|
||||
export const redisSubscriber = new Redis(); // 用于订阅消息
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import { useConfig } from '@kevisual/use-config';
|
||||
import childProcess from 'child_process';
|
||||
const config = useConfig<{
|
||||
appName: string;
|
||||
}>();
|
||||
|
||||
export const selfRestart = async () => {
|
||||
const appName = config.appName || 'codecenter';
|
||||
const appName = 'codecenter';
|
||||
// 检测 pm2 是否安装和是否有 appName 这个应用
|
||||
try {
|
||||
const res = childProcess.execSync(`pm2 list`);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useConfig } from '@kevisual/use-config';
|
||||
import { Sequelize } from 'sequelize';
|
||||
|
||||
type PostgresConfig = {
|
||||
import { config } from './config.ts';
|
||||
export type PostgresConfig = {
|
||||
postgres: {
|
||||
username: string;
|
||||
password: string;
|
||||
@@ -10,14 +9,17 @@ type PostgresConfig = {
|
||||
database: string;
|
||||
};
|
||||
};
|
||||
const config = useConfig<PostgresConfig>();
|
||||
|
||||
const postgresConfig = config.postgres;
|
||||
|
||||
if (!postgresConfig) {
|
||||
console.error('postgres config is required');
|
||||
if (!config.POSTGRES_PASSWORD || !config.POSTGRES_USER) {
|
||||
console.error('postgres config is required password and user');
|
||||
process.exit(1);
|
||||
}
|
||||
const postgresConfig = {
|
||||
username: config.POSTGRES_USER,
|
||||
password: config.POSTGRES_PASSWORD,
|
||||
host: config.POSTGRES_HOST || 'localhost',
|
||||
port: parseInt(config.POSTGRES_PORT || '5432'),
|
||||
database: config.POSTGRES_DB || 'postgres',
|
||||
};
|
||||
// connect to db
|
||||
export const sequelize = new Sequelize({
|
||||
dialect: 'postgres',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import fetch from 'node-fetch';
|
||||
import { useConfig } from '@kevisual/use-config';
|
||||
import { useConfig } from '@kevisual/use-config/env';
|
||||
|
||||
type GithubConfig = {
|
||||
clientId: string;
|
||||
|
||||
Reference in New Issue
Block a user