import { Awaitable, Dict, Promisify } from 'cosmokit'; export abstract class Service { static readonly setup: unique symbol; static readonly invoke: unique symbol; static readonly extend: unique symbol; static readonly tracker: unique symbol; static readonly provide: unique symbol; static readonly immediate: unique symbol; protected start(): Awaitable; protected stop(): Awaitable; protected fork?(ctx: C, config: any): void; protected ctx: C; name: string; config: T; constructor(...args: Spread); constructor(ctx: C, ...args: Spread); constructor(ctx: C, name: string, immediate?: boolean); protected [symbols.filter](ctx: Context): boolean; protected [symbols.setup](): void; protected [symbols.extend](props?: any): any; static [Symbol.hasInstance](instance: any): boolean; } export interface Tracker { associate?: string; property?: string; } export const symbols: { shadow: symbol; receiver: symbol; original: symbol; store: typeof Context.store; events: typeof Context.events; static: typeof Context.static; filter: typeof Context.filter; expose: typeof Context.expose; isolate: typeof Context.isolate; internal: typeof Context.internal; intercept: typeof Context.intercept; setup: typeof Service.setup; invoke: typeof Service.invoke; extend: typeof Service.extend; tracker: typeof Service.tracker; provide: typeof Service.provide; immediate: typeof Service.immediate; }; export function isConstructor(func: any): func is new (...args: any) => any; export function resolveConfig(plugin: any, config: any): any; export function isUnproxyable(value: any): boolean; export function joinPrototype(proto1: {}, proto2: {}): any; export function isObject(value: any): value is {}; export function getTraceable(ctx: Context, value: T, noTrap?: boolean): T; export function withProps(target: any, props?: {}): any; export function createCallable(name: string, proto: {}, tracker: Tracker): any; export type Inject = string[] | Dict; export function Inject(inject: Inject): (value: any, ctx: ClassDecoratorContext | ClassMethodDecoratorContext) => void; export namespace Inject { interface Meta { required: boolean; } function resolve(inject: Inject | null | undefined): { [k: string]: { required: boolean; }; }; } export type Plugin = Plugin.Function | Plugin.Constructor | Plugin.Object; export namespace Plugin { interface Base { name?: string; reactive?: boolean; reusable?: boolean; Config?: (config: any) => T; inject?: Inject; intercept?: Dict; } interface Transform { schema?: true; Config: (config: S) => T; } interface Function extends Base { (ctx: C, config: T): void; } interface Constructor extends Base { new (ctx: C, config: T): void; } interface Object extends Base { apply: (ctx: C, config: T) => void; } } export type Spread = undefined extends T ? [config?: T] : [config: T]; export interface Context { /** @deprecated use `ctx.inject()` instead */ using(deps: Inject, callback: Plugin.Function): ForkScope; inject(deps: Inject, callback: Plugin.Function): ForkScope; plugin(plugin: Plugin.Function & Plugin.Transform, ...args: Spread): ForkScope; plugin(plugin: Plugin.Constructor & Plugin.Transform, ...args: Spread): ForkScope; plugin(plugin: Plugin.Object & Plugin.Transform, ...args: Spread): ForkScope; plugin(plugin: Plugin.Function, ...args: Spread): ForkScope; plugin(plugin: Plugin.Constructor, ...args: Spread): ForkScope; plugin(plugin: Plugin.Object, ...args: Spread): ForkScope; } declare class Registry { ctx: C; private _counter; private _internal; protected context: Context; constructor(ctx: C, config: any); get counter(): number; get size(): number; resolve(plugin: Plugin, assert?: boolean): Function | undefined; get(plugin: Plugin): MainScope | undefined; has(plugin: Plugin): boolean; set(plugin: Plugin, state: MainScope): void; delete(plugin: Plugin): MainScope | undefined; keys(): IterableIterator; values(): IterableIterator>; entries(): IterableIterator<[Function, MainScope]>; forEach(callback: (value: MainScope, key: Function, map: Map>) => void): void; using(inject: Inject, callback: Plugin.Function): ForkScope; inject(inject: Inject, callback: Plugin.Function): ForkScope; plugin(plugin: Plugin, config?: any, error?: any): ForkScope; } export interface Context { scope: EffectScope; runtime: MainScope; effect(callback: Callable): T; effect(callback: Callable, config: R): T; /** @deprecated use `ctx.effect()` instead */ collect(label: string, callback: () => void): () => void; accept(callback?: (config: this['config']) => void | boolean, options?: AcceptOptions): () => boolean; accept(keys: (keyof this['config'])[], callback?: (config: this['config']) => void | boolean, options?: AcceptOptions): () => boolean; decline(keys: (keyof this['config'])[]): () => boolean; } export type Disposable = () => void; export type DisposableLike = Disposable | { dispose: Disposable; }; export type Callable = ((...args: R) => T) | (new (...args: R) => T); export interface AcceptOptions { passive?: boolean; immediate?: boolean; } export interface Acceptor extends AcceptOptions { keys?: string[]; callback?: (config: any) => void | boolean; } export const enum ScopeStatus { PENDING = 0, LOADING = 1, ACTIVE = 2, FAILED = 3, DISPOSED = 4 } export class CordisError extends Error { code: CordisError.Code; constructor(code: CordisError.Code, message?: string); } export namespace CordisError { type Code = keyof typeof Code; const Code: { readonly INACTIVE_EFFECT: "cannot create effect on inactive context"; }; } export abstract class EffectScope { parent: C; config: C['config']; uid: number | null; ctx: C; disposables: Disposable[]; error: any; status: ScopeStatus; isActive: boolean; protected context: Context; protected proxy: any; protected acceptors: Acceptor[]; protected tasks: Set>; protected hasError: boolean; abstract runtime: MainScope; abstract dispose(): boolean; abstract update(config: C['config'], forced?: boolean): void; constructor(parent: C, config: C['config']); protected get _config(): any; assertActive(): void; effect(callback: Callable, config?: any): { dispose: Disposable; } | (() => void); collect(label: string, callback: () => any): () => any; restart(): void; protected _getStatus(): ScopeStatus; updateStatus(callback?: () => void): void; ensure(callback: () => Promise): void; cancel(reason?: any): void; get ready(): boolean; reset(): void; protected init(error?: any): void; start(): true | undefined; accept(callback?: (config: C['config']) => void | boolean, options?: AcceptOptions): () => boolean; accept(keys: string[], callback?: (config: C['config']) => void | boolean, options?: AcceptOptions): () => boolean; decline(keys: string[]): () => boolean; checkUpdate(resolved: any, forced?: boolean): boolean[]; } export class ForkScope extends EffectScope { runtime: MainScope; dispose: () => boolean; constructor(parent: Context, runtime: MainScope, config: C['config'], error?: any); start(): true | undefined; update(config: any, forced?: boolean): void; } export class MainScope extends EffectScope { plugin: Plugin; value: any; runtime: this; schema: any; name?: string; inject: Dict; forkables: Function[]; children: ForkScope[]; isReusable?: boolean; isReactive?: boolean; constructor(ctx: C, plugin: Plugin, config: any, error?: any); get isForkable(): boolean; fork(parent: Context, config: any, error?: any): ForkScope; dispose(): boolean; private setup; private apply; reset(): void; start(): true | undefined; update(config: C['config'], forced?: boolean): void; } export interface Context { get(name: K): undefined | this[K]; get(name: string): any; set(name: K, value: undefined | this[K]): () => void; set(name: string, value: any): () => void; /** @deprecated use `ctx.set()` instead */ provide(name: string, value?: any, builtin?: boolean): void; accessor(name: string, options: Omit): void; alias(name: string, aliases: string[]): void; mixin(name: K, mixins: (keyof this & keyof this[K])[] | Dict): void; mixin(source: T, mixins: (keyof this & keyof T)[] | Dict): void; } declare class ReflectService { ctx: Context; static resolveInject(ctx: Context, name: string): readonly [string, Context.Internal.Service | Context.Internal.Accessor]; static checkInject(ctx: Context, name: string, error: Error): void; static handler: ProxyHandler; constructor(ctx: Context); get(name: string): any; set(name: string, value: any): () => void; provide(name: string, value?: any, builtin?: boolean): void; _accessor(name: string, options: Omit): () => void; accessor(name: string, options: Omit): void; alias(name: string, aliases: string[]): void; _mixin(source: any, mixins: string[] | Dict): () => void; mixin(source: any, mixins: string[] | Dict): void; trace(value: T): T; bind(callback: T): T; } export function isBailed(value: any): boolean; export type Parameters = F extends (...args: infer P) => any ? P : never; export type ReturnType = F extends (...args: any) => infer R ? R : never; export type ThisType = F extends (this: infer T, ...args: any) => any ? T : never; export type GetEvents = C[typeof Context.events]; export interface Context { [Context.events]: Events; parallel>(name: K, ...args: Parameters[K]>): Promise; parallel>(thisArg: ThisType[K]>, name: K, ...args: Parameters[K]>): Promise; emit>(name: K, ...args: Parameters[K]>): void; emit>(thisArg: ThisType[K]>, name: K, ...args: Parameters[K]>): void; serial>(name: K, ...args: Parameters[K]>): Promisify[K]>>; serial>(thisArg: ThisType[K]>, name: K, ...args: Parameters[K]>): Promisify[K]>>; bail>(name: K, ...args: Parameters[K]>): ReturnType[K]>; bail>(thisArg: ThisType[K]>, name: K, ...args: Parameters[K]>): ReturnType[K]>; on>(name: K, listener: GetEvents[K], options?: boolean | EventOptions): () => boolean; once>(name: K, listener: GetEvents[K], options?: boolean | EventOptions): () => boolean; off>(name: K, listener: GetEvents[K]): boolean; start(): Promise; stop(): Promise; } export interface EventOptions { prepend?: boolean; global?: boolean; } export interface Hook extends EventOptions { ctx: Context; callback: (...args: any[]) => any; } declare class Lifecycle { private ctx; isActive: boolean; _tasks: Set>; _hooks: Record; constructor(ctx: Context); flush(): Promise; filterHooks(hooks: Hook[], thisArg?: object): Hook[]; dispatch(type: string, args: any[]): Generator; parallel(...args: any[]): Promise; emit(...args: any[]): void; serial(...args: any[]): Promise; bail(...args: any[]): any; register(label: string, hooks: Hook[], callback: any, options: EventOptions): () => any; unregister(hooks: Hook[], callback: any): true | undefined; on(name: string, listener: (...args: any) => any, options?: boolean | EventOptions): any; once(name: string, listener: (...args: any) => any, options?: boolean | EventOptions): any; start(): Promise; stop(): Promise; } export interface Events { 'fork'(ctx: C, config: C['config']): void; 'ready'(): Awaitable; 'dispose'(): Awaitable; 'internal/fork'(fork: ForkScope): void; 'internal/runtime'(runtime: MainScope): void; 'internal/status'(scope: EffectScope, oldValue: ScopeStatus): void; 'internal/info'(this: C, format: any, ...param: any[]): void; 'internal/error'(this: C, format: any, ...param: any[]): void; 'internal/warning'(this: C, format: any, ...param: any[]): void; 'internal/before-service'(this: C, name: string, value: any): void; 'internal/service'(this: C, name: string, value: any): void; 'internal/before-update'(fork: ForkScope, config: any): void; 'internal/update'(fork: ForkScope, oldConfig: any): void; 'internal/inject'(this: C, name: string): boolean | undefined; 'internal/listener'(this: C, name: string, listener: any, prepend: boolean): void; 'internal/event'(type: 'emit' | 'parallel' | 'serial' | 'bail', name: string, args: any[], thisArg: any): void; } export { Lifecycle, ReflectService, Registry }; export namespace Context { type Parameterized = C & { config: T; }; /** @deprecated use `string[]` instead */ interface MixinOptions { methods?: string[]; accessors?: string[]; prototype?: {}; } interface Item { value?: any; source: C; } type Internal = Internal.Service | Internal.Accessor | Internal.Alias; namespace Internal { interface Service { type: 'service'; builtin?: boolean; prototype?: {}; } interface Accessor { type: 'accessor'; get: (this: Context, receiver: any) => any; set?: (this: Context, value: any, receiver: any) => boolean; } interface Alias { type: 'alias'; name: string; } } } export interface Intercept { } export interface Context { [Context.store]: Dict, symbol>; [Context.isolate]: Dict; [Context.intercept]: Intercept; [Context.internal]: Dict; root: this; lifecycle: Lifecycle; reflect: ReflectService; registry: Registry; config: any; } export class Context { static readonly store: unique symbol; static readonly events: unique symbol; static readonly static: unique symbol; static readonly filter: unique symbol; static readonly expose: unique symbol; static readonly isolate: unique symbol; static readonly internal: unique symbol; static readonly intercept: unique symbol; static readonly origin = "ctx"; static readonly current = "ctx"; static is(value: any): value is C; /** @deprecated use `Service.traceable` instead */ static associate(object: T, name: string): T; constructor(config?: any); get name(): string; get events(): Lifecycle; /** @deprecated */ get state(): EffectScope; extend(meta?: {}): this; isolate(name: string, label?: symbol): this; intercept(name: K, config: Intercept[K]): this; }