From 9cdb98041be12c996b6e50e446a6a35eb819873e Mon Sep 17 00:00:00 2001 From: Shigma Date: Sun, 22 Oct 2023 11:59:33 +0800 Subject: [PATCH] refa: refactor internal services --- adapters/lark/src/bot.ts | 2 +- packages/axios/src/index.ts | 101 +++++++++++++-------------------- packages/core/package.json | 8 +-- packages/core/src/index.ts | 82 ++++++++++++++++---------- packages/core/src/internal.ts | 50 ---------------- packages/protocol/package.json | 2 +- 6 files changed, 98 insertions(+), 147 deletions(-) delete mode 100644 packages/core/src/internal.ts diff --git a/adapters/lark/src/bot.ts b/adapters/lark/src/bot.ts index e82dcdb9..7930ba2d 100644 --- a/adapters/lark/src/bot.ts +++ b/adapters/lark/src/bot.ts @@ -33,7 +33,7 @@ export class LarkBot extends Bot { 'Content-Type': 'application/json; charset=utf-8', }, }) - this.assetsQuester = Quester.create() + this.assetsQuester = ctx.http this.internal = new Internal(this.http) diff --git a/packages/axios/src/index.ts b/packages/axios/src/index.ts index d27a629a..c4392e09 100644 --- a/packages/axios/src/index.ts +++ b/packages/axios/src/index.ts @@ -1,4 +1,3 @@ -import { Context } from 'cordis' import { Agent } from 'agent-base' import { arrayBufferToBase64, base64ToArrayBuffer, Dict, pick, trimSlash } from 'cosmokit' import { ClientRequestArgs } from 'http' @@ -7,18 +6,6 @@ import axios, { AxiosRequestConfig, AxiosResponse, Method } from 'axios' import * as Axios from 'axios' import { isPrivate } from './ip' -declare module 'cordis' { - interface Context { - http: Quester - } - - namespace Context { - interface Config { - request?: Quester.Config - } - } -} - export interface Quester { (method: Method, url: string, config?: AxiosRequestConfig): Promise axios(config?: AxiosRequestConfig): Promise> @@ -27,12 +14,50 @@ export interface Quester { } export class Quester { - constructor(ctx: Context, config: Context.Config) { - return Quester.create(config.request) + constructor(config: Quester.Config) { + const request = async (config: AxiosRequestConfig = {}) => { + const options = http.prepare() + const error = new Error() as Axios.AxiosError + return axios({ + ...options, + ...config, + url: http.resolve(config.url!), + headers: { + ...options.headers, + ...config.headers, + }, + }).catch((cause) => { + if (!axios.isAxiosError(cause)) throw cause + Object.assign(error, cause) + error.isAxiosError = true + error.cause = cause + throw error + }) + } + + const http = (async (method, url, config) => { + const response = await request({ url, ...config, method }) + return response.data + }) as Quester + + Object.setPrototypeOf(http, Object.getPrototypeOf(this)) + for (const key of ['extend', 'get', 'delete', 'post', 'put', 'patch', 'head', 'ws']) { + http[key] = this[key].bind(http) + } + + http.config = config + http.axios = (...args: any[]) => { + if (typeof args[0] === 'string') { + return request({ url: args[0], ...args[1] }) + } else { + return request(args[0]) + } + } + return http } extend(newConfig: Quester.Config): Quester { - return Quester.create({ + return new Quester({ ...this.config, ...newConfig, headers: { @@ -171,50 +196,6 @@ export namespace Quester { timeout?: number proxyAgent?: string } - - export function create(this: typeof Quester, config: Quester.Config = {}) { - const request = async (config: AxiosRequestConfig = {}) => { - const options = http.prepare() - const error = new Error() as Axios.AxiosError - return axios({ - ...options, - ...config, - url: http.resolve(config.url!), - headers: { - ...options.headers, - ...config.headers, - }, - }).catch((cause) => { - if (!axios.isAxiosError(cause)) throw cause - Object.assign(error, cause) - error.isAxiosError = true - error.cause = cause - throw error - }) - } - - const http = (async (method, url, config) => { - const response = await request({ url, ...config, method }) - return response.data - }) as Quester - - Object.setPrototypeOf(http, this.prototype) - for (const key of ['extend', 'get', 'delete', 'post', 'put', 'patch', 'head', 'ws']) { - http[key] = this.prototype[key].bind(http) - } - - http.config = config - http.axios = (...args: any[]) => { - if (typeof args[0] === 'string') { - return request({ url: args[0], ...args[1] }) - } else { - return request(args[0]) - } - } - return http - } } -Context.service('http', Quester) - export default Quester diff --git a/packages/core/package.json b/packages/core/package.json index f9b74b96..d15f4b9e 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -35,12 +35,12 @@ }, "dependencies": { "@satorijs/element": "^2.5.1", - "@satorijs/protocol": "^1.0.2", - "cordis": "^2.9.2", - "cordis-axios": "^3.3.2", + "@satorijs/protocol": "^1.1.0", + "cordis": "^2.10.0", + "cordis-axios": "^4.0.0", "cosmokit": "^1.5.1", "ws": "^8.14.2", "reggol": "^1.5.2", - "schemastery": "^3.13.1" + "schemastery": "^3.14.0" } } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 2b540892..f6f1fedc 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -6,7 +6,6 @@ import Schema from 'schemastery' import Logger from 'reggol' import Quester from 'cordis-axios' import { SendOptions } from '@satorijs/protocol' -import { Internal } from './internal' import h from '@satorijs/element' h.warn = new Logger('element').warn @@ -23,7 +22,6 @@ export * as Universal from '@satorijs/protocol' export * from './bot' export * from './adapter' -export * from './internal' export * from './message' export * from './session' @@ -48,6 +46,14 @@ Quester.createConfig = function createConfig(this, endpoint) { }).description('请求设置') } +export type Component = h.Render, Session> + +export namespace Component { + export interface Options { + session?: boolean + } +} + type EventCallback = (this: Session, session: Session, ...args: R) => T export interface Events extends cordis.Events { @@ -92,14 +98,34 @@ export interface Events extends cordis.Events { export interface Context { [Context.config]: Context.Config [Context.events]: Events - bots: Bot[] & Dict + http: Quester } export class Context extends cordis.Context { static readonly session = Symbol('session') - constructor(options?: Context.Config) { - super(options) + public bots = new Proxy([] as Bot[] & Dict, { + get(target, prop) { + if (prop in target || typeof prop === 'symbol') { + return Reflect.get(target, prop) + } + return target.find(bot => bot.sid === prop) + }, + deleteProperty(target, prop) { + if (prop in target || typeof prop === 'symbol') { + return Reflect.deleteProperty(target, prop) + } + const bot = target.findIndex(bot => bot.sid === prop) + if (bot < 0) return true + target.splice(bot, 1) + return true + }, + }) + + constructor(config: Context.Config = {}) { + super(config) + + this.http = new Quester(config.request) this.on('internal/warning', (format, ...args) => { this.logger('app').warn(format, ...args) @@ -109,10 +135,29 @@ export class Context extends cordis.Context { logger(name: string) { return new Logger(name) } + + component(name: string, component: Component, options: Component.Options = {}) { + const render: Component = async (attrs, children, session) => { + if (options.session && session.type === 'send') { + throw new Error('interactive components is not available outside sessions') + } + const result = await component(attrs, children, session) + return session.transform(h.normalize(result)) + } + const service = 'component:' + name + this.root.provide(service) + this[service] = render + return this.collect('component', () => { + this[service] = null + return true + }) + } } export namespace Context { - export interface Config extends cordis.Context.Config {} + export interface Config extends cordis.Context.Config { + request?: Quester.Config + } export const Config: Config.Static = Schema.intersect([ Schema.object({}), @@ -122,28 +167,3 @@ export namespace Context { export interface Static extends Schema {} } } - -Context.service('internal', Internal) - -Context.service('bots', class { - constructor(root: Context) { - const list: Bot[] = [] - return new Proxy(list, { - get(target, prop) { - if (prop in target || typeof prop === 'symbol') { - return target[prop] - } - return list.find(bot => bot.sid === prop) - }, - deleteProperty(target, prop) { - if (prop in target || typeof prop === 'symbol') { - return delete target[prop] - } - const bot = target.findIndex(bot => bot.sid === prop) - if (bot < 0) return true - target.splice(bot, 1) - return true - }, - }) - } -}) diff --git a/packages/core/src/internal.ts b/packages/core/src/internal.ts deleted file mode 100644 index bc337216..00000000 --- a/packages/core/src/internal.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Awaitable, defineProperty } from 'cosmokit' -import { Context, Session } from '.' -import h from '@satorijs/element' - -declare module '.' { - interface Context { - internal: Internal - component(name: string, component: Component, options?: Component.Options): () => boolean - } -} - -export type Component = h.Render, Session> - -export namespace Component { - export interface Options { - session?: boolean - } -} - -export class Internal { - static readonly methods = ['component'] - - public counter = 0 - - constructor(private root: Context) { - defineProperty(this, Context.current, root) - } - - protected get caller() { - return this[Context.current] as Context - } - - component(name: string, component: Component, options: Component.Options = {}) { - const render: Component = async (attrs, children, session) => { - if (options.session && session.type === 'send') { - throw new Error('interactive components is not available outside sessions') - } - const result = await component(attrs, children, session) - return session.transform(h.normalize(result)) - } - const ctx = this.caller - const service = 'component:' + name - Context.service(service) - ctx[service] = render - return ctx.collect('component', () => { - ctx[service] = null - return true - }) - } -} diff --git a/packages/protocol/package.json b/packages/protocol/package.json index 695cde67..aef1a1cf 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -1,7 +1,7 @@ { "name": "@satorijs/protocol", "description": "Protocol types for Satori protocol", - "version": "1.0.2", + "version": "1.1.0", "main": "lib/index.js", "types": "lib/index.d.ts", "exports": {