release: v0.23.0

1. add item api
2. support rollup source map
3. fix database drvice error
4. support loliserver
5. support 1.19 bukkit chat
6. config add migrate options
7.

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
2022-06-20 00:48:00 +08:00
parent b5fac23c5c
commit 15d1f8392b
26 changed files with 2752 additions and 188 deletions

View File

@ -5,7 +5,7 @@ import * as base64 from 'base64-js'
const Arrays = Java.type('java.util.Arrays')
const Level = Java.type('java.util.logging.Level')
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 {
ALL,
@ -18,12 +18,114 @@ enum LogLevel {
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)
} else if (global.debug) {
console.debug('readSourceMap can\'t found', fileName, 'source map file', sourceMappingURL)
}
}
if (sourceContent) {
sourceMaps[fileName] = new SourceMapBuilder(JSON.parse(sourceContent))
sourceFileMaps[fileName] = Paths.get(fileName, '..', sourceMaps[fileName].sources[0]).toFile().getCanonicalPath()
}
}
}
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} => §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 } = 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 {
Console: any
memory: any
private static sourceMaps: { [key: string]: SourceMapBuilder } = {}
private static sourceFileMaps: { [key: string]: string } = {}
private _name: string = ''
private _level: LogLevel = LogLevel.INFO
@ -92,91 +194,8 @@ export class MiaoScriptConsole implements Console {
ex(ex: Error) {
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[] {
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 } = 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
return jsconsole.getStackTrace(ex, color)
}
assert(value: any, message?: string, ...optionalParams: any[]): void {
throw new Error("Method not implemented.")

View File

@ -11,10 +11,21 @@ export namespace constants {
}
export namespace Reflect {
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 = {
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 {

View File

@ -6,6 +6,10 @@ export namespace database {
* 数据库配置
*/
export interface DataBaseConfig {
/**
* 数据库类型
*/
type: 'h2' | 'mysql' | 'mongodb' | 'sqlite' | 'postgres' | 'redis'
/**
* 数据库连接串
*/

View File

@ -4,11 +4,13 @@ export * from './web'
export * from './amqp'
export * from './chat'
export * from './task'
export * from './item'
export * from './event'
export * from './proxy'
export * from './plugin'
export * from './server'
export * from './console'
export { jsconsole as console } from './console'
export * from './channel'
export * from './command'
export * from './database'

20
packages/api/src/item.ts Normal file
View 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
}
}

View File

@ -149,7 +149,15 @@ export namespace plugin {
/**
* 插件名称 不填默认为类名
*/
name?: string
name: string
/**
* 插件中文名称
*/
cname?: string
/**
* 插件等级 付费插件自动注入
*/
level?: number
/**
* 前缀
*/