Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 002f2c47c6 | |||
| 8633d9ea95 | |||
| 07a5d0c8de | |||
| dd76e563c8 | |||
| 7b85ff5b7c | |||
| 359aeb9d63 | |||
| 3901d9fb5f | |||
| c2867da047 | |||
| 65832c9fae | |||
| d9dffa704d | |||
| b39f29de6a | |||
| 56334c6f6e | |||
| 72673b2a67 | |||
| 597bdb721a | |||
| 6e0456d777 | |||
| fb67b06230 | |||
| 203560dcf2 | |||
| 3f58f5992c | |||
| ac16754c9c | |||
| 42d637dd63 | |||
| df0d246136 | |||
| e563e1b507 | |||
| 3b822c613a | |||
| 2967c2a1fe | |||
| 1c579c9789 | |||
| 2fe9bce2ea | |||
| 496d278a93 | |||
| bdf674b678 | |||
| 67fe13deac | |||
| 30846cdc87 | |||
| d8d03149df | |||
| b6d7847a79 | |||
| 58f59f8260 | |||
| f3fa14990f | |||
| 15d1f8392b | |||
| b5fac23c5c | |||
| 148f6c28c4 | |||
| 880065495e | |||
| 7fc70a92d5 | |||
| df6da12a8a |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
.yarn*
|
||||||
.vscode
|
.vscode
|
||||||
.theia
|
.theia
|
||||||
node_modules
|
node_modules
|
||||||
|
|||||||
27
lerna.json
27
lerna.json
@@ -1,17 +1,16 @@
|
|||||||
{
|
{
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"command": {
|
"command": {
|
||||||
"run": {
|
"run": {
|
||||||
"stream": true
|
"stream": true
|
||||||
},
|
|
||||||
"publish": {
|
|
||||||
"access": "public",
|
|
||||||
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -12,14 +12,16 @@
|
|||||||
"build": "lerna run build",
|
"build": "lerna run build",
|
||||||
"ug": "yarn upgrade-interactive --latest",
|
"ug": "yarn upgrade-interactive --latest",
|
||||||
"np": "./script/push.sh",
|
"np": "./script/push.sh",
|
||||||
"lsp": "npm login --registry=https://registry.npmjs.org --scope=@ccms",
|
"lsp": "npm login -scope=@ccms",
|
||||||
"lp": "lerna publish --registry https://registry.npmjs.org",
|
"lp": "lerna publish --verify-access --force-publish",
|
||||||
"lpb": "lerna publish --registry https://registry.npmjs.org --canary --pre-dist-tag beta"
|
"lpb": "lerna publish --preid beta --dist-tag beta --verify-access --force-publish",
|
||||||
|
"lpc": "lerna publish --canary --preid beta --pre-dist-tag beta --verify-access --force-publish",
|
||||||
|
"lpf": "lerna publish from-package --yes"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"lerna": "^4.0.0"
|
"lerna": "^6.4.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/amqp",
|
"name": "@ccms/amqp",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript amqp package",
|
"description": "MiaoScript amqp package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,17 +19,17 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.21.0",
|
"@ccms/api": "^0.27.6",
|
||||||
"@ccms/common": "^0.21.0",
|
"@ccms/common": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0"
|
"@ccms/container": "^0.27.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.21.0",
|
"@ccms/nashorn": "^0.27.6",
|
||||||
"@javatypes/amqp-client": "^0.0.3",
|
"@javatypes/amqp-client": "^0.0.3",
|
||||||
"@javatypes/spring-amqp": "^0.0.3",
|
"@javatypes/spring-amqp": "^0.0.3",
|
||||||
"@javatypes/spring-rabbit": "^0.0.3",
|
"@javatypes/spring-rabbit": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/api",
|
"name": "@ccms/api",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript api package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,16 +19,16 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/common": "^0.21.0",
|
"@ccms/common": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0",
|
"@ccms/container": "^0.27.6",
|
||||||
"@ccms/polyfill": "^0.21.0",
|
"@ccms/polyfill": "^0.27.6",
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"source-map-builder": "^0.0.7"
|
"source-map-builder": "^0.0.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/base64-js": "^1.3.0",
|
"@types/base64-js": "^1.3.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import * as base64 from 'base64-js'
|
|||||||
const Arrays = Java.type('java.util.Arrays')
|
const Arrays = Java.type('java.util.Arrays')
|
||||||
const Level = Java.type('java.util.logging.Level')
|
const Level = Java.type('java.util.logging.Level')
|
||||||
const Paths = Java.type('java.nio.file.Paths')
|
const Paths = Java.type('java.nio.file.Paths')
|
||||||
const ignoreLogPrefix = ['java.', 'javax.', 'sun.', 'net.minecraft.', 'org.bukkit.', 'jdk.nashorn.', 'org.openjdk.nashorn', 'io.netty.', 'org.spongepowered.', 'org.apache', 'org.springframework']
|
const ignoreLogPrefix = ['java.', 'javax.', 'sun.', 'net.minecraft.', 'org.bukkit.', 'jdk.internal.dynalink.', 'jdk.nashorn.', 'org.openjdk.nashorn', 'io.netty.', 'org.spongepowered.', 'org.apache', 'org.springframework']
|
||||||
|
|
||||||
enum LogLevel {
|
enum LogLevel {
|
||||||
ALL,
|
ALL,
|
||||||
@@ -18,12 +18,114 @@ enum LogLevel {
|
|||||||
OFF
|
OFF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sourceMaps: { [key: string]: SourceMapBuilder } = {}
|
||||||
|
const sourceFileMaps: { [key: string]: string } = {}
|
||||||
|
|
||||||
|
global.setGlobal('MiaoScriptSourceMaps', sourceMaps)
|
||||||
|
global.setGlobal('MiaoScriptSourceFileMaps', sourceFileMaps)
|
||||||
|
|
||||||
|
export namespace jsconsole {
|
||||||
|
export function readSourceMap(fileName: string, lineNumber: any) {
|
||||||
|
try {
|
||||||
|
if (fileName.endsWith('js') || fileName.endsWith('ms')) {
|
||||||
|
if (sourceMaps[fileName] === undefined) {
|
||||||
|
sourceMaps[fileName] = null
|
||||||
|
let sourceLine = base.read(fileName).split('\n')
|
||||||
|
let lastLine = sourceLine[sourceLine.length - 1] || sourceLine[sourceLine.length - 2]
|
||||||
|
// lastLine is similar //# sourceMappingURL=data:application/json;base64,
|
||||||
|
if (lastLine.startsWith('//# sourceMappingURL=')) {
|
||||||
|
let sourceContent = null
|
||||||
|
let sourceMappingURL = lastLine.split('sourceMappingURL=', 2)[1]
|
||||||
|
if (sourceMappingURL.startsWith('data:application/json;base64,')) {
|
||||||
|
sourceContent = String.fromCharCode(...Array.from(base64.toByteArray(sourceMappingURL.split(',', 2)[1])))
|
||||||
|
} else if (sourceMappingURL.startsWith('http://') || sourceMappingURL.startsWith('https://')) {
|
||||||
|
// TODO
|
||||||
|
} else {
|
||||||
|
let file = Paths.get(Paths.get(fileName, '..', sourceMappingURL).toFile().getCanonicalPath()).toFile()
|
||||||
|
if (file.exists()) {
|
||||||
|
sourceContent = base.read(file)
|
||||||
|
sourceFileMaps[fileName] = file.getCanonicalPath()
|
||||||
|
} else if (global.debug) {
|
||||||
|
console.debug('readSourceMap can\'t found', fileName, 'source map file', sourceMappingURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sourceContent) {
|
||||||
|
sourceMaps[fileName] = new SourceMapBuilder(JSON.parse(sourceContent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sourceMaps[fileName]) {
|
||||||
|
let sourceMapping = sourceMaps[fileName].getSource(lineNumber, 25, true, true)
|
||||||
|
if (sourceMapping) {
|
||||||
|
fileName = Paths.get(fileName, '..', sourceMapping.sourcePath).toFile().getCanonicalPath()
|
||||||
|
lineNumber = sourceMapping.mapping.sourceLine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.debug('search source map', fileName, 'line', lineNumber, 'error:', error)
|
||||||
|
if (global.debug) {
|
||||||
|
console.ex(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
fileName,
|
||||||
|
lineNumber
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStackTrace(ex: Error, color: boolean = true): string[] {
|
||||||
|
if (!ex) return []
|
||||||
|
let stack = ex.getStackTrace()
|
||||||
|
let cache = [(color ? '§c' : '') + ex]
|
||||||
|
//@ts-ignore
|
||||||
|
if (stack.class) {
|
||||||
|
stack = Arrays.asList(stack)
|
||||||
|
}
|
||||||
|
stack.forEach(trace => {
|
||||||
|
if (!trace.fileName || trace.fileName.startsWith('jar:file:') || trace.fileName.startsWith('file:')) { return }
|
||||||
|
if (trace.className.startsWith('<')) {
|
||||||
|
let { fileName, lineNumber } = readSourceMap(trace.fileName, trace.lineNumber)
|
||||||
|
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
||||||
|
if (color) {
|
||||||
|
cache.push(` §e->§c ${fileName}:${lineNumber}(${trace.lineNumber}) => §4${trace.methodName}`)
|
||||||
|
} else {
|
||||||
|
cache.push(` -> ${fileName}:${lineNumber}(${trace.lineNumber}) => ${trace.methodName}`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let className = trace.className
|
||||||
|
var fileName = trace.fileName as string
|
||||||
|
var lineNumber = trace.lineNumber
|
||||||
|
if (className.startsWith('jdk.nashorn.internal.scripts') || className.startsWith('org.openjdk.nashorn.internal.scripts')) {
|
||||||
|
className = className.substr(className.lastIndexOf('$') + 1)
|
||||||
|
var { fileName, lineNumber } = readSourceMap(fileName, lineNumber)
|
||||||
|
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
||||||
|
} else {
|
||||||
|
if (!global.debug) {
|
||||||
|
for (let prefix in ignoreLogPrefix) {
|
||||||
|
if (className.startsWith(ignoreLogPrefix[prefix])) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (className.startsWith('jdk.nashorn.internal.') || className.startsWith('org.openjdk.nashorn.internal.')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (color) {
|
||||||
|
cache.push(` §e->§c ${className}.${trace.methodName}(§4${fileName}:${lineNumber}§c)`)
|
||||||
|
} else {
|
||||||
|
cache.push(` -> ${className}.${trace.methodName}(${fileName}:${lineNumber})`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return cache
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class MiaoScriptConsole implements Console {
|
export class MiaoScriptConsole implements Console {
|
||||||
Console: any
|
Console: any
|
||||||
memory: any
|
memory: any
|
||||||
|
|
||||||
private static sourceMaps: { [key: string]: SourceMapBuilder } = {}
|
|
||||||
private static sourceFileMaps: { [key: string]: string } = {}
|
|
||||||
private _name: string = ''
|
private _name: string = ''
|
||||||
private _level: LogLevel = LogLevel.INFO
|
private _level: LogLevel = LogLevel.INFO
|
||||||
|
|
||||||
@@ -92,91 +194,8 @@ export class MiaoScriptConsole implements Console {
|
|||||||
ex(ex: Error) {
|
ex(ex: Error) {
|
||||||
this.stack(ex).forEach(line => this.console(line))
|
this.stack(ex).forEach(line => this.console(line))
|
||||||
}
|
}
|
||||||
readSourceMap(fileName: string, lineNumber: any) {
|
|
||||||
try {
|
|
||||||
if (fileName.endsWith('js')) {
|
|
||||||
if (MiaoScriptConsole.sourceMaps[fileName] === undefined) {
|
|
||||||
MiaoScriptConsole.sourceMaps[fileName] = null
|
|
||||||
let sourceLine = base.read(fileName).split('\n')
|
|
||||||
let lastLine = sourceLine[sourceLine.length - 1]
|
|
||||||
// lastLine is similar //# sourceMappingURL=data:application/json;base64,
|
|
||||||
if (lastLine.startsWith('//# sourceMappingURL=')) {
|
|
||||||
let sourceContent = null
|
|
||||||
let sourceMappingURL = lastLine.split('sourceMappingURL=', 2)[1]
|
|
||||||
if (sourceMappingURL.startsWith('data:application/json;base64,')) {
|
|
||||||
sourceContent = String.fromCharCode(...Array.from(base64.toByteArray(sourceMappingURL.split(',', 2)[1])))
|
|
||||||
} else if (sourceMappingURL.startsWith('http://') || sourceMappingURL.startsWith('https://')) {
|
|
||||||
// TODO
|
|
||||||
} else {
|
|
||||||
let file = Paths.get(Paths.get(fileName, '..', sourceMappingURL).toFile().getCanonicalPath()).toFile()
|
|
||||||
if (file.exists()) { sourceContent = base.read(file) }
|
|
||||||
}
|
|
||||||
if (sourceContent) {
|
|
||||||
MiaoScriptConsole.sourceMaps[fileName] = new SourceMapBuilder(JSON.parse(sourceContent))
|
|
||||||
MiaoScriptConsole.sourceFileMaps[fileName] = Paths.get(fileName, '..', MiaoScriptConsole.sourceMaps[fileName].sources[0]).toFile().getCanonicalPath()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (MiaoScriptConsole.sourceMaps[fileName]) {
|
|
||||||
let sourceMapping = MiaoScriptConsole.sourceMaps[fileName].getSource(lineNumber, 25, true, true)
|
|
||||||
fileName = MiaoScriptConsole.sourceFileMaps[fileName]
|
|
||||||
if (sourceMapping && lineNumber != sourceMapping.mapping.sourceLine) { lineNumber = sourceMapping.mapping.sourceLine }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
console.debug('search source map', fileName, 'line', lineNumber, 'error:', error)
|
|
||||||
if (global.debug) {
|
|
||||||
console.ex(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
fileName,
|
|
||||||
lineNumber
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stack(ex: Error, color: boolean = true): string[] {
|
stack(ex: Error, color: boolean = true): string[] {
|
||||||
if (!ex) return []
|
return jsconsole.getStackTrace(ex, color)
|
||||||
let stack = ex.getStackTrace()
|
|
||||||
let cache = [(color ? '§c' : '') + ex]
|
|
||||||
//@ts-ignore
|
|
||||||
if (stack.class) {
|
|
||||||
stack = Arrays.asList(stack)
|
|
||||||
}
|
|
||||||
stack.forEach(trace => {
|
|
||||||
if (!trace.fileName || trace.fileName.startsWith('jar:file:') || trace.fileName.startsWith('file:')) { return }
|
|
||||||
if (trace.className.startsWith('<')) {
|
|
||||||
let { fileName, lineNumber } = this.readSourceMap(trace.fileName, trace.lineNumber)
|
|
||||||
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
|
||||||
if (color) {
|
|
||||||
cache.push(` §e->§c ${fileName}:${lineNumber} => §4${trace.methodName}`)
|
|
||||||
} else {
|
|
||||||
cache.push(` -> ${fileName}:${lineNumber} => ${trace.methodName}`)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let className = trace.className
|
|
||||||
var fileName = trace.fileName as string
|
|
||||||
var lineNumber = trace.lineNumber
|
|
||||||
if (className.startsWith('jdk.nashorn.internal.scripts') || className.startsWith('org.openjdk.nashorn.internal.scripts')) {
|
|
||||||
className = className.substr(className.lastIndexOf('$') + 1)
|
|
||||||
var { fileName, lineNumber } = this.readSourceMap(fileName, lineNumber)
|
|
||||||
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
|
|
||||||
} else {
|
|
||||||
if (!global.debug) {
|
|
||||||
for (let prefix in ignoreLogPrefix) {
|
|
||||||
if (className.startsWith(ignoreLogPrefix[prefix])) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (color) {
|
|
||||||
cache.push(` §e->§c ${className}.${trace.methodName}(§4${fileName}:${lineNumber}§c)`)
|
|
||||||
} else {
|
|
||||||
cache.push(` -> ${className}.${trace.methodName}(${fileName}:${lineNumber})`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return cache
|
|
||||||
}
|
}
|
||||||
assert(value: any, message?: string, ...optionalParams: any[]): void {
|
assert(value: any, message?: string, ...optionalParams: any[]): void {
|
||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
|
|||||||
@@ -11,10 +11,21 @@ export namespace constants {
|
|||||||
}
|
}
|
||||||
export namespace Reflect {
|
export namespace Reflect {
|
||||||
export const Method = {
|
export const Method = {
|
||||||
getServerConnection: [/*spigot 1.8.8*/'aq',/*spigot 1.12.2*/ 'an', /*spigot 1.14.4+*/'getServerConnection', /*catserver 1.12.2*/'func_147137_ag']
|
getServerConnection: [
|
||||||
|
/*spigot 1.8.8*/'aq',
|
||||||
|
/*spigot 1.12.2*/ 'an',
|
||||||
|
/*spigot 1.14.4+*/'getServerConnection',
|
||||||
|
/*spigot 1.19+*/'ad',
|
||||||
|
/*catserver 1.12.2*/'func_147137_ag'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
export const Field = {
|
export const Field = {
|
||||||
listeningChannels: [/*spigot 1.8.8-1.12.2*/'g', /*spigot 1.14.4*/'f', /*spigot 1.15.2+*/'listeningChannels', /*catserver 1.12.2*/'field_151274_e']
|
listeningChannels: [
|
||||||
|
/*spigot 1.8.8-1.12.2*/'g',
|
||||||
|
/*spigot 1.14.4*/'f',
|
||||||
|
/*spigot 1.15.2+*/'listeningChannels',
|
||||||
|
/*catserver 1.12.2*/'field_151274_e'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export enum ServerType {
|
export enum ServerType {
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ export namespace database {
|
|||||||
* 数据库配置
|
* 数据库配置
|
||||||
*/
|
*/
|
||||||
export interface DataBaseConfig {
|
export interface DataBaseConfig {
|
||||||
|
/**
|
||||||
|
* 数据库类型
|
||||||
|
*/
|
||||||
|
type: 'h2' | 'mysql' | 'mongodb' | 'sqlite' | 'postgres' | 'redis'
|
||||||
/**
|
/**
|
||||||
* 数据库连接串
|
* 数据库连接串
|
||||||
*/
|
*/
|
||||||
@@ -26,6 +30,10 @@ export namespace database {
|
|||||||
* 链接属性
|
* 链接属性
|
||||||
*/
|
*/
|
||||||
properties?: { [key: string]: any }
|
properties?: { [key: string]: any }
|
||||||
|
/**
|
||||||
|
* 调试模式
|
||||||
|
*/
|
||||||
|
debug?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
@@ -35,6 +43,9 @@ export namespace database {
|
|||||||
abstract createDatabase(name: string, config: DataBaseConfig): DataBase
|
abstract createDatabase(name: string, config: DataBaseConfig): DataBase
|
||||||
abstract removeDatabase(name: string): boolean
|
abstract removeDatabase(name: string): boolean
|
||||||
abstract getDatabase(name: string): DataBase
|
abstract getDatabase(name: string): DataBase
|
||||||
|
abstract startWebManager(...args: string[])
|
||||||
|
abstract stopWebManager()
|
||||||
|
abstract shutdown()
|
||||||
}
|
}
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class DataBase {
|
export abstract class DataBase {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export namespace event {
|
|||||||
|
|
||||||
private mapEvent = [];
|
private mapEvent = [];
|
||||||
private listenerMap = [];
|
private listenerMap = [];
|
||||||
|
private cacheSlowEventKey = {};
|
||||||
|
|
||||||
protected baseEventDir = '';
|
protected baseEventDir = '';
|
||||||
|
|
||||||
@@ -92,17 +93,23 @@ export namespace event {
|
|||||||
return eventCls
|
return eventCls
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(name, exec, eventCls) {
|
/**
|
||||||
|
* 创建命令执行器
|
||||||
|
* @param name 插件名称
|
||||||
|
* @param exec 执行方法
|
||||||
|
* @param eventCls 事件类
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
createExecute(name, exec, eventCls) {
|
||||||
return (...args: any[]) => {
|
return (...args: any[]) => {
|
||||||
|
let event = args[args.length - 1]
|
||||||
try {
|
try {
|
||||||
let event = args[args.length - 1]
|
if (!eventCls.isAssignableFrom(event.getClass())) { return }
|
||||||
if (eventCls.isAssignableFrom(event.getClass())) {
|
let time = Date.now(); exec(event); let cost = Date.now() - time
|
||||||
let time = Date.now()
|
if (cost > global.ScriptSlowExecuteTime && !event.async) {
|
||||||
exec(event)
|
let eventKey = `${name}-${this.class2Name(eventCls)}`
|
||||||
let cost = Date.now() - time
|
if (!this.cacheSlowEventKey[eventKey]) { return this.cacheSlowEventKey[eventKey] = cost }
|
||||||
if (cost > global.ScriptSlowExecuteTime) {
|
console.i18n("ms.api.event.execute.slow", { name, event: this.class2Name(eventCls), cost })
|
||||||
console.i18n("ms.api.event.execute.slow", { name, event: this.class2Name(eventCls), cost })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
console.i18n("ms.api.event.execute.error", { name, event: this.class2Name(eventCls), ex })
|
console.i18n("ms.api.event.execute.error", { name, event: this.class2Name(eventCls), ex })
|
||||||
@@ -113,11 +120,11 @@ export namespace event {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加事件监听
|
* 添加事件监听
|
||||||
* @param plugin {any}
|
* @param plugin {any} 插件
|
||||||
* @param event {string}
|
* @param event {string} 事件名称
|
||||||
* @param exec {function}
|
* @param exec {function} 事件执行器
|
||||||
* @param priority {string} [LOWEST,LOW,NORMAL,HIGH,HIGHEST,MONITOR]
|
* @param priority {string} [LOWEST,LOW,NORMAL,HIGH,HIGHEST,MONITOR] 优先级
|
||||||
* @param ignoreCancel
|
* @param ignoreCancel 是否忽略已取消事件
|
||||||
*/
|
*/
|
||||||
listen(plugin: any, event: string, exec: (event: any) => void, priority: EventPriority = EventPriority.NORMAL, ignoreCancel = false) {
|
listen(plugin: any, event: string, exec: (event: any) => void, priority: EventPriority = EventPriority.NORMAL, ignoreCancel = false) {
|
||||||
if (!plugin || !plugin.description || !plugin.description.name) throw new TypeError(i18n.translate("ms.api.event.listen.plugin.name.empty"))
|
if (!plugin || !plugin.description || !plugin.description.name) throw new TypeError(i18n.translate("ms.api.event.listen.plugin.name.empty"))
|
||||||
@@ -135,7 +142,7 @@ export namespace event {
|
|||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
var listener = this.register(
|
var listener = this.register(
|
||||||
eventCls,
|
eventCls,
|
||||||
this.execute(name, exec, eventCls),
|
this.createExecute(name, exec, eventCls),
|
||||||
priority,
|
priority,
|
||||||
ignoreCancel
|
ignoreCancel
|
||||||
)
|
)
|
||||||
@@ -171,7 +178,7 @@ export namespace event {
|
|||||||
disable(plugin: any) {
|
disable(plugin: any) {
|
||||||
var eventCache = this.listenerMap[plugin.description.name]
|
var eventCache = this.listenerMap[plugin.description.name]
|
||||||
if (eventCache) {
|
if (eventCache) {
|
||||||
eventCache.forEach(off => off())
|
eventCache.forEach((off: () => any) => off())
|
||||||
delete this.listenerMap[plugin.description.name]
|
delete this.listenerMap[plugin.description.name]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ export * from './web'
|
|||||||
export * from './amqp'
|
export * from './amqp'
|
||||||
export * from './chat'
|
export * from './chat'
|
||||||
export * from './task'
|
export * from './task'
|
||||||
|
export * from './item'
|
||||||
export * from './event'
|
export * from './event'
|
||||||
export * from './proxy'
|
export * from './proxy'
|
||||||
export * from './plugin'
|
export * from './plugin'
|
||||||
export * from './server'
|
export * from './server'
|
||||||
export * from './console'
|
export * from './console'
|
||||||
|
export { jsconsole as console } from './console'
|
||||||
export * from './channel'
|
export * from './channel'
|
||||||
export * from './command'
|
export * from './command'
|
||||||
export * from './database'
|
export * from './database'
|
||||||
|
|||||||
20
packages/api/src/item.ts
Normal file
20
packages/api/src/item.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { injectable } from '@ccms/container'
|
||||||
|
|
||||||
|
export namespace item {
|
||||||
|
@injectable()
|
||||||
|
export abstract class Item {
|
||||||
|
abstract builder(): ItemBuilder
|
||||||
|
abstract toJson(item: any): string
|
||||||
|
abstract fromJson(json: string): any
|
||||||
|
}
|
||||||
|
export interface ItemBuilder {
|
||||||
|
from(item: any): ItemBuilder
|
||||||
|
create(type: string | number): ItemBuilder
|
||||||
|
name(name: string): ItemBuilder
|
||||||
|
lore(...lores: string[]): ItemBuilder
|
||||||
|
amount(amount: number): ItemBuilder
|
||||||
|
durability(durability: number): ItemBuilder
|
||||||
|
clone(): any
|
||||||
|
build(): any
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,11 @@ const UUID = Java.type('java.util.UUID')
|
|||||||
const Math = Java.type('java.lang.Math')
|
const Math = Java.type('java.lang.Math')
|
||||||
|
|
||||||
export namespace particle {
|
export namespace particle {
|
||||||
|
@injectable()
|
||||||
|
export abstract class ParticleSpawner {
|
||||||
|
abstract spawn(location: any, particle: Particle)
|
||||||
|
abstract spawnToPlayer(player: any, location: any, particle: Particle)
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 表示一个特效对象
|
* 表示一个特效对象
|
||||||
*
|
*
|
||||||
@@ -23,6 +28,11 @@ export namespace particle {
|
|||||||
private extra: number = 0;
|
private extra: number = 0;
|
||||||
private data: Object = null;
|
private data: Object = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only Show To Player
|
||||||
|
*/
|
||||||
|
private player: any
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.uuid = UUID.randomUUID().toString()
|
this.uuid = UUID.randomUUID().toString()
|
||||||
}
|
}
|
||||||
@@ -105,6 +115,15 @@ export namespace particle {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPlayer() {
|
||||||
|
return this.player
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlayer(player) {
|
||||||
|
this.player = player
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过给定一个坐标就可以使用已经指定的参数来播放粒子
|
* 通过给定一个坐标就可以使用已经指定的参数来播放粒子
|
||||||
*
|
*
|
||||||
@@ -112,9 +131,14 @@ export namespace particle {
|
|||||||
*/
|
*/
|
||||||
spawn(location: any) {
|
spawn(location: any) {
|
||||||
if (!this.spawner) throw new Error(`particle ${this.uuid} not set spawner can't spawn!`)
|
if (!this.spawner) throw new Error(`particle ${this.uuid} not set spawner can't spawn!`)
|
||||||
this.spawner.spawn(location, this)
|
if (this.player) {
|
||||||
|
this.spawner.spawnToPlayer(this.player, location, this)
|
||||||
|
} else {
|
||||||
|
this.spawner.spawn(location, this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表示一条线
|
* 表示一条线
|
||||||
*
|
*
|
||||||
@@ -158,8 +182,7 @@ export namespace particle {
|
|||||||
|
|
||||||
show() {
|
show() {
|
||||||
for (let i = 0; i < this.length; i += this.step) {
|
for (let i = 0; i < this.length; i += this.step) {
|
||||||
let vectorTemp = this.vector.clone().multiply(i)
|
this.spawn(this.start.clone().add(this.vector.clone().multiply(i)))
|
||||||
this.spawn(this.start.clone().add(vectorTemp))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,15 +257,6 @@ export namespace particle {
|
|||||||
this.length = this.vector.length()
|
this.length = this.vector.length()
|
||||||
this.vector.normalize()
|
this.vector.normalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
public static buildLine(locA: any, locB: any, step: number, particle: any) {
|
|
||||||
let vectorAB = locB.clone().subtract(locA).toVector()
|
|
||||||
let vectorLength = vectorAB.length()
|
|
||||||
vectorAB.normalize()
|
|
||||||
for (let i = 0; i < vectorLength; i += step) {
|
|
||||||
ParticleManager.globalSpawner.spawn(locA.clone().add(vectorAB.clone().multiply(i)), particle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 表示一个弧
|
* 表示一个弧
|
||||||
@@ -331,9 +345,10 @@ export namespace particle {
|
|||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class ParticleManager {
|
export abstract class ParticleManager {
|
||||||
public static globalSpawner: ParticleSpawner = undefined
|
|
||||||
@Autowired()
|
@Autowired()
|
||||||
private taskManager: task.TaskManager
|
private taskManager: task.TaskManager
|
||||||
|
@Autowired()
|
||||||
|
private particleSpawner: particle.ParticleSpawner
|
||||||
|
|
||||||
protected taskId: java.util.concurrent.atomic.AtomicInteger
|
protected taskId: java.util.concurrent.atomic.AtomicInteger
|
||||||
protected cacheTasks = new Map<string, ParticleTask>()
|
protected cacheTasks = new Map<string, ParticleTask>()
|
||||||
@@ -354,6 +369,10 @@ export namespace particle {
|
|||||||
return this.taskManager
|
return this.taskManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getParticleSpawner() {
|
||||||
|
return this.particleSpawner
|
||||||
|
}
|
||||||
|
|
||||||
public create(particle: Particle, plugin?: plugin.Plugin) {
|
public create(particle: Particle, plugin?: plugin.Plugin) {
|
||||||
let uuid = particle.getUUID()
|
let uuid = particle.getUUID()
|
||||||
if (this.cacheTasks.has(uuid)) {
|
if (this.cacheTasks.has(uuid)) {
|
||||||
@@ -389,14 +408,12 @@ export namespace particle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected create0(owner: plugin.Plugin, particle: Particle): ParticleTask {
|
protected create0(owner: plugin.Plugin, particle: Particle): ParticleTask {
|
||||||
particle.setSpawner(this.getGlobalSpawner())
|
particle.setSpawner(this.getParticleSpawner())
|
||||||
return new ParticleTask(owner, particle, this)
|
return new ParticleTask(owner, particle, this)
|
||||||
}
|
}
|
||||||
protected abstract getGlobalSpawner(): ParticleSpawner
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ParticleTask {
|
export class ParticleTask {
|
||||||
|
|
||||||
private particle: Particle
|
private particle: Particle
|
||||||
private isAsync: boolean = false
|
private isAsync: boolean = false
|
||||||
private interval: number = 0
|
private interval: number = 0
|
||||||
@@ -486,9 +503,4 @@ export namespace particle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class ParticleSpawner {
|
|
||||||
abstract spawnParticle(location: any, particle: any, count: number)
|
|
||||||
abstract spawn(location: any, particle: Particle)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,7 +149,19 @@ export namespace plugin {
|
|||||||
/**
|
/**
|
||||||
* 插件名称 不填默认为类名
|
* 插件名称 不填默认为类名
|
||||||
*/
|
*/
|
||||||
name?: string
|
name: string
|
||||||
|
/**
|
||||||
|
* 插件中文名称
|
||||||
|
*/
|
||||||
|
cname?: string
|
||||||
|
/**
|
||||||
|
* 付费插件ID
|
||||||
|
*/
|
||||||
|
pid?: number
|
||||||
|
/**
|
||||||
|
* 付费插件等级 付费插件自动注入
|
||||||
|
*/
|
||||||
|
level?: number
|
||||||
/**
|
/**
|
||||||
* 前缀
|
* 前缀
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export namespace server {
|
|||||||
origin: any
|
origin: any
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class NativePluginManager {
|
export abstract class NativePluginManager {
|
||||||
list(): NativePlugin[] {
|
list(): NativePlugin[] {
|
||||||
@@ -53,6 +54,7 @@ export namespace server {
|
|||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MiaoScript Server
|
* MiaoScript Server
|
||||||
*/
|
*/
|
||||||
@@ -98,6 +100,7 @@ export namespace server {
|
|||||||
throw new Error("Method not implemented.")
|
throw new Error("Method not implemented.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class ServerChecker {
|
export class ServerChecker {
|
||||||
@Autowired(ServerType)
|
@Autowired(ServerType)
|
||||||
@@ -116,6 +119,22 @@ export namespace server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@injectable()
|
||||||
|
export class NativePluginChecker {
|
||||||
|
@Autowired(NativePluginManager)
|
||||||
|
private nativePluginManager: NativePluginManager
|
||||||
|
|
||||||
|
check(plugins: string[]) {
|
||||||
|
// Not set plugins -> allow
|
||||||
|
if (!plugins || !plugins.length) return true
|
||||||
|
for (const plugin of plugins) {
|
||||||
|
if (!this.nativePluginManager.has(plugin)) { return false }
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export abstract class ReflectServer extends server.Server {
|
export abstract class ReflectServer extends server.Server {
|
||||||
@Autowired(ContainerInstance)
|
@Autowired(ContainerInstance)
|
||||||
@@ -172,13 +191,23 @@ export namespace server {
|
|||||||
}
|
}
|
||||||
protected reflectRootLogger(consoleServer: any) {
|
protected reflectRootLogger(consoleServer: any) {
|
||||||
try {
|
try {
|
||||||
this.rootLogger = reflect.on(consoleServer).get('LOGGER').get().parent
|
this.rootLogger = reflect.on(consoleServer).get('LOGGER').get()
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (global.debug) {
|
if (global.debug) {
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.rootLogger = reflect.on(consoleServer).get(0).get().parent
|
this.rootLogger = reflect.on(consoleServer).get(0).get()
|
||||||
|
} catch (error: any) {
|
||||||
|
if (global.debug) {
|
||||||
|
console.ex(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.rootLogger.class.name.indexOf('slf4j') !== -1) {
|
||||||
|
try {
|
||||||
|
let LogManager = Java.type('org.apache.logging.log4j.LogManager')
|
||||||
|
this.rootLogger = LogManager.getLogger('ROOT')
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (global.debug) {
|
if (global.debug) {
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
@@ -189,11 +218,11 @@ export namespace server {
|
|||||||
console.error('Error Logger Class: ' + this.rootLogger.class.name)
|
console.error('Error Logger Class: ' + this.rootLogger.class.name)
|
||||||
this.rootLogger = undefined
|
this.rootLogger = undefined
|
||||||
}
|
}
|
||||||
|
if (!this.rootLogger) { console.error("Can't found rootLogger!") }
|
||||||
// get root logger
|
// get root logger
|
||||||
for (let index = 0; index < 5 && this.rootLogger.parent; index++) {
|
for (let index = 0; index < 5 && this.rootLogger.parent; index++) {
|
||||||
this.rootLogger = this.rootLogger.parent
|
this.rootLogger = this.rootLogger.parent
|
||||||
}
|
}
|
||||||
if (!this.rootLogger) { console.error("Can't found rootLogger!") }
|
|
||||||
this.container.bind(constants.ServiceIdentifier.RootLogger).toConstantValue(this.rootLogger)
|
this.container.bind(constants.ServiceIdentifier.RootLogger).toConstantValue(this.rootLogger)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/bukkit",
|
"name": "@ccms/bukkit",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript bukkit package",
|
"description": "MiaoScript bukkit package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/spigot-api": "^0.0.3",
|
"@javatypes/spigot-api": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.21.0",
|
"@ccms/api": "^0.27.6",
|
||||||
"@ccms/common": "^0.21.0",
|
"@ccms/common": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0"
|
"@ccms/container": "^0.27.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { event, plugin } from '@ccms/api'
|
|||||||
import { inject, provideSingleton } from '@ccms/container'
|
import { inject, provideSingleton } from '@ccms/container'
|
||||||
import * as reflect from '@ccms/common/dist/reflect'
|
import * as reflect from '@ccms/common/dist/reflect'
|
||||||
|
|
||||||
|
const URL = Java.type('java.net.URL')
|
||||||
const Bukkit = Java.type("org.bukkit.Bukkit")
|
const Bukkit = Java.type("org.bukkit.Bukkit")
|
||||||
const Event = Java.type("org.bukkit.event.Event")
|
const Event = Java.type("org.bukkit.event.Event")
|
||||||
const Modifier = Java.type("java.lang.reflect.Modifier")
|
const Modifier = Java.type("java.lang.reflect.Modifier")
|
||||||
@@ -19,7 +20,15 @@ export class BukkitEvent extends event.Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getJarFile(resource: string) {
|
getJarFile(resource: string) {
|
||||||
return super.getJarFile('org/bukkit/Bukkit.class', Bukkit.class.classLoader)
|
try {
|
||||||
|
return super.getJarFile('org/bukkit/Bukkit.class', Bukkit.class.classLoader)
|
||||||
|
} catch (error) {
|
||||||
|
// 兼容 LoliServer 的 Bukkit 包无法获取的问题
|
||||||
|
let ModList = Java.type('net.minecraftforge.fml.ModList').get()
|
||||||
|
let forgeFile = ModList.getModFileById("forge").getFile().getFilePath()
|
||||||
|
let jarPath = `jar:file:${forgeFile}!/org/bukkit/Bukkit.class`
|
||||||
|
return new URL(jarPath).openConnection().jarFile
|
||||||
|
}
|
||||||
}
|
}
|
||||||
isValidEvent(clazz: any): boolean {
|
isValidEvent(clazz: any): boolean {
|
||||||
// 继承于 org.bukkit.event.Event
|
// 继承于 org.bukkit.event.Event
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { server } from '@ccms/api'
|
|||||||
import { Container } from '@ccms/container'
|
import { Container } from '@ccms/container'
|
||||||
|
|
||||||
import { BukkitConsole } from './console'
|
import { BukkitConsole } from './console'
|
||||||
|
import './item'
|
||||||
import './chat'
|
import './chat'
|
||||||
import './task'
|
import './task'
|
||||||
import './event'
|
import './event'
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ let bukkitChatInvoke: BukkitChatInvoke
|
|||||||
abstract class BukkitChatInvoke {
|
abstract class BukkitChatInvoke {
|
||||||
private downgrade: boolean = false
|
private downgrade: boolean = false
|
||||||
protected RemapUtils: any
|
protected RemapUtils: any
|
||||||
|
protected ComponentSerializer: any
|
||||||
|
|
||||||
protected ChatSerializer: any
|
protected ChatSerializer: any
|
||||||
protected nmsChatSerializerMethodName: string
|
protected nmsChatSerializerMethodName: string
|
||||||
protected PacketPlayOutChat: any
|
protected PacketPlayOutChat: any
|
||||||
protected chatMessageTypes: any
|
protected chatMessageTypes: any
|
||||||
protected playerConnectionFieldName: string
|
protected playerConnectionFieldName: string
|
||||||
|
protected playerFieldName: string
|
||||||
protected sendPacketMethodName: string
|
protected sendPacketMethodName: string
|
||||||
|
|
||||||
constructor(private nmsVersion) {
|
constructor(private nmsVersion) {
|
||||||
@@ -20,12 +22,12 @@ abstract class BukkitChatInvoke {
|
|||||||
init() {
|
init() {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
|
this.ComponentSerializer = Java.type('net.md_5.bungee.chat.ComponentSerializer')
|
||||||
this.RemapUtils = Java.type('catserver.server.remapper.RemapUtils')
|
this.RemapUtils = Java.type('catserver.server.remapper.RemapUtils')
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
}
|
}
|
||||||
let nmsChatSerializerClass = this.getNmsChatSerializerClass()
|
let nmsChatSerializerClass = this.getNmsChatSerializerClass()
|
||||||
let nmsChatSerializerMethod = this.remapMethod(nmsChatSerializerClass, 'a', 'func_150699_a', base.getClass('java.lang.String'))
|
this.nmsChatSerializerMethodName = this.getNmsChatSerializerMethodName(nmsChatSerializerClass)
|
||||||
this.nmsChatSerializerMethodName = nmsChatSerializerMethod.getName()
|
|
||||||
this.ChatSerializer = Java.type(nmsChatSerializerClass.getName())
|
this.ChatSerializer = Java.type(nmsChatSerializerClass.getName())
|
||||||
let packetTypeClass = this.getPacketPlayOutChatClass()
|
let packetTypeClass = this.getPacketPlayOutChatClass()
|
||||||
this.PacketPlayOutChat = Java.type(packetTypeClass.getName())
|
this.PacketPlayOutChat = Java.type(packetTypeClass.getName())
|
||||||
@@ -37,12 +39,14 @@ abstract class BukkitChatInvoke {
|
|||||||
if (nmsChatMessageTypeClass.isEnum()) {
|
if (nmsChatMessageTypeClass.isEnum()) {
|
||||||
this.chatMessageTypes = nmsChatMessageTypeClass.getEnumConstants()
|
this.chatMessageTypes = nmsChatMessageTypeClass.getEnumConstants()
|
||||||
break
|
break
|
||||||
|
} else if (nmsChatMessageTypeClass.getName() == 'int') {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let playerConnectionField = this.getPlayerConnectionField()
|
let playerConnectionField = this.getPlayerConnectionField()
|
||||||
this.playerConnectionFieldName = playerConnectionField.getName()
|
this.playerConnectionFieldName = playerConnectionField.getName()
|
||||||
this.sendPacketMethodName = this.remapMethod(playerConnectionField.getType(), 'sendPacket', 'func_179290_a', this.getPacketClass()).getName()
|
this.sendPacketMethodName = this.getSendPacketMethodName(playerConnectionField.getType())
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
org.bukkit.Bukkit.getConsoleSender().sendMessage(`§6[§cMS§6][§bbukkit§6][§achat§6] §cNMS Inject Error §4${ex} §cDowngrade to Command Mode...`)
|
org.bukkit.Bukkit.getConsoleSender().sendMessage(`§6[§cMS§6][§bbukkit§6][§achat§6] §cNMS Inject Error §4${ex} §cDowngrade to Command Mode...`)
|
||||||
this.downgrade = true
|
this.downgrade = true
|
||||||
@@ -50,10 +54,12 @@ abstract class BukkitChatInvoke {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract getNmsChatSerializerClass()
|
abstract getNmsChatSerializerClass()
|
||||||
|
abstract getNmsChatSerializerMethodName(nmsChatSerializerClass: any)
|
||||||
abstract getPacketPlayOutChatClass()
|
abstract getPacketPlayOutChatClass()
|
||||||
abstract getPacketPlayOutChat(sender: any, json: any, type: number)
|
abstract getPacketPlayOutChat(sender: any, json: any, type: number)
|
||||||
abstract getPlayerConnectionField()
|
abstract getPlayerConnectionField()
|
||||||
abstract getPacketClass()
|
abstract getPacketClass()
|
||||||
|
abstract getSendPacketMethodName(playerConnectionClass: any)
|
||||||
|
|
||||||
nmsCls(name: string) {
|
nmsCls(name: string) {
|
||||||
return base.getClass(['net.minecraft.server', this.nmsVersion, name].join('.'))
|
return base.getClass(['net.minecraft.server', this.nmsVersion, name].join('.'))
|
||||||
@@ -83,9 +89,9 @@ abstract class BukkitChatInvoke {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
json(sender: { name: string }, json: string) {
|
json(sender: any, json: string) {
|
||||||
if (this.downgrade) {
|
if (this.downgrade) {
|
||||||
return '/tellraw ' + sender.name + ' ' + json
|
return sender.spigot().sendMessage(this.ComponentSerializer.parse(json))
|
||||||
} else {
|
} else {
|
||||||
this.send(sender, json, 0)
|
this.send(sender, json, 0)
|
||||||
return false
|
return false
|
||||||
@@ -100,6 +106,13 @@ abstract class BukkitChatInvoke {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BukkitChatInvokeBase extends BukkitChatInvoke {
|
class BukkitChatInvokeBase extends BukkitChatInvoke {
|
||||||
|
getSendPacketMethodName(playerConnectionClass: any) {
|
||||||
|
return this.remapMethod(playerConnectionClass, 'sendPacket', 'func_179290_a', this.getPacketClass()).getName()
|
||||||
|
}
|
||||||
|
getNmsChatSerializerMethodName(nmsChatSerializerClass: any) {
|
||||||
|
let nmsChatSerializerMethod = this.remapMethod(nmsChatSerializerClass, 'a', 'func_150699_a', base.getClass('java.lang.String'))
|
||||||
|
return nmsChatSerializerMethod.getName()
|
||||||
|
}
|
||||||
getPacketPlayOutChat(sender: any, json: any, type: number) {
|
getPacketPlayOutChat(sender: any, json: any, type: number) {
|
||||||
return new this.PacketPlayOutChat(this.ChatSerializer[this.nmsChatSerializerMethodName](json), type)
|
return new this.PacketPlayOutChat(this.ChatSerializer[this.nmsChatSerializerMethodName](json), type)
|
||||||
}
|
}
|
||||||
@@ -148,18 +161,35 @@ class BukkitChatInvoke_1_17_1 extends BukkitChatInvoke_1_16_5 {
|
|||||||
return base.getClass('net.minecraft.network.protocol.Packet')
|
return base.getClass('net.minecraft.network.protocol.Packet')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class BukkitChatInvoke_1_18_2 extends BukkitChatInvoke_1_17_1 {
|
||||||
|
getSendPacketMethodName(playerConnectionClass: any) {
|
||||||
|
return playerConnectionClass.getMethod('a', this.getPacketClass()).getName()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class BukkitChatInvoke_1_19 extends BukkitChatInvoke_1_18_2 {
|
||||||
|
getPacketPlayOutChatClass() {
|
||||||
|
return base.getClass('net.minecraft.network.protocol.game.ClientboundSystemChatPacket')
|
||||||
|
}
|
||||||
|
getPacketPlayOutChat(sender: any, json: any, type: number) {
|
||||||
|
return new this.PacketPlayOutChat(this.ChatSerializer[this.nmsChatSerializerMethodName](json), type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
let Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let nmsVersion = Bukkit.getServer().class.name.split('.')[3]
|
let nmsVersion = Bukkit.getServer().class.name.split('.')[3]
|
||||||
let nmsSubVersion = nmsVersion.split("_")[1]
|
let nmsSubVersion = nmsVersion.split("_")[1]
|
||||||
if (nmsSubVersion >= 8) {
|
if (nmsSubVersion >= 19) {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_8(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_19(nmsVersion)
|
||||||
} else if (nmsSubVersion >= 16) {
|
} else if (nmsSubVersion >= 18) {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_16_5(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_18_2(nmsVersion)
|
||||||
} else if (nmsSubVersion >= 17) {
|
} else if (nmsSubVersion >= 17) {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_17_1(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_17_1(nmsVersion)
|
||||||
|
} else if (nmsSubVersion >= 16) {
|
||||||
|
bukkitChatInvoke = new BukkitChatInvoke_1_16_5(nmsVersion)
|
||||||
|
} else if (nmsSubVersion >= 8) {
|
||||||
|
bukkitChatInvoke = new BukkitChatInvoke_1_8(nmsVersion)
|
||||||
} else {
|
} else {
|
||||||
bukkitChatInvoke = new BukkitChatInvoke_1_7_10(nmsVersion)
|
bukkitChatInvoke = new BukkitChatInvoke_1_7_10(nmsVersion)
|
||||||
}
|
}
|
||||||
|
|||||||
2270
packages/bukkit/src/internal/item.ts
Normal file
2270
packages/bukkit/src/internal/item.ts
Normal file
File diff suppressed because it is too large
Load Diff
128
packages/bukkit/src/item.ts
Normal file
128
packages/bukkit/src/item.ts
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
import { item } from "@ccms/api"
|
||||||
|
import { provideSingleton } from "@ccms/container"
|
||||||
|
|
||||||
|
import { itemIds } from './internal/item'
|
||||||
|
|
||||||
|
const Material: typeof org.bukkit.Material = Java.type('org.bukkit.Material')
|
||||||
|
const ItemStack: typeof org.bukkit.inventory.ItemStack = Java.type('org.bukkit.inventory.ItemStack')
|
||||||
|
|
||||||
|
@provideSingleton(item.Item)
|
||||||
|
export class BukkitItem extends item.Item {
|
||||||
|
private CraftItemStack: any
|
||||||
|
private NBTTagCompound: any
|
||||||
|
private nmsSaveNBTMethodName: any
|
||||||
|
private MojangsonParser: any
|
||||||
|
private nmsItemStack: any
|
||||||
|
private mpParseMethodName: any
|
||||||
|
private nmsVersion: any
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.reflect()
|
||||||
|
}
|
||||||
|
builder(): item.ItemBuilder {
|
||||||
|
return new BukkitItemBuilder()
|
||||||
|
}
|
||||||
|
toJson(item: any): string {
|
||||||
|
let nbt = new this.NBTTagCompound()
|
||||||
|
return this.CraftItemStack.asNMSCopy(item)[this.nmsSaveNBTMethodName](nbt).toString()
|
||||||
|
}
|
||||||
|
fromJson(json: string) {
|
||||||
|
return this.CraftItemStack.asBukkitCopy(new this.nmsItemStack(this.MojangsonParser[this.mpParseMethodName](json)))
|
||||||
|
}
|
||||||
|
private obcCls(name: string) {
|
||||||
|
return base.getClass(['org.bukkit.craftbukkit', this.nmsVersion, name].join('.'))
|
||||||
|
}
|
||||||
|
private nmsCls(name: string) {
|
||||||
|
return base.getClass(['net.minecraft.server', this.nmsVersion, name].join('.'))
|
||||||
|
}
|
||||||
|
private reflect() {
|
||||||
|
try {
|
||||||
|
let Bukkit: typeof org.bukkit.Bukkit = Java.type('org.bukkit.Bukkit')
|
||||||
|
// @ts-ignore
|
||||||
|
this.nmsVersion = Bukkit.getServer().class.name.split('.')[3]
|
||||||
|
let CraftItemStackClass = this.obcCls('inventory.CraftItemStack')
|
||||||
|
this.CraftItemStack = Java.type(CraftItemStackClass.getName())
|
||||||
|
// @ts-ignore
|
||||||
|
let asNMSCopyMethod = CraftItemStackClass.getMethod('asNMSCopy', ItemStack.class)
|
||||||
|
let nmsItemStackClass = asNMSCopyMethod.getReturnType()
|
||||||
|
this.nmsItemStack = Java.type(nmsItemStackClass.getName())
|
||||||
|
let nmsNBTTagCompoundClass = undefined
|
||||||
|
for (let method of Java.from(nmsItemStackClass.getMethods())) {
|
||||||
|
let rt = method.getReturnType()
|
||||||
|
if (method.getParameterTypes().length == 0 && "NBTTagCompound" == rt.getSimpleName()) {
|
||||||
|
nmsNBTTagCompoundClass = rt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.NBTTagCompound = Java.type(nmsNBTTagCompoundClass.getName())
|
||||||
|
for (let method of Java.from(nmsItemStackClass.getMethods())) {
|
||||||
|
let params = method.getParameterTypes()
|
||||||
|
let rt = method.getReturnType()
|
||||||
|
if (params.length == 1 && "NBTTagCompound" == params[0].getSimpleName() && "NBTTagCompound" == rt.getSimpleName()) {
|
||||||
|
this.nmsSaveNBTMethodName = method.getName()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.MojangsonParser = this.nmsCls('MojangsonParser').static
|
||||||
|
} catch (error) {
|
||||||
|
this.MojangsonParser = Java.type('net.minecraft.nbt.MojangsonParser')
|
||||||
|
}
|
||||||
|
for (let method of Java.from(this.MojangsonParser.class.getMethods())) {
|
||||||
|
let params = method.getParameterTypes()
|
||||||
|
let rt = method.getReturnType()
|
||||||
|
if (params.length == 1 && "String" == params[0].getSimpleName() && "NBTTagCompound" == rt.getSimpleName()) {
|
||||||
|
this.mpParseMethodName = method.getName()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log('Bukkit 物品管理器初始化失败:', error)
|
||||||
|
if (global.debug) {
|
||||||
|
console.ex(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BukkitItemBuilder implements item.ItemBuilder {
|
||||||
|
private itemStack: org.bukkit.inventory.ItemStack
|
||||||
|
private itemMeta: org.bukkit.inventory.meta.ItemMeta
|
||||||
|
|
||||||
|
from(itemStack: any): item.ItemBuilder {
|
||||||
|
this.itemStack = itemStack
|
||||||
|
this.itemMeta = this.itemStack.getItemMeta()
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
create(type: string | number): item.ItemBuilder {
|
||||||
|
let material = undefined
|
||||||
|
if (typeof type == 'number') {
|
||||||
|
type = itemIds[type]
|
||||||
|
}
|
||||||
|
material = Material[type] || Material[Material['LEGACY_PREFIX'] + type]
|
||||||
|
this.itemStack = new ItemStack(material)
|
||||||
|
this.itemMeta = this.itemStack.getItemMeta()
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
name(name: string): item.ItemBuilder {
|
||||||
|
this.itemMeta.setDisplayName(name)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
lore(...lores: string[]): item.ItemBuilder {
|
||||||
|
this.itemMeta.setLore(lores)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
amount(amount: number): item.ItemBuilder {
|
||||||
|
this.itemStack.setAmount(amount)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
durability(durability: number): item.ItemBuilder {
|
||||||
|
this.itemStack.setDurability(durability)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
clone() {
|
||||||
|
return this.build().clone()
|
||||||
|
}
|
||||||
|
build() {
|
||||||
|
this.itemStack.setItemMeta(this.itemMeta)
|
||||||
|
return this.itemStack
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,20 +3,11 @@ import { particle } from '@ccms/api'
|
|||||||
|
|
||||||
@provideSingleton(particle.ParticleManager)
|
@provideSingleton(particle.ParticleManager)
|
||||||
export class BukkitParticleManager extends particle.ParticleManager {
|
export class BukkitParticleManager extends particle.ParticleManager {
|
||||||
private globalSpawner = new BukkitParticleSpawner()
|
|
||||||
constructor() {
|
|
||||||
super()
|
|
||||||
particle.ParticleManager.globalSpawner = this.globalSpawner
|
|
||||||
}
|
|
||||||
protected getGlobalSpawner() {
|
|
||||||
return this.globalSpawner
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@provideSingleton(particle.ParticleSpawner)
|
||||||
export class BukkitParticleSpawner extends particle.ParticleSpawner {
|
export class BukkitParticleSpawner extends particle.ParticleSpawner {
|
||||||
spawnParticle(location: any, particle: any, count: number = 1) {
|
spawn(location: org.bukkit.Location, particle: particle.Particle) {
|
||||||
location.getWorld().spawnParticle(particle, location, count)
|
|
||||||
}
|
|
||||||
spawn(location: any, particle: particle.Particle) {
|
|
||||||
location.getWorld().spawnParticle(
|
location.getWorld().spawnParticle(
|
||||||
particle.getParticle(),
|
particle.getParticle(),
|
||||||
location,
|
location,
|
||||||
@@ -28,4 +19,15 @@ export class BukkitParticleSpawner extends particle.ParticleSpawner {
|
|||||||
particle.getData()
|
particle.getData()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
spawnToPlayer(player: org.bukkit.entity.Player, location: org.bukkit.Location, particle: particle.Particle) {
|
||||||
|
player.spawnParticle(
|
||||||
|
particle.getParticle(),
|
||||||
|
location,
|
||||||
|
particle.getCount(),
|
||||||
|
particle.getOffsetX(),
|
||||||
|
particle.getOffsetY(),
|
||||||
|
particle.getOffsetZ(),
|
||||||
|
particle.getExtra(),
|
||||||
|
particle.getData())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "src",
|
"baseUrl": "src",
|
||||||
"outDir": "dist"
|
"outDir": "dist",
|
||||||
|
"resolveJsonModule": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/bungee",
|
"name": "@ccms/bungee",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript bungee package",
|
"description": "MiaoScript bungee package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/bungee-api": "^0.0.3",
|
"@javatypes/bungee-api": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.21.0",
|
"@ccms/api": "^0.27.6",
|
||||||
"@ccms/common": "^0.21.0",
|
"@ccms/common": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0"
|
"@ccms/container": "^0.27.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
packages/client/.gitignore
vendored
1
packages/client/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
src/emp.ts
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"private": true,
|
|
||||||
"name": "@ccms/client",
|
|
||||||
"version": "0.21.0",
|
|
||||||
"description": "MiaoScript client package",
|
|
||||||
"keywords": [
|
|
||||||
"miaoscript",
|
|
||||||
"minecraft",
|
|
||||||
"bukkit",
|
|
||||||
"sponge"
|
|
||||||
],
|
|
||||||
"author": "MiaoWoo <admin@yumc.pw>",
|
|
||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
|
||||||
"license": "ISC",
|
|
||||||
"main": "dist/index.js",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "ts-node-dev --respawn --debounce=1500 src/index.ts",
|
|
||||||
"clean": "rimraf dist",
|
|
||||||
"watch": "tsc --watch",
|
|
||||||
"build": "yarn clean && tsc",
|
|
||||||
"start": "node dist/index.js",
|
|
||||||
"debug": "DEBUG=minecraft-protocol node dist/index.js",
|
|
||||||
"emp": "node dist/emp.js",
|
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"axios": "^0.27.2",
|
|
||||||
"minecraft-protocol": "^1.34.0",
|
|
||||||
"minecraft-protocol-forge": "^1.0.0",
|
|
||||||
"proxy-agent": "^5.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^17.0.25",
|
|
||||||
"rimraf": "^3.0.2",
|
|
||||||
"typescript": "^4.6.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
class MessagePart {
|
|
||||||
text: string
|
|
||||||
color: string
|
|
||||||
clickEvent: MessagePartEvent
|
|
||||||
hoverEvent: MessagePartEvent
|
|
||||||
translate: string
|
|
||||||
with: MessagePart[]
|
|
||||||
extra: MessagePart[]
|
|
||||||
}
|
|
||||||
|
|
||||||
class MessagePartEvent {
|
|
||||||
action: string
|
|
||||||
value: string
|
|
||||||
}
|
|
||||||
|
|
||||||
var colorMap = []
|
|
||||||
colorMap['0'] = '38;5;0'
|
|
||||||
colorMap['1'] = '38;5;4'
|
|
||||||
colorMap['2'] = '38;5;2'
|
|
||||||
colorMap['3'] = '38;5;6'
|
|
||||||
colorMap['4'] = '38;5;1'
|
|
||||||
colorMap['5'] = '38;5;5'
|
|
||||||
colorMap['6'] = '38;5;3'
|
|
||||||
colorMap['7'] = '38;5;7'
|
|
||||||
colorMap['8'] = '38;5;8'
|
|
||||||
colorMap['9'] = '38;5;12'
|
|
||||||
colorMap['a'] = '38;5;10'
|
|
||||||
colorMap['b'] = '38;5;14'
|
|
||||||
colorMap['c'] = '38;5;9'
|
|
||||||
colorMap['d'] = '38;5;13'
|
|
||||||
colorMap['e'] = '38;5;11'
|
|
||||||
colorMap['f'] = '38;5;15'
|
|
||||||
colorMap['r'] = '0'
|
|
||||||
colorMap['l'] = '1'
|
|
||||||
colorMap['n'] = '4'
|
|
||||||
var regexMap = []
|
|
||||||
for (const c in colorMap) {
|
|
||||||
regexMap[colorMap[c]] = new RegExp(`§${c}`, "g")
|
|
||||||
}
|
|
||||||
function mcColor2ANSI(str) {
|
|
||||||
for (const regex in regexMap) {
|
|
||||||
str = str.replace(regexMap[regex], `\u001b[${regex}m`)
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
let jsonColorMap = {
|
|
||||||
"black": '0',
|
|
||||||
"dark_blue": '1',
|
|
||||||
"dark_green": '2',
|
|
||||||
"dark_aqua": '3',
|
|
||||||
"dark_red": '4',
|
|
||||||
"dark_purple": '5',
|
|
||||||
"gold": '6',
|
|
||||||
"gray": '7',
|
|
||||||
"dark_gray": '8',
|
|
||||||
"blue": '9',
|
|
||||||
"green": 'a',
|
|
||||||
"aqua": 'b',
|
|
||||||
"red": 'c',
|
|
||||||
"light_purple": 'd',
|
|
||||||
"yellow": 'e',
|
|
||||||
"white": 'f',
|
|
||||||
"obfuscated": 'k',
|
|
||||||
"bold": 'l',
|
|
||||||
"strikethrough": 'm',
|
|
||||||
"underline": 'n',
|
|
||||||
"italic": 'o',
|
|
||||||
"reset": 'r',
|
|
||||||
};
|
|
||||||
|
|
||||||
function json2text(json: MessagePart): string {
|
|
||||||
let temp = "";
|
|
||||||
if (json.color) {
|
|
||||||
temp += `§${jsonColorMap[json.color]}`
|
|
||||||
}
|
|
||||||
temp += json.text || json.translate || ''
|
|
||||||
if (json.extra) {
|
|
||||||
json.extra.forEach((ext) => {
|
|
||||||
temp += json2text(ext)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return temp += '§r'
|
|
||||||
}
|
|
||||||
|
|
||||||
function $(input: any) {
|
|
||||||
if (typeof input === "string") {
|
|
||||||
input = JSON.parse(input)
|
|
||||||
}
|
|
||||||
input = json2text(input) + '§r'
|
|
||||||
if (input.startsWith('§卐')) {
|
|
||||||
input = input.substring(2)
|
|
||||||
}
|
|
||||||
return mcColor2ANSI(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
json2text,
|
|
||||||
mcColor2ANSI,
|
|
||||||
$
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { $ } from './color'
|
|
||||||
|
|
||||||
export function attachEvents(client) {
|
|
||||||
client.on('chat', (packet) => {
|
|
||||||
// Listen for chat messages and echo them back.
|
|
||||||
var jsonMsg = JSON.parse(packet.message)
|
|
||||||
console.log($(jsonMsg))
|
|
||||||
})
|
|
||||||
client.on('state', (newState, oldState) => {
|
|
||||||
console.log('Client Change State', oldState, 'to', newState)
|
|
||||||
let targetServer = process.argv[6]
|
|
||||||
if (newState == "play" && targetServer) {
|
|
||||||
setTimeout(() => {
|
|
||||||
client.write('chat', {
|
|
||||||
message: '/server ' + targetServer
|
|
||||||
})
|
|
||||||
}, 3000)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
client.on('update_health', (packet) => {
|
|
||||||
if (packet.health <= 0) {
|
|
||||||
console.log("Player Dead Auto Respawn...")
|
|
||||||
client.write('client_command', { payload: 0 })
|
|
||||||
} else if (packet.health > 0) {
|
|
||||||
}
|
|
||||||
})
|
|
||||||
client.on('kick_disconnect', (packet) => {
|
|
||||||
console.log($(packet.reason))
|
|
||||||
})
|
|
||||||
client.on('disconnect', (packet) => {
|
|
||||||
console.log($(packet.reason))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
export function attachForge(client) {
|
|
||||||
client.on('custom_payload', function(packet) {
|
|
||||||
if (packet.channel === 'FML|HS') {
|
|
||||||
client.write('custom_payload', {
|
|
||||||
channel: 'FML|HS',
|
|
||||||
data: Buffer.of(0x01, 0x02)
|
|
||||||
});
|
|
||||||
client.write('custom_payload', {
|
|
||||||
channel: 'FML|HS',
|
|
||||||
data: Buffer.of(0x02, 0x00)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
import { createInterface } from 'readline'
|
|
||||||
import { Client, createClient } from 'minecraft-protocol'
|
|
||||||
|
|
||||||
import { attachForge } from './forge'
|
|
||||||
import { attachEvents } from './event'
|
|
||||||
|
|
||||||
let readUserInfo = process.argv[2] || 'Mr_jtb'
|
|
||||||
let realUserInfo = readUserInfo.split(":")
|
|
||||||
let username = realUserInfo[0]
|
|
||||||
let password = realUserInfo[1] || ''
|
|
||||||
let version = process.argv[3] || '1.12.2'
|
|
||||||
let readAddress = process.argv[4] || '192.168.2.25:25565'
|
|
||||||
let realAddress = readAddress.split(":")
|
|
||||||
let address = realAddress[0]
|
|
||||||
let port = parseInt(realAddress[1] || "25565")
|
|
||||||
let client = commandLineCreateClient()
|
|
||||||
|
|
||||||
function commandLineCreateClient() {
|
|
||||||
return createConnection(address, port, username, password)
|
|
||||||
}
|
|
||||||
|
|
||||||
function createConnection(host: string, port: number, username: string, password: string) {
|
|
||||||
let clientOptions: any = {
|
|
||||||
version,
|
|
||||||
host,
|
|
||||||
port,
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
// clientToken: 'd02c7f39-2376-45da-a5a5-50e24fa8b185',
|
|
||||||
//@ts-ignore
|
|
||||||
// authServer: 'https://skin.yumc.pw/api/yggdrasil/authserver',
|
|
||||||
// sessionServer: 'https://skin.yumc.pw/api/yggdrasil/sessionserver'
|
|
||||||
}
|
|
||||||
if (clientOptions.password) {
|
|
||||||
clientOptions.clientToken = 'd02c7f39-2376-45da-a5a5-50e24fa8b185'
|
|
||||||
clientOptions.authServer = 'https://skin.yumc.pw/api/yggdrasil/authserver'
|
|
||||||
clientOptions.sessionServer = 'https://skin.yumc.pw/api/yggdrasil/sessionserver'
|
|
||||||
}
|
|
||||||
let client = createClient(clientOptions)
|
|
||||||
|
|
||||||
attachCommon(client)
|
|
||||||
attachForge(client)
|
|
||||||
attachEvents(client)
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
function attachCommon(client: Client) {
|
|
||||||
client.on('login', () => {
|
|
||||||
// client.registerChannel('updater', ['string', []])
|
|
||||||
// client.registerChannel('updater-enabled', ['string', []])
|
|
||||||
// client.registerChannel('dragoncore', ['string', []])
|
|
||||||
// client.registerChannel('dragoncore:main', ['string', []])
|
|
||||||
client.on('REGISTER', (array) => {
|
|
||||||
for (const channel of array) {
|
|
||||||
client.on('channel', console.log)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// client.on('dragoncore:main', (data) => {
|
|
||||||
// console.log(data)
|
|
||||||
// })
|
|
||||||
})
|
|
||||||
client.on('custom_payload', (data) => {
|
|
||||||
console.log('custom_payload' + JSON.stringify(data))
|
|
||||||
})
|
|
||||||
client.on('error', (error) => {
|
|
||||||
console.log("Client Error", error)
|
|
||||||
})
|
|
||||||
client.on('end', (resone) => {
|
|
||||||
console.log("Client End Resone:", resone)
|
|
||||||
if (`${resone}` != "SocketClosed") {
|
|
||||||
setTimeout(() => {
|
|
||||||
client = commandLineCreateClient()
|
|
||||||
}, 500)
|
|
||||||
} else {
|
|
||||||
process.exit(0)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const rl = createInterface({
|
|
||||||
input: process.stdin,
|
|
||||||
output: process.stdout,
|
|
||||||
completer: (line, func) => {
|
|
||||||
let args = line.split(' ')
|
|
||||||
let comp = args[args.length - 1]
|
|
||||||
client.once('tab_complete', (msg) => {
|
|
||||||
let mcts = msg.matches.filter(s => s)
|
|
||||||
func(null, [mcts, comp])
|
|
||||||
})
|
|
||||||
client.write('tab_complete', {
|
|
||||||
text: line
|
|
||||||
})
|
|
||||||
},
|
|
||||||
terminal: true,
|
|
||||||
prompt: ''
|
|
||||||
})
|
|
||||||
|
|
||||||
rl.on('line', function (line) {
|
|
||||||
switch (line) {
|
|
||||||
case "":
|
|
||||||
break
|
|
||||||
case "eval":
|
|
||||||
break
|
|
||||||
case "write":
|
|
||||||
break
|
|
||||||
case "/respawn":
|
|
||||||
client.write('client_command', { payload: 0 })
|
|
||||||
break
|
|
||||||
case "//reco":
|
|
||||||
client.end("")
|
|
||||||
client = commandLineCreateClient()
|
|
||||||
break
|
|
||||||
case "//quit":
|
|
||||||
console.info('Disconnected')
|
|
||||||
client.end("")
|
|
||||||
break
|
|
||||||
case "//end":
|
|
||||||
console.info('Forcibly ended client')
|
|
||||||
process.exit(0)
|
|
||||||
default:
|
|
||||||
client.write('chat', { message: line })
|
|
||||||
}
|
|
||||||
rl.prompt()
|
|
||||||
})
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
while :; do
|
|
||||||
yarn emp
|
|
||||||
echo 进程退出 休眠120秒!
|
|
||||||
sleep 120
|
|
||||||
done
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/common",
|
"name": "@ccms/common",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript common package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.21.0",
|
"@ccms/nashorn": "^0.27.6",
|
||||||
"@javatypes/jdk": "^0.0.3",
|
"@javatypes/jdk": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"gitHead": "562e2d00175c9d3a99c8b672aa07e6d92706a027"
|
"gitHead": "562e2d00175c9d3a99c8b672aa07e6d92706a027"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,20 @@ interface RequestConfig {
|
|||||||
method?: Method
|
method?: Method
|
||||||
headers?: { [key: string]: string }
|
headers?: { [key: string]: string }
|
||||||
params?: { [key: string]: string }
|
params?: { [key: string]: string }
|
||||||
data?: any
|
data?: any,
|
||||||
|
connectTimeout?: number,
|
||||||
|
readTimeout?: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
function request(config: RequestConfig) {
|
function request(config: RequestConfig) {
|
||||||
// @ts-ignore XMLHttpRequest class only exist nashorn polyfill
|
// @ts-ignore XMLHttpRequest class only exist nashorn polyfill
|
||||||
let xhr = new XMLHttpRequest()
|
let xhr = new XMLHttpRequest()
|
||||||
|
if (config.connectTimeout) {
|
||||||
|
xhr.connectTimeout = config.connectTimeout
|
||||||
|
}
|
||||||
|
if (config.readTimeout) {
|
||||||
|
xhr.readTimeout = config.readTimeout
|
||||||
|
}
|
||||||
xhr.open(config.method, config.url, false)
|
xhr.open(config.method, config.url, false)
|
||||||
for (const header in config.headers) {
|
for (const header in config.headers) {
|
||||||
xhr.setRequestHeader(header, config.headers[header])
|
xhr.setRequestHeader(header, config.headers[header])
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class Reflect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!field) throw new Error(`can't reflect field ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} from ${this.class.getName()}!`)
|
if (!field) throw new Error(`can't reflect field ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} from ${this.class.getName()}!`)
|
||||||
|
fieldCache.set(key, field)
|
||||||
return accessible(field)
|
return accessible(field)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,12 +130,14 @@ function declaredField(clazz: java.lang.Class<any>, name: string | java.lang.Str
|
|||||||
let field = null
|
let field = null
|
||||||
// noinspection JSUnresolvedVariable
|
// noinspection JSUnresolvedVariable
|
||||||
while (target !== JavaObject.class) {
|
while (target !== JavaObject.class) {
|
||||||
|
console.debug(`reflect field ${name} from ${target.getName()}`)
|
||||||
try {
|
try {
|
||||||
field = target.getDeclaredField(name)
|
field = target.getDeclaredField(name)
|
||||||
if (field !== null) { break }
|
if (field !== null) { break }
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (target === undefined) { break }
|
if (target === undefined) { break }
|
||||||
target = target.getSuperclass()
|
target = target.getSuperclass()
|
||||||
|
console.debug(`切换到超类: ${target.getName()}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (field === null) {
|
if (field === null) {
|
||||||
@@ -146,21 +149,32 @@ function declaredField(clazz: java.lang.Class<any>, name: string | java.lang.Str
|
|||||||
function declaredMethod(clazz: java.lang.Class<any>, nameOrIndex: string | number, ...clazzs: java.lang.Class<any>[]): java.lang.reflect.Method {
|
function declaredMethod(clazz: java.lang.Class<any>, nameOrIndex: string | number, ...clazzs: java.lang.Class<any>[]): java.lang.reflect.Method {
|
||||||
let key = clazz.getName() + '.' + nameOrIndex + ':' + (clazzs || []).map(c => c.getName()).join(':')
|
let key = clazz.getName() + '.' + nameOrIndex + ':' + (clazzs || []).map(c => c.getName()).join(':')
|
||||||
if (methodCache.has(key)) { return methodCache.get(key) }
|
if (methodCache.has(key)) { return methodCache.get(key) }
|
||||||
|
let target = clazz
|
||||||
if (typeof nameOrIndex === "number") {
|
if (typeof nameOrIndex === "number") {
|
||||||
methodCache.set(key, declaredMethods(clazz)[nameOrIndex])
|
methodCache.set(key, declaredMethods(clazz)[nameOrIndex])
|
||||||
} else {
|
} else {
|
||||||
try {
|
while (target !== JavaObject.class && !methodCache.has(key)) {
|
||||||
methodCache.set(key, clazz.getMethod(nameOrIndex, clazzs as any))
|
|
||||||
} catch (ex: any) {
|
|
||||||
try {
|
try {
|
||||||
methodCache.set(key, clazz.getDeclaredMethod(nameOrIndex, clazzs as any))
|
console.debug(`reflect method ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} from ${target.getName()}`)
|
||||||
} catch (ex: any) {
|
try {
|
||||||
for (const m of Java.from(declaredMethods(clazz))) {
|
methodCache.set(key, target.getMethod(nameOrIndex, clazzs as any))
|
||||||
if (m.getName() == nameOrIndex) {
|
} catch (ex: any) {
|
||||||
methodCache.set(key, m)
|
try {
|
||||||
break
|
methodCache.set(key, target.getDeclaredMethod(nameOrIndex, clazzs as any))
|
||||||
|
} catch (ex: any) {
|
||||||
|
for (const m of Java.from(declaredMethods(target))) {
|
||||||
|
if (m.getName() == nameOrIndex) {
|
||||||
|
methodCache.set(key, m)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`method ${typeof nameOrIndex == "number" ? 'index' : 'name'} ${nameOrIndex} not found.`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (target === undefined) { break }
|
||||||
|
target = target.getSuperclass()
|
||||||
|
console.debug(`切换到超类: ${target.getName()}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ class ChatMessagePart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
convert() {
|
convert() {
|
||||||
return this.internal;
|
return this.internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Tellraw {
|
class Tellraw {
|
||||||
static duplicateChar = '§卐'
|
static duplicateChar = '§卐'
|
||||||
static create() {
|
static create() {
|
||||||
return new Tellraw().then(Tellraw.duplicateChar);
|
return new Tellraw().then(Tellraw.duplicateChar)
|
||||||
}
|
}
|
||||||
|
|
||||||
private cache: string = '';
|
private cache: string = '';
|
||||||
@@ -32,77 +32,81 @@ class Tellraw {
|
|||||||
|
|
||||||
then(part: ChatMessagePart | string) {
|
then(part: ChatMessagePart | string) {
|
||||||
if (typeof part === "string") {
|
if (typeof part === "string") {
|
||||||
var newPart = new ChatMessagePart();
|
var newPart = new ChatMessagePart()
|
||||||
newPart.text = part
|
newPart.text = part
|
||||||
this.then(newPart);
|
this.then(newPart)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
var last = this.latest();
|
var last = this.latest()
|
||||||
if (!last.text) {
|
if (!last.text) {
|
||||||
last.text = part.text;
|
last.text = part.text
|
||||||
} else {
|
} else {
|
||||||
this.parts.push(part);
|
this.parts.push(part)
|
||||||
}
|
}
|
||||||
this.cache = null;
|
this.cache = null
|
||||||
}
|
}
|
||||||
|
|
||||||
text(text: string) {
|
text(text: string) {
|
||||||
this.latest().text = text;
|
this.latest().text = text
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
tip(text: string) {
|
tip(texts: string) {
|
||||||
this.latest().hover("show_text", text);
|
return this.hover(texts)
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
item(text: string) {
|
hover(texts: string) {
|
||||||
this.latest().hover("show_item", text);
|
this.latest().hover("show_text", texts)
|
||||||
return this;
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
item(item: string) {
|
||||||
|
this.latest().hover("show_item", item)
|
||||||
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
command(command: string) {
|
command(command: string) {
|
||||||
this.latest().click("run_command", command);
|
this.latest().click("run_command", command)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
suggest(url: string) {
|
suggest(url: string) {
|
||||||
this.latest().click("suggest_command", url);
|
this.latest().click("suggest_command", url)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
file(path: string) {
|
file(path: string) {
|
||||||
this.latest().click("open_file", path);
|
this.latest().click("open_file", path)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
link(url: string) {
|
link(url: string) {
|
||||||
this.latest().click("open_url", url);
|
this.latest().click("open_url", url)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
latest() {
|
latest() {
|
||||||
return this.parts[this.parts.length - 1];
|
return this.parts[this.parts.length - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
json() {
|
json() {
|
||||||
if (!this.cache) {
|
if (!this.cache) {
|
||||||
var temp = [];
|
var temp = []
|
||||||
this.parts.forEach(t => {
|
this.parts.forEach(t => {
|
||||||
temp.push(t.convert());
|
temp.push(t.convert())
|
||||||
});
|
})
|
||||||
this.cache = JSON.stringify(temp);
|
this.cache = JSON.stringify(temp)
|
||||||
console.trace(this.cache);
|
console.trace(this.cache)
|
||||||
}
|
}
|
||||||
return this.cache;
|
return this.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
string() {
|
string() {
|
||||||
var temp = '';
|
var temp = ''
|
||||||
this.parts.forEach(t => {
|
this.parts.forEach(t => {
|
||||||
temp += t.text
|
temp += t.text
|
||||||
});
|
})
|
||||||
return temp;
|
return temp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
35
packages/common/src/version.ts
Normal file
35
packages/common/src/version.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
export type Version = [string, string, string]
|
||||||
|
|
||||||
|
export class VersionUtils {
|
||||||
|
static isEqual(version: string, targetVersion: string): boolean {
|
||||||
|
return version == targetVersion
|
||||||
|
}
|
||||||
|
static isGreaterOrEqual(version: string, targetVersion: string): boolean {
|
||||||
|
const v1 = parseVersion(version)
|
||||||
|
const v2 = parseVersion(targetVersion)
|
||||||
|
|
||||||
|
return (
|
||||||
|
v1[0] > v2[0] ||
|
||||||
|
(v1[0] === v2[0] && v1[1] > v2[1]) ||
|
||||||
|
(v1[0] === v2[0] && v1[1] === v2[1] && v1[2] >= v2[2])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
static isGreater(version: string, targetVersion: string): boolean {
|
||||||
|
const v1 = parseVersion(version)
|
||||||
|
const v2 = parseVersion(targetVersion)
|
||||||
|
|
||||||
|
return (
|
||||||
|
v1[0] > v2[0] ||
|
||||||
|
(v1[0] === v2[0] && v1[1] > v2[1]) ||
|
||||||
|
(v1[0] === v2[0] && v1[1] === v2[1] && v1[2] > v2[2])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseVersion(version: string = ""): Version {
|
||||||
|
const v: Version = ['0', '0', '0']
|
||||||
|
|
||||||
|
version.split(".").forEach((value, i) => (v[i] = value))
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/compile",
|
"name": "@ccms/compile",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript compile package",
|
"description": "MiaoScript compile package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/container",
|
"name": "@ccms/container",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript container package",
|
"description": "MiaoScript container package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,10 +19,10 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.21.0",
|
"@ccms/nashorn": "^0.27.6",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"inversify": "^6.0.1",
|
"inversify": "^6.0.1",
|
||||||
|
|||||||
@@ -102,8 +102,8 @@ export const MavenDepend = (groupId: string, artifactId: string, version: string
|
|||||||
const loadedMavenDepend = new Set<string>()
|
const loadedMavenDepend = new Set<string>()
|
||||||
|
|
||||||
export function loadMavenDepend(groupId: string, artifactId: string, version: string, recursion = false) {
|
export function loadMavenDepend(groupId: string, artifactId: string, version: string, recursion = false) {
|
||||||
|
const key = `${groupId}:${artifactId}:${version}`
|
||||||
try {
|
try {
|
||||||
const key = `${groupId}:${artifactId}:${version}`
|
|
||||||
if (loadedMavenDepend.has(key)) { return }
|
if (loadedMavenDepend.has(key)) { return }
|
||||||
console.info('loading maven dependency', key)
|
console.info('loading maven dependency', key)
|
||||||
let [pom, _] = base.loadMavenDepend(groupId, artifactId, version)
|
let [pom, _] = base.loadMavenDepend(groupId, artifactId, version)
|
||||||
@@ -137,7 +137,7 @@ export function loadMavenDepend(groupId: string, artifactId: string, version: st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.warn('attachMavenDepend failed. Error: ' + error)
|
console.warn('load maven dependency', key, 'failed. Error:', error)
|
||||||
if (global.debug) {
|
if (global.debug) {
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/core",
|
"name": "@ccms/core",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript core package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -20,12 +20,12 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.21.0",
|
"@ccms/api": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0"
|
"@ccms/container": "^0.27.6"
|
||||||
},
|
},
|
||||||
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
||||||
}
|
}
|
||||||
|
|||||||
1
packages/core/src/.gitignore
vendored
Normal file
1
packages/core/src/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
script
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
let containerStartTime = Date.now()
|
let containerStartTime = Date.now()
|
||||||
console.i18n("ms.core.ioc.initialize", { scope: global.scope })
|
console.i18n("ms.core.ioc.initialize", { scope: global.scope })
|
||||||
import { plugin, server, task, constants } from '@ccms/api'
|
import { plugin, server, task, constants, console as jsconsole } from '@ccms/api'
|
||||||
import { DefaultContainer as container, provideSingleton, ContainerInstance, buildProviderModule, Autowired } from '@ccms/container'
|
import { DefaultContainer as container, provideSingleton, ContainerInstance, buildProviderModule, Autowired } from '@ccms/container'
|
||||||
console.i18n("ms.core.ioc.completed", { scope: global.scope, time: (Date.now() - containerStartTime) / 1000 })
|
console.i18n("ms.core.ioc.completed", { scope: global.scope, time: (Date.now() - containerStartTime) / 1000 })
|
||||||
import * as yaml from 'js-yaml'
|
import * as yaml from 'js-yaml'
|
||||||
import http from '@ccms/common/dist/http'
|
import http from '@ccms/common/dist/http'
|
||||||
import * as fs from '@ccms/common/dist/fs'
|
import * as fs from '@ccms/common/dist/fs'
|
||||||
|
import { VersionUtils } from '@ccms/common/dist/version'
|
||||||
|
|
||||||
const UUID = Java.type('java.util.UUID')
|
const UUID = Java.type('java.util.UUID')
|
||||||
|
const MiaoScriptAPI = Java.type('pw.yumc.MiaoScript.api.MiaoScriptAPI')
|
||||||
|
|
||||||
@provideSingleton(MiaoScriptCore)
|
@provideSingleton(MiaoScriptCore)
|
||||||
class MiaoScriptCore {
|
class MiaoScriptCore {
|
||||||
@@ -23,8 +25,17 @@ class MiaoScriptCore {
|
|||||||
enable() {
|
enable() {
|
||||||
process.emit('core.before.enable')
|
process.emit('core.before.enable')
|
||||||
this.loadServerConsole()
|
this.loadServerConsole()
|
||||||
|
try {
|
||||||
|
MiaoScriptAPI.setPluginManager(this.pluginManager)
|
||||||
|
} catch (error) {
|
||||||
|
}
|
||||||
this.loadPlugins()
|
this.loadPlugins()
|
||||||
process.emit('core.after.enable')
|
process.emit('core.after.enable')
|
||||||
|
console.i18n("ms.core.engine.completed", {
|
||||||
|
loader: base.version,
|
||||||
|
version: 'v' + global.ScriptEngineVersion,
|
||||||
|
time: (Date.now() - global.ScriptEngineStartTime) / 1000
|
||||||
|
})
|
||||||
return () => this.disable()
|
return () => this.disable()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +110,7 @@ function loadCoreScript(name) {
|
|||||||
try {
|
try {
|
||||||
let scriptname = name + (global.debug ? '-debug' : '')
|
let scriptname = name + (global.debug ? '-debug' : '')
|
||||||
engineLoad({
|
engineLoad({
|
||||||
script: http.get(`https://ms.yumc.pw/api/plugin/download/name/${scriptname}`),
|
script: http.get(`https://mscript.yumc.pw/api/plugin/download/name/${scriptname}`),
|
||||||
name: `core/${scriptname}.js`
|
name: `core/${scriptname}.js`
|
||||||
})
|
})
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -123,6 +134,31 @@ function loadMiaoScriptConfig() {
|
|||||||
global.ScriptSlowExecuteTime = global.ScriptEngineConfig.slow_execute || 50
|
global.ScriptSlowExecuteTime = global.ScriptEngineConfig.slow_execute || 50
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createCore() {
|
||||||
|
let corePackageStartTime = new Date().getTime()
|
||||||
|
container.bind(ContainerInstance).toConstantValue(container)
|
||||||
|
container.bind(plugin.PluginInstance).toConstantValue(base.getInstance())
|
||||||
|
container.bind(plugin.PluginFolder).toConstantValue('plugins')
|
||||||
|
let type = detectServer()
|
||||||
|
|
||||||
|
process.emit('core.before.initialize.detect')
|
||||||
|
console.i18n("ms.core.initialize.detect", { scope: global.scope, type })
|
||||||
|
container.bind(server.ServerType).toConstantValue(type)
|
||||||
|
container.bind(server.ServerChecker).toSelf().inSingletonScope()
|
||||||
|
container.bind(server.NativePluginManager).toSelf().inSingletonScope()
|
||||||
|
container.bind(server.NativePluginChecker).toSelf().inSingletonScope()
|
||||||
|
process.emit('core.after.initialize.detect')
|
||||||
|
|
||||||
|
process.emit('core.before.package.initialize')
|
||||||
|
console.i18n("ms.core.package.initialize", { scope: global.scope, type })
|
||||||
|
require(`${global.scope}/${type}`).default(container)
|
||||||
|
require(`${global.scope}/plugin`)
|
||||||
|
container.load(buildProviderModule())
|
||||||
|
console.i18n("ms.core.package.completed", { scope: global.scope, type, time: (Date.now() - corePackageStartTime) / 1000 })
|
||||||
|
process.emit('core.after.package.initialize')
|
||||||
|
return container.get<MiaoScriptCore>(MiaoScriptCore)
|
||||||
|
}
|
||||||
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
process.emit('core.before.initialize')
|
process.emit('core.before.initialize')
|
||||||
loadMiaoScriptConfig()
|
loadMiaoScriptConfig()
|
||||||
@@ -130,43 +166,16 @@ function initialize() {
|
|||||||
global.setGlobal('loadCoreScript', loadCoreScript)
|
global.setGlobal('loadCoreScript', loadCoreScript)
|
||||||
loadCoreScript('initialize')
|
loadCoreScript('initialize')
|
||||||
try {
|
try {
|
||||||
let corePackageStartTime = new Date().getTime()
|
let core = createCore()
|
||||||
container.bind(ContainerInstance).toConstantValue(container)
|
return VersionUtils.isGreaterOrEqual(base.version, '0.22.0') ? core : core.enable()
|
||||||
container.bind(plugin.PluginInstance).toConstantValue(base.getInstance())
|
|
||||||
container.bind(plugin.PluginFolder).toConstantValue('plugins')
|
|
||||||
let type = detectServer()
|
|
||||||
|
|
||||||
process.emit('core.before.initialize.detect')
|
|
||||||
console.i18n("ms.core.initialize.detect", { scope: global.scope, type })
|
|
||||||
container.bind(server.ServerType).toConstantValue(type)
|
|
||||||
container.bind(server.ServerChecker).toSelf().inSingletonScope()
|
|
||||||
container.bind(server.NativePluginManager).toSelf().inSingletonScope()
|
|
||||||
process.emit('core.after.initialize.detect')
|
|
||||||
|
|
||||||
process.emit('core.before.package.initialize')
|
|
||||||
console.i18n("ms.core.package.initialize", { scope: global.scope, type })
|
|
||||||
require(`${global.scope}/${type}`).default(container)
|
|
||||||
require(`${global.scope}/plugin`)
|
|
||||||
container.load(buildProviderModule())
|
|
||||||
console.i18n("ms.core.package.completed", { scope: global.scope, type, time: (Date.now() - corePackageStartTime) / 1000 })
|
|
||||||
process.emit('core.after.package.initialize')
|
|
||||||
|
|
||||||
let disable = container.get<MiaoScriptCore>(MiaoScriptCore).enable()
|
|
||||||
console.i18n("ms.core.engine.completed", {
|
|
||||||
loader: base.version,
|
|
||||||
version: 'v' + global.ScriptEngineVersion,
|
|
||||||
time: (Date.now() - global.ScriptEngineStartTime) / 1000
|
|
||||||
})
|
|
||||||
process.emit('core.after.initialize')
|
|
||||||
return disable
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (console.console) {
|
let core = { enable: () => () => console.i18n('ms.core.engine.disable.abnormal') }
|
||||||
console.i18n("ms.core.initialize.error", { error })
|
console.i18n("core.initialize.error", { error })
|
||||||
console.ex(error)
|
jsconsole.getStackTrace(error, false).forEach(line => console.log(line))
|
||||||
} else {
|
process.emit('core.initialize.error')
|
||||||
error.printStackTrace()
|
return VersionUtils.isGreaterOrEqual(base.version, '0.22.0') ? core : core.enable()
|
||||||
}
|
} finally {
|
||||||
return () => console.i18n('ms.core.engine.disable.abnormal')
|
process.emit('core.after.initialize')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/database",
|
"name": "@ccms/database",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript database package",
|
"description": "MiaoScript database package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -21,11 +21,11 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/spring-jdbc": "^0.0.3",
|
"@javatypes/spring-jdbc": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.21.0",
|
"@ccms/api": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0"
|
"@ccms/container": "^0.27.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { database } from '@ccms/api'
|
import { database } from '@ccms/api'
|
||||||
import { JSClass, postConstruct } from '@ccms/container'
|
import { JSClass } from '@ccms/container'
|
||||||
|
|
||||||
|
const Thread = Java.type('java.lang.Thread')
|
||||||
|
const JavaString = Java.type('java.lang.String')
|
||||||
const Properties = Java.type('java.util.Properties')
|
const Properties = Java.type('java.util.Properties')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,9 +27,21 @@ export class DataBase extends database.DataBase {
|
|||||||
|
|
||||||
private createDataSource(dbConfig: database.DataBaseConfig) {
|
private createDataSource(dbConfig: database.DataBaseConfig) {
|
||||||
if (typeof dbConfig.url === "string") {
|
if (typeof dbConfig.url === "string") {
|
||||||
|
let originClassLoader = Thread.currentThread().getContextClassLoader()
|
||||||
|
Thread.currentThread().setContextClassLoader(base.getInstance().class.classLoader)
|
||||||
let config = new this.HikariConfig()
|
let config = new this.HikariConfig()
|
||||||
if (dbConfig.driverClassName) {
|
if (dbConfig.driverClassName) {
|
||||||
config.setDriverClassName(dbConfig.driverClassName)
|
config.setDriverClassName(dbConfig.driverClassName)
|
||||||
|
} else {
|
||||||
|
switch (dbConfig.type) {
|
||||||
|
case "h2":
|
||||||
|
config.setDriverClassName("org.h2.Driver")
|
||||||
|
break
|
||||||
|
case "sqlite":
|
||||||
|
config.setDriverClassName("org.sqlite.JDBC")
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (dbConfig.username) {
|
if (dbConfig.username) {
|
||||||
config.setUsername(dbConfig.username)
|
config.setUsername(dbConfig.username)
|
||||||
@@ -43,15 +57,17 @@ export class DataBase extends database.DataBase {
|
|||||||
}
|
}
|
||||||
config.setDataSourceProperties(properties)
|
config.setDataSourceProperties(properties)
|
||||||
}
|
}
|
||||||
|
console.debug('createDataSource from config ' + JSON.stringify(dbConfig))
|
||||||
this.dataSource = new this.HikariDataSource(config)
|
this.dataSource = new this.HikariDataSource(config)
|
||||||
|
Thread.currentThread().setContextClassLoader(originClassLoader)
|
||||||
} else {
|
} else {
|
||||||
this.dataSource = dbConfig.url
|
this.dataSource = dbConfig.url
|
||||||
}
|
}
|
||||||
|
this.jdbcTemplate = new this.JdbcTemplate(this.dataSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
@postConstruct()
|
getDataSource() {
|
||||||
private initialize() {
|
return this.dataSource
|
||||||
this.jdbcTemplate = new this.JdbcTemplate(this.dataSource)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,7 +78,7 @@ export class DataBase extends database.DataBase {
|
|||||||
query<T>(sql: string, ...args: any[]): Array<T> {
|
query<T>(sql: string, ...args: any[]): Array<T> {
|
||||||
let startTime = Date.now()
|
let startTime = Date.now()
|
||||||
let result = Java.from<any>(this.jdbcTemplate.queryForList(sql, args))
|
let result = Java.from<any>(this.jdbcTemplate.queryForList(sql, args))
|
||||||
console.debug(java.lang.String.format(`\n[DB] query \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
console.debug(JavaString.format(`\n[DB] query \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +90,7 @@ export class DataBase extends database.DataBase {
|
|||||||
update(sql: string, ...args: any[]): number {
|
update(sql: string, ...args: any[]): number {
|
||||||
let startTime = Date.now()
|
let startTime = Date.now()
|
||||||
let result = this.jdbcTemplate.update(sql, args)
|
let result = this.jdbcTemplate.update(sql, args)
|
||||||
console.debug(java.lang.String.format(`\n[DB] update \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
console.debug(JavaString.format(`\n[DB] update \nSQL : ${sql.replace(/\?/ig, '%s')} \nCOST : ${Date.now() - startTime}ms`, args))
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +101,7 @@ export class DataBase extends database.DataBase {
|
|||||||
execute(sql: string): void {
|
execute(sql: string): void {
|
||||||
let startTime = Date.now()
|
let startTime = Date.now()
|
||||||
this.jdbcTemplate.execute(sql)
|
this.jdbcTemplate.execute(sql)
|
||||||
console.debug(java.lang.String.format(`\n[DB] execute \nSQL : sql} \nCOST : ${Date.now() - startTime}ms`))
|
console.debug(`\n[DB] execute \nSQL : ${sql} \nCOST : ${Date.now() - startTime}ms`)
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
import 'reflect-metadata'
|
|
||||||
|
|
||||||
export function id() {
|
|
||||||
return (target: Object, propertyKey: string | symbol) => void {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { database } from '@ccms/api'
|
import { database } from '@ccms/api'
|
||||||
import { provideSingleton } from '@ccms/container'
|
import { JSClass, provideSingleton } from '@ccms/container'
|
||||||
import { DataBase } from './database'
|
import { DataBase } from './database'
|
||||||
|
|
||||||
@provideSingleton(database.DataBaseManager)
|
@provideSingleton(database.DataBaseManager)
|
||||||
@@ -7,11 +7,32 @@ export class DataBaseManager extends database.DataBaseManager {
|
|||||||
private mainDatabase: DataBase
|
private mainDatabase: DataBase
|
||||||
private databases = new Map<string, DataBase>()
|
private databases = new Map<string, DataBase>()
|
||||||
|
|
||||||
|
@JSClass('org.h2.tools.Server')
|
||||||
|
private Server: any
|
||||||
|
|
||||||
|
private webManager: any
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
process.on('exit', () => this.disable())
|
process.on('exit', () => this.shutdown())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startWebManager(...args: string[]) {
|
||||||
|
this.webManager = this.Server.createWebServer(args)
|
||||||
|
this.webManager.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
stopWebManager() {
|
||||||
|
if (this.webManager) {
|
||||||
|
this.webManager.stop()
|
||||||
|
this.webManager.shutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shutdown() {
|
||||||
|
this.stopWebManager()
|
||||||
|
this.disable()
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 设置主数据库
|
* 设置主数据库
|
||||||
* @param mainDatabase 主数据库
|
* @param mainDatabase 主数据库
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import { DataBase } from "./database"
|
|
||||||
|
|
||||||
export class Model<T> {
|
|
||||||
constructor(private database: DataBase) {
|
|
||||||
|
|
||||||
}
|
|
||||||
queryForList(): Array<T> {
|
|
||||||
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -34,7 +34,7 @@ ms.api.command.tab.completer.slow: "§c注意! §6玩家 §a{player} §6执行
|
|||||||
ms.api.command.tab.completer.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6补全时发生异常 §4{ex}"
|
ms.api.command.tab.completer.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6补全时发生异常 §4{ex}"
|
||||||
|
|
||||||
ms.plugin.initialize: "初始化 MiaoScript 插件系统: 实例: {plugin} 加载器: {loader}..."
|
ms.plugin.initialize: "初始化 MiaoScript 插件系统: 实例: {plugin} 加载器: {loader}..."
|
||||||
ms.plugin.event.map: "总计 {count} 个 {type} 事件 映射完成..."
|
ms.plugin.event.map: "映射 {type} 事件 成功 总计 {count} 个 {type} 事件..."
|
||||||
ms.plugin.event.map.error: "映射 {type} 事件 异常 将无法使用事件简称. Error: {error}"
|
ms.plugin.event.map.error: "映射 {type} 事件 异常 将无法使用事件简称. Error: {error}"
|
||||||
ms.plugin.manager.scan: "扫描器 {scanner} 扫描 {folder} 中的插件..."
|
ms.plugin.manager.scan: "扫描器 {scanner} 扫描 {folder} 中的插件..."
|
||||||
ms.plugin.manager.scan.finish: "扫描器 {scanner} 在 {folder} 中 发现 {size} 个插件 开始编译..."
|
ms.plugin.manager.scan.finish: "扫描器 {scanner} 在 {folder} 中 发现 {size} 个插件 开始编译..."
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/i18n",
|
"name": "@ccms/i18n",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript i18n package",
|
"description": "MiaoScript i18n package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.21.0",
|
"@ccms/nashorn": "^0.27.6",
|
||||||
"@types/js-yaml": "^4.0.5",
|
"@types/js-yaml": "^4.0.5",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-yaml": "^4.1.0"
|
"js-yaml": "^4.1.0"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/keyvalue",
|
"name": "@ccms/keyvalue",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript keyvalue package",
|
"description": "MiaoScript keyvalue package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,18 +19,18 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.21.0",
|
"@ccms/api": "^0.27.6",
|
||||||
"@ccms/common": "^0.21.0",
|
"@ccms/common": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0"
|
"@ccms/container": "^0.27.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.21.0",
|
"@ccms/nashorn": "^0.27.6",
|
||||||
"@javatypes/amqp-client": "^0.0.3",
|
"@javatypes/amqp-client": "^0.0.3",
|
||||||
"@javatypes/spring-amqp": "^0.0.3",
|
"@javatypes/spring-amqp": "^0.0.3",
|
||||||
"@javatypes/spring-rabbit": "^0.0.3",
|
"@javatypes/spring-rabbit": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"gitHead": "2589633069d24f646ac09261b1b2304c21d4ea75"
|
"gitHead": "2589633069d24f646ac09261b1b2304c21d4ea75"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/molang",
|
"name": "@ccms/molang",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "A fast parser for Minecraft's MoLang",
|
"description": "A fast parser for Minecraft's MoLang",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
@@ -21,9 +21,9 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/solvedDev/MoLang#readme",
|
"homepage": "https://github.com/solvedDev/MoLang#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^17.0.25",
|
"@types/node": "^18.13.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"tslib": "^2.3.1",
|
"tslib": "^2.5.0",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/nashorn",
|
"name": "@ccms/nashorn",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript nashorn package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,10 @@ declare global {
|
|||||||
scope: string
|
scope: string
|
||||||
logger: any
|
logger: any
|
||||||
debug: boolean
|
debug: boolean
|
||||||
level: string
|
/**
|
||||||
|
* 引擎日志等级
|
||||||
|
*/
|
||||||
|
ScriptEngineLoggerLevel: string
|
||||||
/**
|
/**
|
||||||
* 引擎配置
|
* 引擎配置
|
||||||
*/
|
*/
|
||||||
@@ -61,8 +64,18 @@ declare global {
|
|||||||
* 引擎渠道
|
* 引擎渠道
|
||||||
*/
|
*/
|
||||||
ScriptEngineChannel: string
|
ScriptEngineChannel: string
|
||||||
|
/**
|
||||||
|
* 慢执行检测时间
|
||||||
|
*/
|
||||||
ScriptSlowExecuteTime: number
|
ScriptSlowExecuteTime: number
|
||||||
ScriptEngineStartTime: number
|
ScriptEngineStartTime: number
|
||||||
|
/**
|
||||||
|
* 设置全局对象
|
||||||
|
* @param key 对象名称
|
||||||
|
* @param value 对象值
|
||||||
|
* @param config 对象属性
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
setGlobal: (key: string, value: any, config?: PropertyDescriptor & ThisType<any>) => void
|
setGlobal: (key: string, value: any, config?: PropertyDescriptor & ThisType<any>) => void
|
||||||
noop: () => void
|
noop: () => void
|
||||||
console: Console
|
console: Console
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/nodejs",
|
"name": "@ccms/nodejs",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript nodejs package",
|
"description": "MiaoScript nodejs package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.21.0",
|
"@ccms/nashorn": "^0.27.6",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"tslib": "^2.3.1",
|
"tslib": "^2.5.0",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
"gitHead": "781524f83e52cad26d7c480513e3c525df867121"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/nukkit",
|
"name": "@ccms/nukkit",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript nukkit package",
|
"description": "MiaoScript nukkit package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/nukkit-api": "^0.0.3",
|
"@javatypes/nukkit-api": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.21.0",
|
"@ccms/api": "^0.27.6",
|
||||||
"@ccms/common": "^0.21.0",
|
"@ccms/common": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0"
|
"@ccms/container": "^0.27.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/plugin",
|
"name": "@ccms/plugin",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript plugin package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -22,15 +22,15 @@
|
|||||||
"@types/crypto-js": "^4.1.1",
|
"@types/crypto-js": "^4.1.1",
|
||||||
"@types/js-yaml": "^4.0.5",
|
"@types/js-yaml": "^4.0.5",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.21.0",
|
"@ccms/api": "^0.27.6",
|
||||||
"@ccms/common": "^0.21.0",
|
"@ccms/common": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0",
|
"@ccms/container": "^0.27.6",
|
||||||
"@ccms/i18n": "^0.21.0",
|
"@ccms/i18n": "^0.27.6",
|
||||||
"@ccms/verify": "^0.21.1",
|
"@ccms/verify": "^0.25.1",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"js-yaml": "^4.1.0"
|
"js-yaml": "^4.1.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export class PluginCommandManager {
|
|||||||
permission = `${pluginInstance.description.name.toLocaleLowerCase()}.${command}.${subcommand || 'main'}`
|
permission = `${pluginInstance.description.name.toLocaleLowerCase()}.${command}.${subcommand || 'main'}`
|
||||||
}
|
}
|
||||||
if (!sender.hasPermission(permission)) {
|
if (!sender.hasPermission(permission)) {
|
||||||
return pluginInstance.logger.sender(sender, `§c你需要 ${permission} 权限 才可执行此命令.`)
|
return pluginInstance.logger.sender(sender, `§c你需要 §4${permission} §c权限 才可执行此命令.`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args.shift()
|
args.shift()
|
||||||
@@ -98,7 +98,7 @@ export class PluginCommandManager {
|
|||||||
return (args.length == 1 ? cmdSubCache : []).concat(originCompleter?.apply(pluginInstance, [sender, command, args]) || [])
|
return (args.length == 1 ? cmdSubCache : []).concat(originCompleter?.apply(pluginInstance, [sender, command, args]) || [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!cmdCompleter) { console.warn(`[${pluginInstance.description.name}] command ${cmd.name} is not registry tabCompleter`) }
|
if (!cmdCompleter) { console.debug(`[${pluginInstance.description.name}] command ${cmd.name} is not registry tabCompleter`) }
|
||||||
return [cmdExecutor, cmdCompleter]
|
return [cmdExecutor, cmdCompleter]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import { interfaces } from './interfaces'
|
|||||||
import { getPluginConfigMetadata } from './utils'
|
import { getPluginConfigMetadata } from './utils'
|
||||||
|
|
||||||
import { PluginConfigLoader } from './config/interfaces'
|
import { PluginConfigLoader } from './config/interfaces'
|
||||||
import './config/loader/json-loader'
|
import './config/loader'
|
||||||
import './config/loader/yaml-loader'
|
|
||||||
|
|
||||||
@provideSingleton(PluginConfigManager)
|
@provideSingleton(PluginConfigManager)
|
||||||
export class PluginConfigManager {
|
export class PluginConfigManager {
|
||||||
@@ -68,30 +67,25 @@ export class PluginConfigManager {
|
|||||||
private loadConfig0(plugin: plugin.Plugin, metadata: interfaces.ConfigMetadata) {
|
private loadConfig0(plugin: plugin.Plugin, metadata: interfaces.ConfigMetadata) {
|
||||||
try {
|
try {
|
||||||
let defaultValue = metadata.default ?? plugin[metadata.variable]
|
let defaultValue = metadata.default ?? plugin[metadata.variable]
|
||||||
let configValue = defaultValue || {}
|
metadata.file = fs.concat(
|
||||||
if (defaultValue) {
|
fs.file(plugin.description.loadMetadata.file).parent,
|
||||||
metadata.file = fs.concat(
|
plugin.description.name,
|
||||||
fs.file(plugin.description.loadMetadata.file).parent,
|
metadata.filename
|
||||||
plugin.description.name,
|
)
|
||||||
metadata.filename
|
let configLoader = this.getConfigLoader(metadata.format)
|
||||||
)
|
if (!fs.exists(metadata.file) && defaultValue) {
|
||||||
let configLoader = this.getConfigLoader(metadata.format)
|
base.save(metadata.file, configLoader.dump(defaultValue))
|
||||||
if (!fs.exists(metadata.file)) {
|
console.i18n("ms.plugin.manager.config.save.default", {
|
||||||
base.save(metadata.file, configLoader.dump(defaultValue))
|
plugin: plugin.description.name,
|
||||||
console.i18n("ms.plugin.manager.config.save.default", {
|
name: metadata.name,
|
||||||
plugin: plugin.description.name,
|
format: metadata.format
|
||||||
name: metadata.name,
|
})
|
||||||
format: metadata.format
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
configValue = configLoader.load(base.read(metadata.file)) || {}
|
|
||||||
if (defaultValue && this.setDefaultValue(configValue, defaultValue, !!metadata.default)) {
|
|
||||||
base.save(metadata.file, configLoader.dump(configValue))
|
|
||||||
}
|
|
||||||
console.debug(`[${plugin.description.name}] Load Config ${metadata.variable} from file ${metadata.file} =>
|
|
||||||
${JSON.stringify(configValue, undefined, 4).substring(0, 500)}`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
let configValue = configLoader.load(base.read(metadata.file)) || {}
|
||||||
|
if (metadata.migrate && defaultValue && this.setDefaultValue(configValue, defaultValue, !!metadata.default)) {
|
||||||
|
base.save(metadata.file, configLoader.dump(configValue))
|
||||||
|
}
|
||||||
|
console.debug(`[${plugin.description.name}] Load Config ${metadata.variable} from file ${metadata.file}`)
|
||||||
this.defienConfigProp(plugin, metadata, configValue)
|
this.defienConfigProp(plugin, metadata, configValue)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.i18n("ms.plugin.manager.config.load.error", {
|
console.i18n("ms.plugin.manager.config.load.error", {
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ export function config(metadata: interfaces.ConfigMetadata = {}) {
|
|||||||
metadata.variable = key
|
metadata.variable = key
|
||||||
metadata.version = metadata.version ?? 1
|
metadata.version = metadata.version ?? 1
|
||||||
metadata.format = metadata.format ?? 'yml'
|
metadata.format = metadata.format ?? 'yml'
|
||||||
|
metadata.migrate = metadata.migrate ?? true
|
||||||
metadata.autosave = metadata.autosave ?? false
|
metadata.autosave = metadata.autosave ?? false
|
||||||
metadata.filename = metadata.filename ?? metadata.name + '.' + metadata.format
|
metadata.filename = metadata.filename ?? metadata.name + '.' + metadata.format
|
||||||
let previousMetadata = getPluginConfigMetadata(target)
|
let previousMetadata = getPluginConfigMetadata(target)
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import { getPluginListenerMetadata } from './utils'
|
|||||||
@provideSingleton(PluginEventManager)
|
@provideSingleton(PluginEventManager)
|
||||||
export class PluginEventManager {
|
export class PluginEventManager {
|
||||||
@Autowired()
|
@Autowired()
|
||||||
private EventManager: event.Event
|
private eventManager: event.Event
|
||||||
@Autowired()
|
@Autowired()
|
||||||
private ServerChecker: server.ServerChecker
|
private serverChecker: server.ServerChecker
|
||||||
|
@Autowired()
|
||||||
|
private nativePluginChecker: server.NativePluginChecker
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
process.on('plugin.before.enable', this.registryListener.bind(this))
|
process.on('plugin.before.enable', this.registryListener.bind(this))
|
||||||
@@ -15,26 +17,31 @@ export class PluginEventManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mapEventName() {
|
mapEventName() {
|
||||||
return this.EventManager.mapEventName().toFixed(0)
|
return this.eventManager.mapEventName().toFixed(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
private registryListener(pluginInstance: plugin.Plugin) {
|
private registryListener(pluginInstance: plugin.Plugin) {
|
||||||
let events = getPluginListenerMetadata(pluginInstance)
|
let events = getPluginListenerMetadata(pluginInstance)
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
// ignore space listener
|
// ignore space listener
|
||||||
if (!this.ServerChecker.check(event.servers)) {
|
if (!this.serverChecker.check(event.servers)) {
|
||||||
console.debug(`[${pluginInstance.description.name}] ${event.target.constructor.name} incompatible event ${event.name} server(${event.servers}) ignore.`)
|
console.debug(`[${pluginInstance.description.name}] ${event.target.constructor.name} incompatible server(${event.servers}) ignore event ${event.name}.`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// ignore space listener
|
||||||
|
if (!this.nativePluginChecker.check(event.plugins)) {
|
||||||
|
console.debug(`[${pluginInstance.description.name}] ${event.target.constructor.name} require native plugins(${event.plugins}) ignore event ${event.name}.`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// here must bind this to pluginInstance
|
// here must bind this to pluginInstance
|
||||||
let exec = event.target[event.executor]
|
let exec = event.target[event.executor]
|
||||||
let execBinded = exec.bind(pluginInstance)
|
let execBinded = exec.bind(pluginInstance)
|
||||||
execBinded.executor = event.executor
|
execBinded.executor = event.executor
|
||||||
exec.off = this.EventManager.listen(pluginInstance, event.name, execBinded, event.priority, event.ignoreCancel)
|
exec.off = this.eventManager.listen(pluginInstance, event.name, execBinded, event.priority, event.ignoreCancel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unregistryListener(pluginInstance: plugin.Plugin) {
|
private unregistryListener(pluginInstance: plugin.Plugin) {
|
||||||
this.EventManager.disable(pluginInstance)
|
this.eventManager.disable(pluginInstance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ export namespace interfaces {
|
|||||||
* 是否忽略已取消的事件
|
* 是否忽略已取消的事件
|
||||||
*/
|
*/
|
||||||
ignoreCancel?: boolean
|
ignoreCancel?: boolean
|
||||||
|
/**
|
||||||
|
* 依赖插件 没有就不加载
|
||||||
|
*/
|
||||||
|
plugins?: string[]
|
||||||
}
|
}
|
||||||
export interface ConfigMetadata extends plugin.BaseMetadata {
|
export interface ConfigMetadata extends plugin.BaseMetadata {
|
||||||
/**
|
/**
|
||||||
@@ -91,6 +95,10 @@ export namespace interfaces {
|
|||||||
* 配置文件格式 默认 yml
|
* 配置文件格式 默认 yml
|
||||||
*/
|
*/
|
||||||
format?: string
|
format?: string
|
||||||
|
/**
|
||||||
|
* 是否合并默认配置
|
||||||
|
*/
|
||||||
|
migrate?: boolean
|
||||||
/**
|
/**
|
||||||
* 自动保存 默认为 false
|
* 自动保存 默认为 false
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,12 +2,11 @@ import i18n from '@ccms/i18n'
|
|||||||
import { plugin, server } from '@ccms/api'
|
import { plugin, server } from '@ccms/api'
|
||||||
import { provideSingleton, Container, ContainerInstance, Autowired } from '@ccms/container'
|
import { provideSingleton, Container, ContainerInstance, Autowired } from '@ccms/container'
|
||||||
|
|
||||||
import './config'
|
|
||||||
import { interfaces } from './interfaces'
|
import { interfaces } from './interfaces'
|
||||||
import { PluginTaskManager } from './task'
|
import { PluginTaskManager } from './task'
|
||||||
import { PluginEventManager } from './event'
|
import { PluginEventManager } from './event'
|
||||||
import { PluginCommandManager } from './command'
|
|
||||||
import { PluginConfigManager } from './config'
|
import { PluginConfigManager } from './config'
|
||||||
|
import { PluginCommandManager } from './command'
|
||||||
|
|
||||||
const Thread = Java.type('java.lang.Thread')
|
const Thread = Java.type('java.lang.Thread')
|
||||||
|
|
||||||
@@ -69,7 +68,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
try {
|
try {
|
||||||
console.i18n('ms.plugin.event.map', { count: this.eventManager.mapEventName(), type: this.serverType })
|
console.i18n('ms.plugin.event.map', { count: this.eventManager.mapEventName(), type: this.serverType })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.i18n('ms.plugin.event.map.error', { error })
|
console.i18n('ms.plugin.event.map.error', { type: this.serverType, error })
|
||||||
}
|
}
|
||||||
let pluginScanner = this.container.getAll<plugin.PluginScanner>(plugin.PluginScanner)
|
let pluginScanner = this.container.getAll<plugin.PluginScanner>(plugin.PluginScanner)
|
||||||
pluginScanner.forEach((scanner) => {
|
pluginScanner.forEach((scanner) => {
|
||||||
@@ -93,18 +92,17 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
for (const [, scanner] of this.sacnnerMap) {
|
for (const [, scanner] of this.sacnnerMap) {
|
||||||
try {
|
try {
|
||||||
console.i18n('ms.plugin.manager.scan', { scanner: scanner.type, folder })
|
console.i18n('ms.plugin.manager.scan', { scanner: scanner.type, folder })
|
||||||
let plugins = scanner.scan(folder)
|
let loadMetadatas = scanner.scan(folder)
|
||||||
console.i18n('ms.plugin.manager.scan.finish', { scanner: scanner.type, folder, size: plugins.length })
|
console.i18n('ms.plugin.manager.scan.finish', { scanner: scanner.type, folder, size: loadMetadatas.length })
|
||||||
plugins.forEach(loadMetadata => {
|
for (const loadMetadata of loadMetadatas) {
|
||||||
try {
|
try {
|
||||||
this.loadAndRequirePlugin(loadMetadata)
|
this.loadAndRequirePlugin(loadMetadata)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(`plugin scanner ${scanner.type} load ${loadMetadata.file} occurred error ${error}`)
|
console.console(`§c扫描器 §4${scanner.type} §c文件 §4${loadMetadata.file.toString().replace(root, '')} §c编译失败 请提供下列错误给开发者`)
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(`plugin scanner ${scanner.type} occurred error ${error}`)
|
|
||||||
console.ex(error)
|
console.ex(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,8 +227,16 @@ export class PluginManagerImpl implements plugin.PluginManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has(name: string) {
|
||||||
|
return this.instanceMap.has(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
get(name: string) {
|
||||||
|
return this.instanceMap.get(name) || null
|
||||||
|
}
|
||||||
|
|
||||||
getPlugin(name: string) {
|
getPlugin(name: string) {
|
||||||
return this.instanceMap.get(name)
|
return this.instanceMap.get(name) || null
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlugins() {
|
getPlugins() {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/polyfill",
|
"name": "@ccms/polyfill",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript polyfill package",
|
"description": "MiaoScript polyfill package",
|
||||||
"author": "MiaoWoo <admin@yumc.pw>",
|
"author": "MiaoWoo <admin@yumc.pw>",
|
||||||
"homepage": "https://github.com/circlecloud/ms.git",
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
@@ -14,14 +14,14 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/i18n": "^0.21.0",
|
"@ccms/i18n": "^0.27.6",
|
||||||
"@ccms/nodejs": "^0.21.0",
|
"@ccms/nodejs": "^0.27.6",
|
||||||
"core-js": "^3.22.1"
|
"core-js": "^3.27.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.21.0",
|
"@ccms/nashorn": "^0.27.6",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2134
packages/polyfill/src/buffer.ts
Normal file
2134
packages/polyfill/src/buffer.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -12,5 +12,7 @@ import 'core-js'
|
|||||||
process.on('exit', () => require.disable())
|
process.on('exit', () => require.disable())
|
||||||
global.setGlobal('Proxy', require('./proxy').Proxy)
|
global.setGlobal('Proxy', require('./proxy').Proxy)
|
||||||
global.setGlobal('XMLHttpRequest', require('./xml-http-request').XMLHttpRequest)
|
global.setGlobal('XMLHttpRequest', require('./xml-http-request').XMLHttpRequest)
|
||||||
|
global.setGlobal('Buffer', require('./buffer').Buffer)
|
||||||
global.setGlobal('Blob', require('blob-polyfill').Blob)
|
global.setGlobal('Blob', require('blob-polyfill').Blob)
|
||||||
console.i18n("ms.polyfill.completed", { time: (new Date().getTime() - polyfillStartTime) / 1000 })
|
console.i18n("ms.polyfill.completed", { time: (new Date().getTime() - polyfillStartTime) / 1000 })
|
||||||
|
export default true
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { EventEmitter } from 'events'
|
|||||||
|
|
||||||
const System = Java.type('java.lang.System')
|
const System = Java.type('java.lang.System')
|
||||||
const Thread = Java.type('java.lang.Thread')
|
const Thread = Java.type('java.lang.Thread')
|
||||||
|
const ManagementFactory = Java.type('java.lang.management.ManagementFactory')
|
||||||
const InterruptedException = Java.type('java.lang.InterruptedException')
|
const InterruptedException = Java.type('java.lang.InterruptedException')
|
||||||
const ThreadGroup = Java.type("java.lang.ThreadGroup")
|
const ThreadGroup = Java.type("java.lang.ThreadGroup")
|
||||||
const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
|
const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
|
||||||
@@ -15,19 +16,35 @@ const DelayQueue = Java.type('java.util.concurrent.DelayQueue')
|
|||||||
const JavaScriptTask = Java.type(base.getJavaScriptTaskClass().name)
|
const JavaScriptTask = Java.type(base.getJavaScriptTaskClass().name)
|
||||||
|
|
||||||
const threadCount = new AtomicInteger(0)
|
const threadCount = new AtomicInteger(0)
|
||||||
const threadGroup = new ThreadGroup("@ccms/ployfill-micro-task")
|
const threadGroup = new ThreadGroup("@ccms/micro-task")
|
||||||
const microTaskPool = new ThreadPoolExecutor(
|
const microTaskPool = new ThreadPoolExecutor(
|
||||||
100, 200, 60, TimeUnit.SECONDS,
|
100, 200, 60, TimeUnit.SECONDS,
|
||||||
new LinkedBlockingQueue(300),
|
new LinkedBlockingQueue(1024),
|
||||||
new ThreadFactory((run: any) => new Thread(threadGroup, run, "@ccms/micro-task-" + threadCount.incrementAndGet()))
|
new ThreadFactory((run: any) => new Thread(threadGroup, run, "@ccms/micro-task-" + threadCount.incrementAndGet()))
|
||||||
)
|
)
|
||||||
class Process extends EventEmitter {
|
class Process extends EventEmitter {
|
||||||
|
readonly version = base.version
|
||||||
|
readonly versions = []
|
||||||
|
readonly config = {}
|
||||||
|
readonly pid: number = parseInt(ManagementFactory.getRuntimeMXBean().getName().split('@')[0])
|
||||||
|
readonly ppid: number
|
||||||
|
title: string
|
||||||
|
readonly arch: string = System.getProperty("os.arch")
|
||||||
|
readonly platform = System.getProperty("os.name")
|
||||||
|
|
||||||
env = {
|
env = {
|
||||||
__noSuchProperty__: (prop) => {
|
__noSuchProperty__: (prop) => {
|
||||||
return System.getenv(prop)
|
return System.getenv(prop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
platform = System.getProperty("os.name")
|
|
||||||
|
stdout = System.out
|
||||||
|
stderr = System.err
|
||||||
|
stdin = System.in
|
||||||
|
|
||||||
|
execArgv = ''
|
||||||
|
execPath = ''
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
this.on('exit', () => {
|
this.on('exit', () => {
|
||||||
@@ -49,10 +66,10 @@ class Process extends EventEmitter {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
nextTick(func: Function, ...args: any[]) {
|
nextTick(callback: Function, ...args: any[]): void {
|
||||||
microTaskPool.execute(() => {
|
microTaskPool.execute(() => {
|
||||||
try {
|
try {
|
||||||
func(args)
|
callback(args)
|
||||||
} catch (origin: any) {
|
} catch (origin: any) {
|
||||||
try {
|
try {
|
||||||
super.emit('error', origin)
|
super.emit('error', origin)
|
||||||
@@ -65,9 +82,44 @@ class Process extends EventEmitter {
|
|||||||
}
|
}
|
||||||
exit(code: number) {
|
exit(code: number) {
|
||||||
console.log(`process exit by code ${code}!`)
|
console.log(`process exit by code ${code}!`)
|
||||||
this.emit('exit', code)
|
this.emit('exit', this.exitCode = code)
|
||||||
|
}
|
||||||
|
exitCode = 0
|
||||||
|
openStdin() {
|
||||||
|
throw new Error('MiaoScript unsupport openStdin.')
|
||||||
|
}
|
||||||
|
chdir(directory: string): void {
|
||||||
|
console.error('MiaoScript unsupport chdir. lock at ' + root)
|
||||||
|
}
|
||||||
|
cwd() {
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
getgid(): number {
|
||||||
|
throw new Error('MiaoScript unsupport getgid.')
|
||||||
|
}
|
||||||
|
setgid(id: number | string) {
|
||||||
|
throw new Error('MiaoScript unsupport setgid.')
|
||||||
|
}
|
||||||
|
getuid(): number {
|
||||||
|
throw new Error('MiaoScript unsupport getuid.')
|
||||||
|
}
|
||||||
|
setuid(id: number | string) {
|
||||||
|
throw new Error('MiaoScript unsupport setuid.')
|
||||||
|
}
|
||||||
|
setUncaughtExceptionCaptureCallback(cb: ((err: Error) => void) | null) {
|
||||||
|
if (cb == null) {
|
||||||
|
this.removeAllListeners('error')
|
||||||
|
} else {
|
||||||
|
this.on('error', cb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hasUncaughtExceptionCaptureCallback() {
|
||||||
|
return this.listenerCount('error') > 0
|
||||||
|
}
|
||||||
|
kill(pid: number, signal?: string | number): true {
|
||||||
|
throw new Error('MiaoScript unsupport kill.')
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
return "[object process]"
|
return "[object process]"
|
||||||
}
|
}
|
||||||
@@ -76,16 +128,16 @@ class Process extends EventEmitter {
|
|||||||
class EventLoop {
|
class EventLoop {
|
||||||
private eventLoopMainThread = undefined
|
private eventLoopMainThread = undefined
|
||||||
private eventLoopTaskQueue = new DelayQueue()
|
private eventLoopTaskQueue = new DelayQueue()
|
||||||
private taskExecTimeout = 3
|
private taskExecuteTimeout = 3000
|
||||||
private fixedThreadPool = undefined
|
private fixedThreadPool = undefined
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.taskExecTimeout = parseInt(process.env.MS_NODE_EVENT_LOOP_TIMEOUT) || 3
|
this.taskExecuteTimeout = parseInt(process.env.MS_TASK_EXECUTE_TIMEOUT) || 3000
|
||||||
this.fixedThreadPool = new ThreadPoolExecutor(
|
this.fixedThreadPool = new ThreadPoolExecutor(
|
||||||
1, 1, 0, TimeUnit.SECONDS,
|
1, 1, 0, TimeUnit.SECONDS,
|
||||||
new LinkedBlockingQueue(300),
|
new LinkedBlockingQueue(1024),
|
||||||
new ThreadFactory((run: any) => {
|
new ThreadFactory((run: any) => {
|
||||||
let thread = new Thread(run, "@ccms/node-shim/event-loop-exec")
|
let thread = new Thread(run, "@ccms/event-loop")
|
||||||
thread.setDaemon(true)
|
thread.setDaemon(true)
|
||||||
return thread
|
return thread
|
||||||
}))
|
}))
|
||||||
@@ -115,7 +167,7 @@ class EventLoop {
|
|||||||
this.intervalTasks = undefined
|
this.intervalTasks = undefined
|
||||||
this.eventLoopMainThread = undefined
|
this.eventLoopMainThread = undefined
|
||||||
}
|
}
|
||||||
}, "@ccms/node-shim/event-loop")
|
}, "@ccms/event-loop")
|
||||||
this.eventLoopMainThread.setDaemon(true)
|
this.eventLoopMainThread.setDaemon(true)
|
||||||
process.on('exit', () => {
|
process.on('exit', () => {
|
||||||
this.eventLoopMainThread.interrupt()
|
this.eventLoopMainThread.interrupt()
|
||||||
@@ -137,7 +189,9 @@ class EventLoop {
|
|||||||
if (!callback) {
|
if (!callback) {
|
||||||
throw new Error(`task ${name} callback function can't be null!`)
|
throw new Error(`task ${name} callback function can't be null!`)
|
||||||
}
|
}
|
||||||
if (this.fixedThreadPool.isShutdown()) { return console.warn(`FixedThreadPool isTerminated! ignore Task ${name}!`) }
|
if (this.fixedThreadPool.isShutdown()) {
|
||||||
|
return console.warn(`FixedThreadPool isTerminated! ignore Task ${name}!`)
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
this.fixedThreadPool.submit(new Callable({
|
this.fixedThreadPool.submit(new Callable({
|
||||||
call: () => {
|
call: () => {
|
||||||
@@ -153,13 +207,13 @@ class EventLoop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})).get(this.taskExecTimeout, TimeUnit.SECONDS)
|
})).get(this.taskExecuteTimeout, TimeUnit.MILLISECONDS)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error instanceof InterruptedException) {
|
if (error instanceof InterruptedException) {
|
||||||
return console.warn(`FixedThreadPool isInterrupted exit! Task ${name} exec exit!`)
|
return console.warn(`FixedThreadPool isInterrupted exit! Task ${name} exec exit!`)
|
||||||
}
|
}
|
||||||
if (error instanceof TimeoutException) {
|
if (error instanceof TimeoutException) {
|
||||||
return console.warn(`Task ${name} => ${callback} exec time greater than ${this.taskExecTimeout}s!`)
|
return console.warn(`Task ${name} => ${callback} exec time greater than ${this.taskExecuteTimeout}s!`)
|
||||||
}
|
}
|
||||||
throw error.getCause && error.getCause() || error
|
throw error.getCause && error.getCause() || error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,13 +68,14 @@ type EventType =
|
|||||||
| 'timeout'
|
| 'timeout'
|
||||||
| 'loadend'
|
| 'loadend'
|
||||||
| 'loadstart'
|
| 'loadstart'
|
||||||
type HttpHeader = { [key: string]: string }
|
type RequestHttpHeader = { [key: string]: string }
|
||||||
|
type HttpHeader = { [key: string]: string[] }
|
||||||
|
|
||||||
const executor = Executors.newCachedThreadPool()
|
const executor = Executors.newCachedThreadPool()
|
||||||
|
|
||||||
export class XMLHttpRequest {
|
export class XMLHttpRequest {
|
||||||
private _timeout: number = 120000;
|
private _connectTimeout: number = 5000;
|
||||||
|
private _readTimeout: number = 120000;
|
||||||
private _responseType: ResponseType = 'text';
|
private _responseType: ResponseType = 'text';
|
||||||
private _withCredentials: boolean
|
private _withCredentials: boolean
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ export class XMLHttpRequest {
|
|||||||
private _url: string
|
private _url: string
|
||||||
private _async: boolean
|
private _async: boolean
|
||||||
private _mimeType: string
|
private _mimeType: string
|
||||||
private _requestHeaders: HttpHeader = {};
|
private _requestHeaders: RequestHttpHeader = {};
|
||||||
|
|
||||||
private _status: number = 0;
|
private _status: number = 0;
|
||||||
private _statusText: string = null;
|
private _statusText: string = null;
|
||||||
@@ -96,10 +97,22 @@ export class XMLHttpRequest {
|
|||||||
private _connection = null;
|
private _connection = null;
|
||||||
|
|
||||||
get timeout() {
|
get timeout() {
|
||||||
return this._timeout
|
return this._readTimeout
|
||||||
}
|
}
|
||||||
set timeout(timeout: number) {
|
set timeout(timeout: number) {
|
||||||
this._timeout = timeout
|
this._readTimeout = timeout
|
||||||
|
}
|
||||||
|
get connectTimeout() {
|
||||||
|
return this._connectTimeout
|
||||||
|
}
|
||||||
|
set connectTimeout(timeout: number) {
|
||||||
|
this._connectTimeout = timeout
|
||||||
|
}
|
||||||
|
get readTimeout() {
|
||||||
|
return this._readTimeout
|
||||||
|
}
|
||||||
|
set readTimeout(timeout: number) {
|
||||||
|
this._readTimeout = timeout
|
||||||
}
|
}
|
||||||
get readyState() {
|
get readyState() {
|
||||||
return this._readyState
|
return this._readyState
|
||||||
@@ -143,7 +156,7 @@ export class XMLHttpRequest {
|
|||||||
this._requestHeaders[key] = val
|
this._requestHeaders[key] = val
|
||||||
}
|
}
|
||||||
getResponseHeader(key: string): string {
|
getResponseHeader(key: string): string {
|
||||||
return this._responseHeaders[key]
|
return this._responseHeaders[key]?.[0]
|
||||||
}
|
}
|
||||||
getAllResponseHeaders(): any {
|
getAllResponseHeaders(): any {
|
||||||
return this._responseHeaders
|
return this._responseHeaders
|
||||||
@@ -169,8 +182,8 @@ export class XMLHttpRequest {
|
|||||||
this._connection.setRequestMethod(this._method)
|
this._connection.setRequestMethod(this._method)
|
||||||
this._connection.setDoOutput(true)
|
this._connection.setDoOutput(true)
|
||||||
this._connection.setDoInput(true)
|
this._connection.setDoInput(true)
|
||||||
this._connection.setConnectTimeout(this._timeout)
|
this._connection.setConnectTimeout(this._connectTimeout)
|
||||||
this._connection.setReadTimeout(this._timeout)
|
this._connection.setReadTimeout(this._readTimeout)
|
||||||
|
|
||||||
this.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
|
this.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
|
||||||
this.setReadyState(ReadyState.OPENED)
|
this.setReadyState(ReadyState.OPENED)
|
||||||
@@ -181,7 +194,7 @@ export class XMLHttpRequest {
|
|||||||
}
|
}
|
||||||
if (this._readyState !== ReadyState.OPENED) { throw new Error(`Error Status ${this._readyState}!`) }
|
if (this._readyState !== ReadyState.OPENED) { throw new Error(`Error Status ${this._readyState}!`) }
|
||||||
let future = executor.submit(new Callable({ call: () => this._send(body) }))
|
let future = executor.submit(new Callable({ call: () => this._send(body) }))
|
||||||
if (!this._async) { future.get(this._timeout, TimeUnit.MILLISECONDS) }
|
if (!this._async) { future.get(this._connectTimeout + this._readTimeout + 100, TimeUnit.MILLISECONDS) }
|
||||||
return future
|
return future
|
||||||
}
|
}
|
||||||
get() {
|
get() {
|
||||||
@@ -199,22 +212,23 @@ export class XMLHttpRequest {
|
|||||||
}
|
}
|
||||||
abort() {
|
abort() {
|
||||||
this._connection.disconnect()
|
this._connection.disconnect()
|
||||||
this.onabort && this.onabort()
|
this.onabort?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
private _send(body?: string | object) {
|
private _send(body?: string | object) {
|
||||||
try {
|
try {
|
||||||
this._connection.connect()
|
this._connection.connect()
|
||||||
this.onloadstart && this.onloadstart()
|
this.onloadstart?.()
|
||||||
if (body) {
|
if (body) {
|
||||||
let bodyType = Object.prototype.toString.call(body)
|
let bodyType = Object.prototype.toString.call(body)
|
||||||
if (typeof body !== "string") { throw new Error(`body(${bodyType}) must be string!`) }
|
if (typeof body !== "string") { throw new Error(`body(${bodyType}) must be string.`) }
|
||||||
var out = this._connection.getOutputStream()
|
var out = this._connection.getOutputStream()
|
||||||
out.write(new JavaString(body).getBytes(UTF_8))
|
out.write(new JavaString(body).getBytes(UTF_8))
|
||||||
out.flush()
|
out.flush()
|
||||||
out.close()
|
out.close()
|
||||||
}
|
}
|
||||||
this.setReadyState(ReadyState.LOADING)
|
this.setReadyState(ReadyState.LOADING)
|
||||||
|
this.onload?.()
|
||||||
this._status = this._connection.getResponseCode()
|
this._status = this._connection.getResponseCode()
|
||||||
this._statusText = this._connection.getResponseMessage()
|
this._statusText = this._connection.getResponseMessage()
|
||||||
if (this._status >= 0 && this._status < 300) {
|
if (this._status >= 0 && this._status < 300) {
|
||||||
@@ -224,8 +238,8 @@ export class XMLHttpRequest {
|
|||||||
} else {
|
} else {
|
||||||
this._responseText = this.readOutput(this._connection.getErrorStream())
|
this._responseText = this.readOutput(this._connection.getErrorStream())
|
||||||
}
|
}
|
||||||
this.setResponseHeaders(this._connection.getHeaderFields())
|
this.setResponseHeaders()
|
||||||
this.onloadend && this.onloadend()
|
this.onloadend?.()
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
if (ex instanceof SocketTimeoutException && this.ontimeout) {
|
if (ex instanceof SocketTimeoutException && this.ontimeout) {
|
||||||
return this.ontimeout(ex)
|
return this.ontimeout(ex)
|
||||||
@@ -239,15 +253,15 @@ export class XMLHttpRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setResponseHeaders(header: any) {
|
private setResponseHeaders() {
|
||||||
header.forEach((key: string | number, value: string | any[]) => {
|
this._connection.getHeaderFields().forEach((key: string | number, value: any[]) => {
|
||||||
this._responseHeaders[key + ''] = value[value.length - 1] + ''
|
this._responseHeaders[key + ''] = Java.from(value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private setReadyState(state: ReadyState) {
|
private setReadyState(state: ReadyState) {
|
||||||
this._readyState = state
|
this._readyState = state
|
||||||
this.onreadystatechange && this.onreadystatechange()
|
this.onreadystatechange?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
private readOutput(input: any) {
|
private readOutput(input: any) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/protocol",
|
"name": "@ccms/protocol",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript protocol package",
|
"description": "MiaoScript protocol package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
packages/qrcode/package.json
Normal file
26
packages/qrcode/package.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "@ccms/qrcode",
|
||||||
|
"version": "0.27.6",
|
||||||
|
"description": "MiaoScript qrcode package",
|
||||||
|
"keywords": [
|
||||||
|
"miaoscript",
|
||||||
|
"minecraft",
|
||||||
|
"bukkit",
|
||||||
|
"sponge"
|
||||||
|
],
|
||||||
|
"author": "MiaoWoo <admin@yumc.pw>",
|
||||||
|
"homepage": "https://github.com/circlecloud/ms.git",
|
||||||
|
"license": "ISC",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rimraf dist",
|
||||||
|
"watch": "tsc --watch",
|
||||||
|
"build": "yarn clean && tsc",
|
||||||
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rimraf": "^4.1.2",
|
||||||
|
"typescript": "^4.9.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
1243
packages/qrcode/src/index.ts
Normal file
1243
packages/qrcode/src/index.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/sponge",
|
"name": "@ccms/sponge",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript api package",
|
"description": "MiaoScript sponge package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@javatypes/sponge-api": "^0.0.3",
|
"@javatypes/sponge-api": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.21.0",
|
"@ccms/api": "^0.27.6",
|
||||||
"@ccms/common": "^0.21.0",
|
"@ccms/common": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0"
|
"@ccms/container": "^0.27.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,15 @@
|
|||||||
import { provideSingleton } from '@ccms/container'
|
import { provideSingleton } from '@ccms/container'
|
||||||
import { particle, plugin } from '@ccms/api'
|
import { particle } from '@ccms/api'
|
||||||
|
|
||||||
@provideSingleton(particle.ParticleManager)
|
@provideSingleton(particle.ParticleManager)
|
||||||
export class SpongeParticleManager extends particle.ParticleManager {
|
export class SpongeParticleManager extends particle.ParticleManager {
|
||||||
private globalSpawner = new SpongeParticleSpawner()
|
|
||||||
constructor() {
|
|
||||||
super()
|
|
||||||
particle.ParticleManager.globalSpawner = this.globalSpawner
|
|
||||||
}
|
|
||||||
protected getGlobalSpawner() {
|
|
||||||
return this.globalSpawner
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@provideSingleton(particle.ParticleSpawner)
|
||||||
export class SpongeParticleSpawner extends particle.ParticleSpawner {
|
export class SpongeParticleSpawner extends particle.ParticleSpawner {
|
||||||
spawnParticle(location: org.spongepowered.api.world.Location<any>, particle: any, count: number = 1) {
|
|
||||||
location.getPosition()
|
|
||||||
// location.getWorld().spawnParticle(particle, location, count)
|
|
||||||
}
|
|
||||||
spawn(location: any, particle: particle.Particle) {
|
spawn(location: any, particle: particle.Particle) {
|
||||||
location.getWorld().spawnParticle(
|
throw new Error('Not Impl.')
|
||||||
particle.getParticle(),
|
}
|
||||||
location,
|
spawnToPlayer(player: any, location: any, particle: particle.Particle) {
|
||||||
particle.getCount(),
|
throw new Error('Not Impl.')
|
||||||
particle.getOffsetX(),
|
|
||||||
particle.getOffsetY(),
|
|
||||||
particle.getOffsetZ(),
|
|
||||||
particle.getExtra(),
|
|
||||||
particle.getData()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/spring",
|
"name": "@ccms/spring",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript spring package",
|
"description": "MiaoScript spring package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -20,13 +20,13 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.21.0",
|
"@ccms/api": "^0.27.6",
|
||||||
"@ccms/common": "^0.21.0",
|
"@ccms/common": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0",
|
"@ccms/container": "^0.27.6",
|
||||||
"@ccms/database": "^0.21.0"
|
"@ccms/database": "^0.27.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/web",
|
"name": "@ccms/web",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript web package",
|
"description": "MiaoScript web package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -25,11 +25,11 @@
|
|||||||
"@javatypes/spring-web": "^0.0.3",
|
"@javatypes/spring-web": "^0.0.3",
|
||||||
"@javatypes/tomcat": "^0.0.3",
|
"@javatypes/tomcat": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ccms/api": "^0.21.0",
|
"@ccms/api": "^0.27.6",
|
||||||
"@ccms/container": "^0.21.0"
|
"@ccms/container": "^0.27.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
packages/websocket/.prettierrc
Normal file
4
packages/websocket/.prettierrc
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": true
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ccms/websocket",
|
"name": "@ccms/websocket",
|
||||||
"version": "0.21.0",
|
"version": "0.27.6",
|
||||||
"description": "MiaoScript websocket package",
|
"description": "MiaoScript websocket package",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"miaoscript",
|
"miaoscript",
|
||||||
@@ -19,14 +19,15 @@
|
|||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@socket.io/component-emitter": "3.1.0",
|
||||||
"backo2": "^1.0.2",
|
"backo2": "^1.0.2",
|
||||||
"parseuri": "^0.0.6"
|
"parseuri": "^0.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ccms/nashorn": "^0.21.0",
|
"@ccms/nashorn": "^0.27.6",
|
||||||
"@javatypes/tomcat-websocket-api": "^0.0.3",
|
"@javatypes/tomcat-websocket-api": "^0.0.3",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^4.1.2",
|
||||||
"typescript": "^4.6.3"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export class WebSocket extends EventEmitter {
|
|||||||
|
|
||||||
private client: Transport
|
private client: Transport
|
||||||
|
|
||||||
constructor(url: string, subProtocol: string = '', headers: WebSocketHeader = {}) {
|
constructor(url: string, subProtocol: string | string[] = '', headers: WebSocketHeader = {}) {
|
||||||
super()
|
super()
|
||||||
this.manager = manager
|
this.manager = manager
|
||||||
this._url = url
|
this._url = url
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export class NettyWebSocket extends Transport {
|
|||||||
private _host: string
|
private _host: string
|
||||||
private _port: number
|
private _port: number
|
||||||
private channel: any
|
private channel: any
|
||||||
private b = new Bootstrap();
|
private b: any
|
||||||
|
|
||||||
constructor(url: string, subProtocol: string = '', headers: WebSocketHeader = {}) {
|
constructor(url: string, subProtocol: string = '', headers: WebSocketHeader = {}) {
|
||||||
super(url, subProtocol, headers)
|
super(url, subProtocol, headers)
|
||||||
@@ -102,6 +102,7 @@ export class NettyWebSocket extends Transport {
|
|||||||
// HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
|
// HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
|
||||||
let handler = new WebSocketClientHandler(WebSocketClientHandshakerFactory
|
let handler = new WebSocketClientHandler(WebSocketClientHandshakerFactory
|
||||||
.newHandshaker(uri, WebSocketVersion.V13, null, false, headers), this)
|
.newHandshaker(uri, WebSocketVersion.V13, null, false, headers), this)
|
||||||
|
this.b = new Bootstrap()
|
||||||
this.b.group(group)
|
this.b.group(group)
|
||||||
.channel(socketChannelClass)
|
.channel(socketChannelClass)
|
||||||
.handler(new ChannelInitializer({
|
.handler(new ChannelInitializer({
|
||||||
@@ -123,18 +124,22 @@ export class NettyWebSocket extends Transport {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
this.b.connect(this._host, this._port).addListener(new ChannelFutureListener((future: any) => {
|
this.b.connect(this._host, this._port).addListener(new ChannelFutureListener((future: any) => {
|
||||||
this.channel = future.sync().channel()
|
try {
|
||||||
this.onconnection({})
|
this.channel = future.sync().channel()
|
||||||
handler.handshakeFuture.addListener(new ChannelFutureListener((future: any) => {
|
this.onconnection({})
|
||||||
try {
|
handler.handshakeFuture.addListener(new ChannelFutureListener((future: any) => {
|
||||||
future.sync()
|
try {
|
||||||
// only trigger onconnect when not have error
|
future.sync()
|
||||||
this.onconnect({})
|
// only trigger onconnect when not have error
|
||||||
} catch (error: any) {
|
this.onconnect({})
|
||||||
// ignore error exceptionCaught from handler
|
} catch (error: any) {
|
||||||
// this.onerror({ error })
|
// ignore error exceptionCaught from handler
|
||||||
}
|
// this.onerror({ error })
|
||||||
}))
|
}
|
||||||
|
}))
|
||||||
|
} catch (error: any) {
|
||||||
|
this.onerror({ error })
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
doSend(text: string) {
|
doSend(text: string) {
|
||||||
|
|||||||
@@ -1 +1,57 @@
|
|||||||
export = (namepsace) => (...args) => { }//console.debug(namepsace, ...args)
|
export = (namepsace) =>
|
||||||
|
(...args) => {
|
||||||
|
console.trace(`[${namepsace}] ` + format(...args))
|
||||||
|
} //console.debug(namepsace, ...args)
|
||||||
|
let formatters: any = {}
|
||||||
|
formatters.s = function (v) {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
formatters.j = function (v) {
|
||||||
|
try {
|
||||||
|
return JSON.stringify(v)
|
||||||
|
} catch (error: any) {
|
||||||
|
return "[UnexpectedJSONParseError]: " + error.message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Coerce `val`.
|
||||||
|
*
|
||||||
|
* @param {Mixed} val
|
||||||
|
* @return {Mixed}
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
function coerce(val) {
|
||||||
|
if (val instanceof Error) {
|
||||||
|
return val.stack || val.message
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
function format(...args) {
|
||||||
|
// Apply any `formatters` transformations
|
||||||
|
args[0] = coerce(args[0])
|
||||||
|
|
||||||
|
if (typeof args[0] !== "string") {
|
||||||
|
// Anything else let's inspect with %O
|
||||||
|
args.unshift("%O")
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = 0
|
||||||
|
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
||||||
|
// If we encounter an escaped % then don't increase the array index
|
||||||
|
if (match === "%%") {
|
||||||
|
return "%"
|
||||||
|
}
|
||||||
|
index++
|
||||||
|
const formatter = formatters[format]
|
||||||
|
if (typeof formatter === "function") {
|
||||||
|
const val = args[index]
|
||||||
|
match = formatter.call(format, val)
|
||||||
|
|
||||||
|
// Now we need to remove `args[index]` since it's inlined in the `format`
|
||||||
|
args.splice(index, 1)
|
||||||
|
index--
|
||||||
|
}
|
||||||
|
return match
|
||||||
|
})
|
||||||
|
return args[0]
|
||||||
|
}
|
||||||
|
|||||||
12
packages/websocket/src/engine.io-client/contrib/has-cors.ts
Normal file
12
packages/websocket/src/engine.io-client/contrib/has-cors.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// imported from https://github.com/component/has-cors
|
||||||
|
let value = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
value = typeof XMLHttpRequest !== 'undefined' &&
|
||||||
|
'withCredentials' in new XMLHttpRequest();
|
||||||
|
} catch (err) {
|
||||||
|
// if XMLHttp support is disabled in IE then it will throw
|
||||||
|
// when trying to create
|
||||||
|
}
|
||||||
|
|
||||||
|
export const hasCORS = value;
|
||||||
38
packages/websocket/src/engine.io-client/contrib/parseqs.ts
Normal file
38
packages/websocket/src/engine.io-client/contrib/parseqs.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// imported from https://github.com/galkn/querystring
|
||||||
|
/**
|
||||||
|
* Compiles a querystring
|
||||||
|
* Returns string representation of the object
|
||||||
|
*
|
||||||
|
* @param {Object}
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function encode(obj) {
|
||||||
|
let str = ''
|
||||||
|
|
||||||
|
for (let i in obj) {
|
||||||
|
if (obj.hasOwnProperty(i)) {
|
||||||
|
if (str.length) str += '&'
|
||||||
|
str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a simple querystring into an object
|
||||||
|
*
|
||||||
|
* @param {String} qs
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function decode(qs) {
|
||||||
|
let qry = {}
|
||||||
|
let pairs = qs.split('&')
|
||||||
|
for (let i = 0, l = pairs.length; i < l; i++) {
|
||||||
|
let pair = pairs[i].split('=')
|
||||||
|
qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1])
|
||||||
|
}
|
||||||
|
return qry
|
||||||
|
}
|
||||||
68
packages/websocket/src/engine.io-client/contrib/parseuri.ts
Normal file
68
packages/websocket/src/engine.io-client/contrib/parseuri.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// imported from https://github.com/galkn/parseuri
|
||||||
|
/**
|
||||||
|
* Parses an URI
|
||||||
|
*
|
||||||
|
* @author Steven Levithan <stevenlevithan.com> (MIT license)
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
const re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
|
||||||
|
|
||||||
|
const parts = [
|
||||||
|
'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
|
||||||
|
]
|
||||||
|
|
||||||
|
export function parse(str) {
|
||||||
|
const src = str,
|
||||||
|
b = str.indexOf('['),
|
||||||
|
e = str.indexOf(']')
|
||||||
|
|
||||||
|
if (b != -1 && e != -1) {
|
||||||
|
str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
let m = re.exec(str || ''),
|
||||||
|
uri = {} as any,
|
||||||
|
i = 14
|
||||||
|
|
||||||
|
while (i--) {
|
||||||
|
uri[parts[i]] = m[i] || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b != -1 && e != -1) {
|
||||||
|
uri.source = src
|
||||||
|
uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':')
|
||||||
|
uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':')
|
||||||
|
uri.ipv6uri = true
|
||||||
|
}
|
||||||
|
|
||||||
|
uri.pathNames = pathNames(uri, uri['path'])
|
||||||
|
uri.queryKey = queryKey(uri, uri['query'])
|
||||||
|
|
||||||
|
return uri
|
||||||
|
}
|
||||||
|
|
||||||
|
function pathNames(obj, path) {
|
||||||
|
const regx = /\/{2,9}/g,
|
||||||
|
names = path.replace(regx, "/").split("/")
|
||||||
|
|
||||||
|
if (path.slice(0, 1) == '/' || path.length === 0) {
|
||||||
|
names.splice(0, 1)
|
||||||
|
}
|
||||||
|
if (path.slice(-1) == '/') {
|
||||||
|
names.splice(names.length - 1, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
|
function queryKey(uri, query) {
|
||||||
|
const data = {}
|
||||||
|
|
||||||
|
query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g, function ($0, $1, $2) {
|
||||||
|
if ($1) {
|
||||||
|
data[$1] = $2
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
62
packages/websocket/src/engine.io-client/contrib/yeast.ts
Normal file
62
packages/websocket/src/engine.io-client/contrib/yeast.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// imported from https://github.com/unshiftio/yeast
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split('')
|
||||||
|
, length = 64
|
||||||
|
, map = {}
|
||||||
|
let seed = 0
|
||||||
|
, i = 0
|
||||||
|
, prev
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a string representing the specified number.
|
||||||
|
*
|
||||||
|
* @param {Number} num The number to convert.
|
||||||
|
* @returns {String} The string representation of the number.
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
export function encode(num) {
|
||||||
|
let encoded = ''
|
||||||
|
|
||||||
|
do {
|
||||||
|
encoded = alphabet[num % length] + encoded
|
||||||
|
num = Math.floor(num / length)
|
||||||
|
} while (num > 0)
|
||||||
|
|
||||||
|
return encoded
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the integer value specified by the given string.
|
||||||
|
*
|
||||||
|
* @param {String} str The string to convert.
|
||||||
|
* @returns {Number} The integer value represented by the string.
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
export function decode(str) {
|
||||||
|
let decoded = 0
|
||||||
|
|
||||||
|
for (i = 0; i < str.length; i++) {
|
||||||
|
decoded = decoded * length + map[str.charAt(i)]
|
||||||
|
}
|
||||||
|
|
||||||
|
return decoded
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Yeast: A tiny growing id generator.
|
||||||
|
*
|
||||||
|
* @returns {String} A unique id.
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
export function yeast() {
|
||||||
|
const now = encode(+new Date())
|
||||||
|
|
||||||
|
if (now !== prev) return seed = 0, prev = now
|
||||||
|
return now + '.' + encode(seed++)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Map each character to its index.
|
||||||
|
//
|
||||||
|
for (; i < length; i++) map[alphabet[i]] = i
|
||||||
@@ -1,16 +1,10 @@
|
|||||||
import { Socket } from './socket'
|
import { Socket } from "./socket"
|
||||||
|
|
||||||
export default (uri, opts) => new Socket(uri, opts)
|
export { Socket }
|
||||||
|
export { SocketOptions } from "./socket"
|
||||||
/**
|
export const protocol = Socket.protocol
|
||||||
* Expose deps for legacy compatibility
|
export { Transport } from "./transport"
|
||||||
* and standalone browser access.
|
export { transports } from "./transports/index"
|
||||||
*/
|
export { installTimerFunctions } from "./util"
|
||||||
const protocol = Socket.protocol // this is an int
|
export { parse } from "./contrib/parseuri"
|
||||||
export { Socket, protocol }
|
export { nextTick } from "./transports/websocket-constructor"
|
||||||
// module.exports.Transport = require("./transport")
|
|
||||||
// module.exports.transports = require("./transports/index")
|
|
||||||
// module.exports.parser = require("../engine.io-parser")
|
|
||||||
export * from './transport'
|
|
||||||
export * from './transports/index'
|
|
||||||
export * from '../engine.io-parser'
|
|
||||||
|
|||||||
@@ -1,21 +1,295 @@
|
|||||||
import transports from "./transports"
|
// import { transports } from "./transports/index.js";
|
||||||
// const transports = require("./transports/index")
|
import { transports } from "./transports"
|
||||||
const Emitter = require("component-emitter")
|
import { installTimerFunctions, byteLength } from "./util"
|
||||||
const debug = (...args: any) => console.debug('engine.io-client:socket', ...args)//require("debug")("engine.io-client:socket")
|
import { decode } from "./contrib/parseqs"
|
||||||
import parser from "../engine.io-parser"
|
import { parse } from "./contrib/parseuri"
|
||||||
const parseuri = require("parseuri")
|
// import debugModule from "debug"; // debug()
|
||||||
const parseqs = require("parseqs")
|
import { Emitter } from "@socket.io/component-emitter"
|
||||||
import { installTimerFunctions } from "./util"
|
// import { protocol } from "engine.io-parser";
|
||||||
|
import { protocol } from "../engine.io-parser"
|
||||||
|
import type { Packet, BinaryType, PacketType, RawData } from "../engine.io-parser"
|
||||||
|
import { CloseDetails, Transport } from "./transport"
|
||||||
|
|
||||||
|
// const debug = debugModule("engine.io-client:socket"); // debug()
|
||||||
|
const debug = require('../debug')('engine.io-client:socket')
|
||||||
|
|
||||||
|
export interface SocketOptions {
|
||||||
|
/**
|
||||||
|
* The host that we're connecting to. Set from the URI passed when connecting
|
||||||
|
*/
|
||||||
|
host: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hostname for our connection. Set from the URI passed when connecting
|
||||||
|
*/
|
||||||
|
hostname: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is a secure connection. Set from the URI passed when connecting
|
||||||
|
*/
|
||||||
|
secure: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The port for our connection. Set from the URI passed when connecting
|
||||||
|
*/
|
||||||
|
port: string | number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any query parameters in our uri. Set from the URI passed when connecting
|
||||||
|
*/
|
||||||
|
query: { [key: string]: any }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `http.Agent` to use, defaults to `false` (NodeJS only)
|
||||||
|
*/
|
||||||
|
agent: string | boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the client should try to upgrade the transport from
|
||||||
|
* long-polling to something better.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
upgrade: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces base 64 encoding for polling transport even when XHR2
|
||||||
|
* responseType is available and WebSocket even if the used standard
|
||||||
|
* supports binary.
|
||||||
|
*/
|
||||||
|
forceBase64: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The param name to use as our timestamp key
|
||||||
|
* @default 't'
|
||||||
|
*/
|
||||||
|
timestampParam: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to add the timestamp with each transport request. Note: this
|
||||||
|
* is ignored if the browser is IE or Android, in which case requests
|
||||||
|
* are always stamped
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
timestampRequests: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of transports to try (in order). Engine.io always attempts to
|
||||||
|
* connect directly with the first one, provided the feature detection test
|
||||||
|
* for it passes.
|
||||||
|
* @default ['polling','websocket']
|
||||||
|
*/
|
||||||
|
transports: string[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The port the policy server listens on
|
||||||
|
* @default 843
|
||||||
|
*/
|
||||||
|
policyPost: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true and if the previous websocket connection to the server succeeded,
|
||||||
|
* the connection attempt will bypass the normal upgrade process and will
|
||||||
|
* initially try websocket. A connection attempt following a transport error
|
||||||
|
* will use the normal upgrade process. It is recommended you turn this on
|
||||||
|
* only when using SSL/TLS connections, or if you know that your network does
|
||||||
|
* not block websockets.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
rememberUpgrade: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are we only interested in transports that support binary?
|
||||||
|
*/
|
||||||
|
onlyBinaryUpgrades: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timeout for xhr-polling requests in milliseconds (0) (only for polling transport)
|
||||||
|
*/
|
||||||
|
requestTimeout: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transport options for Node.js client (headers etc)
|
||||||
|
*/
|
||||||
|
transportOptions: Object
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (SSL) Certificate, Private key and CA certificates to use for SSL.
|
||||||
|
* Can be used in Node.js client environment to manually specify
|
||||||
|
* certificate information.
|
||||||
|
*/
|
||||||
|
pfx: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (SSL) Private key to use for SSL. Can be used in Node.js client
|
||||||
|
* environment to manually specify certificate information.
|
||||||
|
*/
|
||||||
|
key: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (SSL) A string or passphrase for the private key or pfx. Can be
|
||||||
|
* used in Node.js client environment to manually specify certificate
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
passphrase: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (SSL) Public x509 certificate to use. Can be used in Node.js client
|
||||||
|
* environment to manually specify certificate information.
|
||||||
|
*/
|
||||||
|
cert: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (SSL) An authority certificate or array of authority certificates to
|
||||||
|
* check the remote host against.. Can be used in Node.js client
|
||||||
|
* environment to manually specify certificate information.
|
||||||
|
*/
|
||||||
|
ca: string | string[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (SSL) A string describing the ciphers to use or exclude. Consult the
|
||||||
|
* [cipher format list]
|
||||||
|
* (http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT) for
|
||||||
|
* details on the format.. Can be used in Node.js client environment to
|
||||||
|
* manually specify certificate information.
|
||||||
|
*/
|
||||||
|
ciphers: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (SSL) If true, the server certificate is verified against the list of
|
||||||
|
* supplied CAs. An 'error' event is emitted if verification fails.
|
||||||
|
* Verification happens at the connection level, before the HTTP request
|
||||||
|
* is sent. Can be used in Node.js client environment to manually specify
|
||||||
|
* certificate information.
|
||||||
|
*/
|
||||||
|
rejectUnauthorized: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Headers that will be passed for each request to the server (via xhr-polling and via websockets).
|
||||||
|
* These values then can be used during handshake or for special proxies.
|
||||||
|
*/
|
||||||
|
extraHeaders?: { [header: string]: string }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to include credentials (cookies, authorization headers, TLS
|
||||||
|
* client certificates, etc.) with cross-origin XHR polling requests
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
withCredentials: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to automatically close the connection whenever the beforeunload event is received.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
closeOnBeforeunload: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to always use the native timeouts. This allows the client to
|
||||||
|
* reconnect when the native timeout functions are overridden, such as when
|
||||||
|
* mock clocks are installed.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
useNativeTimers: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* weather we should unref the reconnect timer when it is
|
||||||
|
* create automatically
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
autoUnref: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parameters of the WebSocket permessage-deflate extension (see ws module api docs). Set to false to disable.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
perMessageDeflate: { threshold: number }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to get our client file from, in the case of the server
|
||||||
|
* serving it
|
||||||
|
* @default '/engine.io'
|
||||||
|
*/
|
||||||
|
path: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether we should add a trailing slash to the request path.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
addTrailingSlash: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Either a single protocol string or an array of protocol strings. These strings are used to indicate sub-protocols,
|
||||||
|
* so that a single server can implement multiple WebSocket sub-protocols (for example, you might want one server to
|
||||||
|
* be able to handle different types of interactions depending on the specified protocol)
|
||||||
|
* @default []
|
||||||
|
*/
|
||||||
|
protocols: string | string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HandshakeData {
|
||||||
|
sid: string
|
||||||
|
upgrades: string[]
|
||||||
|
pingInterval: number
|
||||||
|
pingTimeout: number
|
||||||
|
maxPayload: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SocketReservedEvents {
|
||||||
|
open: () => void
|
||||||
|
handshake: (data: HandshakeData) => void
|
||||||
|
packet: (packet: Packet) => void
|
||||||
|
packetCreate: (packet: Packet) => void
|
||||||
|
data: (data) => void
|
||||||
|
message: (data) => void
|
||||||
|
drain: () => void
|
||||||
|
flush: () => void
|
||||||
|
heartbeat: () => void
|
||||||
|
ping: () => void
|
||||||
|
pong: () => void
|
||||||
|
error: (err: string | Error) => void
|
||||||
|
upgrading: (transport) => void
|
||||||
|
upgrade: (transport) => void
|
||||||
|
upgradeError: (err: Error) => void
|
||||||
|
close: (reason: string, description?: CloseDetails | Error) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
type SocketState = "opening" | "open" | "closing" | "closed"
|
||||||
|
|
||||||
|
export class Socket extends Emitter<{}, {}, SocketReservedEvents> {
|
||||||
|
public id: string
|
||||||
|
public transport: Transport
|
||||||
|
public binaryType: BinaryType
|
||||||
|
public readyState: SocketState
|
||||||
|
public writeBuffer: Packet[] = [];
|
||||||
|
|
||||||
|
private prevBufferLen: number
|
||||||
|
private upgrades
|
||||||
|
private pingInterval: number
|
||||||
|
private pingTimeout: number
|
||||||
|
private pingTimeoutTimer: NodeJS.Timer
|
||||||
|
private setTimeoutFn: typeof setTimeout
|
||||||
|
private clearTimeoutFn: typeof clearTimeout
|
||||||
|
private readonly beforeunloadEventListener: () => void
|
||||||
|
private readonly offlineEventListener: () => void
|
||||||
|
private upgrading: boolean
|
||||||
|
private maxPayload?: number
|
||||||
|
|
||||||
|
private readonly opts: Partial<SocketOptions>
|
||||||
|
private readonly secure: boolean
|
||||||
|
private readonly hostname: string
|
||||||
|
private readonly port: string | number
|
||||||
|
private readonly transports: string[]
|
||||||
|
|
||||||
|
static priorWebsocketSuccess: boolean
|
||||||
|
static protocol = protocol;
|
||||||
|
|
||||||
export class Socket extends Emitter {
|
|
||||||
/**
|
/**
|
||||||
* Socket constructor.
|
* Socket constructor.
|
||||||
*
|
*
|
||||||
* @param {String|Object} uri or options
|
* @param {String|Object} uri or options
|
||||||
* @param {Object} options
|
* @param {Object} opts - options
|
||||||
* @api public
|
* @api public
|
||||||
*/
|
*/
|
||||||
constructor(uri, opts: any = {}) {
|
constructor(uri, opts: Partial<SocketOptions> = {}) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
if (uri && "object" === typeof uri) {
|
if (uri && "object" === typeof uri) {
|
||||||
@@ -24,13 +298,13 @@ export class Socket extends Emitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (uri) {
|
if (uri) {
|
||||||
uri = parseuri(uri)
|
uri = parse(uri)
|
||||||
opts.hostname = uri.host
|
opts.hostname = uri.host
|
||||||
opts.secure = uri.protocol === "https" || uri.protocol === "wss"
|
opts.secure = uri.protocol === "https" || uri.protocol === "wss"
|
||||||
opts.port = uri.port
|
opts.port = uri.port
|
||||||
if (uri.query) opts.query = uri.query
|
if (uri.query) opts.query = uri.query
|
||||||
} else if (opts.host) {
|
} else if (opts.host) {
|
||||||
opts.hostname = parseuri(opts.host).host
|
opts.hostname = parse(opts.host).host
|
||||||
}
|
}
|
||||||
|
|
||||||
installTimerFunctions(this, opts)
|
installTimerFunctions(this, opts)
|
||||||
@@ -53,11 +327,10 @@ export class Socket extends Emitter {
|
|||||||
(typeof location !== "undefined" && location.port
|
(typeof location !== "undefined" && location.port
|
||||||
? location.port
|
? location.port
|
||||||
: this.secure
|
: this.secure
|
||||||
? 443
|
? "443"
|
||||||
: 80)
|
: "80")
|
||||||
|
|
||||||
this.transports = ["websocket"]
|
this.transports = opts.transports || ["polling", "websocket"]
|
||||||
this.readyState = ""
|
|
||||||
this.writeBuffer = []
|
this.writeBuffer = []
|
||||||
this.prevBufferLen = 0
|
this.prevBufferLen = 0
|
||||||
|
|
||||||
@@ -67,9 +340,9 @@ export class Socket extends Emitter {
|
|||||||
agent: false,
|
agent: false,
|
||||||
withCredentials: false,
|
withCredentials: false,
|
||||||
upgrade: true,
|
upgrade: true,
|
||||||
jsonp: true,
|
|
||||||
timestampParam: "t",
|
timestampParam: "t",
|
||||||
rememberUpgrade: false,
|
rememberUpgrade: false,
|
||||||
|
addTrailingSlash: true,
|
||||||
rejectUnauthorized: true,
|
rejectUnauthorized: true,
|
||||||
perMessageDeflate: {
|
perMessageDeflate: {
|
||||||
threshold: 1024
|
threshold: 1024
|
||||||
@@ -80,10 +353,12 @@ export class Socket extends Emitter {
|
|||||||
opts
|
opts
|
||||||
)
|
)
|
||||||
|
|
||||||
this.opts.path = this.opts.path.replace(/\/$/, "") + "/"
|
this.opts.path =
|
||||||
|
this.opts.path.replace(/\/$/, "") +
|
||||||
|
(this.opts.addTrailingSlash ? "/" : "")
|
||||||
|
|
||||||
if (typeof this.opts.query === "string") {
|
if (typeof this.opts.query === "string") {
|
||||||
this.opts.query = parseqs.decode(this.opts.query)
|
this.opts.query = decode(this.opts.query)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set on handshake
|
// set on handshake
|
||||||
@@ -100,21 +375,20 @@ export class Socket extends Emitter {
|
|||||||
// Firefox closes the connection when the "beforeunload" event is emitted but not Chrome. This event listener
|
// Firefox closes the connection when the "beforeunload" event is emitted but not Chrome. This event listener
|
||||||
// ensures every browser behaves the same (no "disconnect" event at the Socket.IO level when the page is
|
// ensures every browser behaves the same (no "disconnect" event at the Socket.IO level when the page is
|
||||||
// closed/reloaded)
|
// closed/reloaded)
|
||||||
addEventListener(
|
this.beforeunloadEventListener = () => {
|
||||||
"beforeunload",
|
if (this.transport) {
|
||||||
() => {
|
// silently close the transport
|
||||||
if (this.transport) {
|
this.transport.removeAllListeners()
|
||||||
// silently close the transport
|
this.transport.close()
|
||||||
this.transport.removeAllListeners()
|
}
|
||||||
this.transport.close()
|
}
|
||||||
}
|
addEventListener("beforeunload", this.beforeunloadEventListener, false)
|
||||||
},
|
|
||||||
false
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (this.hostname !== "localhost") {
|
if (this.hostname !== "localhost") {
|
||||||
this.offlineEventListener = () => {
|
this.offlineEventListener = () => {
|
||||||
this.onClose("transport close")
|
this.onClose("transport close", {
|
||||||
|
description: "network connection lost",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
addEventListener("offline", this.offlineEventListener, false)
|
addEventListener("offline", this.offlineEventListener, false)
|
||||||
}
|
}
|
||||||
@@ -126,19 +400,16 @@ export class Socket extends Emitter {
|
|||||||
/**
|
/**
|
||||||
* Creates transport of the given type.
|
* Creates transport of the given type.
|
||||||
*
|
*
|
||||||
* @param {String} transport name
|
* @param {String} name - transport name
|
||||||
* @return {Transport}
|
* @return {Transport}
|
||||||
* @api private
|
* @private
|
||||||
*/
|
*/
|
||||||
createTransport(name, opt?) {
|
private createTransport(name) {
|
||||||
if (name != 'websocket') {
|
|
||||||
throw new Error('Only Support WebSocket in MiaoScript!')
|
|
||||||
}
|
|
||||||
debug('creating transport "%s"', name)
|
debug('creating transport "%s"', name)
|
||||||
const query: any = clone(this.opts.query)
|
const query: any = Object.assign({}, this.opts.query)
|
||||||
|
|
||||||
// append engine.io protocol identifier
|
// append engine.io protocol identifier
|
||||||
query.EIO = parser.protocol
|
query.EIO = protocol
|
||||||
|
|
||||||
// transport name
|
// transport name
|
||||||
query.transport = name
|
query.transport = name
|
||||||
@@ -155,21 +426,21 @@ export class Socket extends Emitter {
|
|||||||
socket: this,
|
socket: this,
|
||||||
hostname: this.hostname,
|
hostname: this.hostname,
|
||||||
secure: this.secure,
|
secure: this.secure,
|
||||||
port: this.port
|
port: this.port,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
debug("options: %j", JSON.stringify(opts))
|
debug("options: %j", opts)
|
||||||
debug("new func", transports[name])
|
|
||||||
return new transports[name](opts)
|
return new transports[name](opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes transport to use and starts probe.
|
* Initializes transport to use and starts probe.
|
||||||
*
|
*
|
||||||
* @api private
|
* @private
|
||||||
*/
|
*/
|
||||||
open() {
|
private open() {
|
||||||
let transport
|
let transport
|
||||||
if (
|
if (
|
||||||
this.opts.rememberUpgrade &&
|
this.opts.rememberUpgrade &&
|
||||||
@@ -180,7 +451,7 @@ export class Socket extends Emitter {
|
|||||||
} else if (0 === this.transports.length) {
|
} else if (0 === this.transports.length) {
|
||||||
// Emit error on next tick so it can be listened to
|
// Emit error on next tick so it can be listened to
|
||||||
this.setTimeoutFn(() => {
|
this.setTimeoutFn(() => {
|
||||||
this.emit("error", "No transports available")
|
this.emitReserved("error", "No transports available")
|
||||||
}, 0)
|
}, 0)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
@@ -191,8 +462,8 @@ export class Socket extends Emitter {
|
|||||||
// Retry with the next transport if the transport is disabled (jsonp: false)
|
// Retry with the next transport if the transport is disabled (jsonp: false)
|
||||||
try {
|
try {
|
||||||
transport = this.createTransport(transport)
|
transport = this.createTransport(transport)
|
||||||
} catch (error: any) {
|
} catch (e) {
|
||||||
debug("error while creating transport: %s", error)
|
debug("error while creating transport: %s", e)
|
||||||
this.transports.shift()
|
this.transports.shift()
|
||||||
this.open()
|
this.open()
|
||||||
return
|
return
|
||||||
@@ -205,9 +476,9 @@ export class Socket extends Emitter {
|
|||||||
/**
|
/**
|
||||||
* Sets the current transport. Disables the existing one (if any).
|
* Sets the current transport. Disables the existing one (if any).
|
||||||
*
|
*
|
||||||
* @api private
|
* @private
|
||||||
*/
|
*/
|
||||||
setTransport(transport) {
|
private setTransport(transport) {
|
||||||
debug("setting transport %s", transport.name)
|
debug("setting transport %s", transport.name)
|
||||||
|
|
||||||
if (this.transport) {
|
if (this.transport) {
|
||||||
@@ -223,9 +494,7 @@ export class Socket extends Emitter {
|
|||||||
.on("drain", this.onDrain.bind(this))
|
.on("drain", this.onDrain.bind(this))
|
||||||
.on("packet", this.onPacket.bind(this))
|
.on("packet", this.onPacket.bind(this))
|
||||||
.on("error", this.onError.bind(this))
|
.on("error", this.onError.bind(this))
|
||||||
.on("close", () => {
|
.on("close", (reason) => this.onClose("transport close", reason))
|
||||||
this.onClose("transport close")
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -234,9 +503,9 @@ export class Socket extends Emitter {
|
|||||||
* @param {String} transport name
|
* @param {String} transport name
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
probe(name) {
|
private probe(name) {
|
||||||
debug('probing transport "%s"', name)
|
debug('probing transport "%s"', name)
|
||||||
let transport = this.createTransport(name, { probe: 1 })
|
let transport = this.createTransport(name)
|
||||||
let failed = false
|
let failed = false
|
||||||
|
|
||||||
Socket.priorWebsocketSuccess = false
|
Socket.priorWebsocketSuccess = false
|
||||||
@@ -251,7 +520,7 @@ export class Socket extends Emitter {
|
|||||||
if ("pong" === msg.type && "probe" === msg.data) {
|
if ("pong" === msg.type && "probe" === msg.data) {
|
||||||
debug('probe transport "%s" pong', name)
|
debug('probe transport "%s" pong', name)
|
||||||
this.upgrading = true
|
this.upgrading = true
|
||||||
this.emit("upgrading", transport)
|
this.emitReserved("upgrading", transport)
|
||||||
if (!transport) return
|
if (!transport) return
|
||||||
Socket.priorWebsocketSuccess = "websocket" === transport.name
|
Socket.priorWebsocketSuccess = "websocket" === transport.name
|
||||||
|
|
||||||
@@ -265,16 +534,17 @@ export class Socket extends Emitter {
|
|||||||
|
|
||||||
this.setTransport(transport)
|
this.setTransport(transport)
|
||||||
transport.send([{ type: "upgrade" }])
|
transport.send([{ type: "upgrade" }])
|
||||||
this.emit("upgrade", transport)
|
this.emitReserved("upgrade", transport)
|
||||||
transport = null
|
transport = null
|
||||||
this.upgrading = false
|
this.upgrading = false
|
||||||
this.flush()
|
this.flush()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
debug('probe transport "%s" failed', name)
|
debug('probe transport "%s" failed', name)
|
||||||
const err: any = new Error("probe error")
|
const err = new Error("probe error")
|
||||||
|
// @ts-ignore
|
||||||
err.transport = transport.name
|
err.transport = transport.name
|
||||||
this.emit("upgradeError", err)
|
this.emitReserved("upgradeError", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -293,14 +563,15 @@ export class Socket extends Emitter {
|
|||||||
|
|
||||||
// Handle any error that happens while probing
|
// Handle any error that happens while probing
|
||||||
const onerror = err => {
|
const onerror = err => {
|
||||||
const error: any = new Error("probe error: " + err)
|
const error = new Error("probe error: " + err)
|
||||||
|
// @ts-ignore
|
||||||
error.transport = transport.name
|
error.transport = transport.name
|
||||||
|
|
||||||
freezeTransport()
|
freezeTransport()
|
||||||
|
|
||||||
debug('probe transport "%s" failed because of error: %s', name, err)
|
debug('probe transport "%s" failed because of error: %s', name, err)
|
||||||
|
|
||||||
this.emit("upgradeError", error)
|
this.emitReserved("upgradeError", error)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTransportClose() {
|
function onTransportClose() {
|
||||||
@@ -325,8 +596,8 @@ export class Socket extends Emitter {
|
|||||||
transport.removeListener("open", onTransportOpen)
|
transport.removeListener("open", onTransportOpen)
|
||||||
transport.removeListener("error", onerror)
|
transport.removeListener("error", onerror)
|
||||||
transport.removeListener("close", onTransportClose)
|
transport.removeListener("close", onTransportClose)
|
||||||
this.removeListener("close", onclose)
|
this.off("close", onclose)
|
||||||
this.removeListener("upgrading", onupgrade)
|
this.off("upgrading", onupgrade)
|
||||||
}
|
}
|
||||||
|
|
||||||
transport.once("open", onTransportOpen)
|
transport.once("open", onTransportOpen)
|
||||||
@@ -342,13 +613,13 @@ export class Socket extends Emitter {
|
|||||||
/**
|
/**
|
||||||
* Called when connection is deemed open.
|
* Called when connection is deemed open.
|
||||||
*
|
*
|
||||||
* @api public
|
* @api private
|
||||||
*/
|
*/
|
||||||
onOpen() {
|
private onOpen() {
|
||||||
debug("socket open")
|
debug("socket open")
|
||||||
this.readyState = "open"
|
this.readyState = "open"
|
||||||
Socket.priorWebsocketSuccess = "websocket" === this.transport.name
|
Socket.priorWebsocketSuccess = "websocket" === this.transport.name
|
||||||
this.emit("open")
|
this.emitReserved("open")
|
||||||
this.flush()
|
this.flush()
|
||||||
|
|
||||||
// we check for `readyState` in case an `open`
|
// we check for `readyState` in case an `open`
|
||||||
@@ -372,7 +643,7 @@ export class Socket extends Emitter {
|
|||||||
*
|
*
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
onPacket(packet) {
|
private onPacket(packet) {
|
||||||
if (
|
if (
|
||||||
"opening" === this.readyState ||
|
"opening" === this.readyState ||
|
||||||
"open" === this.readyState ||
|
"open" === this.readyState ||
|
||||||
@@ -380,10 +651,10 @@ export class Socket extends Emitter {
|
|||||||
) {
|
) {
|
||||||
debug('socket receive: type "%s", data "%s"', packet.type, packet.data)
|
debug('socket receive: type "%s", data "%s"', packet.type, packet.data)
|
||||||
|
|
||||||
this.emit("packet", packet)
|
this.emitReserved("packet", packet)
|
||||||
|
|
||||||
// Socket is live - any packet counts
|
// Socket is live - any packet counts
|
||||||
this.emit("heartbeat")
|
this.emitReserved("heartbeat")
|
||||||
|
|
||||||
switch (packet.type) {
|
switch (packet.type) {
|
||||||
case "open":
|
case "open":
|
||||||
@@ -393,19 +664,20 @@ export class Socket extends Emitter {
|
|||||||
case "ping":
|
case "ping":
|
||||||
this.resetPingTimeout()
|
this.resetPingTimeout()
|
||||||
this.sendPacket("pong")
|
this.sendPacket("pong")
|
||||||
this.emit("ping")
|
this.emitReserved("ping")
|
||||||
this.emit("pong")
|
this.emitReserved("pong")
|
||||||
break
|
break
|
||||||
|
|
||||||
case "error":
|
case "error":
|
||||||
const err: any = new Error("server error")
|
const err = new Error("server error")
|
||||||
|
// @ts-ignore
|
||||||
err.code = packet.data
|
err.code = packet.data
|
||||||
this.onError(err)
|
this.onError(err)
|
||||||
break
|
break
|
||||||
|
|
||||||
case "message":
|
case "message":
|
||||||
this.emit("data", packet.data)
|
this.emitReserved("data", packet.data)
|
||||||
this.emit("message", packet.data)
|
this.emitReserved("message", packet.data)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -416,16 +688,17 @@ export class Socket extends Emitter {
|
|||||||
/**
|
/**
|
||||||
* Called upon handshake completion.
|
* Called upon handshake completion.
|
||||||
*
|
*
|
||||||
* @param {Object} handshake obj
|
* @param {Object} data - handshake obj
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
onHandshake(data) {
|
private onHandshake(data) {
|
||||||
this.emit("handshake", data)
|
this.emitReserved("handshake", data)
|
||||||
this.id = data.sid
|
this.id = data.sid
|
||||||
this.transport.query.sid = data.sid
|
this.transport.query.sid = data.sid
|
||||||
this.upgrades = this.filterUpgrades(data.upgrades)
|
this.upgrades = this.filterUpgrades(data.upgrades)
|
||||||
this.pingInterval = data.pingInterval
|
this.pingInterval = data.pingInterval
|
||||||
this.pingTimeout = data.pingTimeout
|
this.pingTimeout = data.pingTimeout
|
||||||
|
this.maxPayload = data.maxPayload
|
||||||
this.onOpen()
|
this.onOpen()
|
||||||
// In case open handler closes socket
|
// In case open handler closes socket
|
||||||
if ("closed" === this.readyState) return
|
if ("closed" === this.readyState) return
|
||||||
@@ -437,7 +710,7 @@ export class Socket extends Emitter {
|
|||||||
*
|
*
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
resetPingTimeout() {
|
private resetPingTimeout() {
|
||||||
this.clearTimeoutFn(this.pingTimeoutTimer)
|
this.clearTimeoutFn(this.pingTimeoutTimer)
|
||||||
this.pingTimeoutTimer = this.setTimeoutFn(() => {
|
this.pingTimeoutTimer = this.setTimeoutFn(() => {
|
||||||
this.onClose("ping timeout")
|
this.onClose("ping timeout")
|
||||||
@@ -452,7 +725,7 @@ export class Socket extends Emitter {
|
|||||||
*
|
*
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
onDrain() {
|
private onDrain() {
|
||||||
this.writeBuffer.splice(0, this.prevBufferLen)
|
this.writeBuffer.splice(0, this.prevBufferLen)
|
||||||
|
|
||||||
// setting prevBufferLen = 0 is very important
|
// setting prevBufferLen = 0 is very important
|
||||||
@@ -461,7 +734,7 @@ export class Socket extends Emitter {
|
|||||||
this.prevBufferLen = 0
|
this.prevBufferLen = 0
|
||||||
|
|
||||||
if (0 === this.writeBuffer.length) {
|
if (0 === this.writeBuffer.length) {
|
||||||
this.emit("drain")
|
this.emitReserved("drain")
|
||||||
} else {
|
} else {
|
||||||
this.flush()
|
this.flush()
|
||||||
}
|
}
|
||||||
@@ -472,22 +745,53 @@ export class Socket extends Emitter {
|
|||||||
*
|
*
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
flush() {
|
private flush() {
|
||||||
if (
|
if (
|
||||||
"closed" !== this.readyState &&
|
"closed" !== this.readyState &&
|
||||||
this.transport.writable &&
|
this.transport.writable &&
|
||||||
!this.upgrading &&
|
!this.upgrading &&
|
||||||
this.writeBuffer.length
|
this.writeBuffer.length
|
||||||
) {
|
) {
|
||||||
debug("flushing %d packets in socket", this.writeBuffer.length)
|
const packets = this.getWritablePackets()
|
||||||
this.transport.send(this.writeBuffer)
|
debug("flushing %d packets in socket", packets.length)
|
||||||
|
this.transport.send(packets)
|
||||||
// keep track of current length of writeBuffer
|
// keep track of current length of writeBuffer
|
||||||
// splice writeBuffer and callbackBuffer on `drain`
|
// splice writeBuffer and callbackBuffer on `drain`
|
||||||
this.prevBufferLen = this.writeBuffer.length
|
this.prevBufferLen = packets.length
|
||||||
this.emit("flush")
|
this.emitReserved("flush")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure the encoded size of the writeBuffer is below the maxPayload value sent by the server (only for HTTP
|
||||||
|
* long-polling)
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private getWritablePackets() {
|
||||||
|
const shouldCheckPayloadSize =
|
||||||
|
this.maxPayload &&
|
||||||
|
this.transport.name === "polling" &&
|
||||||
|
this.writeBuffer.length > 1
|
||||||
|
if (!shouldCheckPayloadSize) {
|
||||||
|
return this.writeBuffer
|
||||||
|
}
|
||||||
|
let payloadSize = 1 // first packet type
|
||||||
|
for (let i = 0; i < this.writeBuffer.length; i++) {
|
||||||
|
const data = this.writeBuffer[i].data
|
||||||
|
if (data) {
|
||||||
|
payloadSize += byteLength(data)
|
||||||
|
}
|
||||||
|
if (i > 0 && payloadSize > this.maxPayload) {
|
||||||
|
debug("only send %d out of %d packets", i, this.writeBuffer.length)
|
||||||
|
return this.writeBuffer.slice(0, i)
|
||||||
|
}
|
||||||
|
payloadSize += 2 // separator + packet type
|
||||||
|
}
|
||||||
|
debug("payload size is %d (max: %d)", payloadSize, this.maxPayload)
|
||||||
|
return this.writeBuffer
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message.
|
* Sends a message.
|
||||||
*
|
*
|
||||||
@@ -497,12 +801,12 @@ export class Socket extends Emitter {
|
|||||||
* @return {Socket} for chaining.
|
* @return {Socket} for chaining.
|
||||||
* @api public
|
* @api public
|
||||||
*/
|
*/
|
||||||
write(msg, options, fn) {
|
public write(msg, options, fn?) {
|
||||||
this.sendPacket("message", msg, options, fn)
|
this.sendPacket("message", msg, options, fn)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
send(msg, options, fn) {
|
public send(msg, options, fn?) {
|
||||||
this.sendPacket("message", msg, options, fn)
|
this.sendPacket("message", msg, options, fn)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -516,7 +820,7 @@ export class Socket extends Emitter {
|
|||||||
* @param {Function} callback function.
|
* @param {Function} callback function.
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
sendPacket(type, data?, options?, fn?) {
|
private sendPacket(type, data?, options?, fn?) {
|
||||||
if ("function" === typeof data) {
|
if ("function" === typeof data) {
|
||||||
fn = data
|
fn = data
|
||||||
data = undefined
|
data = undefined
|
||||||
@@ -539,7 +843,7 @@ export class Socket extends Emitter {
|
|||||||
data: data,
|
data: data,
|
||||||
options: options
|
options: options
|
||||||
}
|
}
|
||||||
this.emit("packetCreate", packet)
|
this.emitReserved("packetCreate", packet)
|
||||||
this.writeBuffer.push(packet)
|
this.writeBuffer.push(packet)
|
||||||
if (fn) this.once("flush", fn)
|
if (fn) this.once("flush", fn)
|
||||||
this.flush()
|
this.flush()
|
||||||
@@ -548,9 +852,9 @@ export class Socket extends Emitter {
|
|||||||
/**
|
/**
|
||||||
* Closes the connection.
|
* Closes the connection.
|
||||||
*
|
*
|
||||||
* @api private
|
* @api public
|
||||||
*/
|
*/
|
||||||
close() {
|
public close() {
|
||||||
const close = () => {
|
const close = () => {
|
||||||
this.onClose("forced close")
|
this.onClose("forced close")
|
||||||
debug("socket closing - telling transport to close")
|
debug("socket closing - telling transport to close")
|
||||||
@@ -558,8 +862,8 @@ export class Socket extends Emitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const cleanupAndClose = () => {
|
const cleanupAndClose = () => {
|
||||||
this.removeListener("upgrade", cleanupAndClose)
|
this.off("upgrade", cleanupAndClose)
|
||||||
this.removeListener("upgradeError", cleanupAndClose)
|
this.off("upgradeError", cleanupAndClose)
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,10 +899,10 @@ export class Socket extends Emitter {
|
|||||||
*
|
*
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
onError(err) {
|
private onError(err) {
|
||||||
debug("socket error %j", err)
|
debug("socket error %j", err)
|
||||||
Socket.priorWebsocketSuccess = false
|
Socket.priorWebsocketSuccess = false
|
||||||
this.emit("error", err)
|
this.emitReserved("error", err)
|
||||||
this.onClose("transport error", err)
|
this.onClose("transport error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,7 +911,7 @@ export class Socket extends Emitter {
|
|||||||
*
|
*
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
onClose(reason, desc?) {
|
private onClose(reason: string, description?: CloseDetails | Error) {
|
||||||
if (
|
if (
|
||||||
"opening" === this.readyState ||
|
"opening" === this.readyState ||
|
||||||
"open" === this.readyState ||
|
"open" === this.readyState ||
|
||||||
@@ -616,7 +920,6 @@ export class Socket extends Emitter {
|
|||||||
debug('socket close with reason: "%s"', reason)
|
debug('socket close with reason: "%s"', reason)
|
||||||
|
|
||||||
// clear timers
|
// clear timers
|
||||||
this.clearTimeoutFn(this.pingIntervalTimer)
|
|
||||||
this.clearTimeoutFn(this.pingTimeoutTimer)
|
this.clearTimeoutFn(this.pingTimeoutTimer)
|
||||||
|
|
||||||
// stop event from firing again for transport
|
// stop event from firing again for transport
|
||||||
@@ -629,6 +932,11 @@ export class Socket extends Emitter {
|
|||||||
this.transport.removeAllListeners()
|
this.transport.removeAllListeners()
|
||||||
|
|
||||||
if (typeof removeEventListener === "function") {
|
if (typeof removeEventListener === "function") {
|
||||||
|
removeEventListener(
|
||||||
|
"beforeunload",
|
||||||
|
this.beforeunloadEventListener,
|
||||||
|
false
|
||||||
|
)
|
||||||
removeEventListener("offline", this.offlineEventListener, false)
|
removeEventListener("offline", this.offlineEventListener, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,7 +947,7 @@ export class Socket extends Emitter {
|
|||||||
this.id = null
|
this.id = null
|
||||||
|
|
||||||
// emit close event
|
// emit close event
|
||||||
this.emit("close", reason, desc)
|
this.emitReserved("close", reason, description)
|
||||||
|
|
||||||
// clean buffers after, so users can still
|
// clean buffers after, so users can still
|
||||||
// grab the buffers on `close` event
|
// grab the buffers on `close` event
|
||||||
@@ -655,7 +963,7 @@ export class Socket extends Emitter {
|
|||||||
* @api private
|
* @api private
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
filterUpgrades(upgrades) {
|
private filterUpgrades(upgrades) {
|
||||||
const filteredUpgrades = []
|
const filteredUpgrades = []
|
||||||
let i = 0
|
let i = 0
|
||||||
const j = upgrades.length
|
const j = upgrades.length
|
||||||
@@ -666,23 +974,3 @@ export class Socket extends Emitter {
|
|||||||
return filteredUpgrades
|
return filteredUpgrades
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket.priorWebsocketSuccess = false
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Protocol version.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
Socket.protocol = parser.protocol // this is an int
|
|
||||||
|
|
||||||
function clone(obj) {
|
|
||||||
const o = {}
|
|
||||||
for (let i in obj) {
|
|
||||||
if (obj.hasOwnProperty(i)) {
|
|
||||||
o[i] = obj[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return o
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,61 +1,103 @@
|
|||||||
import parser from "../engine.io-parser"
|
// import { decodePacket, Packet, RawData } from "engine.io-parser"
|
||||||
const Emitter = require("component-emitter")
|
import { decodePacket, Packet, RawData } from "../engine.io-parser"
|
||||||
|
import { Emitter } from "@socket.io/component-emitter"
|
||||||
import { installTimerFunctions } from "./util"
|
import { installTimerFunctions } from "./util"
|
||||||
const debug = (...args: any) => console.debug('engine.io-client:transport', ...args)//require("debug")("engine.io-client:transport")
|
// import debugModule from "debug"; // debug()
|
||||||
|
import { SocketOptions } from "./socket"
|
||||||
|
|
||||||
|
// const debug = debugModule("engine.io-client:transport"); // debug()
|
||||||
|
const debug = require('../debug')("engine.io-client:transport") // debug()
|
||||||
|
|
||||||
|
class TransportError extends Error {
|
||||||
|
public readonly type = "TransportError";
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
reason: string,
|
||||||
|
readonly description: any,
|
||||||
|
readonly context: any
|
||||||
|
) {
|
||||||
|
super(reason)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CloseDetails {
|
||||||
|
description: string
|
||||||
|
context?: unknown // context should be typed as CloseEvent | XMLHttpRequest, but these types are not available on non-browser platforms
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TransportReservedEvents {
|
||||||
|
open: () => void
|
||||||
|
error: (err: TransportError) => void
|
||||||
|
packet: (packet: Packet) => void
|
||||||
|
close: (details?: CloseDetails) => void
|
||||||
|
poll: () => void
|
||||||
|
pollComplete: () => void
|
||||||
|
drain: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
type TransportState = "opening" | "open" | "closed" | "pausing" | "paused"
|
||||||
|
|
||||||
|
export abstract class Transport extends Emitter<
|
||||||
|
Record<never, never>,
|
||||||
|
Record<never, never>,
|
||||||
|
TransportReservedEvents
|
||||||
|
> {
|
||||||
|
public query: Record<string, string>
|
||||||
|
public writable: boolean = false;
|
||||||
|
|
||||||
|
protected opts: SocketOptions
|
||||||
|
protected supportsBinary: boolean
|
||||||
|
protected readyState: TransportState
|
||||||
|
protected socket: any
|
||||||
|
protected setTimeoutFn: typeof setTimeout
|
||||||
|
|
||||||
export class Transport extends Emitter {
|
|
||||||
/**
|
/**
|
||||||
* Transport abstract constructor.
|
* Transport abstract constructor.
|
||||||
*
|
*
|
||||||
* @param {Object} options.
|
* @param {Object} opts - options
|
||||||
* @api private
|
* @protected
|
||||||
*/
|
*/
|
||||||
constructor(opts) {
|
constructor(opts) {
|
||||||
super()
|
super()
|
||||||
installTimerFunctions(this, opts)
|
installTimerFunctions(this, opts)
|
||||||
|
|
||||||
this.opts = opts
|
this.opts = opts
|
||||||
this.query = opts.query
|
this.query = opts.query
|
||||||
this.readyState = ""
|
|
||||||
this.socket = opts.socket
|
this.socket = opts.socket
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emits an error.
|
* Emits an error.
|
||||||
*
|
*
|
||||||
* @param {String} str
|
* @param {String} reason
|
||||||
|
* @param description
|
||||||
|
* @param context - the error context
|
||||||
* @return {Transport} for chaining
|
* @return {Transport} for chaining
|
||||||
* @api public
|
* @protected
|
||||||
*/
|
*/
|
||||||
onError(msg, desc) {
|
protected onError(reason: string, description: any, context?: any) {
|
||||||
const err: any = new Error(msg)
|
super.emitReserved(
|
||||||
err.type = "TransportError"
|
"error",
|
||||||
err.description = desc
|
new TransportError(reason, description, context)
|
||||||
this.emit("error", err)
|
)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the transport.
|
* Opens the transport.
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
*/
|
||||||
open() {
|
public open() {
|
||||||
if ("closed" === this.readyState || "" === this.readyState) {
|
this.readyState = "opening"
|
||||||
this.readyState = "opening"
|
this.doOpen()
|
||||||
this.doOpen()
|
|
||||||
}
|
|
||||||
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the transport.
|
* Closes the transport.
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
*/
|
||||||
close() {
|
public close() {
|
||||||
if ("opening" === this.readyState || "open" === this.readyState) {
|
if (this.readyState === "opening" || this.readyState === "open") {
|
||||||
this.doClose()
|
this.doClose()
|
||||||
this.onClose()
|
this.onClose()
|
||||||
}
|
}
|
||||||
@@ -67,10 +109,9 @@ export class Transport extends Emitter {
|
|||||||
* Sends multiple packets.
|
* Sends multiple packets.
|
||||||
*
|
*
|
||||||
* @param {Array} packets
|
* @param {Array} packets
|
||||||
* @api private
|
|
||||||
*/
|
*/
|
||||||
send(packets) {
|
public send(packets) {
|
||||||
if ("open" === this.readyState) {
|
if (this.readyState === "open") {
|
||||||
this.write(packets)
|
this.write(packets)
|
||||||
} else {
|
} else {
|
||||||
// this might happen if the transport was silently closed in the beforeunload event handler
|
// this might happen if the transport was silently closed in the beforeunload event handler
|
||||||
@@ -81,39 +122,58 @@ export class Transport extends Emitter {
|
|||||||
/**
|
/**
|
||||||
* Called upon open
|
* Called upon open
|
||||||
*
|
*
|
||||||
* @api private
|
* @protected
|
||||||
*/
|
*/
|
||||||
onOpen() {
|
protected onOpen() {
|
||||||
this.readyState = "open"
|
this.readyState = "open"
|
||||||
this.writable = true
|
this.writable = true
|
||||||
this.emit("open")
|
super.emitReserved("open")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called with data.
|
* Called with data.
|
||||||
*
|
*
|
||||||
* @param {String} data
|
* @param {String} data
|
||||||
* @api private
|
* @protected
|
||||||
*/
|
*/
|
||||||
onData(data) {
|
protected onData(data: RawData) {
|
||||||
const packet = parser.decodePacket(data, this.socket.binaryType)
|
const packet = decodePacket(data, this.socket.binaryType)
|
||||||
this.onPacket(packet)
|
this.onPacket(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called with a decoded packet.
|
* Called with a decoded packet.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
*/
|
*/
|
||||||
onPacket(packet) {
|
protected onPacket(packet: Packet) {
|
||||||
this.emit("packet", packet)
|
super.emitReserved("packet", packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called upon close.
|
* Called upon close.
|
||||||
*
|
*
|
||||||
* @api private
|
* @protected
|
||||||
*/
|
*/
|
||||||
onClose() {
|
protected onClose(details?: CloseDetails) {
|
||||||
this.readyState = "closed"
|
this.readyState = "closed"
|
||||||
this.emit("close")
|
super.emitReserved("close", details)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the transport
|
||||||
|
*/
|
||||||
|
public abstract get name(): string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pauses the transport, in order not to lose packets during an upgrade.
|
||||||
|
*
|
||||||
|
* @param onPause
|
||||||
|
*/
|
||||||
|
public pause(onPause: () => void) { }
|
||||||
|
|
||||||
|
protected abstract doOpen()
|
||||||
|
protected abstract doClose()
|
||||||
|
protected abstract write(packets: Packet[])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { WS } from "./websocket"
|
import { WS } from "./websocket.js"
|
||||||
export default {
|
|
||||||
'websocket': WS
|
export const transports = {
|
||||||
|
websocket: WS,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { WebSocket as ws } from "../../client"
|
||||||
|
|
||||||
|
export const WebSocket = ws
|
||||||
|
export const usingBrowserWebSocket = false
|
||||||
|
export const defaultBinaryType = "nodebuffer"
|
||||||
|
export const nextTick = process.nextTick
|
||||||
@@ -1,21 +1,18 @@
|
|||||||
import { Transport } from '../transport'
|
import { Transport } from "../transport"
|
||||||
// const Transport = require("../transport")
|
import { encode } from "../contrib/parseqs"
|
||||||
import parser from '../../engine.io-parser'
|
import { yeast } from "../contrib/yeast"
|
||||||
// const parser = require("../engine.io-parser")
|
import { pick } from "../util"
|
||||||
const parseqs = require("parseqs")
|
import {
|
||||||
const yeast = require("yeast")
|
defaultBinaryType,
|
||||||
import { pick } from '../util'
|
nextTick,
|
||||||
// const { pick } = require("../util")
|
usingBrowserWebSocket,
|
||||||
import { WebSocket } from '../../client'
|
WebSocket
|
||||||
const usingBrowserWebSocket = true
|
} from "./websocket-constructor"
|
||||||
// const {
|
// import debugModule from "debug" // debug()
|
||||||
// WebSocket,
|
import { encodePacket } from "../../engine.io-parser"
|
||||||
// usingBrowserWebSocket,
|
|
||||||
// defaultBinaryType,
|
|
||||||
// nextTick
|
|
||||||
// } = require("./websocket-constructor")
|
|
||||||
|
|
||||||
const debug = (...args: any) => console.debug('engine.io-client:websocket', ...args)//require("debug")("engine.io-client:websocket")
|
// const debug = debugModule("engine.io-client:websocket") // debug()
|
||||||
|
const debug = (...args: any) => console.debug('engine.io-client:websocket', ...args)
|
||||||
|
|
||||||
// detect ReactNative environment
|
// detect ReactNative environment
|
||||||
const isReactNative =
|
const isReactNative =
|
||||||
@@ -24,11 +21,13 @@ const isReactNative =
|
|||||||
navigator.product.toLowerCase() === "reactnative"
|
navigator.product.toLowerCase() === "reactnative"
|
||||||
|
|
||||||
export class WS extends Transport {
|
export class WS extends Transport {
|
||||||
|
private ws: any
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WebSocket transport constructor.
|
* WebSocket transport constructor.
|
||||||
*
|
*
|
||||||
* @api {Object} connection options
|
* @param {Object} opts - connection options
|
||||||
* @api public
|
* @protected
|
||||||
*/
|
*/
|
||||||
constructor(opts) {
|
constructor(opts) {
|
||||||
super(opts)
|
super(opts)
|
||||||
@@ -36,21 +35,11 @@ export class WS extends Transport {
|
|||||||
this.supportsBinary = !opts.forceBase64
|
this.supportsBinary = !opts.forceBase64
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
override get name() {
|
||||||
* Transport name.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
get name() {
|
|
||||||
return "websocket"
|
return "websocket"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
override doOpen() {
|
||||||
* Opens socket.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
doOpen() {
|
|
||||||
if (!this.check()) {
|
if (!this.check()) {
|
||||||
// let probe timeout
|
// let probe timeout
|
||||||
return
|
return
|
||||||
@@ -86,17 +75,17 @@ export class WS extends Transport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.ws = new WebSocket(uri, protocols)
|
this.ws =
|
||||||
// usingBrowserWebSocket && !isReactNative
|
usingBrowserWebSocket && !isReactNative
|
||||||
// ? protocols
|
? protocols
|
||||||
// ? new WebSocket(uri, protocols)
|
? new WebSocket(uri, protocols)
|
||||||
// : new WebSocket(uri)
|
: new WebSocket(uri)
|
||||||
// : new WebSocket(uri, protocols, opts)
|
: new WebSocket(uri, protocols, opts)
|
||||||
} catch (err) {
|
} catch (err: any) {
|
||||||
return this.emit("error", err)
|
return this.emitReserved("error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ws.binaryType = this.socket.binaryType || 'arraybuffer'
|
this.ws.binaryType = this.socket.binaryType || defaultBinaryType
|
||||||
|
|
||||||
this.addEventListeners()
|
this.addEventListeners()
|
||||||
}
|
}
|
||||||
@@ -104,27 +93,25 @@ export class WS extends Transport {
|
|||||||
/**
|
/**
|
||||||
* Adds event listeners to the socket
|
* Adds event listeners to the socket
|
||||||
*
|
*
|
||||||
* @api private
|
* @private
|
||||||
*/
|
*/
|
||||||
addEventListeners() {
|
private addEventListeners() {
|
||||||
this.ws.onopen = () => {
|
this.ws.onopen = () => {
|
||||||
if (this.opts.autoUnref) {
|
if (this.opts.autoUnref) {
|
||||||
this.ws._socket.unref()
|
this.ws._socket.unref()
|
||||||
}
|
}
|
||||||
this.onOpen()
|
this.onOpen()
|
||||||
}
|
}
|
||||||
this.ws.onclose = this.onClose.bind(this)
|
this.ws.onclose = (closeEvent) =>
|
||||||
this.ws.onmessage = ev => this.onData(ev.data)
|
this.onClose({
|
||||||
this.ws.onerror = e => this.onError("websocket error", e)
|
description: "websocket connection closed",
|
||||||
|
context: closeEvent,
|
||||||
|
})
|
||||||
|
this.ws.onmessage = (ev) => this.onData(ev.data)
|
||||||
|
this.ws.onerror = (e) => this.onError("websocket error", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
override write(packets) {
|
||||||
* Writes data to socket.
|
|
||||||
*
|
|
||||||
* @param {Array} array of packets.
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
write(packets) {
|
|
||||||
this.writable = false
|
this.writable = false
|
||||||
|
|
||||||
// encodePacket efficient as it uses WS framing
|
// encodePacket efficient as it uses WS framing
|
||||||
@@ -133,9 +120,9 @@ export class WS extends Transport {
|
|||||||
const packet = packets[i]
|
const packet = packets[i]
|
||||||
const lastPacket = i === packets.length - 1
|
const lastPacket = i === packets.length - 1
|
||||||
|
|
||||||
parser.encodePacket(packet, this.supportsBinary, data => {
|
encodePacket(packet, this.supportsBinary, (data) => {
|
||||||
// always create a new object (GH-437)
|
// always create a new object (GH-437)
|
||||||
const opts: any = {}
|
const opts: { compress?: boolean } = {}
|
||||||
if (!usingBrowserWebSocket) {
|
if (!usingBrowserWebSocket) {
|
||||||
if (packet.options) {
|
if (packet.options) {
|
||||||
opts.compress = packet.options.compress
|
opts.compress = packet.options.compress
|
||||||
@@ -143,6 +130,7 @@ export class WS extends Transport {
|
|||||||
|
|
||||||
if (this.opts.perMessageDeflate) {
|
if (this.opts.perMessageDeflate) {
|
||||||
const len =
|
const len =
|
||||||
|
// @ts-ignore
|
||||||
"string" === typeof data ? Buffer.byteLength(data) : data.length
|
"string" === typeof data ? Buffer.byteLength(data) : data.length
|
||||||
if (len < this.opts.perMessageDeflate.threshold) {
|
if (len < this.opts.perMessageDeflate.threshold) {
|
||||||
opts.compress = false
|
opts.compress = false
|
||||||
@@ -160,37 +148,23 @@ export class WS extends Transport {
|
|||||||
} else {
|
} else {
|
||||||
this.ws.send(data, opts)
|
this.ws.send(data, opts)
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (e) {
|
||||||
debug("websocket closed before onclose event")
|
debug("websocket closed before onclose event")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastPacket) {
|
if (lastPacket) {
|
||||||
// fake drain
|
// fake drain
|
||||||
// defer to next tick to allow Socket to clear writeBuffer
|
// defer to next tick to allow Socket to clear writeBuffer
|
||||||
process.nextTick(() => {
|
nextTick(() => {
|
||||||
this.writable = true
|
this.writable = true
|
||||||
this.emit("drain")
|
this.emitReserved("drain")
|
||||||
}, this.setTimeoutFn)
|
}, this.setTimeoutFn)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
override doClose() {
|
||||||
* Called upon close
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
onClose() {
|
|
||||||
Transport.prototype.onClose.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes socket.
|
|
||||||
*
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
doClose() {
|
|
||||||
if (typeof this.ws !== "undefined") {
|
if (typeof this.ws !== "undefined") {
|
||||||
this.ws.close()
|
this.ws.close()
|
||||||
this.ws = null
|
this.ws = null
|
||||||
@@ -200,10 +174,10 @@ export class WS extends Transport {
|
|||||||
/**
|
/**
|
||||||
* Generates uri for connection.
|
* Generates uri for connection.
|
||||||
*
|
*
|
||||||
* @api private
|
* @private
|
||||||
*/
|
*/
|
||||||
uri() {
|
uri() {
|
||||||
let query = this.query || {}
|
let query: { b64?: number } = this.query || {}
|
||||||
const schema = this.opts.secure ? "wss" : "ws"
|
const schema = this.opts.secure ? "wss" : "ws"
|
||||||
let port = ""
|
let port = ""
|
||||||
|
|
||||||
@@ -226,21 +200,16 @@ export class WS extends Transport {
|
|||||||
query.b64 = 1
|
query.b64 = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
query = parseqs.encode(query)
|
const encodedQuery = encode(query)
|
||||||
|
|
||||||
// prepend ? to query
|
|
||||||
if (query.length) {
|
|
||||||
query = "?" + query
|
|
||||||
}
|
|
||||||
|
|
||||||
const ipv6 = this.opts.hostname.indexOf(":") !== -1
|
const ipv6 = this.opts.hostname.indexOf(":") !== -1
|
||||||
|
|
||||||
return (
|
return (
|
||||||
schema +
|
schema +
|
||||||
"://" +
|
"://" +
|
||||||
(ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) +
|
(ipv6 ? "[" + this.opts.hostname + "]" : this.opts.hostname) +
|
||||||
port +
|
port +
|
||||||
this.opts.path +
|
this.opts.path +
|
||||||
query
|
(encodedQuery.length ? "?" + encodedQuery : "")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,12 +217,9 @@ export class WS extends Transport {
|
|||||||
* Feature detection for WebSocket.
|
* Feature detection for WebSocket.
|
||||||
*
|
*
|
||||||
* @return {Boolean} whether this transport is available.
|
* @return {Boolean} whether this transport is available.
|
||||||
* @api public
|
* @private
|
||||||
*/
|
*/
|
||||||
check() {
|
private check() {
|
||||||
return (
|
return !!WebSocket
|
||||||
!!WebSocket &&
|
|
||||||
!("__initialize" in WebSocket && this.name === WS.prototype.name)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
const pick = (obj, ...attr) => {
|
// import { globalThisShim as globalThis } from "./globalThis.js"
|
||||||
|
|
||||||
|
export function pick(obj, ...attr) {
|
||||||
return attr.reduce((acc, k) => {
|
return attr.reduce((acc, k) => {
|
||||||
if (obj.hasOwnProperty(k)) {
|
if (obj.hasOwnProperty(k)) {
|
||||||
acc[k] = obj[k]
|
acc[k] = obj[k]
|
||||||
@@ -8,16 +10,46 @@ const pick = (obj, ...attr) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Keep a reference to the real timeout functions so they can be used when overridden
|
// Keep a reference to the real timeout functions so they can be used when overridden
|
||||||
const NATIVE_SET_TIMEOUT = setTimeout
|
const NATIVE_SET_TIMEOUT = globalThis.setTimeout
|
||||||
const NATIVE_CLEAR_TIMEOUT = clearTimeout
|
const NATIVE_CLEAR_TIMEOUT = globalThis.clearTimeout
|
||||||
|
|
||||||
const installTimerFunctions = (obj, opts) => {
|
export function installTimerFunctions(obj, opts) {
|
||||||
if (opts.useNativeTimers) {
|
if (opts.useNativeTimers) {
|
||||||
obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globalThis)
|
obj.setTimeoutFn = NATIVE_SET_TIMEOUT.bind(globalThis)
|
||||||
obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globalThis)
|
obj.clearTimeoutFn = NATIVE_CLEAR_TIMEOUT.bind(globalThis)
|
||||||
} else {
|
} else {
|
||||||
obj.setTimeoutFn = setTimeout.bind(globalThis)
|
obj.setTimeoutFn = globalThis.setTimeout.bind(globalThis)
|
||||||
obj.clearTimeoutFn = clearTimeout.bind(globalThis)
|
obj.clearTimeoutFn = globalThis.clearTimeout.bind(globalThis)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export { pick, installTimerFunctions }
|
|
||||||
|
// base64 encoded buffers are about 33% bigger (https://en.wikipedia.org/wiki/Base64)
|
||||||
|
const BASE64_OVERHEAD = 1.33
|
||||||
|
|
||||||
|
// we could also have used `new Blob([obj]).size`, but it isn't supported in IE9
|
||||||
|
export function byteLength(obj) {
|
||||||
|
if (typeof obj === "string") {
|
||||||
|
return utf8Length(obj)
|
||||||
|
}
|
||||||
|
// arraybuffer or blob
|
||||||
|
return Math.ceil((obj.byteLength || obj.size) * BASE64_OVERHEAD)
|
||||||
|
}
|
||||||
|
|
||||||
|
function utf8Length(str) {
|
||||||
|
let c = 0,
|
||||||
|
length = 0
|
||||||
|
for (let i = 0, l = str.length; i < l; i++) {
|
||||||
|
c = str.charCodeAt(i)
|
||||||
|
if (c < 0x80) {
|
||||||
|
length += 1
|
||||||
|
} else if (c < 0x800) {
|
||||||
|
length += 2
|
||||||
|
} else if (c < 0xd800 || c >= 0xe000) {
|
||||||
|
length += 3
|
||||||
|
} else {
|
||||||
|
i++
|
||||||
|
length += 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return length
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,21 +1,39 @@
|
|||||||
const PACKET_TYPES = Object.create(null) // no Map = no polyfill
|
const PACKET_TYPES = Object.create(null); // no Map = no polyfill
|
||||||
PACKET_TYPES["open"] = "0"
|
PACKET_TYPES["open"] = "0";
|
||||||
PACKET_TYPES["close"] = "1"
|
PACKET_TYPES["close"] = "1";
|
||||||
PACKET_TYPES["ping"] = "2"
|
PACKET_TYPES["ping"] = "2";
|
||||||
PACKET_TYPES["pong"] = "3"
|
PACKET_TYPES["pong"] = "3";
|
||||||
PACKET_TYPES["message"] = "4"
|
PACKET_TYPES["message"] = "4";
|
||||||
PACKET_TYPES["upgrade"] = "5"
|
PACKET_TYPES["upgrade"] = "5";
|
||||||
PACKET_TYPES["noop"] = "6"
|
PACKET_TYPES["noop"] = "6";
|
||||||
|
|
||||||
const PACKET_TYPES_REVERSE = Object.create(null)
|
const PACKET_TYPES_REVERSE = Object.create(null);
|
||||||
Object.keys(PACKET_TYPES).forEach(key => {
|
Object.keys(PACKET_TYPES).forEach(key => {
|
||||||
PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key
|
PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key;
|
||||||
})
|
});
|
||||||
|
|
||||||
const ERROR_PACKET = { type: "error", data: "parser error" }
|
const ERROR_PACKET: Packet = { type: "error", data: "parser error" };
|
||||||
|
|
||||||
export = {
|
export { PACKET_TYPES, PACKET_TYPES_REVERSE, ERROR_PACKET };
|
||||||
PACKET_TYPES,
|
|
||||||
PACKET_TYPES_REVERSE,
|
export type PacketType =
|
||||||
ERROR_PACKET
|
| "open"
|
||||||
|
| "close"
|
||||||
|
| "ping"
|
||||||
|
| "pong"
|
||||||
|
| "message"
|
||||||
|
| "upgrade"
|
||||||
|
| "noop"
|
||||||
|
| "error";
|
||||||
|
|
||||||
|
// RawData should be "string | Buffer | ArrayBuffer | ArrayBufferView | Blob", but Blob does not exist in Node.js and
|
||||||
|
// requires to add the dom lib in tsconfig.json
|
||||||
|
export type RawData = any;
|
||||||
|
|
||||||
|
export interface Packet {
|
||||||
|
type: PacketType;
|
||||||
|
options?: { compress: boolean };
|
||||||
|
data?: RawData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type BinaryType = "nodebuffer" | "arraybuffer" | "blob";
|
||||||
|
|||||||
@@ -1,48 +1,60 @@
|
|||||||
const { PACKET_TYPES_REVERSE, ERROR_PACKET } = require("./commons")
|
import {
|
||||||
|
ERROR_PACKET,
|
||||||
|
PACKET_TYPES_REVERSE,
|
||||||
|
Packet,
|
||||||
|
BinaryType,
|
||||||
|
RawData
|
||||||
|
} from "./commons.js";
|
||||||
|
|
||||||
export const decodePacket = (encodedPacket, binaryType) => {
|
const decodePacket = (
|
||||||
if (typeof encodedPacket !== "string") {
|
encodedPacket: RawData,
|
||||||
return {
|
binaryType?: BinaryType
|
||||||
type: "message",
|
): Packet => {
|
||||||
data: mapBinary(encodedPacket, binaryType)
|
if (typeof encodedPacket !== "string") {
|
||||||
}
|
return {
|
||||||
}
|
type: "message",
|
||||||
const type = encodedPacket.charAt(0)
|
data: mapBinary(encodedPacket, binaryType)
|
||||||
if (type === "b") {
|
};
|
||||||
const buffer = Buffer.from(encodedPacket.substring(1), "base64")
|
}
|
||||||
return {
|
const type = encodedPacket.charAt(0);
|
||||||
type: "message",
|
if (type === "b") {
|
||||||
data: mapBinary(buffer, binaryType)
|
const buffer = Buffer.from(encodedPacket.substring(1), "base64");
|
||||||
}
|
return {
|
||||||
}
|
type: "message",
|
||||||
if (!PACKET_TYPES_REVERSE[type]) {
|
data: mapBinary(buffer, binaryType)
|
||||||
return ERROR_PACKET
|
};
|
||||||
}
|
}
|
||||||
return encodedPacket.length > 1
|
if (!PACKET_TYPES_REVERSE[type]) {
|
||||||
? {
|
return ERROR_PACKET;
|
||||||
type: PACKET_TYPES_REVERSE[type],
|
}
|
||||||
data: encodedPacket.substring(1)
|
return encodedPacket.length > 1
|
||||||
}
|
? {
|
||||||
: {
|
type: PACKET_TYPES_REVERSE[type],
|
||||||
type: PACKET_TYPES_REVERSE[type]
|
data: encodedPacket.substring(1)
|
||||||
}
|
}
|
||||||
}
|
: {
|
||||||
|
type: PACKET_TYPES_REVERSE[type]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const mapBinary = (data, binaryType) => {
|
const mapBinary = (data: RawData, binaryType?: BinaryType) => {
|
||||||
switch (binaryType) {
|
const isBuffer = Buffer.isBuffer(data);
|
||||||
case "arraybuffer":
|
switch (binaryType) {
|
||||||
return Buffer.isBuffer(data) ? toArrayBuffer(data) : data
|
case "arraybuffer":
|
||||||
case "nodebuffer":
|
return isBuffer ? toArrayBuffer(data) : data;
|
||||||
default:
|
case "nodebuffer":
|
||||||
return data // assuming the data is already a Buffer
|
default:
|
||||||
}
|
return data; // assuming the data is already a Buffer
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const toArrayBuffer = buffer => {
|
const toArrayBuffer = (buffer: Buffer): ArrayBuffer => {
|
||||||
const arrayBuffer = new ArrayBuffer(buffer.length)
|
const arrayBuffer = new ArrayBuffer(buffer.length);
|
||||||
const view = new Uint8Array(arrayBuffer)
|
const view = new Uint8Array(arrayBuffer);
|
||||||
for (let i = 0; i < buffer.length; i++) {
|
for (let i = 0; i < buffer.length; i++) {
|
||||||
view[i] = buffer[i]
|
view[i] = buffer[i];
|
||||||
}
|
}
|
||||||
return arrayBuffer
|
return arrayBuffer;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default decodePacket;
|
||||||
|
|||||||
@@ -1,26 +1,31 @@
|
|||||||
const { PACKET_TYPES } = require("./commons")
|
import { PACKET_TYPES, Packet, RawData } from "./commons.js";
|
||||||
|
|
||||||
export const encodePacket = ({ type, data }, supportsBinary, callback) => {
|
const encodePacket = (
|
||||||
console.trace('encodePacket', type, JSON.stringify(data))
|
{ type, data }: Packet,
|
||||||
if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
|
supportsBinary: boolean,
|
||||||
const buffer = toBuffer(data)
|
callback: (encodedPacket: RawData) => void
|
||||||
return callback(encodeBuffer(buffer, supportsBinary))
|
) => {
|
||||||
}
|
if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
|
||||||
// plain string
|
const buffer = toBuffer(data);
|
||||||
return callback(PACKET_TYPES[type] + (data || ""))
|
return callback(encodeBuffer(buffer, supportsBinary));
|
||||||
}
|
}
|
||||||
|
// plain string
|
||||||
|
return callback(PACKET_TYPES[type] + (data || ""));
|
||||||
|
};
|
||||||
|
|
||||||
const toBuffer = data => {
|
const toBuffer = data => {
|
||||||
if (Buffer.isBuffer(data)) {
|
if (Buffer.isBuffer(data)) {
|
||||||
return data
|
return data;
|
||||||
} else if (data instanceof ArrayBuffer) {
|
} else if (data instanceof ArrayBuffer) {
|
||||||
return Buffer.from(data)
|
return Buffer.from(data);
|
||||||
} else {
|
} else {
|
||||||
return Buffer.from(data.buffer, data.byteOffset, data.byteLength)
|
return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// only 'message' packets can contain binary, so the type prefix is not needed
|
// only 'message' packets can contain binary, so the type prefix is not needed
|
||||||
const encodeBuffer = (data, supportsBinary) => {
|
const encodeBuffer = (data: Buffer, supportsBinary: boolean): RawData => {
|
||||||
return supportsBinary ? data : "b" + data.toString("base64")
|
return supportsBinary ? data : "b" + data.toString("base64");
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default encodePacket;
|
||||||
|
|||||||
@@ -1,42 +1,53 @@
|
|||||||
import { encodePacket } from "./encodePacket"
|
import encodePacket from "./encodePacket.js";
|
||||||
import { decodePacket } from "./decodePacket"
|
import decodePacket from "./decodePacket.js";
|
||||||
|
import { Packet, PacketType, RawData, BinaryType } from "./commons.js";
|
||||||
|
|
||||||
const SEPARATOR = String.fromCharCode(30) // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text
|
const SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text
|
||||||
|
|
||||||
const encodePayload = (packets, callback) => {
|
const encodePayload = (
|
||||||
// some packets may be added to the array while encoding, so the initial length must be saved
|
packets: Packet[],
|
||||||
const length = packets.length
|
callback: (encodedPayload: string) => void
|
||||||
const encodedPackets = new Array(length)
|
) => {
|
||||||
let count = 0
|
// some packets may be added to the array while encoding, so the initial length must be saved
|
||||||
|
const length = packets.length;
|
||||||
|
const encodedPackets = new Array(length);
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
packets.forEach((packet, i) => {
|
packets.forEach((packet, i) => {
|
||||||
// force base64 encoding for binary packets
|
// force base64 encoding for binary packets
|
||||||
encodePacket(packet, false, encodedPacket => {
|
encodePacket(packet, false, encodedPacket => {
|
||||||
encodedPackets[i] = encodedPacket
|
encodedPackets[i] = encodedPacket;
|
||||||
if (++count === length) {
|
if (++count === length) {
|
||||||
callback(encodedPackets.join(SEPARATOR))
|
callback(encodedPackets.join(SEPARATOR));
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
const decodePayload = (encodedPayload, binaryType) => {
|
const decodePayload = (
|
||||||
const encodedPackets = encodedPayload.split(SEPARATOR)
|
encodedPayload: string,
|
||||||
const packets = []
|
binaryType?: BinaryType
|
||||||
for (let i = 0; i < encodedPackets.length; i++) {
|
): Packet[] => {
|
||||||
const decodedPacket = decodePacket(encodedPackets[i], binaryType)
|
const encodedPackets = encodedPayload.split(SEPARATOR);
|
||||||
packets.push(decodedPacket)
|
const packets = [];
|
||||||
if (decodedPacket.type === "error") {
|
for (let i = 0; i < encodedPackets.length; i++) {
|
||||||
break
|
const decodedPacket = decodePacket(encodedPackets[i], binaryType);
|
||||||
}
|
packets.push(decodedPacket);
|
||||||
|
if (decodedPacket.type === "error") {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return packets
|
}
|
||||||
}
|
return packets;
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export const protocol = 4;
|
||||||
protocol: 4,
|
export {
|
||||||
encodePacket,
|
encodePacket,
|
||||||
encodePayload,
|
encodePayload,
|
||||||
decodePacket,
|
decodePacket,
|
||||||
decodePayload
|
decodePayload,
|
||||||
}
|
Packet,
|
||||||
|
PacketType,
|
||||||
|
RawData,
|
||||||
|
BinaryType
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,10 +1,45 @@
|
|||||||
/**
|
// import { createServer } from "http"
|
||||||
* Module dependencies.
|
import { Server, AttachOptions, ServerOptions } from "./server";
|
||||||
*/
|
import transports from "./transports/index";
|
||||||
|
import * as parser from "../engine.io-parser";
|
||||||
|
|
||||||
// const http = require("http")
|
// export { Server, transports, listen, attach, parser }
|
||||||
// const Server = require("./server")
|
export { Server, transports, attach, parser };
|
||||||
import { Server } from './server'
|
export { AttachOptions, ServerOptions } from "./server";
|
||||||
|
// export { uServer } from "./userver";
|
||||||
|
export { Socket } from "./socket";
|
||||||
|
export { Transport } from "./transport";
|
||||||
|
export const protocol = parser.protocol;
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Creates an http.Server exclusively used for WS upgrades.
|
||||||
|
// *
|
||||||
|
// * @param {Number} port
|
||||||
|
// * @param {Function} callback
|
||||||
|
// * @param {Object} options
|
||||||
|
// * @return {Server} websocket.io server
|
||||||
|
// * @api public
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
// function listen(port, options: AttachOptions & ServerOptions, fn) {
|
||||||
|
// if ("function" === typeof options) {
|
||||||
|
// fn = options;
|
||||||
|
// options = {};
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const server = createServer(function(req, res) {
|
||||||
|
// res.writeHead(501);
|
||||||
|
// res.end("Not Implemented");
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // create engine server
|
||||||
|
// const engine = attach(server, options);
|
||||||
|
// engine.httpServer = server;
|
||||||
|
|
||||||
|
// server.listen(port, fn);
|
||||||
|
|
||||||
|
// return engine;
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Captures upgrade requests for a http.Server.
|
* Captures upgrade requests for a http.Server.
|
||||||
@@ -15,12 +50,8 @@ import { Server } from './server'
|
|||||||
* @api public
|
* @api public
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function attach(srv, options) {
|
function attach(server, options: AttachOptions & ServerOptions) {
|
||||||
const engine = new Server(options)
|
const engine = new Server(options);
|
||||||
engine.attach(srv, options)
|
engine.attach(server, options);
|
||||||
return engine
|
return engine;
|
||||||
}
|
|
||||||
|
|
||||||
export = {
|
|
||||||
attach
|
|
||||||
}
|
}
|
||||||
|
|||||||
485
packages/websocket/src/engine.io/parser-v3/index.ts
Normal file
485
packages/websocket/src/engine.io/parser-v3/index.ts
Normal file
@@ -0,0 +1,485 @@
|
|||||||
|
// imported from https://github.com/socketio/engine.io-parser/tree/2.2.x
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module dependencies.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var utf8 = require('./utf8');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current protocol version.
|
||||||
|
*/
|
||||||
|
export const protocol = 3;
|
||||||
|
|
||||||
|
const hasBinary = (packets) => {
|
||||||
|
for (const packet of packets) {
|
||||||
|
if (packet.data instanceof ArrayBuffer || ArrayBuffer.isView(packet.data)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Packet types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const packets = {
|
||||||
|
open: 0 // non-ws
|
||||||
|
, close: 1 // non-ws
|
||||||
|
, ping: 2
|
||||||
|
, pong: 3
|
||||||
|
, message: 4
|
||||||
|
, upgrade: 5
|
||||||
|
, noop: 6
|
||||||
|
};
|
||||||
|
|
||||||
|
var packetslist = Object.keys(packets);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Premade error packet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var err = { type: 'error', data: 'parser error' };
|
||||||
|
|
||||||
|
const EMPTY_BUFFER = Buffer.concat([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a packet.
|
||||||
|
*
|
||||||
|
* <packet type id> [ <data> ]
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* 5hello world
|
||||||
|
* 3
|
||||||
|
* 4
|
||||||
|
*
|
||||||
|
* Binary is encoded in an identical principle
|
||||||
|
*
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function encodePacket (packet, supportsBinary, utf8encode, callback) {
|
||||||
|
if (typeof supportsBinary === 'function') {
|
||||||
|
callback = supportsBinary;
|
||||||
|
supportsBinary = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof utf8encode === 'function') {
|
||||||
|
callback = utf8encode;
|
||||||
|
utf8encode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Buffer.isBuffer(packet.data)) {
|
||||||
|
return encodeBuffer(packet, supportsBinary, callback);
|
||||||
|
} else if (packet.data && (packet.data.buffer || packet.data) instanceof ArrayBuffer) {
|
||||||
|
return encodeBuffer({ type: packet.type, data: arrayBufferToBuffer(packet.data) }, supportsBinary, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sending data as a utf-8 string
|
||||||
|
var encoded = packets[packet.type];
|
||||||
|
|
||||||
|
// data fragment is optional
|
||||||
|
if (undefined !== packet.data) {
|
||||||
|
encoded += utf8encode ? utf8.encode(String(packet.data), { strict: false }) : String(packet.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback('' + encoded);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode Buffer data
|
||||||
|
*/
|
||||||
|
|
||||||
|
function encodeBuffer(packet, supportsBinary, callback) {
|
||||||
|
if (!supportsBinary) {
|
||||||
|
return encodeBase64Packet(packet, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = packet.data;
|
||||||
|
var typeBuffer = Buffer.allocUnsafe(1);
|
||||||
|
typeBuffer[0] = packets[packet.type];
|
||||||
|
return callback(Buffer.concat([typeBuffer, data]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a packet with binary data in a base64 string
|
||||||
|
*
|
||||||
|
* @param {Object} packet, has `type` and `data`
|
||||||
|
* @return {String} base64 encoded message
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function encodeBase64Packet (packet, callback){
|
||||||
|
var data = Buffer.isBuffer(packet.data) ? packet.data : arrayBufferToBuffer(packet.data);
|
||||||
|
var message = 'b' + packets[packet.type];
|
||||||
|
message += data.toString('base64');
|
||||||
|
return callback(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a packet. Data also available as an ArrayBuffer if requested.
|
||||||
|
*
|
||||||
|
* @return {Object} with `type` and `data` (if any)
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function decodePacket (data, binaryType, utf8decode) {
|
||||||
|
if (data === undefined) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
var type;
|
||||||
|
|
||||||
|
// String data
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
|
||||||
|
type = data.charAt(0);
|
||||||
|
|
||||||
|
if (type === 'b') {
|
||||||
|
return decodeBase64Packet(data.substr(1), binaryType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (utf8decode) {
|
||||||
|
data = tryDecode(data);
|
||||||
|
if (data === false) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Number(type) != type || !packetslist[type]) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.length > 1) {
|
||||||
|
return { type: packetslist[type], data: data.substring(1) };
|
||||||
|
} else {
|
||||||
|
return { type: packetslist[type] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary data
|
||||||
|
if (binaryType === 'arraybuffer') {
|
||||||
|
// wrap Buffer/ArrayBuffer data into an Uint8Array
|
||||||
|
var intArray = new Uint8Array(data);
|
||||||
|
type = intArray[0];
|
||||||
|
return { type: packetslist[type], data: intArray.buffer.slice(1) };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data instanceof ArrayBuffer) {
|
||||||
|
data = arrayBufferToBuffer(data);
|
||||||
|
}
|
||||||
|
type = data[0];
|
||||||
|
return { type: packetslist[type], data: data.slice(1) };
|
||||||
|
};
|
||||||
|
|
||||||
|
function tryDecode(data) {
|
||||||
|
try {
|
||||||
|
data = utf8.decode(data, { strict: false });
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a packet encoded in a base64 string.
|
||||||
|
*
|
||||||
|
* @param {String} base64 encoded message
|
||||||
|
* @return {Object} with `type` and `data` (if any)
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function decodeBase64Packet (msg, binaryType) {
|
||||||
|
var type = packetslist[msg.charAt(0)];
|
||||||
|
var data = Buffer.from(msg.substr(1), 'base64');
|
||||||
|
if (binaryType === 'arraybuffer') {
|
||||||
|
var abv = new Uint8Array(data.length);
|
||||||
|
for (var i = 0; i < abv.length; i++){
|
||||||
|
abv[i] = data[i];
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
data = abv.buffer;
|
||||||
|
}
|
||||||
|
return { type: type, data: data };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes multiple messages (payload).
|
||||||
|
*
|
||||||
|
* <length>:data
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* 11:hello world2:hi
|
||||||
|
*
|
||||||
|
* If any contents are binary, they will be encoded as base64 strings. Base64
|
||||||
|
* encoded strings are marked with a b before the length specifier
|
||||||
|
*
|
||||||
|
* @param {Array} packets
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function encodePayload (packets, supportsBinary, callback) {
|
||||||
|
if (typeof supportsBinary === 'function') {
|
||||||
|
callback = supportsBinary;
|
||||||
|
supportsBinary = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportsBinary && hasBinary(packets)) {
|
||||||
|
return encodePayloadAsBinary(packets, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!packets.length) {
|
||||||
|
return callback('0:');
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeOne(packet, doneCallback) {
|
||||||
|
encodePacket(packet, supportsBinary, false, function(message) {
|
||||||
|
doneCallback(null, setLengthHeader(message));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
map(packets, encodeOne, function(err, results) {
|
||||||
|
return callback(results.join(''));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function setLengthHeader(message) {
|
||||||
|
return message.length + ':' + message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Async array map using after
|
||||||
|
*/
|
||||||
|
|
||||||
|
function map(ary, each, done) {
|
||||||
|
const results = new Array(ary.length);
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < ary.length; i++) {
|
||||||
|
each(ary[i], (error, msg) => {
|
||||||
|
results[i] = msg;
|
||||||
|
if (++count === ary.length) {
|
||||||
|
done(null, results);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decodes data when a payload is maybe expected. Possible binary contents are
|
||||||
|
* decoded from their base64 representation
|
||||||
|
*
|
||||||
|
* @param {String} data, callback method
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function decodePayload (data, binaryType, callback) {
|
||||||
|
if (typeof data !== 'string') {
|
||||||
|
return decodePayloadAsBinary(data, binaryType, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof binaryType === 'function') {
|
||||||
|
callback = binaryType;
|
||||||
|
binaryType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data === '') {
|
||||||
|
// parser error - ignoring payload
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var length = '', n, msg, packet;
|
||||||
|
|
||||||
|
for (var i = 0, l = data.length; i < l; i++) {
|
||||||
|
var chr = data.charAt(i);
|
||||||
|
|
||||||
|
if (chr !== ':') {
|
||||||
|
length += chr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
if (length === '' || (length != (n = Number(length)))) {
|
||||||
|
// parser error - ignoring payload
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = data.substr(i + 1, n);
|
||||||
|
|
||||||
|
if (length != msg.length) {
|
||||||
|
// parser error - ignoring payload
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.length) {
|
||||||
|
packet = decodePacket(msg, binaryType, false);
|
||||||
|
|
||||||
|
if (err.type === packet.type && err.data === packet.data) {
|
||||||
|
// parser error in individual packet - ignoring payload
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var more = callback(packet, i + n, l);
|
||||||
|
if (false === more) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance cursor
|
||||||
|
i += n;
|
||||||
|
length = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length !== '') {
|
||||||
|
// parser error - ignoring payload
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Converts a buffer to a utf8.js encoded string
|
||||||
|
*
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function bufferToString(buffer) {
|
||||||
|
var str = '';
|
||||||
|
for (var i = 0, l = buffer.length; i < l; i++) {
|
||||||
|
str += String.fromCharCode(buffer[i]);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Converts a utf8.js encoded string to a buffer
|
||||||
|
*
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function stringToBuffer(string) {
|
||||||
|
var buf = Buffer.allocUnsafe(string.length);
|
||||||
|
for (var i = 0, l = string.length; i < l; i++) {
|
||||||
|
buf.writeUInt8(string.charCodeAt(i), i);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Converts an ArrayBuffer to a Buffer
|
||||||
|
*
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
function arrayBufferToBuffer(data) {
|
||||||
|
// data is either an ArrayBuffer or ArrayBufferView.
|
||||||
|
var length = data.byteLength || data.length;
|
||||||
|
var offset = data.byteOffset || 0;
|
||||||
|
|
||||||
|
return Buffer.from(data.buffer || data, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes multiple messages (payload) as binary.
|
||||||
|
*
|
||||||
|
* <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
|
||||||
|
* 255><data>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
|
||||||
|
*
|
||||||
|
* @param {Array} packets
|
||||||
|
* @return {Buffer} encoded payload
|
||||||
|
* @api private
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function encodePayloadAsBinary (packets, callback) {
|
||||||
|
if (!packets.length) {
|
||||||
|
return callback(EMPTY_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
map(packets, encodeOneBinaryPacket, function(err, results) {
|
||||||
|
return callback(Buffer.concat(results));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function encodeOneBinaryPacket(p, doneCallback) {
|
||||||
|
|
||||||
|
function onBinaryPacketEncode(packet) {
|
||||||
|
|
||||||
|
var encodingLength = '' + packet.length;
|
||||||
|
var sizeBuffer;
|
||||||
|
|
||||||
|
if (typeof packet === 'string') {
|
||||||
|
sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
|
||||||
|
sizeBuffer[0] = 0; // is a string (not true binary = 0)
|
||||||
|
for (var i = 0; i < encodingLength.length; i++) {
|
||||||
|
sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
|
||||||
|
}
|
||||||
|
sizeBuffer[sizeBuffer.length - 1] = 255;
|
||||||
|
return doneCallback(null, Buffer.concat([sizeBuffer, stringToBuffer(packet)]));
|
||||||
|
}
|
||||||
|
|
||||||
|
sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2);
|
||||||
|
sizeBuffer[0] = 1; // is binary (true binary = 1)
|
||||||
|
for (var i = 0; i < encodingLength.length; i++) {
|
||||||
|
sizeBuffer[i + 1] = parseInt(encodingLength[i], 10);
|
||||||
|
}
|
||||||
|
sizeBuffer[sizeBuffer.length - 1] = 255;
|
||||||
|
|
||||||
|
doneCallback(null, Buffer.concat([sizeBuffer, packet]));
|
||||||
|
}
|
||||||
|
|
||||||
|
encodePacket(p, true, true, onBinaryPacketEncode);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decodes data when a payload is maybe expected. Strings are decoded by
|
||||||
|
* interpreting each byte as a key code for entries marked to start with 0. See
|
||||||
|
* description of encodePayloadAsBinary
|
||||||
|
|
||||||
|
* @param {Buffer} data, callback method
|
||||||
|
* @api public
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function decodePayloadAsBinary (data, binaryType, callback) {
|
||||||
|
if (typeof binaryType === 'function') {
|
||||||
|
callback = binaryType;
|
||||||
|
binaryType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bufferTail = data;
|
||||||
|
var buffers = [];
|
||||||
|
var i;
|
||||||
|
|
||||||
|
while (bufferTail.length > 0) {
|
||||||
|
var strLen = '';
|
||||||
|
var isString = bufferTail[0] === 0;
|
||||||
|
for (i = 1; ; i++) {
|
||||||
|
if (bufferTail[i] === 255) break;
|
||||||
|
// 310 = char length of Number.MAX_VALUE
|
||||||
|
if (strLen.length > 310) {
|
||||||
|
return callback(err, 0, 1);
|
||||||
|
}
|
||||||
|
strLen += '' + bufferTail[i];
|
||||||
|
}
|
||||||
|
bufferTail = bufferTail.slice(strLen.length + 1);
|
||||||
|
|
||||||
|
var msgLength = parseInt(strLen, 10);
|
||||||
|
|
||||||
|
var msg = bufferTail.slice(1, msgLength + 1);
|
||||||
|
if (isString) msg = bufferToString(msg);
|
||||||
|
buffers.push(msg);
|
||||||
|
bufferTail = bufferTail.slice(msgLength + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var total = buffers.length;
|
||||||
|
for (i = 0; i < total; i++) {
|
||||||
|
var buffer = buffers[i];
|
||||||
|
callback(decodePacket(buffer, binaryType, true), i, total);
|
||||||
|
}
|
||||||
|
};
|
||||||
210
packages/websocket/src/engine.io/parser-v3/utf8.ts
Normal file
210
packages/websocket/src/engine.io/parser-v3/utf8.ts
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
/*! https://mths.be/utf8js v2.1.2 by @mathias */
|
||||||
|
|
||||||
|
var stringFromCharCode = String.fromCharCode;
|
||||||
|
|
||||||
|
// Taken from https://mths.be/punycode
|
||||||
|
function ucs2decode(string) {
|
||||||
|
var output = [];
|
||||||
|
var counter = 0;
|
||||||
|
var length = string.length;
|
||||||
|
var value;
|
||||||
|
var extra;
|
||||||
|
while (counter < length) {
|
||||||
|
value = string.charCodeAt(counter++);
|
||||||
|
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
|
||||||
|
// high surrogate, and there is a next character
|
||||||
|
extra = string.charCodeAt(counter++);
|
||||||
|
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
|
||||||
|
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
|
||||||
|
} else {
|
||||||
|
// unmatched surrogate; only append this code unit, in case the next
|
||||||
|
// code unit is the high surrogate of a surrogate pair
|
||||||
|
output.push(value);
|
||||||
|
counter--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Taken from https://mths.be/punycode
|
||||||
|
function ucs2encode(array) {
|
||||||
|
var length = array.length;
|
||||||
|
var index = -1;
|
||||||
|
var value;
|
||||||
|
var output = '';
|
||||||
|
while (++index < length) {
|
||||||
|
value = array[index];
|
||||||
|
if (value > 0xFFFF) {
|
||||||
|
value -= 0x10000;
|
||||||
|
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
|
||||||
|
value = 0xDC00 | value & 0x3FF;
|
||||||
|
}
|
||||||
|
output += stringFromCharCode(value);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkScalarValue(codePoint, strict) {
|
||||||
|
if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
|
||||||
|
if (strict) {
|
||||||
|
throw Error(
|
||||||
|
'Lone surrogate U+' + codePoint.toString(16).toUpperCase() +
|
||||||
|
' is not a scalar value'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
function createByte(codePoint, shift) {
|
||||||
|
return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeCodePoint(codePoint, strict) {
|
||||||
|
if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
|
||||||
|
return stringFromCharCode(codePoint);
|
||||||
|
}
|
||||||
|
var symbol = '';
|
||||||
|
if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
|
||||||
|
symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
|
||||||
|
}
|
||||||
|
else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
|
||||||
|
if (!checkScalarValue(codePoint, strict)) {
|
||||||
|
codePoint = 0xFFFD;
|
||||||
|
}
|
||||||
|
symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
|
||||||
|
symbol += createByte(codePoint, 6);
|
||||||
|
}
|
||||||
|
else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
|
||||||
|
symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
|
||||||
|
symbol += createByte(codePoint, 12);
|
||||||
|
symbol += createByte(codePoint, 6);
|
||||||
|
}
|
||||||
|
symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
function utf8encode(string, opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
var strict = false !== opts.strict;
|
||||||
|
|
||||||
|
var codePoints = ucs2decode(string);
|
||||||
|
var length = codePoints.length;
|
||||||
|
var index = -1;
|
||||||
|
var codePoint;
|
||||||
|
var byteString = '';
|
||||||
|
while (++index < length) {
|
||||||
|
codePoint = codePoints[index];
|
||||||
|
byteString += encodeCodePoint(codePoint, strict);
|
||||||
|
}
|
||||||
|
return byteString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
function readContinuationByte() {
|
||||||
|
if (byteIndex >= byteCount) {
|
||||||
|
throw Error('Invalid byte index');
|
||||||
|
}
|
||||||
|
|
||||||
|
var continuationByte = byteArray[byteIndex] & 0xFF;
|
||||||
|
byteIndex++;
|
||||||
|
|
||||||
|
if ((continuationByte & 0xC0) == 0x80) {
|
||||||
|
return continuationByte & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we end up here, it’s not a continuation byte
|
||||||
|
throw Error('Invalid continuation byte');
|
||||||
|
}
|
||||||
|
|
||||||
|
function decodeSymbol(strict) {
|
||||||
|
var byte1;
|
||||||
|
var byte2;
|
||||||
|
var byte3;
|
||||||
|
var byte4;
|
||||||
|
var codePoint;
|
||||||
|
|
||||||
|
if (byteIndex > byteCount) {
|
||||||
|
throw Error('Invalid byte index');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (byteIndex == byteCount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read first byte
|
||||||
|
byte1 = byteArray[byteIndex] & 0xFF;
|
||||||
|
byteIndex++;
|
||||||
|
|
||||||
|
// 1-byte sequence (no continuation bytes)
|
||||||
|
if ((byte1 & 0x80) == 0) {
|
||||||
|
return byte1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2-byte sequence
|
||||||
|
if ((byte1 & 0xE0) == 0xC0) {
|
||||||
|
byte2 = readContinuationByte();
|
||||||
|
codePoint = ((byte1 & 0x1F) << 6) | byte2;
|
||||||
|
if (codePoint >= 0x80) {
|
||||||
|
return codePoint;
|
||||||
|
} else {
|
||||||
|
throw Error('Invalid continuation byte');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3-byte sequence (may include unpaired surrogates)
|
||||||
|
if ((byte1 & 0xF0) == 0xE0) {
|
||||||
|
byte2 = readContinuationByte();
|
||||||
|
byte3 = readContinuationByte();
|
||||||
|
codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
|
||||||
|
if (codePoint >= 0x0800) {
|
||||||
|
return checkScalarValue(codePoint, strict) ? codePoint : 0xFFFD;
|
||||||
|
} else {
|
||||||
|
throw Error('Invalid continuation byte');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4-byte sequence
|
||||||
|
if ((byte1 & 0xF8) == 0xF0) {
|
||||||
|
byte2 = readContinuationByte();
|
||||||
|
byte3 = readContinuationByte();
|
||||||
|
byte4 = readContinuationByte();
|
||||||
|
codePoint = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0C) |
|
||||||
|
(byte3 << 0x06) | byte4;
|
||||||
|
if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
|
||||||
|
return codePoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Error('Invalid UTF-8 detected');
|
||||||
|
}
|
||||||
|
|
||||||
|
var byteArray;
|
||||||
|
var byteCount;
|
||||||
|
var byteIndex;
|
||||||
|
function utf8decode(byteString, opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
var strict = false !== opts.strict;
|
||||||
|
|
||||||
|
byteArray = ucs2decode(byteString);
|
||||||
|
byteCount = byteArray.length;
|
||||||
|
byteIndex = 0;
|
||||||
|
var codePoints = [];
|
||||||
|
var tmp;
|
||||||
|
while ((tmp = decodeSymbol(strict)) !== false) {
|
||||||
|
codePoints.push(tmp);
|
||||||
|
}
|
||||||
|
return ucs2encode(codePoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
version: '2.1.2',
|
||||||
|
encode: utf8encode,
|
||||||
|
decode: utf8decode
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user