diff --git a/packages/core/src/context.ts b/packages/core/src/context.ts index a34241ea9..876af1f52 100644 --- a/packages/core/src/context.ts +++ b/packages/core/src/context.ts @@ -8,7 +8,6 @@ import { Commander } from './command' import { I18n } from './i18n' import { Session } from './session' import { Processor } from './middleware' -import { SchemaService } from './schema' import { Permissions } from './permission' import { KoishiDatabase } from './database' import { KoishiBot } from './bot' @@ -38,7 +37,7 @@ type OmitSubstring = S extends `${infer L}${ type BeforeEventName = OmitSubstring type BeforeEventMap = { [E in keyof Events & string as OmitSubstring]: Events[E] } -export interface Events extends satori.Events {} +export interface Events extends cordis.Events {} export interface Context { [Context.events]: Events @@ -59,7 +58,6 @@ export class Context extends satori.Context { this.provide('$filter', new FilterService(this), true) this.provide('$processor', new Processor(this), true) this.provide('i18n', new I18n(this, this.config.i18n), true) - this.provide('schema', new SchemaService(this), true) this.provide('permissions', new Permissions(this), true) this.provide('model', undefined, true) this.provide('http', undefined, true) @@ -79,6 +77,7 @@ export class Context extends satori.Context { } /* eslint-disable max-len */ + /** @deprecated */ waterfall>(name: K, ...args: Parameters[K]>): Promisify[K]>> waterfall>(thisArg: ThisType[K]>, name: K, ...args: Parameters[K]>): Promisify[K]>> async waterfall(...args: [any, ...any[]]) { @@ -91,6 +90,7 @@ export class Context extends satori.Context { return args[0] } + /** @deprecated */ chain>(name: K, ...args: Parameters[K]>): ReturnType[K]> chain>(thisArg: ThisType[K]>, name: K, ...args: Parameters[K]>): ReturnType[K]> chain(...args: [any, ...any[]]) { diff --git a/packages/core/src/filter.ts b/packages/core/src/filter.ts index 6a367fcc4..3d13edc76 100644 --- a/packages/core/src/filter.ts +++ b/packages/core/src/filter.ts @@ -1,5 +1,6 @@ import { defineProperty } from 'cosmokit' import { Eval } from 'minato' +import { Schema } from '@satorijs/core' import { Channel, User } from './database' import { Context } from './context' import { Session } from './session' @@ -105,3 +106,64 @@ export class FilterService { return property(this.caller.exclude(property(this.caller, 'guildId')), 'userId', ...values) } } + +declare global { + interface Schemastery { + computed(options?: Computed.Options): Schema, Computed> + } + + namespace Schemastery { + interface Static { + path(options?: Path.Options): Schema + filter(): Schema> + computed(inner: X, options?: Computed.Options): Schema>, Computed>> + dynamic(name: string): Schema + } + + namespace Path { + interface Options { + filters?: Filter[] + allowCreate?: boolean + } + + type Filter = FileFilter | 'file' | 'directory' + + interface FileFilter { + name: string + extensions: string[] + } + } + } +} + +Schema.dynamic = function dynamic(name) { + return Schema.any().role('dynamic', { name }) as never +} + +Schema.filter = function filter() { + return Schema.any().role('filter') +} + +Schema.computed = function computed(inner, options = {}) { + return Schema.union([ + Schema.from(inner), + Schema.object({ + $switch: Schema.object({ + branches: Schema.array(Schema.object({ + case: Schema.any(), + then: Schema.from(inner), + })), + default: Schema.from(inner), + }), + }).hidden(), + Schema.any().hidden(), + ]).role('computed', options) +} + +Schema.path = function path(options = {}) { + return Schema.string().role('path', options) +} + +Schema.prototype.computed = function computed(this: Schema, options = {}) { + return Schema.computed(this, options).default(this.meta.default) +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 960b9e3e8..8ac279724 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -8,7 +8,6 @@ export * from './database' export * from './filter' export * from './i18n' export * from './middleware' -export * from './schema' export * from './session' export * from './permission' export * from './command' diff --git a/packages/core/src/middleware.ts b/packages/core/src/middleware.ts index d0ecbce10..aeaa91055 100644 --- a/packages/core/src/middleware.ts +++ b/packages/core/src/middleware.ts @@ -1,6 +1,6 @@ import { coerce, makeArray, Random } from '@koishijs/utils' import { Awaitable, defineProperty, Dict, Time } from 'cosmokit' -import { Fragment, h } from '@satorijs/core' +import { EventOptions, Fragment, h } from '@satorijs/core' import { Context } from './context' import { Channel, User } from './database' import { Session } from './session' @@ -62,7 +62,7 @@ export namespace Matcher { } export class Processor { - _hooks: [Context, Middleware][] = [] + _hooks: [Context, Middleware, EventOptions][] = [] _sessions: Dict = Object.create(null) _userCache = new SharedCache>() _channelCache = new SharedCache>() @@ -136,8 +136,11 @@ export class Processor { return this[Context.current] as Context } - middleware(middleware: Middleware, prepend = false) { - return this.caller.lifecycle.register('middleware', this._hooks, middleware, prepend) + middleware(middleware: Middleware, options?: boolean | EventOptions) { + if (typeof options !== 'object') { + options = { prepend: options } + } + return this.caller.lifecycle.register('middleware', this._hooks, middleware, options) } match(pattern: string | RegExp, response: Matcher.Response, options: Matcher.Options) { diff --git a/packages/core/src/permission.ts b/packages/core/src/permission.ts index 3b9881da6..4e520f2e2 100644 --- a/packages/core/src/permission.ts +++ b/packages/core/src/permission.ts @@ -6,7 +6,7 @@ import { createMatch, MatchResult } from './i18n' const logger = new Logger('app') -declare module '@satorijs/core' { +declare module './context' { interface Context { permissions: Permissions } diff --git a/packages/core/src/schema.ts b/packages/core/src/schema.ts deleted file mode 100644 index c03a16141..000000000 --- a/packages/core/src/schema.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { Dict, remove } from 'cosmokit' -import { Schema } from '@satorijs/core' -import { Computed } from './filter' -import { Context } from './context' - -declare global { - interface Schemastery { - computed(options?: Computed.Options): Schema, Computed> - } - - namespace Schemastery { - interface Static { - path(options?: Path.Options): Schema - filter(): Schema> - computed(inner: X, options?: Computed.Options): Schema>, Computed>> - dynamic(name: string): Schema - } - - namespace Path { - interface Options { - filters?: Filter[] - allowCreate?: boolean - } - - type Filter = FileFilter | 'file' | 'directory' - - interface FileFilter { - name: string - extensions: string[] - } - } - } -} - -Schema.dynamic = function dynamic(name) { - return Schema.any().role('dynamic', { name }) as never -} - -Schema.filter = function filter() { - return Schema.any().role('filter') -} - -Schema.computed = function computed(inner, options = {}) { - return Schema.union([ - Schema.from(inner), - Schema.object({ - $switch: Schema.object({ - branches: Schema.array(Schema.object({ - case: Schema.any(), - then: Schema.from(inner), - })), - default: Schema.from(inner), - }), - }).hidden(), - Schema.any().hidden(), - ]).role('computed', options) -} - -Schema.path = function path(options = {}) { - return Schema.string().role('path', options) -} - -Schema.prototype.computed = function computed(this: Schema, options = {}) { - return Schema.computed(this, options).default(this.meta.default) -} - -const kSchemaOrder = Symbol('schema-order') - -declare module '@satorijs/core' { - interface Context { - schema: SchemaService - } - - interface Events { - 'internal/schema'(name: string): void - } -} - -export class SchemaService { - _data: Dict = Object.create(null) - - constructor(public ctx: Context) { - this.extend('intercept.http', Schema.object({ - timeout: Schema.natural().role('ms').description('等待连接建立的最长时间。'), - proxyAgent: Schema.string().description('使用的代理服务器地址。'), - keepAlive: Schema.boolean().description('是否保持连接。'), - })) - } - - extend(name: string, schema: Schema, order = 0) { - const caller = this[Context.current] - const target = this.get(name) - const index = target.list.findIndex(a => a[kSchemaOrder] < order) - schema[kSchemaOrder] = order - if (index >= 0) { - target.list.splice(index, 0, schema) - } else { - target.list.push(schema) - } - this.ctx.emit('internal/schema', name) - caller?.on('dispose', () => { - remove(target.list, schema) - this.ctx.emit('internal/schema', name) - }) - } - - get(name: string) { - return this._data[name] ||= Schema.intersect([]) - } - - set(name: string, schema: Schema) { - const caller = this[Context.current] - this._data[name] = schema - this.ctx.emit('internal/schema', name) - caller?.on('dispose', () => { - delete this._data[name] - this.ctx.emit('internal/schema', name) - }) - } -}