Skip to content

Commit

Permalink
refa: revert edbeaec
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jun 12, 2024
1 parent f57e86d commit 0082b6e
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 86 deletions.
2 changes: 2 additions & 0 deletions packages/core/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Processor } from './middleware'
import { Permissions } from './permission'
import DatabaseMixin from './database'
import BotMixin from './bot'
import { SchemaService } from './schema'

export type EffectScope = cordis.EffectScope<Context>
export type ForkScope = cordis.ForkScope<Context>
Expand Down Expand Up @@ -58,6 +59,7 @@ export class Context extends satori.Context {
])
this.mixin('$commander', ['command'])
this.provide('$filter', new FilterService(this), true)
this.provide('schema', new SchemaService(this), true)
this.provide('$processor', new Processor(this), true)
this.provide('i18n', new I18n(this, this.config.i18n), true)
this.provide('permissions', new Permissions(this), true)
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ class KoishiDatabase {
getAssignedChannels: 'database.getAssignedChannels',
setChannel: 'database.setChannel',
createChannel: 'database.createChannel',
getSelfIds: 'database.getSelfIds',
broadcast: 'broadcast',
})

Expand Down
101 changes: 16 additions & 85 deletions packages/core/src/filter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
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'
Expand Down Expand Up @@ -40,130 +39,62 @@ function property<K extends keyof Session>(ctx: Context, key: K, ...values: Sess
}

export class FilterService {
constructor(private app: Context) {
defineProperty(this, Context.current, app)
constructor(private ctx: Context) {
defineProperty(this, Context.current, ctx)

app.filter = () => true
app.on('internal/runtime', (runtime) => {
ctx.filter = () => true
ctx.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 })
return this.ctx.extend({ filter: () => true })
}

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

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

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

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

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

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

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

channel(...values: string[]) {
return property(this.caller, 'channelId', ...values)
return property(this.ctx, '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)
return property(this.ctx, 'platform', ...values)
}
}

declare global {
interface Schemastery<S, T> {
computed(options?: Computed.Options): Schema<Computed<S>, Computed<T>>
}

namespace Schemastery {
interface Static {
path(options?: Path.Options): Schema<string>
filter(): Schema<Computed<boolean>>
computed<X>(inner: X, options?: Computed.Options): Schema<Computed<TypeS<X>>, Computed<TypeT<X>>>
dynamic(name: string): Schema
}

namespace Path {
interface Options {
filters?: Filter[]
allowCreate?: boolean
}

type Filter = FileFilter | 'file' | 'directory'

interface FileFilter {
name: string
extensions: string[]
}
}
private() {
return this.ctx.intersect((session) => session.isDirect)
}
}

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)
}
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from './database'
export * from './filter'
export * from './i18n'
export * from './middleware'
export * from './schema'
export * from './session'
export * from './permission'
export * from './command'
Expand Down
120 changes: 120 additions & 0 deletions packages/core/src/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Dict, remove } from 'cosmokit'
import { Schema } from '@satorijs/core'
import { Computed } from './filter'
import { Context } from './context'

declare global {
interface Schemastery<S, T> {
computed(options?: Computed.Options): Schema<Computed<S>, Computed<T>>
}

namespace Schemastery {
interface Static {
path(options?: Path.Options): Schema<string>
filter(): Schema<Computed<boolean>>
computed<X>(inner: X, options?: Computed.Options): Schema<Computed<TypeS<X>>, Computed<TypeT<X>>>
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<Schema> = 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)
})
}
}

0 comments on commit 0082b6e

Please sign in to comment.