Skip to content

Commit

Permalink
fix: 项目无法启动,优化init
Browse files Browse the repository at this point in the history
  • Loading branch information
lc-cn committed Mar 9, 2024
1 parent ce71e11 commit ea1ab42
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 122 deletions.
6 changes: 5 additions & 1 deletion core/bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ if (defaultArgv.init) {
path.resolve(process.cwd(), `bot.config.ts`),
`
import {defineConfig} from 'zhin';
import * as path from 'path';
export default defineConfig((env)=>{
return {
Expand All @@ -51,11 +52,14 @@ export default defineConfig((env)=>{
env.mode==='dev' && 'hmr',
'pluginManager',
'setup',
]
].filter(Boolean)
}
})
`,
);
fs.mkdirSync(path.resolve(process.cwd(), `plugins`));
fs.writeFileSync(path.resolve(process.cwd(), `.env`), ``);
fs.writeFileSync(path.resolve(process.cwd(), `.env.${defaultArgv.mode}`), ``);
console.log(`请在.${defaultArgv.mode}.env中配置相应参数后再次调用\`npx zhin -m ${defaultArgv.mode}\` 启动`);
process.exit(0);
}
Expand Down
7 changes: 3 additions & 4 deletions core/src/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { App } from '@/app';
import { EventEmitter } from 'events';
import { Message } from '@/message';
import path from 'path';
import * as process from 'process';
import { getLogger, Logger } from 'log4js';
import { Dict } from '@/types';
import { WORK_DIR } from '@/constans';

export type AdapterBot<A extends Adapter> = A extends Adapter<infer B> ? B : unknown;
export type AdapterReceive<A extends Adapter> = A extends Adapter<infer B, infer R> ? R : unknown;
Expand Down Expand Up @@ -144,10 +144,9 @@ export namespace Adapter {
forward_length?: number;
} & T;
export function load(name: string) {
const projectWorkDir = process.env.PWD || process.cwd();
const maybePath = [
path.join(projectWorkDir, 'node_modules', `@zhinjs`, name), // 官方适配器
path.join(projectWorkDir, 'node_modules', `zhin-` + name), // 社区适配器
path.join(WORK_DIR, 'node_modules', `@zhinjs`, name), // 官方适配器
path.join(WORK_DIR, 'node_modules', `zhin-` + name), // 社区适配器
];
for (const adapterPath of maybePath) {
let result = null;
Expand Down
19 changes: 8 additions & 11 deletions core/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Middleware } from '@/middleware';
import { Plugin, PluginMap } from '@/plugin';
import { Bot, Dict, LogLevel } from '@/types';
import { deepMerge, loadModule, remove } from '@/utils';
import { AppKey, Required } from '@/constans';
import { APP_KEY, REQUIRED_KEY, WORK_DIR } from '@/constans';
import path from 'path';
import { Adapter, AdapterBot, AdapterReceive } from '@/adapter';
import { Message } from '@/message';
Expand All @@ -20,9 +20,6 @@ export function defineConfig(
}
export class App extends EventEmitter {
logger: Logger = getLogger(`[zhin]`);
get work_dir() {
return process.env.PWD || process.cwd();
}
adapters: Map<string, Adapter> = new Map<string, Adapter>();
middlewares: Middleware[] = [];
plugins: PluginMap = new PluginMap();
Expand Down Expand Up @@ -153,7 +150,7 @@ export class App extends EventEmitter {
}
plugin(plugin: Plugin): this {
this.emit('plugin-beforeMount', plugin);
plugin[AppKey] = this;
plugin[APP_KEY] = this;
plugin.mounted(() => {
for (const [name, service] of (plugin as Plugin).services) {
this.logger.debug(`new service(${name.toString()}) register from from(${plugin.display_name})`);
Expand Down Expand Up @@ -241,13 +238,13 @@ export class App extends EventEmitter {
if (!plugin) throw new Error(`"${entry}" is not a valid plugin`);
if (this.plugins.has(plugin.name)) return this;
}
const userPluginDirs = (this.config.pluginDirs || []).map(dir => path.resolve(this.work_dir, dir));
const userPluginDirs = (this.config.pluginDirs || []).map(dir => path.resolve(WORK_DIR, dir));
for (const pluginDir of userPluginDirs) {
plugin.name = plugin.name.replace(`${pluginDir}${path.sep}`, '');
}
this.plugins.set(plugin.name, plugin);
if (plugin[Required].length) {
const requiredServices = plugin[Required];
if (plugin[REQUIRED_KEY].length) {
const requiredServices = plugin[REQUIRED_KEY];
const mountFn = () => {
if (requiredServices.every(key => !!this[key])) {
this.plugin(plugin);
Expand Down Expand Up @@ -292,7 +289,7 @@ export class App extends EventEmitter {
}
this.emit('plugin-beforeUnmount', plugin);
this.plugins.delete(plugin.name);
plugin[AppKey] = null;
plugin[APP_KEY] = null;
for (const [name, service] of plugin.services) {
this.emit('service-destroy', name, service);
}
Expand All @@ -314,10 +311,10 @@ export class App extends EventEmitter {
loadPlugin(name: string): this {
const maybePath = [
...(this.config.pluginDirs || []).map(dir => {
return path.resolve(this.work_dir, dir, name);
return path.resolve(WORK_DIR, dir, name);
}), // 用户自己的插件
path.resolve(__dirname, 'plugins', name), // 内置插件
path.resolve(this.work_dir, 'node_modules', name), //社区插件
path.resolve(WORK_DIR, 'node_modules', name), //社区插件
];
let loaded: boolean = false,
error: unknown;
Expand Down
5 changes: 3 additions & 2 deletions core/src/constans.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export const AppKey=Symbol('AppKey')
export const Required=Symbol('RequiredServices')
export const APP_KEY = Symbol('AppKey');
export const REQUIRED_KEY = Symbol('RequiredServices');
export const WORK_DIR = process.env.PWD || process.cwd();
13 changes: 6 additions & 7 deletions core/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ import { EventEmitter } from 'events';
import { Middleware } from '@/middleware';
import { getCallerStack, remove } from '@/utils';
import { App } from '@/app';
import { AppKey, Required } from '@/constans';
import { APP_KEY, REQUIRED_KEY, WORK_DIR } from '@/constans';
import { Dict } from '@/types';
import path from 'path';
import { Adapter } from '@/adapter';
import * as process from 'process';

export interface Plugin extends Plugin.Options {}

Expand All @@ -16,7 +15,7 @@ export class Plugin extends EventEmitter {
disposes: Function[] = [];
priority: number;
isMounted: boolean = false;
[Required]: (keyof App.Services)[] = [];
[REQUIRED_KEY]: (keyof App.Services)[] = [];
filePath: string;
setup: boolean = false;
private lifecycle: Dict<Plugin.CallBack[]> = {};
Expand All @@ -26,10 +25,10 @@ export class Plugin extends EventEmitter {
commands: Map<string, Command> = new Map<string, Command>();
middlewares: Middleware[] = [];
private _name?: string;
[AppKey]: App | null = null;
[APP_KEY]: App | null = null;

get app() {
return this[AppKey];
return this[APP_KEY];
}

get display_name() {
Expand Down Expand Up @@ -65,7 +64,7 @@ export class Plugin extends EventEmitter {
stack.shift(); // 排除当前文件调用
this.filePath = stack[0]?.getFileName()!;
this.display_name = options.name!;
const prefixArr = [path.join(__dirname, 'plugins'), path.join(process.env.PWD!, 'node_modules')];
const prefixArr = [path.join(__dirname, 'plugins'), path.join(WORK_DIR, 'node_modules')];
this.name = this.filePath;
for (const prefix of prefixArr) {
this.name = this.name.replace(`${prefix}${path.sep}`, '');
Expand All @@ -83,7 +82,7 @@ export class Plugin extends EventEmitter {
}

required<T extends keyof App.Services>(...services: (keyof App.Services)[]) {
this[Required].push(...services);
this[REQUIRED_KEY].push(...services);
}

service<T extends keyof App.Services>(name: T): App.Services[T];
Expand Down
5 changes: 3 additions & 2 deletions core/src/plugins/hmr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { App, Plugin, wrapExport } from '@';
import * as path from 'path';
import * as fs from 'fs';
import * as process from 'process';
import { WORK_DIR } from '@/constans';

const HMR = new Plugin('HMR');
let watcher: FSWatcher;
Expand All @@ -19,11 +20,11 @@ HMR.mounted(app => {
const watchDirs = [
// 只监听本地插件和内置插件的变更,模块的管不了
...(app.config.pluginDirs || []).map(dir => {
return path.resolve(process.env.PWD!, dir);
return path.resolve(WORK_DIR, dir);
}), // 本地目录插件
__dirname, // 内置插件
...configFiles,
path.resolve(process.env.PWD!, `.${process.env.mode}.env`), // 环境变量
path.resolve(WORK_DIR, `.${process.env.mode}.env`), // 环境变量
].filter(Boolean);
watcher = watch(
watchDirs.filter(p => {
Expand Down
6 changes: 3 additions & 3 deletions core/src/plugins/setup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Adapter, App, ArgsType, Command, getCallerStack, Message, Middleware } from '@';
import { Plugin } from '@/plugin';
import * as path from 'path';
import process from 'process';
import { WORK_DIR } from '@/constans';
const setupPlugin = new Plugin('setup');
const resolveCallerPlugin = (): [boolean, Plugin] => {
const callerStack = getCallerStack().map(caller => caller.getFileName());
Expand All @@ -18,8 +18,8 @@ const resolveCallerPlugin = (): [boolean, Plugin] => {

const prefixArr = [
path.join(__dirname),
path.join(process.env.PWD!, 'node_modules'),
...(setupPlugin.app?.config.pluginDirs || []).map(dir => path.resolve(process.env.PWD!, dir)),
path.join(WORK_DIR, 'node_modules'),
...(setupPlugin.app?.config.pluginDirs || []).map(dir => path.resolve(WORK_DIR, dir)),
];
plugin.name = plugin.filePath;
for (const prefix of prefixArr) {
Expand Down
7 changes: 2 additions & 5 deletions core/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import * as path from 'path';
import * as fs from 'fs';
import YAML from 'yaml';
import { Dict, Merge } from '@/types';

export function isEmpty<T>(data: T) {
Expand Down Expand Up @@ -142,13 +139,13 @@ const toFunction = (exp: string): Function => {
};

export function compiler(template: string, ctx: Dict) {
const matched = [...template.matchAll(/{{([^{}]*?)}}/g)];
const matched = [...template.matchAll(/\${([^}]*?)}/g)];
for (const item of matched) {
const tpl = item[1];
let value = getValueWithRuntime(tpl, ctx);
if (value === tpl) continue;
if (typeof value !== 'string') value = JSON.stringify(value, null, 2);
template = template.replace(`{{${item[1]}}}`, value);
template = template.replace(`\${${item[1]}}`, value);
}
return template;
}
Expand Down
7 changes: 4 additions & 3 deletions core/src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'path';
import * as fs from 'fs';
import { deepMerge } from '@/utils';
import process from 'process';
import { WORK_DIR } from '@/constans';
interface Message {
type: 'start' | 'queue';
body: any;
Expand All @@ -18,15 +19,15 @@ const readEnv = (filename: string) => {
return {};
};
export function startAppWorker(config: string, mode: string) {
const commonEnv = readEnv(path.join(process.env.PWD!, '.env'));
const modeEnv = deepMerge(commonEnv, readEnv(path.join(process.env.PWD!, `.env.${mode}`)));
const commonEnv = readEnv(path.join(WORK_DIR, '.env'));
const modeEnv = deepMerge(commonEnv, readEnv(path.join(WORK_DIR, `.env.${mode}`)));
const forkOptions: ForkOptions = {
env: {
...process.env,
mode,
config,
...modeEnv,
PWD: process.env.PWD || process.cwd(),
PWD: WORK_DIR,
},
execArgv: ['-r', 'jiti/register', '-r', 'tsconfig-paths/register'],
stdio: 'inherit',
Expand Down
85 changes: 1 addition & 84 deletions test/plugins/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,88 +64,5 @@ test.mounted(() => {
},
});
});
function xml2Json(xmlText: string) {
const parse = (xmlText: string) => {
xmlText = xmlText.replace(/\s+/g, '');
const xmlRegexp = /<([^>]+)>([^<>]+)<\/\1>/;
const result: Record<string, any> = {};
while (xmlText.length) {
const match = xmlRegexp.exec(xmlText);
if (!match) break;
const [, tagName, content] = match;
if (/(\$\{[^}]+})/.test(content)) {
const [...matches] = content.matchAll(/(\$\{[^}]+})/g);
const keys = matches.map(([item]) => item);
const obj = Object.fromEntries(
keys
.map(key => {
return [key.slice(2, -1), result[key.slice(2, -1)]];
})
.filter(([_, value]) => value !== undefined),
);
const ks = Object.keys(obj);
if (ks.length) {
result[tagName] = obj;
for (const key of ks) {
delete result[key];
}
} else {
if (result[tagName]) {
result[tagName] = [result[tagName], content];
} else {
result[tagName] = content;
}
}
delete result[content.slice(2, -1)];
} else {
if (result[tagName]) {
result[tagName] = [result[tagName], content];
} else {
result[tagName] = content;
}
}
xmlText = xmlText.replace(`<${tagName}>${content}<${tagName}>`, `\${${tagName}}`);
}
return result;
};
if (!/^<xml>(.+)<\/xml>$/.test(xmlText)) throw new Error('Invalid XML string');
const temp = xmlText.match(/^<xml>(.+)<\/xml>$/) as RegExpMatchArray;
return parse(temp[1]);
}
export function json2Xml(content: any, level = 0): string {
const _stringify = (content: any) => {
if (typeof content !== 'object') return content;
return Object.entries(content)
.map(([key, value]) => {
if (Array.isArray(value)) return value.map(v => `<${key}>${json2Xml(v, level + 1)}</${key}>`).join('\n');
if (typeof value === 'object') return `<${key}>\n${json2Xml(value, level + 1)}\n</${key}>`;
return `<${key}>${value}</${key}>`;
})
.join('\n');
};
return `<xml>${_stringify(content)}</xml>`;
}
// console.log(
// xml2Json(
// `
// <xml>
// <test>123</test>
// <foo>
// <bar>
// <a1>b2</a1>
// </bar>
// <bar>abc</bar>
// </foo>
// </xml>
// `.trimStart(),
// ),
// );
// console.log(
// json2Xml({
// test: 123,
// foo: {
// bar: [{ a1: 'b2' }, 'abc'],
// },
// }),
// );
test.command('钓鱼').action(() => '一天天的就知道钓鱼,该上学上学,该上班上班');
export default test;
Loading

0 comments on commit ea1ab42

Please sign in to comment.