mirror of
https://github.com/laochan-eacnet/backend.git
synced 2026-09-29 02:08:05 +03:00
add js object to kxml decorator
add config warpper around environment variables
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import pug from 'pug';
|
||||
import { to_bin } from '@kamyu/kbinxml';
|
||||
|
||||
export function kxml(
|
||||
export function kxmlTemplate(
|
||||
templatePath: string,
|
||||
encoding: 'UTF-8' | 'SHIFT_JIS' = 'UTF-8',
|
||||
): MethodDecorator {
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
import _ from 'lodash';
|
||||
import { to_bin } from '@kamyu/kbinxml';
|
||||
|
||||
function serializeValue(value: any, type: string): string {
|
||||
if (
|
||||
[
|
||||
's8',
|
||||
'u8',
|
||||
's16',
|
||||
'u16',
|
||||
's32',
|
||||
'u32',
|
||||
's64',
|
||||
'u64',
|
||||
'float',
|
||||
'double',
|
||||
].includes(type)
|
||||
) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
if (['b', 'bool'].includes('type')) {
|
||||
return value ? '1' : '0';
|
||||
}
|
||||
|
||||
if (['bin', 'binary'].includes(type)) {
|
||||
if (!(value instanceof Buffer)) {
|
||||
throw new Error('binary with non-buffer value');
|
||||
}
|
||||
|
||||
return value.toString('hex');
|
||||
}
|
||||
|
||||
if (['ip4', 'str', 'string'].includes(type)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (type == 'time') {
|
||||
if (value instanceof Date) {
|
||||
return Math.floor(value.valueOf() / 1000).toString();
|
||||
}
|
||||
|
||||
if (typeof value === 'number') {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
throw new Error('time with not date or number');
|
||||
}
|
||||
|
||||
throw new Error(`unsupported type ${type}`);
|
||||
}
|
||||
|
||||
function serializeObject(obj: Object, name: string, linePrefix: string = '') {
|
||||
let output = `${linePrefix}<${name}`;
|
||||
|
||||
const entries = Object.entries(obj);
|
||||
const attrs = entries
|
||||
.filter(v => v[0].startsWith('$'))
|
||||
.map(v => [v[0].substring(1), v[1]]);
|
||||
|
||||
for (const attr of attrs) {
|
||||
output += ` ${attr[0]}="${_.escape(attr[1])}"`;
|
||||
}
|
||||
|
||||
// handle kxml value shit
|
||||
const value = entries.find(v => v[0] == '__value');
|
||||
|
||||
if (value && value[1] instanceof Array) {
|
||||
output += ` __count="${value[1].length}"`;
|
||||
}
|
||||
|
||||
output += '>';
|
||||
|
||||
if (value) {
|
||||
const type = attrs.find(v => v[0] == '__type');
|
||||
|
||||
if (!type) {
|
||||
// or normal xml innerXml?
|
||||
throw new Error(`value with no type in ${name}`);
|
||||
}
|
||||
|
||||
output += (value[1] instanceof Array ? value[1] : [value[1]])
|
||||
.map(v => serializeValue(v, type[1]))
|
||||
.join(' ');
|
||||
} else {
|
||||
const elements = entries
|
||||
.filter(v => !v[0].startsWith('$'));
|
||||
|
||||
if (elements.length) {
|
||||
output += '\n';
|
||||
|
||||
for (const element of elements) {
|
||||
if (element[1] instanceof Array) {
|
||||
for (const item of element[1])
|
||||
output += serializeObject(item, element[0], linePrefix + ' ');
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
output += serializeObject(element[1], element[0], linePrefix + ' ');
|
||||
}
|
||||
|
||||
output += linePrefix;
|
||||
}
|
||||
}
|
||||
|
||||
return output + `</${name}>\n`;
|
||||
}
|
||||
|
||||
export function kxml(topName: string = 'response', encoding: 'UTF-8' | 'SHIFT_JIS' = 'UTF-8'): MethodDecorator {
|
||||
return function (_target, _propertyKey, descriptor) {
|
||||
const orig = descriptor.value as Function;
|
||||
descriptor.value = async function (...args: any[]) {
|
||||
const obj = await orig.apply(this, args);
|
||||
const xml =
|
||||
`<?xml version="1.0" encoding="${encoding}"?>` + serializeObject(obj, topName);
|
||||
const kxml = to_bin(xml);
|
||||
|
||||
return Buffer.from(kxml.data);
|
||||
} as unknown as any;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
console.log(serializeObject({
|
||||
$attr: 'attr1',
|
||||
sb: {
|
||||
$attr: 'attr2',
|
||||
$__type: 'str',
|
||||
__value: 'sba',
|
||||
},
|
||||
sb1: {
|
||||
$attr: 'attr3',
|
||||
nested: {
|
||||
$attr: 'attr4',
|
||||
$__type: 's32',
|
||||
__value: [1, 1, 4, 5, 1, 4],
|
||||
}
|
||||
},
|
||||
array: [{
|
||||
$attr: 'test'
|
||||
}, {
|
||||
$attr: 'test2'
|
||||
}, {
|
||||
$attr: 'test3'
|
||||
}, {
|
||||
$attr: 'test4'
|
||||
}, {
|
||||
$attr: 'test5'
|
||||
}]
|
||||
}, 'test'))
|
||||
|
||||
+10
-14
@@ -1,22 +1,18 @@
|
||||
import { singleton } from 'tsyringe';
|
||||
import { Context, ILaochanService } from '../types.js';
|
||||
import dedent from 'dedent-js';
|
||||
import { to_bin } from '@kamyu/kbinxml';
|
||||
import { kxml } from '../decorators/to-kxml.js';
|
||||
|
||||
@singleton()
|
||||
export class DefaultService implements ILaochanService {
|
||||
async process(ctx: Context): Promise<Buffer> {
|
||||
const tmp = ctx.service.split('.');
|
||||
const module = tmp[0];
|
||||
const method = tmp[1];
|
||||
@kxml()
|
||||
async process(ctx: Context) {
|
||||
const [module, method] = ctx.service.split('.');
|
||||
|
||||
const xml = dedent`
|
||||
<?xml version="1.0" encoding="SHIFT_JIS"?>
|
||||
<response>
|
||||
<${module} method="${method}" status="0"/>
|
||||
</response>
|
||||
`;
|
||||
|
||||
return Buffer.from(to_bin(xml).data);
|
||||
return {
|
||||
[module]: {
|
||||
$method: method,
|
||||
status: '0',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { kxml } from '../../decorators/render-kxml.js';
|
||||
import { kxmlTemplate } from '../../decorators/render-kxml.js';
|
||||
import { ILaochanService } from '../../types.js';
|
||||
import { singleton } from 'tsyringe';
|
||||
|
||||
@singleton()
|
||||
export default class implements ILaochanService {
|
||||
@kxml('facility/get')
|
||||
@kxmlTemplate('facility/get')
|
||||
async process(): Promise<object> {
|
||||
return {
|
||||
status: 0,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { kxml } from '../../decorators/render-kxml.js';
|
||||
import { kxmlTemplate } from '../../decorators/render-kxml.js';
|
||||
import { ILaochanService } from '../../types.js';
|
||||
import { singleton } from 'tsyringe';
|
||||
|
||||
@singleton()
|
||||
export default class implements ILaochanService {
|
||||
@kxml('message/get')
|
||||
@kxmlTemplate('message/get')
|
||||
async process(): Promise<object> {
|
||||
return {
|
||||
status: 0,
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import { kxml } from '../../decorators/render-kxml.js';
|
||||
import { kxml } from '../../decorators/to-kxml.js';
|
||||
import { ILaochanService } from '../../types.js';
|
||||
import { singleton } from 'tsyringe';
|
||||
|
||||
@singleton()
|
||||
export default class implements ILaochanService {
|
||||
@kxml('pcbtracker/alive')
|
||||
@kxml()
|
||||
async process(): Promise<object> {
|
||||
return {
|
||||
status: 0,
|
||||
expire: 3600,
|
||||
time: Math.floor(new Date().valueOf() / 1000),
|
||||
ecEnable: 1,
|
||||
pcbtracker: {
|
||||
$ecenable: 1,
|
||||
$expire: 3600,
|
||||
$method: 'alive',
|
||||
$status: 0,
|
||||
$time: Math.floor(new Date().valueOf() / 1000),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,41 @@
|
||||
import { kxml } from '../../decorators/render-kxml.js';
|
||||
import { ILaochanService } from '../../types.js';
|
||||
import { singleton } from 'tsyringe';
|
||||
import config from '../../utils/config.js';
|
||||
import { kxml } from '../../decorators/to-kxml.js';
|
||||
|
||||
@singleton()
|
||||
export default class implements ILaochanService {
|
||||
@kxml('services/get')
|
||||
async process(): Promise<object> {
|
||||
@kxml()
|
||||
async process() {
|
||||
const selfServices = [
|
||||
'services', 'dlstatus', 'cardmng',
|
||||
'eacoin', 'userdata', 'userid', 'pcbtracker', 'pcbevent',
|
||||
'message', 'facility', 'apsmanager', 'sidmgr', 'package',
|
||||
'uploaders', 'local', 'local2', 'lobby',
|
||||
]
|
||||
|
||||
return {
|
||||
keepaliveUrl:
|
||||
'ping://127.0.0.1/?pa=127.0.0.1&ia=127.0.0.1&ga=127.0.0.1ma=127.0.0.1&t1=2&t2=15&rt=2',
|
||||
ntpUrl: 'ntp://pool.ntp.org',
|
||||
selfUrl: 'http://localhost:10573',
|
||||
};
|
||||
services: {
|
||||
$expire: 43200,
|
||||
$method: 'get',
|
||||
$mode: 'operation',
|
||||
$product_domain: 1,
|
||||
$statuc: 0,
|
||||
item: [
|
||||
{
|
||||
$name: 'keepalive',
|
||||
$url: 'ping://127.0.0.1/?pa=127.0.0.1&ia=127.0.0.1&ga=127.0.0.1ma=127.0.0.1&t1=2&t2=15&rt=2',
|
||||
},
|
||||
{
|
||||
$name: 'ntp',
|
||||
$url: config.ntpUrl,
|
||||
},
|
||||
...selfServices.map(v => ({
|
||||
$name: v,
|
||||
$url: config.selfUrl,
|
||||
}))
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
|
||||
class Config {
|
||||
get port() {
|
||||
return process.env.PORT ? parseInt(process.env.PORT) : 10573;
|
||||
}
|
||||
|
||||
get selfUrl() {
|
||||
return process.env.SELF_URL ?? 'http://127.0.0.1:10573';
|
||||
}
|
||||
|
||||
get ntpUrl() {
|
||||
return process.env.NTP_URL ?? 'ntp://pool.ntp.org';
|
||||
}
|
||||
|
||||
get mongoUrl() {
|
||||
return process.env.MONGO_URL ?? 'mongodb://127.0.0.1:27017';
|
||||
}
|
||||
|
||||
get isDev() {
|
||||
return process.env.NODE_ENV !== 'production';
|
||||
}
|
||||
}
|
||||
|
||||
export const config = new Config();
|
||||
export default config;
|
||||
Reference in New Issue
Block a user