Skip to content

Commit

Permalink
refa: fix core typings
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jul 10, 2022
1 parent 3fdb20d commit 5b4e074
Show file tree
Hide file tree
Showing 16 changed files with 76 additions and 195 deletions.
6 changes: 2 additions & 4 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,14 @@
"koishi"
],
"devDependencies": {
"@koishijs/plugin-database-memory": "^1.4.0",
"@koishijs/plugin-mock": "^1.0.6",
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"chai-shape": "^1.0.0"
},
"dependencies": {
"@koishijs/utils": "^5.4.5",
"@satorijs/core": "^1.0.0",
"cordis": "^2.0.3",
"@satorijs/core": "^1.0.1",
"cordis": "^2.0.4",
"fastest-levenshtein": "^1.0.12",
"minato": "^1.2.2"
}
Expand Down
10 changes: 8 additions & 2 deletions packages/core/src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ declare module '@satorijs/core' {
}
}

export { satori }
export { Adapter } from '@satorijs/core'
export { Adapter, h, Message, segment } from '@satorijs/core'

export type Filter = satori.Filter<Context>

export const Bot = satori.Bot<Context>
export type Bot = satori.Bot<Context>

export namespace Bot {
export type Status = satori.Bot.Status
export type Config = satori.Bot.Config
}

Bot.prototype.session = function session(this: Bot, payload) {
return new Session(this, payload)
}
Expand Down
9 changes: 3 additions & 6 deletions packages/core/src/command/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ interface CommandMap extends Map<string, Command> {
}

declare module '../context' {
interface Context extends Commander.Mixin {
interface Context {
$commander: Commander
command<D extends string>(def: D, config?: Command.Config): Command<never, never, Argv.ArgumentType<D>>
command<D extends string>(def: D, desc: string, config?: Command.Config): Command<never, never, Argv.ArgumentType<D>>
}

interface Events {
Expand All @@ -34,11 +36,6 @@ declare module '../context' {

export namespace Commander {
export interface Config {}

export interface Mixin {
command<D extends string>(def: D, config?: Command.Config): Command<never, never, Argv.ArgumentType<D>>
command<D extends string>(def: D, desc: string, config?: Command.Config): Command<never, never, Argv.ArgumentType<D>>
}
}

export class Commander {
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/command/parser.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { camelCase, Dict, escapeRegExp, paramCase, segment, Time } from '@koishijs/utils'
import { camelCase, Dict, escapeRegExp, paramCase, Time } from '@koishijs/utils'
import { segment } from '@satorijs/core'
import { Command } from './command'
import { Context } from '../context'
import { Channel, User } from '../database'
Expand Down
21 changes: 13 additions & 8 deletions packages/core/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,21 @@ export interface Events<C extends Context = Context> extends satori.Events<C> {
export interface Context {
[Context.events]: Events<this>
[Context.session]: Session
options: Context.Config
}

export class Context<T extends Context.Config = Context.Config> extends satori.Context<T> {
export class Context extends satori.Context {
constructor(options?: Context.Config) {
super(options)
}

get app() {
return this.root
}
}

export namespace Context {
export interface Config extends satori.Context.Config, Config.Basic, Config.Features, Config.Advanced {}

export const Config = Schema.intersect([]) as Config.Static
export interface Config extends satori.Context.Config, Config.Basic, Config.Message, Config.Advanced {}

export namespace Config {
export interface Basic {
Expand All @@ -48,7 +51,7 @@ export namespace Context {
autoAuthorize?: Computed<Awaitable<number>>
}

export interface Features {
export interface Message {
delay?: DelayConfig
}

Expand All @@ -67,11 +70,13 @@ export namespace Context {

export interface Static extends Schema<Config> {
Basic: Schema<Basic>
Features: Schema<Features>
Message: Schema<Message>
Advanced: Schema<Advanced>
}
}

export const Config = Schema.intersect([]) as Config.Static

defineProperty(Context.Config, 'Basic', Schema.object({
locale: Schema.string().default('zh').description('默认使用的语言。'),
prefix: Schema.union([
Expand All @@ -86,7 +91,7 @@ export namespace Context {
autoAuthorize: Schema.union([Schema.natural(), Function]).default(1).description('当获取不到用户数据时默认使用的权限等级。'),
}).description('基础设置'))

defineProperty(Context.Config, 'Features', Schema.object({
defineProperty(Context.Config, 'Message', Schema.object({
delay: Schema.object({
character: Schema.natural().role('ms').default(0).description('调用 `session.sendQueued()` 时消息间发送的最小延迟,按前一条消息的字数计算。'),
message: Schema.natural().role('ms').default(0.1 * Time.second).description('调用 `session.sendQueued()` 时消息间发送的最小延迟,按固定值计算。'),
Expand All @@ -101,7 +106,7 @@ export namespace Context {
maxListeners: Schema.natural().default(64).description('每种监听器的最大数量。如果超过这个数量,Koishi 会认定为发生了内存泄漏,将产生一个警告。'),
}).description('高级设置'))

Context.Config.list.push(Context.Config.Basic, Context.Config.Features, Context.Config.Advanced)
Context.Config.list.push(Context.Config.Basic, Context.Config.Message, Context.Config.Advanced)
}

// for backward compatibility
Expand Down
22 changes: 13 additions & 9 deletions packages/core/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ declare module './context' {
'model'(name: keyof Tables): void
}

interface Context extends DatabaseService.Mixin {
interface Context {
database: DatabaseService
model: DatabaseService
getSelfIds(type?: string, assignees?: string[]): Dict<string[]>
broadcast(content: string, forced?: boolean): Promise<string[]>
broadcast(channels: readonly string[], content: string, forced?: boolean): Promise<string[]>
}
}

Expand Down Expand Up @@ -58,14 +61,6 @@ export interface Tables {
channel: Channel
}

export namespace DatabaseService {
export interface Mixin {
getSelfIds(type?: string, assignees?: string[]): Dict<string[]>
broadcast(content: string, forced?: boolean): Promise<string[]>
broadcast(channels: readonly string[], content: string, forced?: boolean): Promise<string[]>
}
}

export class DatabaseService extends Database<Tables> {
static readonly methods = ['getSelfIds', 'broadcast']

Expand Down Expand Up @@ -94,6 +89,15 @@ export class DatabaseService extends Database<Tables> {
}, {
primary: ['id', 'platform'],
})

app.on('bot-added', (bot) => {
if (bot.platform in this.tables.user.fields) return
this.extend('user', {
[bot.platform]: { type: 'string', length: 63 },
}, {
unique: [bot.platform as never],
})
})
}

getUser<T extends string, K extends User.Field>(platform: T, id: string, modifier?: Driver.Cursor<K>): Promise<Result<User, K> & Record<T, string>>
Expand Down
7 changes: 2 additions & 5 deletions packages/core/src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { Channel, User } from './database'
import { Context } from './context'

declare module './context' {
interface Context extends Internal.Mixin {
interface Context {
$internal: Internal
middleware(middleware: Middleware, prepend?: boolean): () => boolean
}

interface Events {
Expand Down Expand Up @@ -42,10 +43,6 @@ export namespace Internal {
nickname?: string | string[]
prefix?: Computed<string | string[]>
}

export interface Mixin {
middleware(middleware: Middleware, prepend?: boolean): () => boolean
}
}

export class Internal {
Expand Down
87 changes: 1 addition & 86 deletions packages/core/src/selector.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,11 @@
import { defineProperty, Logger, Promisify, remove } from '@koishijs/utils'
import { GetEvents, Parameters, ReturnType, ThisType } from 'cordis'
import { Context, Events } from './context'
import { Session } from './session'

export type Filter = (session: Session) => boolean

/* eslint-disable max-len */
declare module './context' {
interface Context {
filter: Filter
selector: SelectorService
logger(name: string): Logger
any(): this
never(): this
union(arg: Filter | Context): this
intersect(arg: Filter | Context): this
exclude(arg: Filter | Context): this
user(...values: string[]): this
self(...values: string[]): this
guild(...values: string[]): this
channel(...values: string[]): this
platform(...values: string[]): this
private(...values: string[]): this
waterfall<K extends keyof GetEvents<this>>(name: K, ...args: Parameters<GetEvents<this>[K]>): Promisify<ReturnType<GetEvents<this>[K]>>
waterfall<K extends keyof GetEvents<this>>(thisArg: ThisType<GetEvents<this>[K]>, name: K, ...args: Parameters<GetEvents<this>[K]>): Promisify<ReturnType<GetEvents<this>[K]>>
chain<K extends keyof GetEvents<this>>(name: K, ...args: Parameters<GetEvents<this>[K]>): ReturnType<GetEvents<this>[K]>
Expand All @@ -38,94 +22,25 @@ type BeforeEventName = OmitSubstring<keyof Events & string, 'before-'>

export type BeforeEventMap = { [E in keyof Events & string as OmitSubstring<E, 'before-'>]: Events[E] }

function property<K extends keyof Session>(ctx: Context, key: K, ...values: Session[K][]) {
return ctx.intersect((session: Session) => {
return values.length ? values.includes(session[key]) : !!session[key]
})
}

export class SelectorService<C extends Context = Context> {
static readonly methods = [
'any', 'never', 'union', 'intersect', 'exclude', 'select',
'user', 'self', 'guild', 'channel', 'platform', 'private',
'chain', 'waterfall', 'before', 'logger', 'setTimeout', 'setInterval',
]
static readonly methods = ['chain', 'waterfall', 'before', 'logger', 'setTimeout', 'setInterval']

constructor(private app: C) {
defineProperty(this, Context.current, app)

app.filter = () => true

app.on('internal/warning', (format, ...args) => {
this.logger('app').warn(format, ...args)
})

app.on('internal/runtime', (runtime) => {
if (!runtime.uid) return
runtime.ctx.filter = (session) => {
return runtime.children.some(p => p.ctx.filter(session))
}
})
}

protected get caller() {
return this[Context.current] as Context
}

any() {
return this.caller.extend({ filter: () => true })
}

never() {
return this.caller.extend({ filter: () => false })
}

union(arg: Filter | C) {
const caller = this.caller
const filter = typeof arg === 'function' ? arg : arg.filter
return this.caller.extend({ filter: s => caller.filter(s) || filter(s) })
}

intersect(arg: Filter | C) {
const caller = this.caller
const filter = typeof arg === 'function' ? arg : arg.filter
return this.caller.extend({ filter: s => caller.filter(s) && filter(s) })
}

exclude(arg: Filter | C) {
const caller = this.caller
const filter = typeof arg === 'function' ? arg : arg.filter
return this.caller.extend({ filter: s => caller.filter(s) && !filter(s) })
}

logger(name: string) {
return new Logger(name)
}

user(...values: string[]) {
return property(this.caller, 'userId', ...values)
}

self(...values: string[]) {
return property(this.caller, 'selfId', ...values)
}

guild(...values: string[]) {
return property(this.caller, 'guildId', ...values)
}

channel(...values: string[]) {
return property(this.caller, 'channelId', ...values)
}

platform(...values: string[]) {
return property(this.caller, 'platform', ...values)
}

private(...values: string[]) {
return property(this.caller.exclude(property(this.caller, 'guildId')), 'userId', ...values)
}

async waterfall(...args: [any, ...any[]]) {
const thisArg = typeof args[0] === 'object' ? args.shift() : null
const name = args.shift()
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/session.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineProperty, isNullable, Logger, makeArray, observe, Promisify, segment } from '@koishijs/utils'
import { defineProperty, isNullable, Logger, makeArray, observe, Promisify } from '@koishijs/utils'
import * as satori from '@satorijs/core'
import { Argv, Command } from './command'
import { Context } from './context'
Expand Down Expand Up @@ -49,10 +49,10 @@ export class Session<U extends User.Field = never, G extends Channel.Field = nev
}

private async _preprocess() {
let node: segment.Parsed
let node: satori.segment.Parsed
let content = this.content.trim()
// eslint-disable-next-line no-cond-assign
if (node = segment.from(content, { type: 'quote', caret: true })) {
if (node = satori.segment.from(content, { type: 'quote', caret: true })) {
content = content.slice(node.capture[0].length).trimStart()
this.quote = await this.bot.getMessage(node.data.channelId || this.channelId, node.data.id).catch((error) => {
logger.warn(error)
Expand Down
2 changes: 1 addition & 1 deletion packages/core/tests/middleware.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ before(() => Logger.levels.base = 1)
after(() => Logger.levels.base = 2)

describe('Middleware Runtime', () => {
let callSequence: jest.Mock<any, any[]>[]
let callSequence: jest.Mock[]

beforeEach(() => {
app.$internal._hooks = []
Expand Down
Loading

0 comments on commit 5b4e074

Please sign in to comment.