fix: remove abearxiong/use-config

This commit is contained in:
xion 2024-11-22 22:11:30 +08:00
parent 40f42ca89b
commit 503727c6c4
23 changed files with 134 additions and 26 deletions

View File

@ -69,6 +69,7 @@
}, },
"devDependencies": { "devDependencies": {
"@abearxiong/use-file-store": "^0.0.1", "@abearxiong/use-file-store": "^0.0.1",
"@kevisual/use-config": "^1.0.1",
"@rollup/plugin-alias": "^5.1.1", "@rollup/plugin-alias": "^5.1.1",
"@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-json": "^6.1.0", "@rollup/plugin-json": "^6.1.0",

8
pnpm-lock.yaml generated
View File

@ -126,6 +126,9 @@ importers:
'@abearxiong/use-file-store': '@abearxiong/use-file-store':
specifier: ^0.0.1 specifier: ^0.0.1
version: 0.0.1(esbuild@0.23.1)(typescript@5.6.3) version: 0.0.1(esbuild@0.23.1)(typescript@5.6.3)
'@kevisual/use-config':
specifier: ^1.0.1
version: 1.0.1
'@rollup/plugin-alias': '@rollup/plugin-alias':
specifier: ^5.1.1 specifier: ^5.1.1
version: 5.1.1(rollup@4.27.2) version: 5.1.1(rollup@4.27.2)
@ -1063,6 +1066,9 @@ packages:
'@kevisual/router@0.0.5-alpha-2': '@kevisual/router@0.0.5-alpha-2':
resolution: {integrity: sha512-9cCa7CEji4q2ByMxxaxzqia42EzbBGdNGKqvs25c2qedAvnXbYaRpaiOdNSNiIXg+eTPQ0ah5HDNRcY2XApD8Q==} resolution: {integrity: sha512-9cCa7CEji4q2ByMxxaxzqia42EzbBGdNGKqvs25c2qedAvnXbYaRpaiOdNSNiIXg+eTPQ0ah5HDNRcY2XApD8Q==}
'@kevisual/use-config@1.0.1':
resolution: {integrity: sha512-3osr7pSS/PgvrIGG1Hiv0PUDubkFLei11hI0b9JNHZhnNhqHYv5W21Mr/vUOLJhvn+y5ltlL81ojUePmnYPH7w==}
'@langchain/core@0.3.3': '@langchain/core@0.3.3':
resolution: {integrity: sha512-WAtkmhbdl2T41qzimTzhb3pXCHQxO4onqxzPxgdf3KftQdTwLq0YYBDhozRMZLNAd/+cfH0ymZGaZSsnc9Ogsg==} resolution: {integrity: sha512-WAtkmhbdl2T41qzimTzhb3pXCHQxO4onqxzPxgdf3KftQdTwLq0YYBDhozRMZLNAd/+cfH0ymZGaZSsnc9Ogsg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -4921,6 +4927,8 @@ snapshots:
- bufferutil - bufferutil
- utf-8-validate - utf-8-validate
'@kevisual/use-config@1.0.1': {}
'@langchain/core@0.3.3(openai@4.65.0(encoding@0.1.13)(zod@3.23.8))': '@langchain/core@0.3.3(openai@4.65.0(encoding@0.1.13)(zod@3.23.8))':
dependencies: dependencies:
ansi-styles: 5.2.0 ansi-styles: 5.2.0

View File

@ -1,4 +1,4 @@
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
import { Sequelize } from 'sequelize'; import { Sequelize } from 'sequelize';
import path from 'path'; import path from 'path';
import os from 'os'; import os from 'os';

View File

@ -1,5 +1,5 @@
import { App } from '@kevisual/router'; import { App } from '@kevisual/router';
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
import { dynamicImport } from './lib/dynamic-import.ts'; import { dynamicImport } from './lib/dynamic-import.ts';
import { redisPublisher, redisSubscriber, redis } from './modules/redis.ts'; import { redisPublisher, redisSubscriber, redis } from './modules/redis.ts';
import { minioClient } from './modules/minio.ts'; import { minioClient } from './modules/minio.ts';

View File

@ -1,4 +1,4 @@
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
import { app } from './app.ts'; import { app } from './app.ts';
import './route.ts'; import './route.ts';
const config = useConfig(); const config = useConfig();

View File

@ -1,4 +1,4 @@
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
import { sequelize } from '@/modules/sequelize.ts'; import { sequelize } from '@/modules/sequelize.ts';
import { DataTypes, Model, Op } from 'sequelize'; import { DataTypes, Model, Op } from 'sequelize';
import { createToken, checkToken } from '@kevisual/auth/token'; import { createToken, checkToken } from '@kevisual/auth/token';

View File

@ -1,5 +1,5 @@
import { Queue } from 'bullmq'; import { Queue } from 'bullmq';
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
const config = useConfig(); const config = useConfig();
export const connection = { export const connection = {

View File

@ -1,5 +1,5 @@
import { Client, ClientOptions } from 'minio'; import { Client, ClientOptions } from 'minio';
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
type MinioConfig = { type MinioConfig = {
minio: ClientOptions & { bucketName: string }; minio: ClientOptions & { bucketName: string };

View File

@ -1,5 +1,5 @@
import Neode from 'neode'; import Neode from 'neode';
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
import neo4j from 'neo4j-driver'; import neo4j from 'neo4j-driver';
type NeodeConfig = { type NeodeConfig = {

View File

@ -1,4 +1,4 @@
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
import { Ollama, Message, ChatRequest } from 'ollama'; import { Ollama, Message, ChatRequest } from 'ollama';
const config = useConfig<{ ollama: Ollama['config'] & { model: string } }>(); const config = useConfig<{ ollama: Ollama['config'] & { model: string } }>();

View File

@ -1,5 +1,5 @@
import { Redis } from 'ioredis'; import { Redis } from 'ioredis';
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
const config = useConfig<{ const config = useConfig<{
redis: ConstructorParameters<typeof Redis>; redis: ConstructorParameters<typeof Redis>;

View File

@ -1,4 +1,4 @@
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
import { Sequelize } from 'sequelize'; import { Sequelize } from 'sequelize';
type PostgresConfig = { type PostgresConfig = {

View File

@ -1,4 +1,4 @@
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
import { Sequelize } from 'sequelize'; import { Sequelize } from 'sequelize';
type PostgresConfig = { type PostgresConfig = {

View File

@ -2,7 +2,7 @@
// import { app as adminApp, appendTo } from './admin/index.ts'; // import { app as adminApp, appendTo } from './admin/index.ts';
import './routes/index.ts'; import './routes/index.ts';
import { app } from './app.ts'; import { app } from './app.ts';
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
import { createAuthRoute } from '@kevisual/auth'; import { createAuthRoute } from '@kevisual/auth';
const config = useConfig<{ tokenSecret: string }>(); const config = useConfig<{ tokenSecret: string }>();

View File

@ -1,5 +1,5 @@
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import { useConfig } from '@abearxiong/use-config'; import { useConfig } from '@kevisual/use-config';
type GithubConfig = { type GithubConfig = {
clientId: string; clientId: string;

View File

@ -0,0 +1,22 @@
import { useFileStore } from '@abearxiong/use-file-store';
import glob from 'fast-glob';
import fs from 'fs';
import path from 'path';
export const appsPath = useFileStore('apps', { needExists: true });
export const loadAppInfo = async () => {
const apps = await glob(`${appsPath}/*/\.config.json`, {
cwd: appsPath,
});
const result = apps.map((app) => {
const json = fs.readFileSync(path.join(appsPath, app), 'utf-8');
const pkg = JSON.parse(json);
const { name, version, app: appInfo } = pkg;
if (!name || !version || !appInfo) {
throw new Error('Invalid package.json');
}
return { key: app.split('/')[0], ...appInfo };
});
return result;
};

View File

@ -0,0 +1,10 @@
import fs from 'fs';
export const fileIsExist = (filePath: string): boolean => {
try {
// 使用 F_OK 检查文件或目录是否存在
fs.accessSync(filePath, fs.constants.F_OK);
return true;
} catch (err) {
return false;
}
};

View File

@ -0,0 +1 @@
export * from './app-file.ts';

View File

@ -3,6 +3,7 @@ import { MicroAppModel } from './models.ts';
import { appCheck, installApp } from './module/install-app.ts'; import { appCheck, installApp } from './module/install-app.ts';
import { loadApp } from './module/load-app.ts'; import { loadApp } from './module/load-app.ts';
// 应用上传到 应用管理 的平台
app app
.route({ .route({
path: 'micro-app', path: 'micro-app',
@ -38,6 +39,10 @@ app
.addTo(app); .addTo(app);
// curl http://localhost:4002/api/router?path=micro-app&key=deploy // curl http://localhost:4002/api/router?path=micro-app&key=deploy
// 把对应的应用安装到系统的apps目录下并解压然后把配置项写入数据库配置
// key 是应用的唯一标识和package.json中的key一致绑定关系
// 安装就就一定存在状态。这个时候需要判断这个应用的依赖关系,这个应用的开启状态。
// 修改app的类型这些模块是存在添加不存在则删除。
app app
.route({ .route({
path: 'micro-app', path: 'micro-app',

View File

@ -1,12 +1,10 @@
import { minioClient } from '@/app.ts'; import { minioClient } from '@/app.ts';
import { bucketName } from '@/modules/minio.ts'; import { bucketName } from '@/modules/minio.ts';
import { checkFileExistsSync } from '@/routes/page/module/cache-file.ts'; import { fileIsExist } from '../lib/file.ts';
import { useFileStore } from '@abearxiong/use-file-store';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import * as tar from 'tar'; import * as tar from 'tar';
import { appsPath } from '../lib/index.ts';
const appsPath = useFileStore('apps', { needExists: true });
export type InstallAppOpts = { export type InstallAppOpts = {
path?: string; path?: string;
@ -15,7 +13,7 @@ export type InstallAppOpts = {
export const appCheck = async (opts: InstallAppOpts) => { export const appCheck = async (opts: InstallAppOpts) => {
const { key } = opts; const { key } = opts;
const directory = path.join(appsPath, key); const directory = path.join(appsPath, key);
if (checkFileExistsSync(directory)) { if (fileIsExist(directory)) {
return true; return true;
} }
return false; return false;
@ -25,7 +23,7 @@ export const installApp = async (opts: InstallAppOpts) => {
const fileStream = await minioClient.getObject(bucketName, opts.path); const fileStream = await minioClient.getObject(bucketName, opts.path);
const pathName = opts.path.split('/').pop(); const pathName = opts.path.split('/').pop();
const directory = path.join(appsPath, key); const directory = path.join(appsPath, key);
if (!checkFileExistsSync(directory)) { if (!fileIsExist(directory)) {
fs.mkdirSync(directory, { recursive: true }); fs.mkdirSync(directory, { recursive: true });
} }
const filePath = path.join(directory, pathName); const filePath = path.join(directory, pathName);
@ -44,7 +42,7 @@ export const installApp = async (opts: InstallAppOpts) => {
cwd: extractPath, cwd: extractPath,
}); });
const pkgs = path.join(extractPath, 'package.json'); const pkgs = path.join(extractPath, 'package.json');
if (!checkFileExistsSync(pkgs)) { if (!fileIsExist(pkgs)) {
throw new Error('Invalid package.json'); throw new Error('Invalid package.json');
} }
const json = fs.readFileSync(pkgs, 'utf-8'); const json = fs.readFileSync(pkgs, 'utf-8');
@ -58,3 +56,5 @@ export const installApp = async (opts: InstallAppOpts) => {
// fs.unlinkSync(filePath); // fs.unlinkSync(filePath);
return { path: filePath }; return { path: filePath };
}; };

View File

@ -1,16 +1,17 @@
import { checkFileExistsSync } from '@/routes/page/module/cache-file.ts'; import { fileIsExist } from '../lib/file.ts';
import { useFileStore } from '@abearxiong/use-file-store'; import { useFileStore } from '@abearxiong/use-file-store';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
const appsPath = useFileStore('apps', { needExists: true }); export const appsPath = useFileStore('apps', { needExists: true });
export const loadApp = async (key: string) => {
export const loadAppInfo = async (key: string) => {
const directory = path.join(appsPath, key); const directory = path.join(appsPath, key);
if (!checkFileExistsSync(directory)) { if (!fileIsExist(directory)) {
throw new Error('app not found'); throw new Error('app not found');
} }
const pkgs = path.join(directory, 'package.json'); const pkgs = path.join(directory, 'package.json');
if (!checkFileExistsSync(pkgs)) { if (!fileIsExist(pkgs)) {
throw new Error('Invalid package.json'); throw new Error('Invalid package.json');
} }
const json = fs.readFileSync(pkgs, 'utf-8'); const json = fs.readFileSync(pkgs, 'utf-8');
@ -21,9 +22,21 @@ export const loadApp = async (key: string) => {
} }
const mainEntry = path.join(directory, app.entry); const mainEntry = path.join(directory, app.entry);
if (!checkFileExistsSync(mainEntry)) { if (!fileIsExist(mainEntry)) {
throw new Error('Invalid main entry'); throw new Error('Invalid main entry');
} }
return { mainEntry, app };
};
export const loadApp = async (key: string) => {
const { mainEntry } = await loadAppInfo(key);
// 1. 查询数据库获取app信息查看是否运行中
// 2. 如果运行中,直接返回
// 3. 如果不在运行中加载app
// 3.1 查看app的类型如果是 system-app直接加载
// 3.2 如果是 micro-app查找相关的依赖如果依赖不存在先加载依赖
// 3.3 使用fork加载app
// 4. 记录app的运行状态程序重新启动时重新加载
const main = await import(mainEntry); const main = await import(mainEntry);
return main; return main;
}; };

View File

@ -0,0 +1,37 @@
export enum AppType {
SystemApp = 'system-app',
MicroApp = 'micro-app',
GatewayApp = 'gateway-app',
}
export type AppInfo = {
status?: 'active' | 'inactive'; // 默认运行状态
key: string;
type?: AppType; // 默认类型
entry?: string; // 入口文件
path?: string; // 文件路径
};
export class Manager<T extends AppInfo = any> {
apps: Map<string, T>;
constructor() {
this.apps = new Map();
}
/**
* key是否存在
* @param key
* @returns
*/
checkKey(key: string) {
return this.apps.has(key);
}
/*
* app信息
* @param key
*/
add(app: T) {
this.apps.set(app.key, app);
}
load() {
// 从apps文件夹列表当中中加载app信息
}
}

View File

@ -0,0 +1,11 @@
import { app } from '@/app.ts';
app
.route({
path: 'micro-app-manager',
key: 'list',
})
.define(async (ctx) => {
//
})
.addTo(app);