oox 0.3.0-beta9 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +29 -32
- package/app.js +131 -143
- package/bin/argv.js +63 -70
- package/bin/cli.js +57 -43
- package/bin/configurer.js +60 -62
- package/bin/loader.mjs +392 -279
- package/bin/proxy-import.js +12 -0
- package/bin/proxy-require.js +88 -0
- package/bin/register.js +46 -55
- package/bin/starter.js +63 -66
- package/index.js +155 -168
- package/index.mjs +4 -4
- package/logger.js +25 -40
- package/modules/http/index.js +234 -192
- package/modules/http/utils.js +74 -73
- package/modules/index.js +86 -88
- package/modules/module.js +11 -16
- package/modules/socketio/client.js +97 -101
- package/modules/socketio/index.js +171 -168
- package/modules/socketio/server.js +188 -136
- package/modules/socketio/socket.js +1 -4
- package/package.json +14 -12
- package/types/app.d.ts +50 -51
- package/types/bin/argv.d.ts +8 -8
- package/types/bin/cli.d.ts +6 -2
- package/types/bin/configurer.d.ts +3 -1
- package/types/bin/proxy-import.d.ts +4 -0
- package/types/bin/proxy-require.d.ts +5 -0
- package/types/bin/register.d.ts +1 -1
- package/types/bin/starter.d.ts +5 -1
- package/types/index.d.ts +78 -76
- package/types/logger.d.ts +5 -4
- package/types/modules/http/index.d.ts +58 -47
- package/types/modules/http/utils.d.ts +14 -17
- package/types/modules/index.d.ts +24 -24
- package/types/modules/module.d.ts +11 -13
- package/types/modules/socketio/client.d.ts +23 -23
- package/types/modules/socketio/index.d.ts +37 -37
- package/types/modules/socketio/server.d.ts +44 -35
- package/types/modules/socketio/socket.d.ts +11 -11
- package/types/utils.d.ts +6 -6
- package/utils.js +57 -63
- package/bin/proxyer.js +0 -61
- package/types/bin/proxyer.d.ts +0 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { register } from 'node:module';
|
|
2
|
+
import * as oox from '../index.js';
|
|
3
|
+
/**
|
|
4
|
+
* 注册ECMAScript Module加载器
|
|
5
|
+
*/
|
|
6
|
+
export async function registModuleLoader() {
|
|
7
|
+
register(import.meta.resolve('oox/loader'), import.meta.url, {
|
|
8
|
+
data: {
|
|
9
|
+
ooxConfig: oox.config
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import * as oox from '../index.js';
|
|
5
|
+
import { Module } from 'node:module';
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
/**
|
|
8
|
+
* 为了不重复创建Proxy,这个对象用于保存各个RPC服务的各个属性Proxy
|
|
9
|
+
*/
|
|
10
|
+
const rpcServiceAttrMap = Object.create(null);
|
|
11
|
+
/**
|
|
12
|
+
* 重写 require 缓存
|
|
13
|
+
*/
|
|
14
|
+
function rewriteModuleCache(id, exports) {
|
|
15
|
+
const pathname = id.split(path.sep).slice(0, -1).join(path.sep);
|
|
16
|
+
const pathSplit = pathname.split(path.sep);
|
|
17
|
+
const paths = pathSplit.map((v, i, a) => a.slice(0, i + 1).concat('node_modules').join(path.sep)).reverse();
|
|
18
|
+
const m = new Module(id);
|
|
19
|
+
m.path = pathname;
|
|
20
|
+
m.exports = exports;
|
|
21
|
+
m.filename = m.id;
|
|
22
|
+
m.loaded = true;
|
|
23
|
+
m.children = [];
|
|
24
|
+
m.paths = paths;
|
|
25
|
+
require.cache[id] = m;
|
|
26
|
+
}
|
|
27
|
+
function dotCall(name, action) {
|
|
28
|
+
return new Proxy(function () { }, {
|
|
29
|
+
get(target, key) {
|
|
30
|
+
const attrKey = name + '.' + (action ? action + '.' + key : key);
|
|
31
|
+
if (rpcServiceAttrMap) {
|
|
32
|
+
// 不重复创建Proxy
|
|
33
|
+
return rpcServiceAttrMap[attrKey];
|
|
34
|
+
}
|
|
35
|
+
const attrProxy = dotCall(name, attrKey);
|
|
36
|
+
rpcServiceAttrMap[attrKey] = attrProxy;
|
|
37
|
+
return attrProxy;
|
|
38
|
+
},
|
|
39
|
+
has(target, key) { return true; },
|
|
40
|
+
apply(target, thisArg, args) {
|
|
41
|
+
return oox.rpc(name, action, args);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export function proxyGroup(groupDirectory, excludes = []) {
|
|
46
|
+
if (!groupDirectory)
|
|
47
|
+
return;
|
|
48
|
+
const directory = path.resolve(groupDirectory);
|
|
49
|
+
const stat = fs.statSync(directory);
|
|
50
|
+
if (!stat.isDirectory())
|
|
51
|
+
throw new Error('group must be directory');
|
|
52
|
+
const subs = fs.readdirSync(directory);
|
|
53
|
+
for (const filename of subs) {
|
|
54
|
+
const fullPath = path.resolve(directory + path.sep + filename);
|
|
55
|
+
const stat = fs.statSync(fullPath);
|
|
56
|
+
let id = '', name = '';
|
|
57
|
+
if (stat.isDirectory()) {
|
|
58
|
+
const entries = fs.readdirSync(fullPath);
|
|
59
|
+
for (const entry of entries) {
|
|
60
|
+
if (/^index\.((\w?js)|(ts\w?))$/.test(entry))
|
|
61
|
+
id = path.resolve(fullPath, entry);
|
|
62
|
+
}
|
|
63
|
+
name = filename;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const scriptMatch = filename.match(/(\w+)\.((\w?js)|(ts\w?))$/);
|
|
67
|
+
if (!scriptMatch)
|
|
68
|
+
continue;
|
|
69
|
+
id = fullPath;
|
|
70
|
+
name = scriptMatch[1];
|
|
71
|
+
}
|
|
72
|
+
if (!excludes.includes(name))
|
|
73
|
+
rewriteModuleCache(id, dotCall(name, ''));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 将所有 group 目录下的 commonjs require 转换为 RPC
|
|
78
|
+
*/
|
|
79
|
+
export function inGroupConvertRequireToRPC() {
|
|
80
|
+
const { name, group, ignore } = oox.config;
|
|
81
|
+
// 代理<服务间调用>
|
|
82
|
+
if (group) {
|
|
83
|
+
const excludes = [name];
|
|
84
|
+
if (Array.isArray(ignore))
|
|
85
|
+
excludes.push(...ignore);
|
|
86
|
+
proxyGroup(group, excludes);
|
|
87
|
+
}
|
|
88
|
+
}
|
package/bin/register.js
CHANGED
|
@@ -1,55 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (urlObject.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
await delay(
|
|
36
|
-
connect(url
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
connect(url);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
async function registry(urls) {
|
|
49
|
-
if ('string' === typeof urls)
|
|
50
|
-
urls = [urls];
|
|
51
|
-
for (const url of urls) {
|
|
52
|
-
connect(urlFormatter(url));
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
exports.registry = registry;
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import * as oox from '../index.js';
|
|
3
|
+
import { default as SocketIOModule } from '../modules/socketio/index.js';
|
|
4
|
+
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
5
|
+
function urlFormatter(url) {
|
|
6
|
+
let _url = SocketIOModule.genWebSocketUrl(url);
|
|
7
|
+
const urlObject = new URL(_url);
|
|
8
|
+
if (urlObject.pathname === '/' && !url.endsWith('/'))
|
|
9
|
+
_url += '/socket.io';
|
|
10
|
+
return _url;
|
|
11
|
+
}
|
|
12
|
+
async function connect(url, prevError = null) {
|
|
13
|
+
const socketio = oox.modules.get('socketio');
|
|
14
|
+
const { host } = oox.config;
|
|
15
|
+
const { port, path } = socketio.config;
|
|
16
|
+
const urlObject = new URL(url);
|
|
17
|
+
// check if url is self
|
|
18
|
+
if (urlObject.host === host && urlObject.port === String(port))
|
|
19
|
+
return;
|
|
20
|
+
try {
|
|
21
|
+
const socket = await socketio.connect(url);
|
|
22
|
+
onConnection(socket, url);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (!prevError)
|
|
26
|
+
console.log(chalk.red('[Registry]'), chalk.underline.red(`${url}`), 'error.');
|
|
27
|
+
await delay(2000);
|
|
28
|
+
connect(url, error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function onConnection(socket, url) {
|
|
32
|
+
const { name } = socket.data;
|
|
33
|
+
socket.once('disconnect', async () => {
|
|
34
|
+
console.log(chalk.red('[Registry]'), `Service<${name}>`, chalk.underline.red(`${url}`), 'disconnected.');
|
|
35
|
+
await delay(1000);
|
|
36
|
+
connect(url);
|
|
37
|
+
});
|
|
38
|
+
console.log(chalk.green('[Registry]'), `Service<${name}>`, chalk.underline.green(`${url}`), 'connected.');
|
|
39
|
+
}
|
|
40
|
+
export async function registry(urls) {
|
|
41
|
+
if ('string' === typeof urls)
|
|
42
|
+
urls = [urls];
|
|
43
|
+
for (const url of urls) {
|
|
44
|
+
connect(urlFormatter(url));
|
|
45
|
+
}
|
|
46
|
+
}
|
package/bin/starter.js
CHANGED
|
@@ -1,66 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
const methods = await
|
|
27
|
-
oox.setMethods(methods.default || methods);
|
|
28
|
-
}
|
|
29
|
-
async function
|
|
30
|
-
// 加载环境变量
|
|
31
|
-
|
|
32
|
-
Object.assign(oox.config, env);
|
|
33
|
-
// 获取服务入口地址
|
|
34
|
-
const
|
|
35
|
-
oox.config.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
oox.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
console.log(' at',
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
(0, register_1.registry)(env.registry);
|
|
65
|
-
}
|
|
66
|
-
exports.startup = startup;
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import * as oox from '../index.js';
|
|
4
|
+
import { buildConfig } from './configurer.js';
|
|
5
|
+
import { registry } from './register.js';
|
|
6
|
+
function getEntryInfo(env, entryFilename) {
|
|
7
|
+
const entryMatchRegExp = /(\w+)\.((\w?js)|(ts\w?))$/;
|
|
8
|
+
if (!entryFilename) {
|
|
9
|
+
const args = process.argv.slice(2);
|
|
10
|
+
entryFilename = args.find(arg => !arg.includes('=') && entryMatchRegExp.test(arg));
|
|
11
|
+
}
|
|
12
|
+
if (!entryFilename)
|
|
13
|
+
throw new Error('Cannot find entry file: ' + entryFilename);
|
|
14
|
+
const fullPath = path.resolve(entryFilename);
|
|
15
|
+
const filename = path.basename(fullPath);
|
|
16
|
+
const fullDirectory = path.dirname(fullPath);
|
|
17
|
+
const directory = fullDirectory.split(path.sep).pop();
|
|
18
|
+
const groupFullDirectory = env.group ? path.resolve(env.group) : '';
|
|
19
|
+
const entryMatch = filename.match(entryMatchRegExp);
|
|
20
|
+
const entryFilenameWithoutExtension = entryMatch[1];
|
|
21
|
+
const name = entryFilenameWithoutExtension === 'index' && groupFullDirectory !== fullDirectory ? directory : entryFilenameWithoutExtension;
|
|
22
|
+
return { name, path: fullPath, group: groupFullDirectory };
|
|
23
|
+
}
|
|
24
|
+
async function loadEntry(name, entryPath) {
|
|
25
|
+
// oox.config.name = name
|
|
26
|
+
const methods = await import(`file://${entryPath.replace(/\\/g, '/')}`);
|
|
27
|
+
oox.setMethods(methods.default || methods);
|
|
28
|
+
}
|
|
29
|
+
export async function configure(env, entryFilename) {
|
|
30
|
+
// 加载环境变量
|
|
31
|
+
env = await buildConfig(env);
|
|
32
|
+
Object.assign(oox.config, env);
|
|
33
|
+
// 获取服务入口地址
|
|
34
|
+
const entryInfo = getEntryInfo(env, entryFilename);
|
|
35
|
+
oox.config.name = entryInfo.name;
|
|
36
|
+
oox.config.entryInfo = {
|
|
37
|
+
path: entryInfo.path.replace(/\\/g, '/'),
|
|
38
|
+
group: entryInfo.group.replace(/\\/g, '/'),
|
|
39
|
+
};
|
|
40
|
+
// 模块配置
|
|
41
|
+
oox.modules.setConfig(oox.config);
|
|
42
|
+
oox.emit('app:configured');
|
|
43
|
+
return oox.config;
|
|
44
|
+
}
|
|
45
|
+
export async function startup() {
|
|
46
|
+
const { config } = oox;
|
|
47
|
+
// 加载服务
|
|
48
|
+
await loadEntry(config.name, config.entryInfo.path);
|
|
49
|
+
// 服务启动
|
|
50
|
+
await oox.serve();
|
|
51
|
+
oox.emit('app:served');
|
|
52
|
+
const { http, socketio } = oox.modules.builtins;
|
|
53
|
+
console.log();
|
|
54
|
+
console.log('Service', chalk.bold(`${oox.config.name}`), 'running.');
|
|
55
|
+
if (http.config.enabled)
|
|
56
|
+
console.log(' at', chalk.underline.green(http.getUrl()));
|
|
57
|
+
if (socketio.config.enabled)
|
|
58
|
+
console.log(' at', chalk.underline.green(socketio.getUrl()));
|
|
59
|
+
console.log();
|
|
60
|
+
// 服务注册
|
|
61
|
+
if (config.registry)
|
|
62
|
+
registry(config.registry);
|
|
63
|
+
}
|