feat: add detect app micro
This commit is contained in:
parent
4bbc531ac7
commit
ce6037ead9
@ -23,7 +23,7 @@ export const loadAppInfo = async (): Promise<AppInfoConfig> => {
|
|||||||
const basePath = path.dirname(pkgs);
|
const basePath = path.dirname(pkgs);
|
||||||
if (!configFile) {
|
if (!configFile) {
|
||||||
configFile = path.join(basePath, 'apps.config.json');
|
configFile = path.join(basePath, 'apps.config.json');
|
||||||
fs.writeFileSync(configFile, JSON.stringify({}));
|
fs.writeFileSync(configFile, JSON.stringify({ list: [] }));
|
||||||
return { list: [] };
|
return { list: [] };
|
||||||
}
|
}
|
||||||
const config = fs.readFileSync(configFile, 'utf-8');
|
const config = fs.readFileSync(configFile, 'utf-8');
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { app } from '@/app.ts';
|
import { app } from '@/app.ts';
|
||||||
import { MicroAppModel } from './models.ts';
|
import { MicroAppModel } from './models.ts';
|
||||||
import { appPathCheck, installApp } from './module/install-app.ts';
|
import { appPathCheck, getAppPathKeys, installApp, installAppFromKey } from './module/install-app.ts';
|
||||||
import { loadApp } from './module/load-app.ts';
|
import { loadApp } from './module/load-app.ts';
|
||||||
import { manager } from './manager-app.ts';
|
import { manager } from './manager-app.ts';
|
||||||
|
|
||||||
@ -10,6 +10,7 @@ app
|
|||||||
path: 'micro-app',
|
path: 'micro-app',
|
||||||
key: 'upload',
|
key: 'upload',
|
||||||
middleware: ['auth'],
|
middleware: ['auth'],
|
||||||
|
description: 'Upload micro app',
|
||||||
})
|
})
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const { files, collection } = ctx.query?.data;
|
const { files, collection } = ctx.query?.data;
|
||||||
@ -48,6 +49,7 @@ app
|
|||||||
.route({
|
.route({
|
||||||
path: 'micro-app',
|
path: 'micro-app',
|
||||||
key: 'deploy',
|
key: 'deploy',
|
||||||
|
description: 'Deploy micro app',
|
||||||
})
|
})
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
// const { id, key} = ctx.query?.data;
|
// const { id, key} = ctx.query?.data;
|
||||||
@ -80,6 +82,7 @@ app
|
|||||||
.route({
|
.route({
|
||||||
path: 'micro-app',
|
path: 'micro-app',
|
||||||
key: 'load',
|
key: 'load',
|
||||||
|
description: 'Load micro app, no use',
|
||||||
})
|
})
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
// const { key } = ctx.query?.data;
|
// const { key } = ctx.query?.data;
|
||||||
@ -95,8 +98,7 @@ app
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
ctx.throw(400, e.message);
|
ctx.throw(400, e.message);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.addTo(app);
|
|
||||||
|
|
||||||
// curl http://localhost:4002/api/router?path=micro-app&key=unload
|
// curl http://localhost:4002/api/router?path=micro-app&key=unload
|
||||||
app
|
app
|
||||||
@ -115,3 +117,39 @@ app
|
|||||||
ctx.body = main;
|
ctx.body = main;
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
|
|
||||||
|
app
|
||||||
|
.route({
|
||||||
|
path: 'micro-app',
|
||||||
|
key: 'detect',
|
||||||
|
description: 'Detect micro app,检测apps的没有加载进来的app模块',
|
||||||
|
})
|
||||||
|
.define(async (ctx) => {
|
||||||
|
const list = manager.getAllAppShowInfo();
|
||||||
|
const appPathKeys = await getAppPathKeys();
|
||||||
|
const notIn = appPathKeys.filter((key) => !list.find((item) => item.key === key));
|
||||||
|
console.log('Not in', notIn);
|
||||||
|
const loadInfo = [];
|
||||||
|
if (notIn.length <= 0) {
|
||||||
|
loadInfo.push('ok');
|
||||||
|
ctx.body = {
|
||||||
|
data: loadInfo,
|
||||||
|
};
|
||||||
|
ctx.message = 'All apps are loaded';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const key of notIn) {
|
||||||
|
try {
|
||||||
|
const { showAppInfo } = await installAppFromKey(key);
|
||||||
|
await manager.add(showAppInfo);
|
||||||
|
loadInfo.push(`Load ${key} success`);
|
||||||
|
} catch (e) {
|
||||||
|
loadInfo.push(`Load ${key} error`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.body = {
|
||||||
|
data: loadInfo,
|
||||||
|
notIn,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.addTo(app);
|
||||||
|
@ -47,7 +47,14 @@ export const installApp = async (opts: InstallAppOpts) => {
|
|||||||
file: filePath,
|
file: filePath,
|
||||||
cwd: extractPath,
|
cwd: extractPath,
|
||||||
});
|
});
|
||||||
const pkgs = path.join(extractPath, 'package.json');
|
return installAppFromKey(key);
|
||||||
|
};
|
||||||
|
export const installAppFromKey = async (key: string) => {
|
||||||
|
const directory = path.join(appsPath, key);
|
||||||
|
if (!fileIsExist(directory)) {
|
||||||
|
throw new Error('App not found');
|
||||||
|
}
|
||||||
|
const pkgs = path.join(directory, 'package.json');
|
||||||
if (!fileIsExist(pkgs)) {
|
if (!fileIsExist(pkgs)) {
|
||||||
throw new Error('Invalid package.json');
|
throw new Error('Invalid package.json');
|
||||||
}
|
}
|
||||||
@ -57,8 +64,7 @@ export const installApp = async (opts: InstallAppOpts) => {
|
|||||||
if (!name || !version || !app) {
|
if (!name || !version || !app) {
|
||||||
throw new Error('Invalid package.json');
|
throw new Error('Invalid package.json');
|
||||||
}
|
}
|
||||||
|
const readmeFile = path.join(directory, 'README.md');
|
||||||
const readmeFile = path.join(extractPath, 'README.md');
|
|
||||||
let readmeDesc = '';
|
let readmeDesc = '';
|
||||||
if (fileIsExist(readmeFile)) {
|
if (fileIsExist(readmeFile)) {
|
||||||
readmeDesc = fs.readFileSync(readmeFile, 'utf-8');
|
readmeDesc = fs.readFileSync(readmeFile, 'utf-8');
|
||||||
@ -71,11 +77,19 @@ export const installApp = async (opts: InstallAppOpts) => {
|
|||||||
version,
|
version,
|
||||||
//
|
//
|
||||||
entry: app?.entry || '',
|
entry: app?.entry || '',
|
||||||
path: extractPath,
|
path: directory,
|
||||||
origin: app,
|
origin: app,
|
||||||
};
|
};
|
||||||
app.key = key;
|
app.key = key;
|
||||||
fs.writeFileSync(pkgs, JSON.stringify(pkg, null, 2));
|
fs.writeFileSync(pkgs, JSON.stringify(pkg, null, 2));
|
||||||
// fs.unlinkSync(filePath);
|
return { pkg, showAppInfo };
|
||||||
return { path: filePath, pkg, showAppInfo };
|
};
|
||||||
|
export const getAppPathKeys = async () => {
|
||||||
|
let files = fs.readdirSync(appsPath);
|
||||||
|
files = files.filter((file) => {
|
||||||
|
const stat = fs.statSync(path.join(appsPath, file));
|
||||||
|
if (file === 'node_modules') return false;
|
||||||
|
return stat.isDirectory();
|
||||||
|
});
|
||||||
|
return files;
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,7 @@ import { fork } from 'child_process';
|
|||||||
import { merge } from 'lodash-es';
|
import { merge } from 'lodash-es';
|
||||||
import { deleteFileAppInfo } from './load-app.ts';
|
import { deleteFileAppInfo } from './load-app.ts';
|
||||||
import { fileIsExist } from '@kevisual/use-config';
|
import { fileIsExist } from '@kevisual/use-config';
|
||||||
|
import path from 'path';
|
||||||
// 共享
|
// 共享
|
||||||
export const existDenpend = [
|
export const existDenpend = [
|
||||||
'sequelize', // commonjs
|
'sequelize', // commonjs
|
||||||
@ -82,8 +83,13 @@ export class Manager<T extends AppInfo = any> {
|
|||||||
if (app.status !== 'running') {
|
if (app.status !== 'running') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!fileIsExist(app.entry)) {
|
if (!fileIsExist(app.path)) {
|
||||||
console.error('file not found');
|
console.error('app is not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pathEntry = path.join(app.path, app.entry);
|
||||||
|
if (!fileIsExist(pathEntry)) {
|
||||||
|
console.error('file entry not found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const entry = app.entry + `?timestamp=${app?.timestamp}`;
|
const entry = app.entry + `?timestamp=${app?.timestamp}`;
|
||||||
@ -102,6 +108,7 @@ export class Manager<T extends AppInfo = any> {
|
|||||||
} else if (app.type === AppType.GatewayApp) {
|
} else if (app.type === AppType.GatewayApp) {
|
||||||
console.log('gateway app not support');
|
console.log('gateway app not support');
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* create new app info
|
* create new app info
|
||||||
@ -124,10 +131,21 @@ export class Manager<T extends AppInfo = any> {
|
|||||||
async load() {
|
async load() {
|
||||||
// 从apps文件夹列表当中中加载app信息
|
// 从apps文件夹列表当中中加载app信息
|
||||||
const appInfos = await loadAppInfo();
|
const appInfos = await loadAppInfo();
|
||||||
|
this.appInfo = appInfos;
|
||||||
const list = appInfos?.list || [];
|
const list = appInfos?.list || [];
|
||||||
for (const app of list) {
|
for (const app of list) {
|
||||||
try {
|
try {
|
||||||
this.loadApp(app);
|
const loaded = await this.loadApp(app);
|
||||||
|
if (!loaded) {
|
||||||
|
// 加载失败,如果是running状态,设置为error
|
||||||
|
if (app.status === 'running') {
|
||||||
|
app.status = 'error';
|
||||||
|
console.log('load app error', app); // save app error info
|
||||||
|
await this.saveAppInfo(app);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// console.log('load app success', app);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('load app', e);
|
console.error('load app', e);
|
||||||
}
|
}
|
||||||
|
8
src/routes/micro-app/test/path-keys.test.ts
Normal file
8
src/routes/micro-app/test/path-keys.test.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { getAppPathKeys } from '../module/install-app.ts';
|
||||||
|
|
||||||
|
const main = () => {
|
||||||
|
const keys = getAppPathKeys();
|
||||||
|
console.log('Keys', keys);
|
||||||
|
};
|
||||||
|
|
||||||
|
main();
|
Loading…
x
Reference in New Issue
Block a user