diff --git a/packages/amqp/.npmignore b/packages/amqp/.npmignore deleted file mode 120000 index b4359f69..00000000 --- a/packages/amqp/.npmignore +++ /dev/null @@ -1 +0,0 @@ -../../.npmignore \ No newline at end of file diff --git a/packages/amqp/package.json b/packages/amqp/package.json deleted file mode 100644 index 7377353e..00000000 --- a/packages/amqp/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "@ccms/amqp", - "version": "0.28.0-beta.2", - "description": "MiaoScript amqp package", - "keywords": [ - "miaoscript", - "minecraft", - "bukkit", - "sponge" - ], - "author": "MiaoWoo ", - "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" - }, - "dependencies": { - "@ccms/api": "^0.28.0-beta.2", - "@ccms/common": "^0.28.0-beta.2", - "@ccms/container": "^0.28.0-beta.2" - }, - "devDependencies": { - "@ccms/nashorn": "^0.28.0-beta.2", - "@javatypes/amqp-client": "^0.0.3", - "@javatypes/spring-amqp": "^0.0.3", - "@javatypes/spring-rabbit": "^0.0.3", - "reflect-metadata": "^0.1.13", - "rimraf": "^4.1.2", - "typescript": "^4.9.5" - } -} diff --git a/packages/amqp/src/adapter/admin.ts b/packages/amqp/src/adapter/admin.ts deleted file mode 100644 index 9623029b..00000000 --- a/packages/amqp/src/adapter/admin.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { ConnectionFactoryAdapter } from "./connection" -import { RabbitTemplateAdapter } from "./template" -import { JSClass } from "@ccms/container" - -export const RabbitAdmin = Java.type('org.springframework.amqp.rabbit.core.RabbitAdmin') - -export class RabbitAdminAdapter { - @JSClass('org.springframework.amqp.rabbit.core.RabbitAdmin') - private RabbitAdmin: org.springframework.amqp.rabbit.core.RabbitAdmin - private _Handler: org.springframework.amqp.rabbit.core.RabbitAdmin - constructor(config: RabbitTemplateAdapter | org.springframework.amqp.rabbit.core.RabbitTemplate | ConnectionFactoryAdapter | org.springframework.amqp.rabbit.connection.ConnectionFactory) { - this._Handler = new RabbitAdmin((config instanceof RabbitTemplateAdapter || config instanceof ConnectionFactoryAdapter) ? config.getHandler() : config) - } - getHandler(): org.springframework.amqp.rabbit.core.RabbitAdmin { - return this._Handler - } -} diff --git a/packages/amqp/src/adapter/callback.ts b/packages/amqp/src/adapter/callback.ts deleted file mode 100644 index d4936a94..00000000 --- a/packages/amqp/src/adapter/callback.ts +++ /dev/null @@ -1,30 +0,0 @@ -export const ConfirmCallback = Java.type('org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback') -export const ReturnCallback = Java.type('org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback') - -export abstract class ConfirmCallbackAdapter { - private _Handler: org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback - constructor() { - let ConfirmCallbackImpl = Java.extend(ReturnCallback, { - confirm: (correlationData: org.springframework.amqp.rabbit.connection.CorrelationData, ack: boolean, cause: string) => this.confirm(correlationData, ack, cause) - }) - this._Handler = new ConfirmCallbackImpl() - } - abstract confirm(correlationData: org.springframework.amqp.rabbit.connection.CorrelationData, ack: boolean, cause: string) - getHandler() { - return this._Handler - } -} - -export abstract class ReturnCallbackAdapter { - private _Handler: org.springframework.amqp.rabbit.core.RabbitTemplate.ReturnCallback - constructor() { - let ReturnCallbackImpl = Java.extend(ReturnCallback, { - returnedMessage: (message: org.springframework.amqp.core.Message, replyCode: number, replyText: string, exchange: string, routingKey: string) => this.returnedMessage(message, replyCode, replyText, exchange, routingKey) - }) - this._Handler = new ReturnCallbackImpl() - } - abstract returnedMessage(message: org.springframework.amqp.core.Message, replyCode: number, replyText: string, exchange: string, routingKey: string) - getHandler() { - return this._Handler - } -} diff --git a/packages/amqp/src/adapter/connection.ts b/packages/amqp/src/adapter/connection.ts deleted file mode 100644 index b18fb5f9..00000000 --- a/packages/amqp/src/adapter/connection.ts +++ /dev/null @@ -1,31 +0,0 @@ -import threadPool from '@ccms/common/dist/thread-pool' - -export const ConnectionFactory = Java.type('org.springframework.amqp.rabbit.connection.ConnectionFactory') -const CachingConnectionFactory = Java.type('org.springframework.amqp.rabbit.connection.CachingConnectionFactory') -interface ConnectionConfig { - url: string, - username?: string, - password?: string, - publisherConfirms?: boolean - cacheSize?: number -} - -export class ConnectionFactoryAdapter { - private _Handler: org.springframework.amqp.rabbit.connection.CachingConnectionFactory - - constructor(config: ConnectionConfig) { - if (!config.url) { throw new Error('Connection UrI Can\'t be undefiend!') } - config = { publisherConfirms: true, cacheSize: 50, ...config } - this._Handler = new CachingConnectionFactory(new java.net.URI(config.url)) - config.username && this._Handler.setUsername(config.username) - config.password && this._Handler.setPassword(config.password) - this._Handler.setPublisherConfirms(config.publisherConfirms) - this._Handler.setExecutor(threadPool.create({ - groupName: '@ccms/amqp-rabbit' - })) - this._Handler.setChannelCacheSize(config.cacheSize) - } - getHandler() { - return this._Handler - } -} diff --git a/packages/amqp/src/adapter/container.ts b/packages/amqp/src/adapter/container.ts deleted file mode 100644 index 38aa83c2..00000000 --- a/packages/amqp/src/adapter/container.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { ConnectionFactoryAdapter, ConnectionFactory } from "./connection" -import { ChannelAwareMessageListenerAdapter, ChannelAwareMessageListener } from "./listener" - -export const SimpleMessageListenerContainer = org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer -export const AcknowledgeMode = org.springframework.amqp.core.AcknowledgeMode -interface ContainerConfig { - connectionFactory: ConnectionFactoryAdapter | typeof ConnectionFactory - queueNames: string[] - messageListener: ChannelAwareMessageListenerAdapter | typeof ChannelAwareMessageListener - maxConcurrentConsumers?: number - concurrentConsumers?: number - acknowledgeMode?: org.springframework.amqp.core.AcknowledgeMode -} - -export class MessageListenerContainerAdapter { - private _Handler: org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer - constructor(config: ContainerConfig) { - config = { concurrentConsumers: 5, maxConcurrentConsumers: 10, acknowledgeMode: AcknowledgeMode.AUTO, ...config } - this._Handler = new SimpleMessageListenerContainer(config.connectionFactory instanceof ConnectionFactoryAdapter ? config.connectionFactory.getHandler() : config.connectionFactory) - //@ts-ignore - this._Handler.setQueueNames(config.queueNames) - this._Handler.setMaxConcurrentConsumers(config.maxConcurrentConsumers) - this._Handler.setConcurrentConsumers(config.concurrentConsumers) - this._Handler.setAcknowledgeMode(config.acknowledgeMode) - this._Handler.setMessageListener(config.messageListener instanceof ChannelAwareMessageListenerAdapter ? config.messageListener.getHandler() : config.messageListener) - } - getHandler() { - return this._Handler - } -} diff --git a/packages/amqp/src/adapter/converter.ts b/packages/amqp/src/adapter/converter.ts deleted file mode 100644 index dfe2685d..00000000 --- a/packages/amqp/src/adapter/converter.ts +++ /dev/null @@ -1,37 +0,0 @@ -const JavaString = Java.type('java.lang.String') -const MessageProperties = org.springframework.amqp.core.MessageProperties -const Message = org.springframework.amqp.core.Message - -export const MessageConverter = Java.type('org.springframework.amqp.support.converter.MessageConverter') - -export class MessageConverterAdapter { - private _Handler: org.springframework.amqp.support.converter.MessageConverter - constructor() { - var MessageConverterImpl = Java.extend(MessageConverter, { - toMessage: (object: any, messageProperties: org.springframework.amqp.core.MessageProperties) => this.toMessage(object, messageProperties), - fromMessage: (message: org.springframework.amqp.core.Message) => this.fromMessage(message) - }) - this._Handler = new MessageConverterImpl() - } - toMessage(object: any, messageProperties: org.springframework.amqp.core.MessageProperties) { - if (typeof object == "string") { - messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN) - return new Message(new JavaString(object).getBytes(), messageProperties) - } else { - messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON) - return new Message(new JavaString(JSON.stringify(object)).getBytes(), messageProperties) - } - } - fromMessage(message: org.springframework.amqp.core.Message) { - if (message.getMessageProperties().getContentType() == MessageProperties.CONTENT_TYPE_TEXT_PLAIN) { - return new JavaString(message.getBody(), message.getMessageProperties().getContentEncoding()) - } - if (message.getMessageProperties().getContentType() == MessageProperties.CONTENT_TYPE_JSON) { - return JSON.parse(new JavaString(message.getBody(), message.getMessageProperties().getContentEncoding())) - } - return message - } - getHandler() { - return this._Handler - } -} diff --git a/packages/amqp/src/adapter/index.ts b/packages/amqp/src/adapter/index.ts deleted file mode 100644 index 979742a8..00000000 --- a/packages/amqp/src/adapter/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './admin' -export * from './callback' -export * from './connection' -export * from './container' -export * from './converter' -export * from './listener' -export * from './template' diff --git a/packages/amqp/src/adapter/listener.ts b/packages/amqp/src/adapter/listener.ts deleted file mode 100644 index 9e2d493b..00000000 --- a/packages/amqp/src/adapter/listener.ts +++ /dev/null @@ -1,49 +0,0 @@ -const JavaString = Java.type('java.lang.String') -export const MessageProperties = org.springframework.amqp.core.MessageProperties -export const ChannelAwareMessageListener = Java.type('org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener') -export const AmqpRejectAndDontRequeueException = org.springframework.amqp.AmqpRejectAndDontRequeueException -export const Channel: com.rabbitmq.client.Channel = Java.type('com.rabbitmq.client.Channel') -export const Message = org.springframework.amqp.core.Message -export type MessageHandler = (content: T, message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel) => any -export abstract class ChannelAwareMessageListenerAdapter { - private _Handler: org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener - constructor(manual: boolean = false) { - let ChannelAwareMessageListenerImpl = Java.extend(ChannelAwareMessageListener, { - onMessage: (message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel) => { - let content = new JavaString(message.getBody(), message.getMessageProperties().getContentEncoding() || "UTF-8") - try { - if (message.getMessageProperties().getContentType() == MessageProperties.CONTENT_TYPE_JSON) { - content = JSON.parse(content) - } - } catch (error: any) { - if (manual) { - channel.basicReject(message.getMessageProperties().getDeliveryTag(), true) - } else { - throw new AmqpRejectAndDontRequeueException(`${error}`, error) - } - } - manual ? this.manualOnMessage(content, message, channel) : this.onMessage(content, message, channel) - } - }) - this._Handler = new ChannelAwareMessageListenerImpl() - } - abstract onMessage(content: T, message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel): any - onError(error: Error, message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel): any { } - getHandler() { - return this._Handler - } - private manualOnMessage(content: T, message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel) { - let deliveryTag = message.getMessageProperties().getDeliveryTag() - try { - if (this.onMessage(content, message, channel)) { - channel.basicAck(deliveryTag, false) - } else if (message.getMessageProperties().getRedelivered()) { - channel.basicReject(deliveryTag, true) - } else { - channel.basicNack(deliveryTag, false, true) - } - } catch (error: any) { - channel.basicReject(deliveryTag, this.onError(error, message, channel)) - } - } -} diff --git a/packages/amqp/src/adapter/template.ts b/packages/amqp/src/adapter/template.ts deleted file mode 100644 index b1085386..00000000 --- a/packages/amqp/src/adapter/template.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { MessageConverterAdapter } from "./converter" -import { ConnectionFactoryAdapter } from "./connection" -import { ConfirmCallbackAdapter, ReturnCallbackAdapter } from "./callback" - -export const RabbitTemplate = Java.type('org.springframework.amqp.rabbit.core.RabbitTemplate') - -interface TemplateConfig { - connectionFactory: ConnectionFactoryAdapter | org.springframework.amqp.rabbit.connection.ConnectionFactory - confirmCallback?: ConfirmCallbackAdapter - returnCallback?: ReturnCallbackAdapter - messageConverter?: MessageConverterAdapter -} -export class RabbitTemplateAdapter { - private _Handler: org.springframework.amqp.rabbit.core.RabbitTemplate - constructor(config: TemplateConfig) { - config = { messageConverter: new MessageConverterAdapter(), ...config } - console.debug(JSON.stringify(config)) - this._Handler = new RabbitTemplate(config.connectionFactory instanceof ConnectionFactoryAdapter ? config.connectionFactory.getHandler() : config.connectionFactory) - config.returnCallback && this._Handler.setReturnCallback(config.returnCallback.getHandler()) - config.confirmCallback && this._Handler.setConfirmCallback(config.confirmCallback.getHandler()) - config.messageConverter && this._Handler.setMessageConverter(config.messageConverter.getHandler()) - } - - getHandler() { - return this._Handler - } -} diff --git a/packages/amqp/src/admin.ts b/packages/amqp/src/admin.ts deleted file mode 100644 index dba10ce7..00000000 --- a/packages/amqp/src/admin.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { JSClass } from "@ccms/container" -import { RabbitAdminAdapter, MessageListenerContainerAdapter, AcknowledgeMode, MessageHandler, ChannelAwareMessageListenerAdapter } from "./adapter" - -export class AmqpAdmin { - @JSClass('org.springframework.amqp.core.TopicExchange') - private TopicExchange: typeof org.springframework.amqp.core.TopicExchange - @JSClass('org.springframework.amqp.core.Queue') - private Queue: typeof org.springframework.amqp.core.Queue - @JSClass('org.springframework.amqp.core.Binding') - private Binding: typeof org.springframework.amqp.core.Binding - @JSClass('org.springframework.amqp.rabbit.core.RabbitAdmin') - private RabbitAdmin: typeof org.springframework.amqp.rabbit.core.RabbitAdmin - @JSClass('org.springframework.amqp.core.Binding.DestinationType') - private DestinationType: org.springframework.amqp.core.Binding.DestinationType - - private amqpAdmin: org.springframework.amqp.rabbit.core.RabbitAdmin - - constructor(amqpAdmin: org.springframework.amqp.rabbit.core.RabbitAdmin | any) { - if (amqpAdmin instanceof this.RabbitAdmin) { - this.amqpAdmin = amqpAdmin - } else if (amqpAdmin instanceof RabbitAdminAdapter) { - this.amqpAdmin = amqpAdmin.getHandler() - } else { - this.amqpAdmin = new RabbitAdminAdapter(amqpAdmin).getHandler() - } - } - - getHandler() { - return this.amqpAdmin - } - - getQueueProperties(name: string) { - return this.amqpAdmin.getQueueProperties(name) - } - - declareExchange(name: string) { - let exchange = new this.TopicExchange(name, true, false) - this.amqpAdmin.declareExchange(exchange) - return this - } - - declareQueue(name: string) { - let queue = new this.Queue(name, true) - this.amqpAdmin.declareQueue(queue) - return this - } - - declareBinding(queue: string, exchange: string, routerKey: string, argument: any = null) { - let binding = new this.Binding(queue, org.springframework.amqp.core.Binding.DestinationType.QUEUE, exchange, routerKey, argument) - this.amqpAdmin.declareBinding(binding) - return this - } - - declareQueueAndBindExchange(queue: string, exchange: string, routerKey: string) { - return this.declareQueue(queue).declareExchange(exchange).declareBinding(queue, exchange, routerKey) - } - - createContainer(queue: string, listener: MessageHandler, acknowledgeMode = AcknowledgeMode.AUTO) { - let connection = this.amqpAdmin.getRabbitTemplate().getConnectionFactory() - return new MessageListenerContainerAdapter({ - connectionFactory: connection, - queueNames: [queue], - messageListener: new SimpleMessageHandler(listener), - acknowledgeMode: acknowledgeMode - }).getHandler() - } - - send() - send() { - - } - - getTemplate() { - return this.amqpAdmin.getRabbitTemplate() - } - - close() { - this.getTemplate().stop() - } -} - -export class SimpleMessageHandler extends ChannelAwareMessageListenerAdapter { - constructor(private handler: MessageHandler) { - super() - } - onMessage(content: any, message: org.springframework.amqp.core.Message, channel: com.rabbitmq.client.Channel) { - return this.handler(content, message, channel) - } -} diff --git a/packages/amqp/src/constants.ts b/packages/amqp/src/constants.ts deleted file mode 100644 index b21a8a87..00000000 --- a/packages/amqp/src/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const METADATA_KEY = { - -} \ No newline at end of file diff --git a/packages/amqp/src/index.ts b/packages/amqp/src/index.ts deleted file mode 100644 index 03ead7ab..00000000 --- a/packages/amqp/src/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -/// -/// -/// -/// -/// - -import { amqp } from '@ccms/api' -import { getContainer, reduceMetadata } from '@ccms/container' - -function init() { - const beanFactory = base.getInstance().getAutowireCapableBeanFactory() - getContainer().bind(amqp.rabbit.Template).toDynamicValue((ctx) => { - let metadata = reduceMetadata(ctx) - if (!metadata.named) { - return beanFactory.getBean('rabbitTemplate') - } else { - return beanFactory.getBean(`${metadata.named}-rabbitTemplate`) - } - }) - getContainer().bind(amqp.rabbit.Admin).toDynamicValue((ctx) => { - let metadata = reduceMetadata(ctx) - if (!metadata.named) { - return beanFactory.getBean('rabbitAdmin') - } else { - return beanFactory.getBean(`${metadata.named}-rabbitAdmin`) - } - }) -} -init() - -export * from './admin' -export * from './adapter' -export * from './manager' -export * from './constants' diff --git a/packages/amqp/src/listener.ts b/packages/amqp/src/listener.ts deleted file mode 100644 index cc493772..00000000 --- a/packages/amqp/src/listener.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class AmqpListener { - constructor() { - - } -} \ No newline at end of file diff --git a/packages/amqp/src/manager.ts b/packages/amqp/src/manager.ts deleted file mode 100644 index 4ad8d0f2..00000000 --- a/packages/amqp/src/manager.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { amqp } from "@ccms/api" -import { provideSingleton } from "@ccms/container" - -import { ConnectionFactoryAdapter, RabbitTemplateAdapter, RabbitAdminAdapter } from "./adapter" -import { AmqpAdmin } from "./admin" - -@provideSingleton(amqp.Manager) -export class AmqpManager { - createConnection(url: string, username: string, password: string) { - return new ConnectionFactoryAdapter({ url, username, password }) - } - createTemplate(adapter: ConnectionFactoryAdapter) { - return new RabbitTemplateAdapter({ connectionFactory: adapter }) - } - createAdmin(adapter: RabbitTemplateAdapter | ConnectionFactoryAdapter) { - return new AmqpAdmin(new RabbitAdminAdapter(adapter)) - } -} diff --git a/packages/amqp/tsconfig.json b/packages/amqp/tsconfig.json deleted file mode 100644 index 7aae5d2b..00000000 --- a/packages/amqp/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "baseUrl": "src", - "outDir": "dist" - } -} \ No newline at end of file diff --git a/packages/api/src/amqp.ts b/packages/api/src/amqp.ts deleted file mode 100644 index 0d305015..00000000 --- a/packages/api/src/amqp.ts +++ /dev/null @@ -1,7 +0,0 @@ -export namespace amqp { - export const Manager = Symbol('AmqpManager') - export namespace rabbit { - export const Admin = Symbol('RabbitAdmin') - export const Template = Symbol('RabbitTemplate') - } -} \ No newline at end of file diff --git a/packages/api/src/web.ts b/packages/api/src/web.ts deleted file mode 100644 index 1fd97247..00000000 --- a/packages/api/src/web.ts +++ /dev/null @@ -1,3 +0,0 @@ -export namespace web { - export const Server = Symbol('Server') -} diff --git a/packages/keyvalue/.npmignore b/packages/keyvalue/.npmignore deleted file mode 120000 index b4359f69..00000000 --- a/packages/keyvalue/.npmignore +++ /dev/null @@ -1 +0,0 @@ -../../.npmignore \ No newline at end of file diff --git a/packages/keyvalue/package.json b/packages/keyvalue/package.json deleted file mode 100644 index 151d23cc..00000000 --- a/packages/keyvalue/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@ccms/keyvalue", - "version": "0.28.0-beta.2", - "description": "MiaoScript keyvalue package", - "keywords": [ - "miaoscript", - "minecraft", - "bukkit", - "sponge" - ], - "author": "MiaoWoo ", - "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" - }, - "dependencies": { - "@ccms/api": "^0.28.0-beta.2", - "@ccms/common": "^0.28.0-beta.2", - "@ccms/container": "^0.28.0-beta.2" - }, - "devDependencies": { - "@ccms/nashorn": "^0.28.0-beta.2", - "@javatypes/amqp-client": "^0.0.3", - "@javatypes/spring-amqp": "^0.0.3", - "@javatypes/spring-rabbit": "^0.0.3", - "reflect-metadata": "^0.1.13", - "rimraf": "^4.1.2", - "typescript": "^4.9.5" - }, - "gitHead": "2589633069d24f646ac09261b1b2304c21d4ea75" -} diff --git a/packages/keyvalue/src/index.ts b/packages/keyvalue/src/index.ts deleted file mode 100644 index 6d626d68..00000000 --- a/packages/keyvalue/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -/// -/// -export { } diff --git a/packages/keyvalue/tsconfig.json b/packages/keyvalue/tsconfig.json deleted file mode 100644 index 7aae5d2b..00000000 --- a/packages/keyvalue/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "baseUrl": "src", - "outDir": "dist" - } -} \ No newline at end of file diff --git a/packages/spring/.npmignore b/packages/spring/.npmignore deleted file mode 120000 index b4359f69..00000000 --- a/packages/spring/.npmignore +++ /dev/null @@ -1 +0,0 @@ -../../.npmignore \ No newline at end of file diff --git a/packages/spring/package.json b/packages/spring/package.json deleted file mode 100644 index 7c2cd980..00000000 --- a/packages/spring/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "@ccms/spring", - "version": "0.28.0-beta.2", - "description": "MiaoScript spring package", - "keywords": [ - "miaoscript", - "minecraft", - "bukkit", - "sponge" - ], - "author": "MiaoWoo ", - "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" - }, - "dependencies": { - "@ccms/api": "^0.28.0-beta.2", - "@ccms/common": "^0.28.0-beta.2", - "@ccms/container": "^0.28.0-beta.2", - "@ccms/database": "^0.28.0-beta.2" - } -} diff --git a/packages/spring/src/command.ts b/packages/spring/src/command.ts deleted file mode 100644 index 34812956..00000000 --- a/packages/spring/src/command.ts +++ /dev/null @@ -1,28 +0,0 @@ -import '@ccms/nashorn' - -import { command, plugin } from '@ccms/api' -import { inject, provideSingleton, postConstruct } from '@ccms/container' - -import { CommandMap } from './internal/command' - -@provideSingleton(command.Command) -export class SpringCommand extends command.Command { - @inject(CommandMap) - private commandMap: CommandMap - - protected create(plugin: any, command: string) { - return this.commandMap.register(plugin, command) - } - public tabComplete(sender: any, input: string, index?: number): string[] { - return this.commandMap.tabComplate(sender, input, index) - } - protected remove(plugin: any, command: string) { - this.commandMap.unregister(plugin, command) - } - protected onCommand(plugin: any, command: any, executor: Function) { - command.setExecutor(super.setExecutor(plugin, command, executor)) - } - protected onTabComplete(plugin: any, command: any, tabCompleter: Function) { - command.setTabCompleter(super.setTabCompleter(plugin, command, tabCompleter)) - } -} diff --git a/packages/spring/src/console.ts b/packages/spring/src/console.ts deleted file mode 100644 index 5d835aba..00000000 --- a/packages/spring/src/console.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { MiaoScriptConsole } from '@ccms/api' - -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: string) { - for (const regex in regexMap) { - str = str.replace(regexMap[regex], `\u001b[${regex}m`) - } - 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) - } - if (!sender.sendMessage) { - this.error('第一个参数未实现 sendMessage 无法发送消息!') - return - } - 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(' ')) - } - } - console(...args: string[]): void { - this.logger.info(mcColor2ANSI(args.join(' ') + '§r')) - } -} diff --git a/packages/spring/src/event.ts b/packages/spring/src/event.ts deleted file mode 100644 index b4fb81eb..00000000 --- a/packages/spring/src/event.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { event, plugin } from '@ccms/api' -import { inject, provideSingleton } from '@ccms/container' - -@provideSingleton(event.Event) -export class SpringEvent extends event.Event { - @inject(plugin.PluginInstance) - private pluginInstance: any - - constructor() { - super(''); - } - mapEventName() { - return 0; - } - isValidEvent(clazz: any): boolean { - throw new Error("Method not implemented."); - } - register(eventCls: any, exec: Function, priority: any, ignoreCancel: boolean) { - throw new Error("Method not implemented."); - } - unregister(event: any, listener: any): void { - throw new Error("Method not implemented."); - } -} diff --git a/packages/spring/src/index.ts b/packages/spring/src/index.ts deleted file mode 100644 index 1eb14f44..00000000 --- a/packages/spring/src/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { server } from '@ccms/api' -import { ioc, Container, reduceMetadata } from '@ccms/container' - -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: any) { - console.ex(error) - } - const beanFactory = base.getInstance().getAutowireCapableBeanFactory() - container.bind(server.Console).toConstantValue(SpringConsole) - container.rebind(ioc.Autowired).toDynamicValue((ctx) => { - var metadata: any = reduceMetadata(ctx) - let key = toString.call(metadata.named) - if (key === "[object Function]" || key === "[object Symbol]") { return container.get(metadata.named) } - if (key === '[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 deleted file mode 100644 index 1f927983..00000000 --- a/packages/spring/src/internal/command.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { provideSingleton } from "@ccms/container" -import { plugin } from "@ccms/api" - -type CommandExec = (sender: any, _: any, command: string, args: string[]) => boolean -type TabCompleter = (sender: any, _: any, command: string, args: string[]) => string[] -type CommandStore = { [key: string]: SpringCommand } - -@provideSingleton(CommandMap) -export class CommandMap { - private commands: CommandStore = {} - private pluginCommands: { [key: string]: CommandStore } = {} - - register(plugin: plugin.Plugin, command: string) { - let springCommand = new SpringCommand(plugin, command) - this.commands[command] = springCommand - if (!this.pluginCommands[plugin.description.name]) { this.pluginCommands[plugin.description.name] = {} } - this.pluginCommands[plugin.description.name][command] = springCommand - return springCommand - } - - unregister(plugin: plugin.Plugin, command: string) { - delete this.commands[command] - delete this.pluginCommands[plugin.description.name][command] - } - - dispatch(sender: any, command: string, args: string[]): boolean { - if (command === "help") { - sender.sendMessage('§e--------- §rHelp: Index §e---------------------------') - sender.sendMessage('Use /help [n] to get page n of help.') - for (const cmdName of Object.getOwnPropertyNames(this.commands)) { - sender.sendMessage(`§6/${cmdName}: §rA command provided by plugin §b${this.commands[cmdName].plugin.description.name}§r.`) - } - return - } - let exists = this.commands[command] - if (exists) { - try { - return exists.executor(sender, '', command, Java.to(args)) - } catch (error: any) { - 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).concat('help') } - 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: any) { - console.ex(error) - } - } - return [] - } -} - -export class SpringCommand { - public plugin: plugin.Plugin - public name: string - public executor: CommandExec - public tabCompleter: TabCompleter - - constructor(plugin: plugin.Plugin, command: string, description: string = '暂无描述!') { - this.plugin = plugin - this.name = command - } - - setExecutor = (executor: CommandExec) => this.executor = executor - setTabCompleter = (tabCompleter: TabCompleter) => this.tabCompleter = tabCompleter - toString = () => `SpringCommand(${this.name})` -} diff --git a/packages/spring/src/internal/scanner/mysql-scanner.ts b/packages/spring/src/internal/scanner/mysql-scanner.ts deleted file mode 100644 index 052b9cba..00000000 --- a/packages/spring/src/internal/scanner/mysql-scanner.ts +++ /dev/null @@ -1,48 +0,0 @@ -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' - -interface MySQLPlugin { - name: string - source: string -} - -@provideSingleton(plugin.PluginScanner) -export class MySQLScanner implements plugin.PluginScanner { - type: string = "mysql" - - private cacheDir = 'mysql-plugin-cache' - private cacheFileMap: Map = new Map() - private target: string - - @inject(database.DataBaseManager) - private databaseManager: DataBaseManager - - scan(target: any): plugin.PluginLoadMetadata[] { - this.target = target - let plugins = this.databaseManager.getMainDatabase().query(`SELECT name FROM ${this.target} WHERE LENGTH(source) != 0 AND deleted = 0`) - return plugins.map(p => this.read(p)) - } - read(mysqlPlugin: MySQLPlugin): plugin.PluginLoadMetadata { - // if invoke this function from loadFromFile mysqlPlugin is a string need read from cache - if (typeof mysqlPlugin == "string") { - if (!this.cacheFileMap.has(mysqlPlugin)) { throw new Error(`this file ${mysqlPlugin} is not read from mysql-scanner. can't reload from this scanner!`) } - mysqlPlugin = this.cacheFileMap.get(mysqlPlugin) - } - let cacheFile = fs.concat(root, this.cacheDir, `${mysqlPlugin.name}.js`) - this.cacheFileMap.set(cacheFile, mysqlPlugin) - return { name: mysqlPlugin.name, file: cacheFile, type: this.type, mysqlPlugin, scanner: this } - } - load(metadata: plugin.PluginLoadMetadata) { - if (metadata.type !== this.type) { return } - var plugin: any = this.databaseManager.getMainDatabase().query(`SELECT source FROM ${this.target} WHERE name = ? AND deleted = 0`, metadata.name) - if (plugin.length == 0) { throw new Error(`[MySQLScanner] plugin ${metadata.name} not found at mysql database...`) }; plugin = plugin[0] - if (!plugin.source) { throw new Error(`[MySQLScanner] plugin ${metadata.name} source can\'t be undefiend or empty...`) } - base.save(metadata.file, plugin.source) - //@ts-ignore - metadata.instance = require(metadata.file, { cache: false }) - return metadata - } -} diff --git a/packages/spring/src/server.ts b/packages/spring/src/server.ts deleted file mode 100644 index 118eee42..00000000 --- a/packages/spring/src/server.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { constants, server } from '@ccms/api' -import { provideSingleton, postConstruct, Autowired, Container, ContainerInstance } from '@ccms/container' -import { CommandMap } from './internal/command' - -@provideSingleton(server.Server) -export class SpringServer extends server.Server { - @Autowired(ContainerInstance) - private container: Container - @Autowired() - private commandMap: CommandMap - - private nettyPipeline = base.getInstance().getAutowireCapableBeanFactory() - private rootLogger = Packages.org.slf4j.LoggerFactory.getLogger("root") || global.logger - - @postConstruct() - initialize() { - this.container.bind(constants.ServiceIdentifier.NettyPipeline).toConstantValue(this.nettyPipeline) - this.container.bind(constants.ServiceIdentifier.RootLogger).toConstantValue(this.rootLogger) - } - - getVersion(): string { - return "SpringFramework" - } - getConsoleSender() { - return { - name: 'CONSOLE', - sendMessage: (message: string) => console.console(message) - } - } - dispatchCommand(sender: any, command: string): boolean { - let cmd_args = command.split(" ") - return this.commandMap.dispatch(sender, cmd_args.shift(), cmd_args || []) - } - dispatchConsoleCommand(command: string): boolean { - return this.dispatchCommand(this.getConsoleSender(), command) - } - getNettyPipeline() { - return this.nettyPipeline - } - getRootLogger() { - return this.rootLogger - } -} diff --git a/packages/spring/src/task.ts b/packages/spring/src/task.ts deleted file mode 100644 index 356da015..00000000 --- a/packages/spring/src/task.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { task, plugin } from '@ccms/api' -import { inject, provideSingleton } from '@ccms/container' -import thread_pool from '@ccms/common/dist/thread-pool' - -const AtomicBoolean = Java.type("java.util.concurrent.atomic.AtomicBoolean") -const Thread = Java.type('java.lang.Thread') - -@provideSingleton(task.TaskManager) -export class SpringTaskManager extends task.TaskManager { - @inject(plugin.PluginInstance) - private pluginInstance: any - - private tasks: { [s: string]: task.Cancelable } - private executor: java.util.concurrent.ThreadPoolExecutor - - constructor() { - super() - this.tasks = {} - this.executor = thread_pool.create({ - groupName: '@ccms/spring' - }) - } - - create0(owner: plugin.Plugin, func: Function, id: number): task.Task { - return new SpringTask(owner, func, id, this) - } - callSyncMethod(func: Function): any { - return func() - } - disable0() { - Object.values(this.tasks).forEach((task) => task?.cancel()) - this.executor.shutdown() - } - nextId() { - return this.taskId.incrementAndGet() - } - submit(id: number, task: SpringTask, func: Function) { - this.tasks[id] = task - this.executor.execute(func as any) - } - cancel(id: number) { - delete this.tasks[id] - } -} - -export class SpringTask extends task.Task { - private id: number - private taskManager: SpringTaskManager - private running = new AtomicBoolean(true) - - constructor(owner: plugin.Plugin, func: Function, id: number, taskManager: SpringTaskManager) { - super(owner, func, id) - this.id = taskManager.nextId() - this.taskManager = taskManager - } - - run(...args: any[]) { - if (this.laterTime > 0) { - try { - Thread.sleep(this.laterTime) - } catch (ex: any) { - Thread.currentThread().interrupt() - } - } - while (this.running.get()) { - try { - this.func(...args) - } catch (ex: any) { - console.error("Task exec error:", ex) - console.ex(ex) - } - // If we have a interval of 0 or less, only run once - if (this.interval <= 0) { break } - try { - Thread.sleep(this.interval) - } catch (ex: any) { - Thread.currentThread().interrupt() - } - } - this.cancel() - } - - cancel0() { - var wasRunning = this.running.getAndSet(false) - if (wasRunning) { - this.taskManager.cancel(this.id) - return true - } - return false - } - - submit0(...args: any[]) { - this.taskManager.submit(this.id, this, () => this.run(...args)) - } -} diff --git a/packages/spring/tsconfig.json b/packages/spring/tsconfig.json deleted file mode 100644 index 7aae5d2b..00000000 --- a/packages/spring/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "baseUrl": "src", - "outDir": "dist" - } -} \ No newline at end of file diff --git a/packages/web/.npmignore b/packages/web/.npmignore deleted file mode 120000 index b4359f69..00000000 --- a/packages/web/.npmignore +++ /dev/null @@ -1 +0,0 @@ -../../.npmignore \ No newline at end of file diff --git a/packages/web/package.json b/packages/web/package.json deleted file mode 100644 index 217e8aa5..00000000 --- a/packages/web/package.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "@ccms/web", - "version": "0.28.0-beta.2", - "description": "MiaoScript web package", - "keywords": [ - "miaoscript", - "minecraft", - "bukkit", - "sponge" - ], - "author": "MiaoWoo ", - "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": { - "@javatypes/jdk": "^0.0.3", - "@javatypes/spring-beans": "^0.0.3", - "@javatypes/spring-core": "^0.0.3", - "@javatypes/spring-web": "^0.0.3", - "@javatypes/tomcat": "^0.0.3", - "reflect-metadata": "^0.1.13", - "rimraf": "^4.1.2", - "typescript": "^4.9.5" - }, - "dependencies": { - "@ccms/api": "^0.28.0-beta.2", - "@ccms/container": "^0.28.0-beta.2" - } -} diff --git a/packages/web/src/constants.ts b/packages/web/src/constants.ts deleted file mode 100644 index 0302cc91..00000000 --- a/packages/web/src/constants.ts +++ /dev/null @@ -1,16 +0,0 @@ -export const WebProxyBeanName = 'webServerProxy' -export const FilterProxyBeanName = 'webFilterProxy' -export const METADATA_KEY = { - Controller: Symbol("@ccms/web:Controller"), - Action: Symbol("@ccms/web:Action"), - Param: Symbol("@ccms/web:Param"), - Middleware: Symbol("@ccms/web:Middleware"), -} -export enum PARAM_TYPE { - QUERY = 'QUERY', - BODY = 'BODY', - HEADER = 'HEADER', - COOKIE = 'COOKIE', - REQUEST = 'REQUEST', - RESPONSE = 'RESPONSE', -} diff --git a/packages/web/src/decorators/index.ts b/packages/web/src/decorators/index.ts deleted file mode 100644 index c3152b94..00000000 --- a/packages/web/src/decorators/index.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { plugin } from '@ccms/api' -import { decorate, injectable, getContainer } from "@ccms/container" - -import { METADATA_KEY, PARAM_TYPE } from '../constants' -import { interfaces } from "../interfaces" -import { addControllerMetadata, addControllerAction, addActionParam, getControllerMetadata } from "./utils" - -export const Controllers = (...controllers: any[]) => { - return (target: any, propertyKey: string) => { - for (const controller of controllers) { - addControllerMetadata(getControllerMetadata(controller), target) - } - } -} - -export const Controller = (metadata?: string | interfaces.ControllerMetadata) => { - return (target: any) => { - if (!metadata) { metadata = target.name.toLowerCase().replace('controller', '') } - if (typeof metadata === "string") { metadata = { path: metadata } } - metadata.target = target - metadata.name = metadata.name || target.name - metadata.path = metadata.path ?? `/${metadata}` - metadata.path = metadata.path.startsWith('/') ? metadata.path : `/${metadata.path}` - decorate(injectable(), target) - Reflect.defineMetadata(METADATA_KEY.Controller, metadata, target) - addControllerMetadata(metadata) - } -} - -function action(method: interfaces.Method) { - return (metadata?: string | interfaces.ActionMetadata) => { - return (target: any, propertyKey: string) => { - if (!metadata) { metadata = propertyKey.toLowerCase() } - if (typeof metadata === "string") { metadata = { path: metadata } } - metadata.path = metadata.path ?? `/${propertyKey}` - metadata.path = metadata.path.startsWith('/') ? metadata.path : `/${metadata.path}` - metadata.method = method - metadata.executor = propertyKey - Reflect.defineMetadata(METADATA_KEY.Action, metadata, target[propertyKey]) - addControllerAction(target, propertyKey) - } - } -} -export const Action = action('ALL') -export const Get = action('GET') -export const Post = action('POST') -export const Put = action('PUT') -export const Patch = action('PATCH') -export const Head = action('HEAD') -export const Delete = action('DELETE') - -function param(type: PARAM_TYPE) { - return (metadata?: string | interfaces.ParamMetadata) => { - return (target: any, propertyKey: string, index: number) => { - if (!metadata) { metadata = `${propertyKey}-${index}` } - if (typeof metadata === "string") { metadata = { name: metadata } } - metadata.type = type - metadata.index = index - metadata.paramtype = Reflect.getMetadata("design:paramtypes", target, propertyKey)[index] - addActionParam(target, propertyKey, metadata) - } - } -} -export const Request = param(PARAM_TYPE.REQUEST) -export const Response = param(PARAM_TYPE.RESPONSE) -export const Header = param(PARAM_TYPE.HEADER) -export const Cookie = param(PARAM_TYPE.COOKIE) -export const Query = param(PARAM_TYPE.QUERY) -export const Param = param(PARAM_TYPE.QUERY) -export const Body = param(PARAM_TYPE.BODY) - -function Middleware() { - return (metadata?: string | interfaces.ActionMetadata) => { - return (target: any, propertyKey: string) => { - if (!metadata) { metadata = propertyKey.toLowerCase() } - if (typeof metadata === "string") { metadata = { path: metadata } } - metadata.path = metadata.path ?? `/${propertyKey}` - metadata.path = metadata.path.startsWith('/') ? metadata.path : `/${metadata.path}` - metadata.executor = propertyKey - Reflect.defineMetadata(METADATA_KEY.Action, metadata, target[propertyKey]) - addControllerAction(target, propertyKey) - } - } -} - -export * from './utils' diff --git a/packages/web/src/decorators/utils.ts b/packages/web/src/decorators/utils.ts deleted file mode 100644 index 6f3cde8e..00000000 --- a/packages/web/src/decorators/utils.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { interfaces } from '../interfaces' -import { METADATA_KEY } from '../constants' - -export function getControllerMetadatas(target: any = Reflect): Map { - return Reflect.getMetadata(METADATA_KEY.Controller, target) || new Map() -} -export function addControllerMetadata(metadata: interfaces.ControllerMetadata, target: any = Reflect) { - let metadatas = getControllerMetadatas(target) - metadatas.set(metadata.name, metadata) - Reflect.defineMetadata(METADATA_KEY.Controller, metadatas, target) -} -export function getControllerActions(target: any): string[] { - return Reflect.getMetadata(METADATA_KEY.Action, target.constructor) || [] -} -export function addControllerAction(target: any, propertyKey: string) { - Reflect.defineMetadata(METADATA_KEY.Action, [propertyKey, ...getControllerActions(target)], target.constructor) -} -export function getControllerMetadata(target: any): interfaces.ControllerMetadata { - return Reflect.getMetadata(METADATA_KEY.Controller, target) -} -export function getActionMetadata(target: any, propertyKey: string): interfaces.ActionMetadata { - return Reflect.getMetadata(METADATA_KEY.Action, target[propertyKey]) -} -export function getActionParams(target: any, propertyKey: string): interfaces.ParamMetadata[] { - return Reflect.getMetadata(METADATA_KEY.Param, target[propertyKey]) || [] -} -export function addActionParam(target: any, propertyKey: string, metadata: interfaces.ParamMetadata) { - Reflect.defineMetadata(METADATA_KEY.Param, [metadata, ...getActionParams(target, propertyKey)], target[propertyKey]) -} diff --git a/packages/web/src/index.ts b/packages/web/src/index.ts deleted file mode 100644 index 0137597b..00000000 --- a/packages/web/src/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/// -/// -/// -/// -/// -/// - -export * from './server' -export * from './constants' -export * from './decorators' -export * from './interfaces' diff --git a/packages/web/src/interfaces/context.ts b/packages/web/src/interfaces/context.ts deleted file mode 100644 index 219f276d..00000000 --- a/packages/web/src/interfaces/context.ts +++ /dev/null @@ -1,25 +0,0 @@ -export type RequestHandler = (ctx: Context) => any -export interface InterceptorAdapter { - name: string - preHandle?(ctx: Context): void - postHandle?(ctx: Context): void -} - -type StringKeyAndStringValue = { [key: string]: string } -type StringKeyAndStringOrArrayValue = { [key: string]: string | string[] } - -export type RequestHeaders = StringKeyAndStringOrArrayValue -export type RequestParams = StringKeyAndStringOrArrayValue -export type RequestCookies = StringKeyAndStringValue - -export interface Context { - request?: javax.servlet.http.HttpServletRequest - response?: javax.servlet.http.HttpServletResponse - handler?: RequestHandler - url?: string - headers?: RequestHeaders - cookies?: RequestCookies - params?: RequestParams - body?: any - result?: any -} diff --git a/packages/web/src/interfaces/index.ts b/packages/web/src/interfaces/index.ts deleted file mode 100644 index 7f959aaf..00000000 --- a/packages/web/src/interfaces/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './context' -export * from './metadata' diff --git a/packages/web/src/interfaces/metadata.ts b/packages/web/src/interfaces/metadata.ts deleted file mode 100644 index b9a7eee8..00000000 --- a/packages/web/src/interfaces/metadata.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { PARAM_TYPE } from "../constants" - -export namespace interfaces { - export interface BaseMetadata { - /** - * 名称 为空则为对象名称 - */ - name?: string - /** - * 支持的服务器列表 为空则代表所有 - */ - servers?: string[] - } - export interface WebMetadata extends BaseMetadata { - /** - * 路径 - */ - path: string - /** - * 对象 - */ - target?: any - } - export interface ControllerMetadata extends WebMetadata { - - } - interface Newable { - new(...args: any[]): T - } - interface Abstract { - prototype: T - } - export type ServiceIdentifier = (string | symbol | Newable | Abstract) - export interface MiddlewareMetadata extends BaseMetadata { - /** - * 中间件名称列表 - */ - names: Array> - } - export type Method = 'ALL' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'TRACE' - export interface ActionMetadata extends WebMetadata { - /** - * 请求方法 - */ - method?: Method - /** - * 执行器 - */ - executor?: string - } - export interface ParamMetadata extends BaseMetadata { - /** - * 参数类型 - */ - type?: PARAM_TYPE - /** - * 默认值 - */ - default?: any - /** - * 参数位置 - */ - index?: number - /** - * 参数对象类型 - */ - paramtype?: NewableFunction - /** - * 是否必传 - */ - require?: boolean - /** - * 异常消息 - */ - message?: string - } -} diff --git a/packages/web/src/server.ts b/packages/web/src/server.ts deleted file mode 100644 index 644fca8b..00000000 --- a/packages/web/src/server.ts +++ /dev/null @@ -1,323 +0,0 @@ -import * as querystring from 'querystring' - -import { web, plugin } from '@ccms/api' -import { provideSingleton, JSClass, postConstruct, Container, ContainerInstance, inject } from '@ccms/container' - -import { WebProxyBeanName, FilterProxyBeanName, METADATA_KEY, PARAM_TYPE } from './constants' -import { Context, InterceptorAdapter, RequestHandler, interfaces } from './interfaces' -import { getControllerActions, getActionMetadata, getControllerMetadata, getActionParams, getControllerMetadatas } from './decorators' - -const HttpServletRequestWrapper = Java.type('javax.servlet.http.HttpServletRequestWrapper') -const HttpServletResponseWrapper = Java.type('javax.servlet.http.HttpServletResponseWrapper') -const ServletInputStream = Java.type('javax.servlet.ServletInputStream') -const ServletOutputStream = Java.type('javax.servlet.ServletOutputStream') - -@provideSingleton(web.Server) -export class Server { - @JSClass('pw.yumc.MiaoScript.web.WebServerProxy') - private WebServerProxy: any - @JSClass('pw.yumc.MiaoScript.web.WebFilterProxy') - private WebFilterProxy: any - - @inject(ContainerInstance) - private container: Container - - private StreamUtils = org.springframework.util.StreamUtils - private ResponseEntity = org.springframework.http.ResponseEntity - - private controllerActions: Map - private interceptors: Map - private methodMappings: Map> - - private beanFactory: org.springframework.beans.factory.support.DefaultListableBeanFactory - - @postConstruct() - initialization() { - this.beanFactory = base.getInstance().getAutowireCapableBeanFactory() - this.controllerActions = new Map() - this.interceptors = new Map() - this.methodMappings = new Map() - this.start() - process.on('plugin.after.enable', (plugin: plugin.Plugin) => this.registryPlugin(plugin)) - process.on('plugin.after.disable', (plugin: plugin.Plugin) => this.unregistryPlugin(plugin)) - } - - start() { - this.registryFilterProxy() - this.registryWebProxy() - } - - stop() { - try { - this.beanFactory.destroySingleton(FilterProxyBeanName) - this.beanFactory.destroySingleton(WebProxyBeanName) - } catch (error: any) { - console.ex(error) - } - } - - registryPlugin(plugin: plugin.Plugin) { - let controllers = getControllerMetadatas(plugin).values() - for (const controller of controllers) { - console.debug(`Plugin ${plugin.description.name} Registry Controller ${controller.name}.`) - this.registryController(controller.target) - } - } - - unregistryPlugin(plugin: plugin.Plugin) { - let controllers = getControllerMetadatas(plugin).values() - for (const controller of controllers) { - console.debug(`Plugin ${plugin.description.name} Unregistry Controller ${controller.name}.`) - this.unregistryController(controller.target) - } - } - - registryController(target: any) { - if (!target) { throw new Error('Controller can\'t be undefiend!') } - let controllerMetadata = getControllerMetadata(target) - if (!controllerMetadata) { throw new Error(`Controller ${target.name} must have @Controller decorator!`) } - target = this.bindController(target) - let actions = getControllerActions(target) - this.controllerActions.set(controllerMetadata.name, []) - for (const action of actions) { - let actionMetadata = getActionMetadata(target, action) - this.controllerActions.get(controllerMetadata.name).push(actionMetadata) - let path = `${controllerMetadata.path || ''}${actionMetadata.path || ''}` - if (!path) throw new Error(`Controller ${controllerMetadata.name} Action ${actionMetadata.name} path is empty!`) - if (!this.methodMappings.has(path)) { this.methodMappings.set(path, new Map()) } - console.debug(`Controller ${controllerMetadata.name} Registry ${path} Action to ${actionMetadata.executor || ''} function.`) - this.methodMappings.get(path).set(actionMetadata.method || 'ALL', (ctx: Context) => { - let args = [] - let params = getActionParams(target, action) - for (const index in params) { - let param = params[index] - let paramValue = undefined - switch (param.type) { - case PARAM_TYPE.REQUEST: paramValue = ctx.request; break - case PARAM_TYPE.RESPONSE: paramValue = ctx.response; break - case PARAM_TYPE.QUERY: paramValue = ctx.params[param.name]; break - case PARAM_TYPE.HEADER: paramValue = ctx.headers[param.name]; break - case PARAM_TYPE.BODY: paramValue = ctx.body; break - case PARAM_TYPE.COOKIE: paramValue = ctx.cookies[param.name]; break - } - if (param.require && !paramValue) { - return { - status: 400, - msg: param.message ?? `Param Type ${param.type} require not empty!`, - data: param - } - } - args[param.index] = paramValue ?? param.default - } - return target[actionMetadata.executor].apply(target, args) - }) - } - } - - private bindController(target: any) { - try { - this.container.rebind(METADATA_KEY.Controller).to(target).inSingletonScope().whenTargetNamed(target.name) - } catch{ - this.container.bind(METADATA_KEY.Controller).to(target).inSingletonScope().whenTargetNamed(target.name) - } - return this.container.getNamed(METADATA_KEY.Controller, target.name) - } - - unregistryController(target: any) { - if (!target) { throw new Error('Controller can\'t be undefiend!') } - let controllerMetadata = getControllerMetadata(target) - if (!controllerMetadata) { throw new Error(`Controller ${target.name} must have @Controller decorator!`) } - if (!this.controllerActions.has(controllerMetadata.name)) { return console.warn(`Controller ${controllerMetadata.name} not registry!`) } - let actions = this.controllerActions.get(controllerMetadata.name) - for (const actionMetadata of actions) { - let path = `${controllerMetadata.path || ''}${actionMetadata.path || ''}` - if (!this.methodMappings.has(path)) { continue } - this.methodMappings.get(path).delete(actionMetadata.method) - console.debug(`Controller ${controllerMetadata.name} Unregistry ${path} Action.`) - } - this.controllerActions.delete(controllerMetadata.name) - } - - registryMapping(path: string, handler: RequestHandler) { - console.debug(`Registry Mapping ${path} to handle ${handler.name || ''} function.`) - if (!this.methodMappings.has(path)) { this.methodMappings.set(path, new Map()) } - this.methodMappings.get(path).set("ALL", handler) - } - - unregistryMapping(path: string) { - if (this.methodMappings.has(path)) { this.methodMappings.get(path).delete("ALL") } - } - - registryInterceptor(interceptor: InterceptorAdapter) { - console.debug(`Registry ${interceptor.name} Interceptor.`) - this.interceptors.set(interceptor.name, interceptor) - } - - unregistryInterceptor(interceptor: string | InterceptorAdapter) { - if (typeof interceptor === "string") { interceptor = { name: interceptor } } - console.debug(`Unregistry ${interceptor.name} Interceptor.`) - this.interceptors.delete(interceptor.name) - } - - private registryFilterProxy() { - try { this.beanFactory.destroySingleton(FilterProxyBeanName) } catch (ex: any) { } - var WebFilterProxyNashorn = Java.extend(this.WebFilterProxy, { - doFilter: (servletRequest: javax.servlet.http.HttpServletRequest, servletResponse: javax.servlet.http.HttpServletResponse, filterChain: javax.servlet.FilterChain) => { - filterChain.doFilter(servletRequest, servletResponse) - } - }) - this.beanFactory.registerSingleton(FilterProxyBeanName, new WebFilterProxyNashorn()) - } - - // private getRequestWrapper(servletRequest: javax.servlet.http.HttpServletRequest) { - // var body = org.springframework.util.StreamUtils.copyToByteArray(servletRequest.getInputStream()) - // var HttpServletRequestWrapperAdapter = Java.extend(HttpServletRequestWrapper, { - // getInputStream: () => { - // var bais = new java.io.ByteArrayInputStream(body) - // return new ServletInputStream({ - // read: () => bais.read(), - // isFinished: () => bais.available() == 0 - // }) - // } - // }) - // var wrapper = new HttpServletRequestWrapperAdapter(servletRequest) - // return wrapper - // } - - // private getResponseWrapper(servletResponse: javax.servlet.http.HttpServletResponse) { - // var HttpServletRequestWrapperAdapter = Java.extend(HttpServletRequestWrapper, { - // getOutputStream: () => { - // return new ServletOutputStream({ - // }) - // } - // }) - // var wrapper = new HttpServletRequestWrapperAdapter(servletResponse) - // return wrapper - // } - - private notFound(ctx: Context) { - return { - status: 404, - msg: "handlerMapping Not Found!", - method: ctx.request.getMethod(), - path: ctx.request.getRequestURI(), - timestamp: Date.now() - } - } - - private registryWebProxy() { - try { this.beanFactory.destroySingleton(WebProxyBeanName) } catch (ex: any) { } - var WebServerProxyNashorn = Java.extend(this.WebServerProxy, { - process: (req: javax.servlet.http.HttpServletRequest, resp: javax.servlet.http.HttpServletResponse) => { - let ctx: Context = { request: req, response: resp, params: {}, body: {} } - ctx.url = req.getRequestURI() - // @ts-ignore - ctx.headers = { __noSuchProperty__: (name: string) => req.getHeader(name) } - ctx.cookies = {} - for (const cookie of (req.getCookies() || [])) { - ctx.cookies[cookie.getName()] = cookie.getValue() - } - if (req.getQueryString()) { - ctx.url += `?${req.getQueryString()}` - ctx.params = querystring.parse(req.getQueryString()) - } - if (req.getMethod() == "POST") { - ctx.body = this.StreamUtils.copyToString(req.getInputStream(), java.nio.charset.StandardCharsets.UTF_8) - if ((ctx.headers['Content-Type'] || '').includes('application/json')) { - try { - ctx.body = JSON.parse(ctx.body) - } catch (error: any) { - return { - status: 500, - msg: `parse json body error: ${error}`, - path: ctx.url, - error: console.stack(error, false), - timestamp: Date.now() - } - } - } - } - let result = this.process(ctx) - result?.status && resp.setStatus(result.status) - return result - } - }) - this.beanFactory.registerSingleton(WebProxyBeanName, new WebServerProxyNashorn()) - } - - - private process(ctx: Context) { - let startTime = Date.now() - for (const [_, interceptor] of this.interceptors) { - if (interceptor.preHandle) { - try { - let startTime = Date.now() - ctx.result = interceptor.preHandle(ctx) - let preHandleTime = Date.now() - startTime - if (preHandleTime > 20) { - console.debug(`[WARN] Interceptor ${interceptor.name} preHandle cost time ${preHandleTime}ms!`) - } - if (ctx.result) { return ctx.result } - } catch (error: any) { - console.ex(error) - return { - status: 500, - msg: `Interceptor ${interceptor.name} preHandle error: ${error}`, - path: ctx.url, - error: console.stack(error, false), - timestamp: Date.now() - } - } - } - } - let path = ctx.request.getRequestURI() - if (!this.methodMappings.has(path)) return this.notFound(ctx) - let mappings = this.methodMappings.get(ctx.request.getRequestURI()) - ctx.handler = mappings.get(ctx.request.getMethod()) || mappings.get("ALL") - ctx.result = this.execRequestHandle(ctx) - for (const [_, interceptor] of this.interceptors) { - if (interceptor.postHandle) { - try { - let startTime = Date.now() - ctx.result = interceptor.postHandle(ctx) - let preHandleTime = Date.now() - startTime - if (preHandleTime > 20) { - console.debug(`[WARN] Interceptor ${interceptor.name} preHandle cost time ${preHandleTime}ms!`) - } - } catch (error: any) { - return { - status: 500, - msg: `Interceptor ${interceptor.name} postHandle error: ${error}`, - path: ctx.url, - error: console.stack(error, false), - timestamp: Date.now() - } - } - } - } - console.debug(` -===================== MiaoSpring ===================== -Request Method : ${ctx.request.getMethod()} -Request URL : ${ctx.url} -Request Body : ${JSON.stringify(ctx.body)} -Response Body : ${JSON.stringify(Java.asJSONCompatible(ctx.result))} -Handle Time : ${Date.now() - startTime}ms -======================================================`) - return ctx.result - } - - private execRequestHandle(ctx: Context) { - if (!ctx.handler) return this.notFound(ctx) - try { - return ctx.handler(ctx) - } catch (error: any) { - return { - status: 500, - msg: '' + error, - path: ctx.url, - error: console.stack(error, false), - timestamp: Date.now() - } - } - } -} diff --git a/packages/web/tsconfig.json b/packages/web/tsconfig.json deleted file mode 100644 index 7aae5d2b..00000000 --- a/packages/web/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "baseUrl": "src", - "outDir": "dist" - } -} \ No newline at end of file