feat: add loadMavenDepend & optimize database
Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
parent
579d89ae89
commit
8d0484eefb
@ -1,38 +1,9 @@
|
|||||||
import { interfaces, Container } from "inversify"
|
import { interfaces, Container } from "inversify"
|
||||||
|
import { _proxyGetter } from "./utils"
|
||||||
|
|
||||||
let _container: Container
|
let _container: Container
|
||||||
|
|
||||||
const ContainerInstance = Symbol.for("@ccms/ioc:Container")
|
const ContainerInstance = Symbol.for("@ccms/ioc:Container")
|
||||||
const INJECTION = Symbol.for("INJECTION")
|
|
||||||
|
|
||||||
function _proxyGetter(
|
|
||||||
proto: any,
|
|
||||||
key: string,
|
|
||||||
resolve: () => any,
|
|
||||||
doCache: boolean
|
|
||||||
) {
|
|
||||||
function getter(this: object) {
|
|
||||||
if (doCache && !Reflect.hasMetadata(INJECTION, this, key)) {
|
|
||||||
Reflect.defineMetadata(INJECTION, resolve(), this, key)
|
|
||||||
}
|
|
||||||
if (Reflect.hasMetadata(INJECTION, this, key)) {
|
|
||||||
return Reflect.getMetadata(INJECTION, this, key)
|
|
||||||
} else {
|
|
||||||
return resolve()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setter(this: object, newVal: any) {
|
|
||||||
Reflect.defineMetadata(INJECTION, newVal, this, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(proto, key, {
|
|
||||||
configurable: true,
|
|
||||||
enumerable: true,
|
|
||||||
get: getter,
|
|
||||||
set: setter
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function initContainer(container: Container) {
|
function initContainer(container: Container) {
|
||||||
Reflect.defineMetadata(ContainerInstance, container, Reflect)
|
Reflect.defineMetadata(ContainerInstance, container, Reflect)
|
||||||
|
@ -5,6 +5,7 @@ import { initContainer, getContainer } from './decorators'
|
|||||||
import { interfaces, Container, inject, named } from 'inversify'
|
import { interfaces, Container, inject, named } from 'inversify'
|
||||||
import { fluentProvide } from 'inversify-binding-decorators'
|
import { fluentProvide } from 'inversify-binding-decorators'
|
||||||
import { ioc } from "./constants"
|
import { ioc } from "./constants"
|
||||||
|
import { _proxyGetter } from "./utils"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册一个命名对象
|
* 注册一个命名对象
|
||||||
@ -49,9 +50,11 @@ export const JavaClass = (className: string) => {
|
|||||||
*/
|
*/
|
||||||
export const JSClass = (className: string) => {
|
export const JSClass = (className: string) => {
|
||||||
return function (target: object, propertyKey: string, index?: number) {
|
return function (target: object, propertyKey: string, index?: number) {
|
||||||
try { target[propertyKey] = Java.type(className); return } catch (error: any) { }
|
_proxyGetter(target, propertyKey, () => {
|
||||||
try { target[propertyKey] = base.getClass(className).static; return } catch (error: any) { }
|
try { return Java.type(className) } catch (error: any) { }
|
||||||
|
try { return base.getClass(className).static } catch (error: any) { }
|
||||||
console.warn('JSClass', className, 'Inject target', target.constructor.name, 'propertyKey', propertyKey, 'failed!')
|
console.warn('JSClass', className, 'Inject target', target.constructor.name, 'propertyKey', propertyKey, 'failed!')
|
||||||
|
}, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +91,59 @@ export const Resource = (resourceName?: string | any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DocumentBuilderFactory = Java.type('javax.xml.parsers.DocumentBuilderFactory')
|
||||||
|
|
||||||
|
export const MavenDepend = (groupId: string, artifactId: string, version: string, recursion = false) => {
|
||||||
|
return function (target: any) {
|
||||||
|
loadMavenDepend(groupId, artifactId, version, recursion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadedMavenDepend = new Set<string>()
|
||||||
|
|
||||||
|
export function loadMavenDepend(groupId: string, artifactId: string, version: string, recursion = false) {
|
||||||
|
try {
|
||||||
|
const key = `${groupId}:${artifactId}:${version}`
|
||||||
|
if (loadedMavenDepend.has(key)) { return }
|
||||||
|
console.info('loading maven dependency', key)
|
||||||
|
let [pom, _] = base.loadMavenDepend(groupId, artifactId, version)
|
||||||
|
loadedMavenDepend.add(key)
|
||||||
|
if (recursion) {
|
||||||
|
let doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(pom)
|
||||||
|
let dependencies = doc.getElementsByTagName("dependency")
|
||||||
|
let size = dependencies.length
|
||||||
|
if (!size) { return }
|
||||||
|
console.info(key, 'found', size, 'dependencies loading...')
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
const dependency = dependencies.item(i)
|
||||||
|
const gav = dependency.getChildNodes()
|
||||||
|
const length = gav.length
|
||||||
|
const dependencyVersion = { groupId: '', artifactId: '', version: '' }
|
||||||
|
for (let j = 0; j < length; j++) {
|
||||||
|
const prop = gav.item(j)
|
||||||
|
switch (prop.getNodeName()) {
|
||||||
|
case "groupId":
|
||||||
|
dependencyVersion.groupId = prop.getTextContent()
|
||||||
|
break
|
||||||
|
case "artifactId":
|
||||||
|
dependencyVersion.artifactId = prop.getTextContent()
|
||||||
|
break
|
||||||
|
case "version":
|
||||||
|
dependencyVersion.version = prop.getTextContent()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadMavenDepend(dependencyVersion.groupId, dependencyVersion.artifactId, dependencyVersion.version, recursion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.warn('attachMavenDepend failed. Error: ' + error)
|
||||||
|
if (global.debug) {
|
||||||
|
console.ex(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const reduceMetadata = (ctx: interfaces.Context): any => {
|
export const reduceMetadata = (ctx: interfaces.Context): any => {
|
||||||
return ctx.currentRequest.target.metadata.reduce((result, entry, index) => {
|
return ctx.currentRequest.target.metadata.reduce((result, entry, index) => {
|
||||||
result[entry.key] = entry.value
|
result[entry.key] = entry.value
|
||||||
|
30
packages/container/src/utils.ts
Normal file
30
packages/container/src/utils.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
const INJECTION = Symbol.for("INJECTION")
|
||||||
|
|
||||||
|
export function _proxyGetter(
|
||||||
|
proto: any,
|
||||||
|
key: string,
|
||||||
|
resolve: () => any,
|
||||||
|
doCache: boolean
|
||||||
|
) {
|
||||||
|
function getter(this: object) {
|
||||||
|
if (doCache && !Reflect.hasMetadata(INJECTION, this, key)) {
|
||||||
|
Reflect.defineMetadata(INJECTION, resolve(), this, key)
|
||||||
|
}
|
||||||
|
if (Reflect.hasMetadata(INJECTION, this, key)) {
|
||||||
|
return Reflect.getMetadata(INJECTION, this, key)
|
||||||
|
} else {
|
||||||
|
return resolve()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setter(this: object, newVal: any) {
|
||||||
|
Reflect.defineMetadata(INJECTION, newVal, this, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(proto, key, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: getter,
|
||||||
|
set: setter
|
||||||
|
})
|
||||||
|
}
|
@ -3,7 +3,11 @@ console.i18n("ms.core.ioc.initialize", { scope: global.scope })
|
|||||||
import { plugin, server, task, constants } from '@ccms/api'
|
import { plugin, server, task, constants } 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 http from '@ccms/common/dist/http'
|
import http from '@ccms/common/dist/http'
|
||||||
|
import * as fs from '@ccms/common/dist/fs'
|
||||||
|
|
||||||
|
const UUID = Java.type('java.util.UUID')
|
||||||
|
|
||||||
@provideSingleton(MiaoScriptCore)
|
@provideSingleton(MiaoScriptCore)
|
||||||
class MiaoScriptCore {
|
class MiaoScriptCore {
|
||||||
@ -106,9 +110,24 @@ function loadCoreScript(name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadMiaoScriptConfig() {
|
||||||
|
let configFile = fs.concat(root, 'config.yml')
|
||||||
|
if (!fs.exists(configFile)) {
|
||||||
|
global.ScriptEngineConfig = base.save(configFile, yaml.dump({
|
||||||
|
uuid: UUID.randomUUID().toString(),
|
||||||
|
channel: 'latest',
|
||||||
|
slow_execute: 50
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
global.ScriptEngineConfig = yaml.load(base.read(configFile))
|
||||||
|
}
|
||||||
|
global.ScriptEngineChannel = global.ScriptEngineConfig.channel || 'latest'
|
||||||
|
global.ScriptSlowExecuteTime = global.ScriptEngineConfig.slow_execute || 50
|
||||||
|
}
|
||||||
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
process.emit('core.before.initialize')
|
process.emit('core.before.initialize')
|
||||||
global.ScriptSlowExecuteTime = 50
|
loadMiaoScriptConfig()
|
||||||
global.ScriptEngineVersion = require('../package.json').version
|
global.ScriptEngineVersion = require('../package.json').version
|
||||||
global.setGlobal('loadCoreScript', loadCoreScript)
|
global.setGlobal('loadCoreScript', loadCoreScript)
|
||||||
loadCoreScript('initialize')
|
loadCoreScript('initialize')
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
|
import { JSClass } from '@ccms/container'
|
||||||
import { Model } from './model'
|
import { Model } from './model'
|
||||||
|
|
||||||
const HikariDataSource = Java.type('com.zaxxer.hikari.HikariDataSource')
|
|
||||||
const HikariConfig = Java.type('com.zaxxer.hikari.HikariConfig')
|
|
||||||
const JdbcTemplate = Java.type('org.springframework.jdbc.core.JdbcTemplate')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库配置
|
* 数据库配置
|
||||||
*/
|
*/
|
||||||
@ -33,6 +30,13 @@ export class DataBase {
|
|||||||
private dataSource: javax.sql.DataSource
|
private dataSource: javax.sql.DataSource
|
||||||
private jdbcTemplate: org.springframework.jdbc.core.JdbcTemplate
|
private jdbcTemplate: org.springframework.jdbc.core.JdbcTemplate
|
||||||
|
|
||||||
|
@JSClass('com.zaxxer.hikari.HikariDataSource')
|
||||||
|
private HikariDataSource: any
|
||||||
|
@JSClass('com.zaxxer.hikari.HikariConfig')
|
||||||
|
private HikariConfig: any
|
||||||
|
@JSClass('org.springframework.jdbc.core.JdbcTemplate')
|
||||||
|
private JdbcTemplate: typeof org.springframework.jdbc.core.JdbcTemplate
|
||||||
|
|
||||||
constructor(dbConfig: DataBaseConfig) {
|
constructor(dbConfig: DataBaseConfig) {
|
||||||
if (!dbConfig.url) { throw new Error('DataBase url can\'t be null!') }
|
if (!dbConfig.url) { throw new Error('DataBase url can\'t be null!') }
|
||||||
this.createDataSource(dbConfig)
|
this.createDataSource(dbConfig)
|
||||||
@ -41,24 +45,25 @@ export class DataBase {
|
|||||||
|
|
||||||
private createDataSource(dbConfig: DataBaseConfig) {
|
private createDataSource(dbConfig: DataBaseConfig) {
|
||||||
if (typeof dbConfig.url === "string") {
|
if (typeof dbConfig.url === "string") {
|
||||||
if (!dbConfig.username || !dbConfig.password) {
|
let config = new this.HikariConfig()
|
||||||
throw new Error('DataBase username or password can\'t be null!')
|
|
||||||
}
|
|
||||||
let config = new HikariConfig()
|
|
||||||
if (dbConfig.driverClassName) {
|
if (dbConfig.driverClassName) {
|
||||||
config.setDriverClassName(dbConfig.driverClassName)
|
config.setDriverClassName(dbConfig.driverClassName)
|
||||||
}
|
}
|
||||||
|
if (dbConfig.username) {
|
||||||
config.setUsername(dbConfig.username)
|
config.setUsername(dbConfig.username)
|
||||||
|
}
|
||||||
|
if (dbConfig.password) {
|
||||||
config.setPassword(dbConfig.password)
|
config.setPassword(dbConfig.password)
|
||||||
|
}
|
||||||
config.setJdbcUrl(dbConfig.url)
|
config.setJdbcUrl(dbConfig.url)
|
||||||
this.dataSource = new HikariDataSource(config)
|
this.dataSource = new this.HikariDataSource(config)
|
||||||
} else {
|
} else {
|
||||||
this.dataSource = dbConfig.url
|
this.dataSource = dbConfig.url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initialize() {
|
private initialize() {
|
||||||
this.jdbcTemplate = new JdbcTemplate(this.dataSource)
|
this.jdbcTemplate = new this.JdbcTemplate(this.dataSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,5 +2,11 @@
|
|||||||
/// <reference types="@javatypes/jdk" />
|
/// <reference types="@javatypes/jdk" />
|
||||||
/// <reference types="@javatypes/spring-jdbc" />
|
/// <reference types="@javatypes/spring-jdbc" />
|
||||||
|
|
||||||
|
import { loadMavenDepend } from '@ccms/container'
|
||||||
|
|
||||||
|
loadMavenDepend('com.h2database', 'h2', '2.1.212')
|
||||||
|
loadMavenDepend("com.zaxxer", "HikariCP", "4.0.3")
|
||||||
|
loadMavenDepend("org.springframework", "spring-jdbc", "5.3.19", true)
|
||||||
|
|
||||||
export * from './database'
|
export * from './database'
|
||||||
export * from './manager'
|
export * from './manager'
|
@ -1,25 +1,18 @@
|
|||||||
import { plugin, database } from '@ccms/api'
|
import { database } from '@ccms/api'
|
||||||
import { provideSingleton, inject, postConstruct } from '@ccms/container'
|
import { provideSingleton } from '@ccms/container'
|
||||||
import { DataBase, DataBaseConfig } from './database'
|
import { DataBase, DataBaseConfig } from './database'
|
||||||
|
|
||||||
@provideSingleton(database.DataBaseManager)
|
@provideSingleton(database.DataBaseManager)
|
||||||
export class DataBaseManager {
|
export class DataBaseManager {
|
||||||
@inject(plugin.PluginInstance)
|
|
||||||
private instance: any
|
|
||||||
|
|
||||||
private beanFactory: any
|
|
||||||
private mainDatabase: DataBase
|
private mainDatabase: DataBase
|
||||||
private databases: { [key: string]: DataBase } = {}
|
private databases = new Map<string, DataBase>()
|
||||||
|
|
||||||
@postConstruct()
|
/**
|
||||||
initialize() {
|
* 设置主数据库
|
||||||
try {
|
* @param mainDatabase 主数据库
|
||||||
this.beanFactory = this.instance.getAutowireCapableBeanFactory()
|
*/
|
||||||
let mainDatasource = this.beanFactory.getBean(Packages.javax.sql.DataSource.class)
|
setMainDatabase(mainDatabase: DataBase) {
|
||||||
this.mainDatabase = new DataBase({ url: mainDatasource })
|
this.mainDatabase = mainDatabase
|
||||||
} catch (error: any) {
|
|
||||||
console.ex(error)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,16 +31,19 @@ export class DataBaseManager {
|
|||||||
*/
|
*/
|
||||||
createDatabase(name: string, config: DataBaseConfig) {
|
createDatabase(name: string, config: DataBaseConfig) {
|
||||||
Java.synchronized(() => {
|
Java.synchronized(() => {
|
||||||
if (this.databases[name]) return this.databases[name]
|
if (!this.databases.has(name)) {
|
||||||
return this.databases[name] = new DataBase(config)
|
this.databases.set(name, new DataBase(config))
|
||||||
|
}
|
||||||
|
return this.databases.get(name)
|
||||||
}, this.databases)()
|
}, this.databases)()
|
||||||
}
|
}
|
||||||
|
|
||||||
getDatabase(name: string) {
|
getDatabase(name: string) {
|
||||||
return this.databases[name]
|
return this.databases.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
disable() {
|
disable() {
|
||||||
Object.values(this.databases).forEach((ds) => ds?.close())
|
this.databases.forEach((db) => db.close())
|
||||||
|
this.databases.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,18 @@ declare global {
|
|||||||
logger: any
|
logger: any
|
||||||
debug: boolean
|
debug: boolean
|
||||||
level: string
|
level: string
|
||||||
|
/**
|
||||||
|
* 引擎配置
|
||||||
|
*/
|
||||||
|
ScriptEngineConfig: any
|
||||||
|
/**
|
||||||
|
* 引擎版本
|
||||||
|
*/
|
||||||
ScriptEngineVersion: string
|
ScriptEngineVersion: string
|
||||||
|
/**
|
||||||
|
* 引擎渠道
|
||||||
|
*/
|
||||||
|
ScriptEngineChannel: string
|
||||||
ScriptSlowExecuteTime: number
|
ScriptSlowExecuteTime: number
|
||||||
ScriptEngineStartTime: number
|
ScriptEngineStartTime: number
|
||||||
setGlobal: (key: string, value: any, config?: PropertyDescriptor & ThisType<any>) => void
|
setGlobal: (key: string, value: any, config?: PropertyDescriptor & ThisType<any>) => void
|
||||||
@ -71,6 +82,7 @@ declare global {
|
|||||||
getProxyClass(): any
|
getProxyClass(): any
|
||||||
getJavaScriptTaskClass(): any
|
getJavaScriptTaskClass(): any
|
||||||
getInstance(): any
|
getInstance(): any
|
||||||
|
loadMavenDepend(groupId: string, artifactId: string, version: string): [any, any]
|
||||||
read(path: string): string
|
read(path: string): string
|
||||||
save(path: string, content: string): void
|
save(path: string, content: string): void
|
||||||
delete(path: string): void
|
delete(path: string): void
|
||||||
|
@ -56,7 +56,7 @@ export class PluginCommandManager {
|
|||||||
let cmdKey = 'cmd' + subcommand
|
let cmdKey = 'cmd' + subcommand
|
||||||
if (!cmdSubCache.includes(subcommand)) {
|
if (!cmdSubCache.includes(subcommand)) {
|
||||||
if (!pluginInstance[cmd.executor].apply(pluginInstance, [sender, command, args])) {
|
if (!pluginInstance[cmd.executor].apply(pluginInstance, [sender, command, args])) {
|
||||||
subcommand && pluginInstance.logger.sender(sender, '§4未知的子命令: §c' + subcommand)
|
subcommand && pluginInstance.logger.sender(sender, `§4未知的命令: §b/${command} §c${subcommand}`)
|
||||||
pluginInstance.logger.sender(
|
pluginInstance.logger.sender(
|
||||||
sender,
|
sender,
|
||||||
pluginInstance['cmdhelp'] ?
|
pluginInstance['cmdhelp'] ?
|
||||||
|
@ -17,3 +17,5 @@ export {
|
|||||||
config as Config,
|
config as Config,
|
||||||
playerdata as PlayerData
|
playerdata as PlayerData
|
||||||
} from './decorators'
|
} from './decorators'
|
||||||
|
|
||||||
|
import '@ccms/database'
|
||||||
|
Loading…
Reference in New Issue
Block a user