diff --git a/packages/database/package.json b/packages/database/package.json
index a0e707c4..718fbe1c 100644
--- a/packages/database/package.json
+++ b/packages/database/package.json
@@ -1,6 +1,6 @@
{
"name": "@ccms/database",
- "version": "0.6.7",
+ "version": "0.7.0",
"description": "MiaoScript database package",
"keywords": [
"miaoscript",
diff --git a/packages/database/src/constants.ts b/packages/database/src/constants.ts
new file mode 100644
index 00000000..a6423b97
--- /dev/null
+++ b/packages/database/src/constants.ts
@@ -0,0 +1,3 @@
+export const METADATA_KEY = {
+
+}
\ No newline at end of file
diff --git a/packages/database/src/database.ts b/packages/database/src/database.ts
index 48032d51..08950279 100644
--- a/packages/database/src/database.ts
+++ b/packages/database/src/database.ts
@@ -1,9 +1,33 @@
///
+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')
+/**
+ * 数据库配置
+ */
+export interface DataBaseConfig {
+ /**
+ * 数据库连接串
+ */
+ url: string | javax.sql.DataSource
+ /**
+ * 数据库驱动
+ */
+ driverClassName?: string
+ /**
+ * 用户名
+ */
+ username?: string
+ /**
+ * 密码
+ */
+ password?: string
+}
+
/**
* 数据库封装类
*/
@@ -11,24 +35,27 @@ export class DataBase {
private dataSource: javax.sql.DataSource
private jdbcTemplate: org.springframework.jdbc.core.JdbcTemplate
- constructor(url: string | javax.sql.DataSource, username?: string, password?: string) {
- if (!url) { throw new Error('DataBase url can\'t be null!') }
- this.createDataSource(url, username, password)
+ constructor(dbConfig: DataBaseConfig) {
+ if (!dbConfig.url) { throw new Error('DataBase url can\'t be null!') }
+ this.createDataSource(dbConfig)
this.initialize()
}
- private createDataSource(url: string | javax.sql.DataSource, username?: string, password?: string) {
- if (typeof url === "string") {
- if (!username || !password) {
+ private createDataSource(dbConfig: DataBaseConfig) {
+ if (typeof dbConfig.url === "string") {
+ if (!dbConfig.username || !dbConfig.password) {
throw new Error('DataBase username or password can\'t be null!')
}
let config = new HikariConfig()
- config.setUsername(username)
- config.setPassword(password)
- config.setJdbcUrl(url)
+ if (dbConfig.driverClassName) {
+ config.setDriverClassName(dbConfig.driverClassName)
+ }
+ config.setUsername(dbConfig.username)
+ config.setPassword(dbConfig.password)
+ config.setJdbcUrl(dbConfig.url)
this.dataSource = new HikariDataSource(config)
} else {
- this.dataSource = url
+ this.dataSource = dbConfig.url
}
}
@@ -41,7 +68,21 @@ export class DataBase {
* @param sql SQL语句
*/
query(sql: string, ...args: any[]): Array {
- return this.jdbcTemplate.queryForList(sql, args)
+ let startTime = Date.now()
+ let result = Java.from(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))
+ return result
+ }
+
+ /**
+ * 执行SQL更新
+ * @param sql SQL语句
+ */
+ update(sql: string, ...args: any[]): number {
+ let startTime = Date.now()
+ 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))
+ return result
}
close() {
diff --git a/packages/database/src/decorators.ts b/packages/database/src/decorators.ts
new file mode 100644
index 00000000..34d518a9
--- /dev/null
+++ b/packages/database/src/decorators.ts
@@ -0,0 +1,7 @@
+import 'reflect-metadata'
+
+export function id() {
+ return (target: Object, propertyKey: string | symbol) => void {
+
+ }
+}
\ No newline at end of file
diff --git a/packages/database/src/manager.ts b/packages/database/src/manager.ts
index 84cfb07c..dad42984 100644
--- a/packages/database/src/manager.ts
+++ b/packages/database/src/manager.ts
@@ -1,11 +1,9 @@
import { plugin, database } from '@ccms/api'
-import { provideSingleton, inject, postConstruct, Container, ContainerInstance } from '@ccms/container'
-import { DataBase } from './database'
+import { provideSingleton, inject, postConstruct } from '@ccms/container'
+import { DataBase, DataBaseConfig } from './database'
@provideSingleton(database.DataBaseManager)
export class DataBaseManager {
- @inject(ContainerInstance)
- private container: Container
@inject(plugin.PluginInstance)
private instance: any
@@ -18,20 +16,30 @@ export class DataBaseManager {
try {
this.beanFactory = this.instance.getAutowireCapableBeanFactory()
let mainDatasource = this.beanFactory.getBean(Packages.javax.sql.DataSource.class)
- this.mainDatabase = new DataBase(mainDatasource)
+ this.mainDatabase = new DataBase({ url: mainDatasource })
} catch (error) {
console.ex(error)
}
}
+ /**
+ * 获得主数据库
+ * Get MainDatabase
+ */
getMainDatabase() {
return this.mainDatabase
}
- createDatabase(name: string, url: string, username: string, password: string) {
+ /**
+ * 创建数据库
+ * Create A Database Instance
+ * @param name 数据库名称 用于代码 database Name use at code
+ * @param config 数据库配置
+ */
+ createDatabase(name: string, config: DataBaseConfig) {
Java.synchronized(() => {
if (this.databases[name]) return this.databases[name]
- return this.databases[name] = new DataBase(url, username, password)
+ return this.databases[name] = new DataBase(config)
}, this.databases)()
}
diff --git a/packages/database/src/model.ts b/packages/database/src/model.ts
new file mode 100644
index 00000000..e659d13c
--- /dev/null
+++ b/packages/database/src/model.ts
@@ -0,0 +1,11 @@
+import { DataBase } from "./database"
+
+export class Model {
+ constructor(private database: DataBase) {
+
+ }
+ queryForList(): Array {
+
+ return []
+ }
+}
\ No newline at end of file
diff --git a/packages/spring/package.json b/packages/spring/package.json
index 4cad36ad..797426c0 100644
--- a/packages/spring/package.json
+++ b/packages/spring/package.json
@@ -26,6 +26,7 @@
"dependencies": {
"@ccms/api": "^0.7.0",
"@ccms/common": "^0.7.0",
- "@ccms/container": "^0.7.0"
+ "@ccms/container": "^0.7.0",
+ "@ccms/database": "^0.7.0"
}
}
diff --git a/packages/spring/src/console.ts b/packages/spring/src/console.ts
index 3fbc1a49..5d835aba 100644
--- a/packages/spring/src/console.ts
+++ b/packages/spring/src/console.ts
@@ -28,13 +28,16 @@ function mcColor2ANSI(str: string) {
for (const regex in regexMap) {
str = str.replace(regexMap[regex], `\u001b[${regex}m`)
}
- return str;
+ return str
}
export class SpringConsole extends MiaoScriptConsole {
error(...args: any[]) {
this.logger.error(args.join(' '))
}
+ warn(...args: any[]) {
+ this.logger.warn(args.join(' '))
+ }
sender(sender: any, ...args: any[]) {
sender = sender || {
sendMessage: (message: string) => console.console(message)
@@ -46,7 +49,7 @@ export class SpringConsole extends MiaoScriptConsole {
if (Object.prototype.toString.call(args[0]) === '[object Array]') {
args[0].forEach(line => sender.sendMessage(this.prefix + line))
} else {
- sender.sendMessage(this.prefix + args.join(' '));
+ sender.sendMessage(this.prefix + args.join(' '))
}
}
console(...args: string[]): void {
diff --git a/packages/spring/src/index.ts b/packages/spring/src/index.ts
index 8f8df628..1e0ec712 100644
--- a/packages/spring/src/index.ts
+++ b/packages/spring/src/index.ts
@@ -1,13 +1,29 @@
import { server } from '@ccms/api'
-import { Container } from '@ccms/container'
-import '@ccms/database'
+import { ioc, Container, reduceMetadata } from '@ccms/container'
-import { SpringConsole } from './console';
-import './event';
-import './server';
-import './command';
-import './task';
+import { SpringConsole } from './console'
+import './event'
+import './server'
+import './command'
+import './task'
+
+const toString = {}.toString
export default function SpringImpl(container: Container) {
+ try {
+ require('@ccms/web')
+ require('@ccms/amqp')
+ require('@ccms/database')
+ require('./internal/scanner/mysql-scanner')
+ } catch (error) {
+ console.ex(error)
+ }
+ const beanFactory = base.getInstance().getAutowireCapableBeanFactory()
container.bind(server.Console).toConstantValue(SpringConsole)
+ container.bind(ioc.Autowired).toDynamicValue((ctx) => {
+ var metadata: any = reduceMetadata(ctx)
+ if (toString.call(metadata.named) === "[object Symbol]") { return container.get(metadata.named) }
+ if (toString.call(metadata.named) === '[object jdk.internal.dynalink.beans.StaticClass]') { metadata.named = metadata.named.class }
+ return beanFactory.getBean(metadata.named)
+ })
}
diff --git a/packages/spring/src/internal/command.ts b/packages/spring/src/internal/command.ts
index 21d75401..1b9a2bca 100644
--- a/packages/spring/src/internal/command.ts
+++ b/packages/spring/src/internal/command.ts
@@ -34,12 +34,32 @@ export class CommandMap {
}
let exists = this.commands[command]
if (exists) {
- return exists.executor(sender, '', command, Java.to(args))
+ try {
+ return exists.executor(sender, '', command, Java.to(args))
+ } catch (error) {
+ console.ex(error)
+ }
+ return true
} else {
sender.sendMessage && sender.sendMessage(`Unknown command. Type "/help" for help.`)
return false
}
}
+
+ tabComplate(sender: any, input: string, index?: number): string[] {
+ if (index == 0) { return Object.keys(this.commands) }
+ let [command, ...args] = input.split(' ')
+ let exists = this.commands[command]
+ if (exists && exists.tabCompleter) {
+ try {
+ if (args.length !== index) { args.push('') }
+ return exists.tabCompleter(sender, '', command, Java.to(args))
+ } catch (error) {
+ console.ex(error)
+ }
+ }
+ return []
+ }
}
export class SpringCommand {
diff --git a/packages/spring/src/internal/scanner/mysql-scanner.ts b/packages/spring/src/internal/scanner/mysql-scanner.ts
new file mode 100644
index 00000000..3c4cf467
--- /dev/null
+++ b/packages/spring/src/internal/scanner/mysql-scanner.ts
@@ -0,0 +1,32 @@
+import { plugin, database } from '@ccms/api'
+import { DataBaseManager } from '@ccms/database'
+import { provideSingleton, inject } from '@ccms/container'
+
+import * as fs from '@ccms/common/dist/fs'
+
+@provideSingleton(plugin.PluginScanner)
+export class MySQLScanner implements plugin.PluginScanner {
+ type: string = "mysql"
+
+ private target: string
+
+ @inject(database.DataBaseManager)
+ private databaseManager: DataBaseManager
+
+ scan(target: any): string[] {
+ this.target = target
+ let plugins = this.databaseManager.getMainDatabase().query<{ name: string }>(`SELECT name FROM ${this.target} WHERE LENGTH(source) != 0 AND deleted = 0`)
+ return plugins.map(p => `mysql:${p.name}`)
+ }
+ load(target: any) {
+ if (typeof target !== "string" || !target.startsWith('mysql:')) { return }
+ let name = target.split("mysql:")[1]
+ if (!name) { console.warn(`[PluginScanner][mysql] plugin name can't be null!`); return }
+ var plugin: any = this.databaseManager.getMainDatabase().query<{ source: string }>(`SELECT source FROM ${this.target} WHERE name = ? AND deleted = 0`, name)
+ if (plugin.length == 0) { console.warn(`[PluginScanner][mysql] plugin ${target} not found at mysql database...`); return }
+ let temp = fs.concat(root, 'mysql-plugin-cache', target, `${plugin[0]}.js`)
+ base.save(temp, plugin[0].source)
+ //@ts-ignore
+ return require(temp, { cache: false })
+ }
+}
diff --git a/packages/spring/src/server.ts b/packages/spring/src/server.ts
index 98ec5742..1560ad06 100644
--- a/packages/spring/src/server.ts
+++ b/packages/spring/src/server.ts
@@ -21,6 +21,7 @@ export class SpringServer implements server.Server {
}
getConsoleSender() {
return {
+ name: 'CONSOLE',
sendMessage: (message: string) => console.console(message)
}
}
@@ -50,6 +51,6 @@ export class SpringServer implements server.Server {
throw new Error("Method not implemented.")
}
tabComplete(sender: any, input: string, index?: number) {
- throw new Error("Method not implemented.")
+ return this.commandMap.tabComplate(sender, input, index)
}
}
diff --git a/packages/spring/src/task.ts b/packages/spring/src/task.ts
index 2289bdde..5c2c7cf5 100644
--- a/packages/spring/src/task.ts
+++ b/packages/spring/src/task.ts
@@ -1,29 +1,30 @@
import { task, plugin } from '@ccms/api'
import { inject, provideSingleton } from '@ccms/container'
+import thread_pool from '@ccms/common/dist/thread-pool'
+const AtomicInteger = Java.type("java.util.concurrent.atomic.AtomicInteger")
const AtomicBoolean = Java.type("java.util.concurrent.atomic.AtomicBoolean")
const Thread = Java.type('java.lang.Thread')
-const ThreadPoolExecutor = Java.type('java.util.concurrent.ThreadPoolExecutor')
-const ThreadPoolTaskExecutor = Java.type('org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor')
-let executor: any
-let tasks: { [key: number]: task.Cancelable } = {}
-let taskId = 0
+const taskId = new AtomicInteger(0)
+const tasks: { [key: number]: task.Cancelable } = {}
+const executor = thread_pool.create({
+ groupName: '@ccms/spring'
+})
@provideSingleton(task.TaskManager)
export class SpringTaskManager implements task.TaskManager {
@inject(plugin.PluginInstance)
private pluginInstance: any
+ private innerTaskId: any
+ private innerTasks: { [s: string]: task.Cancelable }
+ private innerExecutor: java.util.concurrent.ThreadPoolExecutor
+
constructor() {
- executor = new ThreadPoolTaskExecutor()
- executor.setCorePoolSize(10)
- executor.setMaxPoolSize(100)
- executor.setQueueCapacity(500)
- executor.setKeepAliveSeconds(60)
- executor.setThreadNamePrefix("@ccms/spring-")
- executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy())
- executor.initialize()
+ this.innerTaskId = taskId
+ this.innerTasks = tasks
+ this.innerExecutor = executor
}
create(func: Function): task.Task {
@@ -34,13 +35,13 @@ export class SpringTaskManager implements task.TaskManager {
return func()
}
disable() {
- Object.values(tasks).forEach((task) => task?.cancel())
- executor.shutdown();
+ Object.values(this.innerTasks).forEach((task) => task?.cancel())
+ this.innerExecutor.shutdown()
}
}
export class SpringTask extends task.Task {
- public id = taskId++
+ public id = taskId.incrementAndGet()
private running = new AtomicBoolean(true)
run(...args: any[]) {
@@ -78,7 +79,7 @@ export class SpringTask extends task.Task {
submit(...args: any[]): task.Cancelable {
tasks[this.id] = this
- executor.execute(() => this.run(...args))
+ executor.execute((() => this.run(...args)) as any)
return {
cancel: () => {
return this.cancel()
diff --git a/packages/web/src/decorators/index.ts b/packages/web/src/decorators/index.ts
index 6f5b7cc0..eb3112aa 100644
--- a/packages/web/src/decorators/index.ts
+++ b/packages/web/src/decorators/index.ts
@@ -3,11 +3,6 @@ export const Controller = () => {
return
}
}
-export const Header = () => {
- return (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor): MethodDecorator => {
- return
- }
-}
export const Post = () => {
return (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor): MethodDecorator => {
return
@@ -18,6 +13,11 @@ export const Get = () => {
return
}
}
+export const Header = () => {
+ return (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor): MethodDecorator => {
+ return
+ }
+}
export const Param = () => {
return (target: Object, propertyKey: string | symbol, parameterIndex: number): ParameterDecorator => {
return
diff --git a/packages/web/src/server.ts b/packages/web/src/server.ts
index ade18dfe..2407b126 100644
--- a/packages/web/src/server.ts
+++ b/packages/web/src/server.ts
@@ -156,9 +156,10 @@ export class Server {
}
console.debug(`
===================== MiaoSpring =====================
-Request URL : ${ctx.url}
-Response Body : ${JSON.stringify(Java.asJSONCompatible(ctx.result))}
-Handle Time : ${Date.now() - startTime}ms
+Request Method : ${ctx.request.getMethod()}
+Request URL : ${ctx.url}
+Response Body : ${JSON.stringify(Java.asJSONCompatible(ctx.result))}
+Handle Time : ${Date.now() - startTime}ms
======================================================`)
return ctx.result
}