fix: init for model

This commit is contained in:
xion 2025-02-28 03:06:35 +08:00
parent 4feba785d1
commit b5242d0734
9 changed files with 359 additions and 156 deletions

View File

@ -1,8 +1,10 @@
{
"name": "code-center-module",
"version": "0.0.1",
"name": "@kevisual/code-center-module",
"version": "0.0.7-alpha.2",
"description": "",
"main": "index.js",
"main": "dist/system.mjs",
"module": "dist/system.mjs",
"types": "dist/system.d.ts",
"scripts": {
"watch": "rollup -c rollup.config.mjs -w",
"dev": "cross-env NODE_ENV=development nodemon --delay 2.5 -e js,cjs,mjs --exec node dist/app.mjs",
@ -10,15 +12,23 @@
"dev:watch": "cross-env NODE_ENV=development concurrently -n \"Watch,Dev\" -c \"green,blue\" \"npm run watch\" \"sleep 1 && npm run dev\" ",
"build": "rimraf dist && rollup -c rollup.config.mjs"
},
"files": [
"dist",
"src"
],
"keywords": [],
"author": "abearxiong <xiongxiao@xiongxiao.me>",
"license": "MIT",
"type": "module",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@kevisual/auth": "1.0.5",
"@kevisual/router": "^0.0.7",
"@kevisual/use-config": "^1.0.8",
"ioredis": "^5.5.0",
"nanoid": "^5.1.2",
"pg": "^8.13.3",
"sequelize": "^6.37.5",
"socket.io": "^4.8.1",
@ -32,7 +42,6 @@
"@rollup/plugin-node-resolve": "^16.0.0",
"@rollup/plugin-replace": "^6.0.2",
"@rollup/plugin-typescript": "^12.1.2",
"rollup-plugin-esbuild": "^6.2.0",
"@types/archiver": "^6.0.3",
"@types/crypto-js": "^4.2.2",
"@types/formidable": "^3.4.5",
@ -48,8 +57,21 @@
"rollup": "^4.34.8",
"rollup-plugin-copy": "^3.5.0",
"rollup-plugin-dts": "^6.1.1",
"rollup-plugin-esbuild": "^6.2.1",
"tape": "^5.9.0",
"tsx": "^4.19.3",
"typescript": "^5.7.3"
},
"exports": {
".": {
"import": "./dist/system.mjs",
"require": "./dist/system.cjs",
"types": "./dist/system.d.ts"
},
"./lib": {
"import": "./dist/lib.mjs",
"require": "./dist/lib.cjs",
"types": "./dist/lib.d.ts"
}
}
}

20
pnpm-lock.yaml generated
View File

@ -20,6 +20,9 @@ importers:
ioredis:
specifier: ^5.5.0
version: 5.5.0
nanoid:
specifier: ^5.1.2
version: 5.1.2
pg:
specifier: ^8.13.3
version: 8.13.3
@ -100,8 +103,8 @@ importers:
specifier: ^6.1.1
version: 6.1.1(rollup@4.34.8)(typescript@5.7.3)
rollup-plugin-esbuild:
specifier: ^6.2.0
version: 6.2.0(esbuild@0.25.0)(rollup@4.34.8)
specifier: ^6.2.1
version: 6.2.1(esbuild@0.25.0)(rollup@4.34.8)
tape:
specifier: ^5.9.0
version: 5.9.0
@ -1172,6 +1175,11 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
nanoid@5.1.2:
resolution: {integrity: sha512-b+CiXQCNMUGe0Ri64S9SXFcP9hogjAJ2Rd6GdVxhPLRm7mhGaM7VgOvCAJ1ZshfHbqVDI3uqTI5C8/GaKuLI7g==}
engines: {node: ^18 || >=20}
hasBin: true
negotiator@0.6.3:
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
engines: {node: '>= 0.6'}
@ -1375,8 +1383,8 @@ packages:
rollup: ^3.29.4 || ^4
typescript: ^4.5 || ^5.0
rollup-plugin-esbuild@6.2.0:
resolution: {integrity: sha512-LbkHaCahA6ceyWzAd6md2yajNS+HfZmZ5o58ShkZp0cQeZOnZECG2D2xWFNBq5SF6X6pfMK2udkZ+wRtvpzyVQ==}
rollup-plugin-esbuild@6.2.1:
resolution: {integrity: sha512-jTNOMGoMRhs0JuueJrJqbW8tOwxumaWYq+V5i+PD+8ecSCVkuX27tGW7BXqDgoULQ55rO7IdNxPcnsWtshz3AA==}
engines: {node: '>=14.18.0'}
peerDependencies:
esbuild: '>=0.18.0'
@ -2809,6 +2817,8 @@ snapshots:
ms@2.1.3: {}
nanoid@5.1.2: {}
negotiator@0.6.3: {}
node-forge@1.3.1: {}
@ -3006,7 +3016,7 @@ snapshots:
optionalDependencies:
'@babel/code-frame': 7.26.2
rollup-plugin-esbuild@6.2.0(esbuild@0.25.0)(rollup@4.34.8):
rollup-plugin-esbuild@6.2.1(esbuild@0.25.0)(rollup@4.34.8):
dependencies:
debug: 4.4.0(supports-color@5.5.0)
es-module-lexer: 1.6.0

View File

@ -1,23 +1,39 @@
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import * as glob from 'fast-glob';
import path from 'path';
import esbuild from 'rollup-plugin-esbuild';
import alias from '@rollup/plugin-alias';
import replace from '@rollup/plugin-replace';
import pkgs from './package.json' with { type: 'json' };
import dts from 'rollup-plugin-dts';
const isDev = process.env.NODE_ENV === 'development';
const version = pkgs.version|| '1.0.0';
const external = [
/@kevisual\/router(\/.*)?/, //, // 路由
/@kevisual\/use-config(\/.*)?/, //
'sequelize', // 数据库 orm
'ioredis', // redis
'socket.io', // socket.io
'minio', // minio
'pm2',
'pg', // pg
'pino', // pino
'pino-pretty', // pino-pretty
'@msgpack/msgpack', // msgpack
]
/**
* @type {import('rollup').RollupOptions}
*/
const config = {
input: './src/index.ts',
input: './src/lib.ts',
output: {
dir: './dist',
entryFileNames: 'app.mjs',
entryFileNames: 'lib.mjs',
chunkFileNames: '[name]-[hash].mjs',
format: 'esm',
},
@ -31,26 +47,6 @@ const config = {
// only esbuild needs to be configured
entries: [
{ find: '@', replacement: path.resolve('src') }, // 配置 @ 为 src 目录
{ find: 'http', replacement: 'node:http' },
{ find: 'https', replacement: 'node:https' },
{ find: 'fs', replacement: 'node:fs' },
{ find: 'path', replacement: 'node:path' },
{ find: 'crypto', replacement: 'node:crypto' },
{ find: 'zlib', replacement: 'node:zlib' },
{ find: 'stream', replacement: 'node:stream' },
{ find: 'net', replacement: 'node:net' },
{ find: 'tty', replacement: 'node:tty' },
{ find: 'tls', replacement: 'node:tls' },
{ find: 'buffer', replacement: 'node:buffer' },
{ find: 'timers', replacement: 'node:timers' },
// { find: 'string_decoder', replacement: 'node:string_decoder' },
{ find: 'dns', replacement: 'node:dns' },
{ find: 'domain', replacement: 'node:domain' },
{ find: 'os', replacement: 'node:os' },
{ find: 'events', replacement: 'node:events' },
{ find: 'url', replacement: 'node:url' },
{ find: 'assert', replacement: 'node:assert' },
{ find: 'util', replacement: 'node:util' },
],
}),
resolve({
@ -64,21 +60,96 @@ const config = {
}),
json(),
],
external: [
/@kevisual\/router(\/.*)?/, //, // 路由
/@kevisual\/use-config(\/.*)?/, //
'sequelize', // 数据库 orm
'ioredis', // redis
'socket.io', // socket.io
'minio', // minio
'pm2',
'pg', // pg
'pino', // pino
'pino-pretty', // pino-pretty
'@msgpack/msgpack', // msgpack
external: external,
};
const configCjs = {
input: './src/lib.ts',
output: {
dir: './dist',
entryFileNames: 'lib.cjs',
chunkFileNames: '[name]-[hash].cjs',
format: 'cjs',
},
plugins: [
replace({
preventAssignment: true, // 防止意外赋值
DEV_SERVER: JSON.stringify(isDev), // 替换 process.env.NODE_ENV
VERSION: JSON.stringify(version), // 替换版本号
}),
alias({
// only esbuild needs to be configured
entries: [
{ find: '@', replacement: path.resolve('src') }, // 配置 @ 为 src 目录
],
}),
resolve({
preferBuiltins: true, // 强制优先使用内置模块
}),
commonjs(),
esbuild({
target: 'node22', // 目标为 Node.js 14
minify: false, // 启用代码压缩
tsconfig: 'tsconfig.json',
}),
json(),
],
external: external,
};
const dtsConfig = {
input: './src/lib.ts',
output: {
dir: './dist',
entryFileNames: 'lib.d.ts',
format: 'esm',
},
plugins: [
dts(),
],
};
export default config;
const systemConfig = [
{
input: './src/system.ts',
output: {
dir: './dist',
entryFileNames: 'system.mjs',
chunkFileNames: '[name]-[hash].mjs',
format: 'esm',
},
plugins: [
replace({
preventAssignment: true, // 防止意外赋值
DEV_SERVER: JSON.stringify(isDev), // 替换 process.env.NODE_ENV
VERSION: JSON.stringify(version), // 替换版本号
}),
alias({
entries: [
{ find: '@', replacement: path.resolve('src') }, // 配置 @ 为 src 目录
],
}),
resolve({
preferBuiltins: true, // 强制优先使用内置模块
}),
commonjs(),
esbuild({
target: 'node22', // 目标为 Node.js 14
minify: false, // 启用代码压缩
tsconfig: 'tsconfig.json',
}),
json(),
],
external: [...external, ],
},
{
input: './src/system.ts',
output: {
dir: './dist',
entryFileNames: 'system.d.ts',
format: 'esm',
},
plugins: [
dts(),
],
},
]
export default [config, dtsConfig, ...systemConfig];

View File

@ -1,14 +1,21 @@
/**
* redis和sequelizeuseContextKey当中
*/
import { app } from './app.ts';
import { UserServices } from './models/user.ts';
import { Org } from './models/org.ts';
import { UserServices, UserInit } from './models/user.ts';
import { Org, OrgInit } from './models/org.ts';
import { useContextKey } from '@kevisual/use-config/context';
import { Sequelize } from 'sequelize';
import { Redis } from 'ioredis';
export const User = UserServices;
export { Org };
export { Org, OrgInit, UserInit };
export const redis = useContextKey<Redis>('redis');
export const sequelize = useContextKey<Sequelize>('sequelize');
export const UserModel = useContextKey<typeof UserServices>('UserModel');
export const OrgModel = useContextKey<typeof Org>('OrgModel');
export const UserModel = useContextKey<typeof UserServices>('UserModel', () => UserServices);
export const OrgModel = useContextKey<typeof Org>('OrgModel', () => Org);
export { app };
export const init = () => {
OrgInit();
UserInit();
};

View File

@ -1,6 +1,5 @@
import { DataTypes, Model, Sequelize } from 'sequelize';
import { useContextKey } from '@kevisual/use-config/context';
const sequelize = useContextKey<Sequelize>('sequelize');
export class Org extends Model {
declare id: string;
declare username: string;
@ -8,37 +7,40 @@ export class Org extends Model {
declare users: { role: string; uid: string }[];
}
Org.init(
{
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4,
export const OrgInit = (newSequelize?: any) => {
const sequelize = useContextKey<Sequelize>('sequelize');
Org.init(
{
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4,
},
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
description: {
type: DataTypes.STRING,
allowNull: true,
},
users: {
type: DataTypes.JSONB,
allowNull: true,
defaultValue: [],
},
},
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
{
sequelize: newSequelize || sequelize,
modelName: 'cf_org',
paranoid: true,
},
description: {
type: DataTypes.STRING,
allowNull: true,
},
users: {
type: DataTypes.JSONB,
allowNull: true,
defaultValue: [],
},
},
{
sequelize,
modelName: 'cf_org',
paranoid: true,
},
);
Org.sync({ alter: true, logging: false }).catch((e) => {
console.error('Org sync', e);
});
);
Org.sync({ alter: true, logging: false }).catch((e) => {
console.error('Org sync', e);
});
return Org;
};
useContextKey('OrgModel', () => Org);

View File

@ -154,80 +154,83 @@ export class User extends Model {
await redis.del(`user:${this.id}:orgs`);
}
}
User.init(
{
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4,
export const UserInit = (newSequelize?: any) => {
const sequelize = useContextKey<Sequelize>('sequelize');
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重复
},
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: {},
},
},
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
// 用户名或者手机号
// 创建后避免修改的字段,当注册用户后,用户名注册则默认不能用手机号
{
sequelize: newSequelize || sequelize,
tableName: 'cf_user', // codeflow user
paranoid: true,
},
nickname: {
type: DataTypes.TEXT,
allowNull: true,
},
alias: {
type: DataTypes.TEXT,
allowNull: true, // 别名网络请求的别名需要唯一不能和username重复
},
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.JSON,
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);
});
);
User.sync({ alter: true, logging: false })
.then((res) => {
initializeUser();
})
.catch((err) => {
console.error('Sync User error', err);
});
return User;
};
const letter = 'abcdefghijklmnopqrstuvwxyz';
const custom = customAlphabet(letter, 6);
export const initializeUser = async (pwd = custom()) => {

33
src/modules/redis.ts Normal file
View File

@ -0,0 +1,33 @@
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 地址
port: 6379, // Redis 服务器的端口号
// password: 'your_password', // Redis 的密码 (如果有)
db: 0, // 要使用的 Redis 数据库索引 (0-15)
keyPrefix: '', // key 前缀
retryStrategy(times) {
// 连接重试策略
return Math.min(times * 50, 2000); // 每次重试时延迟增加
},
maxRetriesPerRequest: null, // 允许请求重试的次数 (如果需要无限次重试)
...config.redis,
});
// 监听连接事件
redis.on('connect', () => {
console.log('Redis 连接成功');
});
redis.on('error', (err) => {
console.error('Redis 连接错误', err);
});
// 初始化 Redis 客户端
export const redisPublisher = new Redis(); // 用于发布消息
export const redisSubscriber = new Redis(); // 用于订阅消息

26
src/modules/sequelize.ts Normal file
View File

@ -0,0 +1,26 @@
import { useConfig } from '@kevisual/use-config';
import { Sequelize } from 'sequelize';
type PostgresConfig = {
postgres: {
username: string;
password: string;
host: string;
port: number;
database: string;
};
};
const config = useConfig<PostgresConfig>();
const postgresConfig = config.postgres;
if (!postgresConfig) {
console.error('postgres config is required');
process.exit(1);
}
// connect to db
export const sequelize = new Sequelize({
dialect: 'postgres',
...postgresConfig,
// logging: false,
});

29
src/system.ts Normal file
View File

@ -0,0 +1,29 @@
/**
* redis和sequelize的初始化放到库当中
*/
import { useConfig } from '@kevisual/use-config';
import { app } from './app.ts';
import * as sequelizeLib from './modules/sequelize.ts';
export const sequelize = useContextKey('sequelize', () => sequelizeLib.sequelize);
import { UserServices, UserInit } from './models/user.ts';
import { Org, OrgInit } from './models/org.ts';
import * as redisLib from './modules/redis.ts';
import { useContextKey } from '@kevisual/use-config/context';
useConfig();
export const redis = useContextKey('redis', () => redisLib.redis);
export const redisPublisher = useContextKey('redisPublisher', () => redisLib.redisPublisher);
export const redisSubscriber = useContextKey('redisSubscriber', () => redisLib.redisSubscriber);
export const UserModel = useContextKey<typeof UserServices>('UserModel', () => UserServices);
export const OrgModel = useContextKey<typeof Org>('OrgModel', () => Org);
export { app };
export const User = UserServices;
export { Org, OrgInit, UserInit };
export const init = () => {
OrgInit();
UserInit();
};