Commit 6e4df9a2 authored by nanahira's avatar nanahira

rework typing system

parent d2b7c7cb
{
"name": "myproject",
"name": "cordis-decorators",
"version": "1.0.7",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "myproject",
"name": "cordis-decorators",
"version": "1.0.7",
"license": "MIT",
"dependencies": {
......
import { PluginRegistrar } from '../plugin-def';
import PluginClass = PluginRegistrar.PluginClass;
import { Context } from 'cordis';
export type Awaitable<T> = [T] extends [Promise<unknown>] ? T : T | Promise<T>;
export type TypedMethodDecorator<F extends (...args: any[]) => any> = <
......@@ -13,23 +11,6 @@ export type TypedMethodDecorator<F extends (...args: any[]) => any> = <
descriptor: TypedPropertyDescriptor<T>,
) => void;
export type FunctionParam<F extends (...args: any[]) => any> = F extends (
...args: infer R
) => any
? R
: never;
export type FunctionReturn<F extends (...args: any[]) => any> = F extends (
...args: any[]
) => infer R
? R
: never;
export type PickEventFunction<M, K extends keyof M = keyof M> = M[K] extends (
...args: any[]
) => any
? (...args: FunctionParam<M[K]>) => Awaitable<FunctionReturn<M[K]>>
: M[K];
export type ParamRenderer = <T>(v: T) => T;
export interface ControlTypeMap {
......@@ -57,6 +38,18 @@ export type ParamsFromClass<T> = T extends { new (...args: infer U): any }
? U
: never;
export type FunctionParams<F extends (...args: any[]) => any> = F extends (
...args: infer U
) => any
? U
: never;
export type FunctionReturn<F extends (...args: any[]) => any> = F extends (
...args: any
) => infer U
? U
: never;
export type Prop<T> = T;
export type PartialDeep<T> = T extends
......
import { Context, Plugin } from 'cordis';
import Schema from 'schemastery';
import { ClassType } from 'schemastery-gen';
import type { Registrar } from '../registrar';
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace PluginRegistrar {
......@@ -20,7 +19,7 @@ export namespace PluginRegistrar {
name?: string;
schema?: Schema<T> | ClassType<T>;
Config?: Schema<T> | ClassType<T>;
using?: Registrar.ServiceName<Ctx>[];
using?: string[];
reusable?: boolean;
}
......
import { Context } from 'cordis';
import { Registrar } from './registrar';
import { generateRenderer, renderObject } from './utility/render-object';
import { generateRenderer } from './utility/render-object';
import { extractObjectMethod } from './utility/utility';
import { ControlType } from './def';
import {
......@@ -9,13 +9,10 @@ import {
Observable,
ObservableInput,
ObservedValueOf,
of,
} from 'rxjs';
import _ from 'lodash';
type RecursiveUnwrapObservable<T> = T extends ObservableInput<any>
? RecursiveUnwrapObservable<ObservedValueOf<T>>
: T;
import ContextTransformer = Registrar.ContextTransformer;
import { RegisterMeta } from './utility/register-meta';
export class RegistrarAspect<Ctx extends Context, T = any> {
constructor(
......@@ -45,8 +42,11 @@ export class RegistrarAspect<Ctx extends Context, T = any> {
this.obj,
key,
);
const r = generateRenderer({ ...this.view, ...extraView });
return this.registrar.transformContext(ctx, contextFilters, r);
return this.registrar.transformContext(
ctx,
contextFilters as RegisterMeta<ContextTransformer<Ctx, any[]>>[],
{ ...this.view, ...extraView },
);
}
registerMethod(
......@@ -57,12 +57,18 @@ export class RegistrarAspect<Ctx extends Context, T = any> {
const data = this.registrar.reflector.get('CordisRegister', this.obj, key);
if (!data) return;
const specificCtx = this.getScopeContext(ctx, key, extraView, false);
const result = data.action(
const result = data.run(
{ ...this.view, ...extraView },
specificCtx,
extractObjectMethod(this.obj, key),
...renderObject(data.args, { ...this.view, ...extraView }),
);
return { ...data, key: key, result, ctx: specificCtx };
return {
...data,
type: data.info.type,
key: key,
result,
ctx: specificCtx,
};
}
private registerWithLoopControl(
......@@ -98,7 +104,7 @@ export class RegistrarAspect<Ctx extends Context, T = any> {
private runLayersWith<R extends ObservableInput<any>>(
ctx: Ctx,
cb: Registrar.ContextFunction<Ctx, R>,
layers: Registrar.ContextCallbackLayer<Ctx>[],
layers: RegisterMeta<Registrar.ContextCallbackLayer<Ctx>>[],
): Observable<ObservedValueOf<R>> {
const rest = [...layers];
const layer = rest.pop();
......@@ -106,7 +112,7 @@ export class RegistrarAspect<Ctx extends Context, T = any> {
return from(cb(ctx));
}
return new Observable((subscriber) => {
layer(ctx, async (nextCtx) => {
layer.run(this.view, ctx, async (nextCtx) => {
if (!rest.length) {
const result = cb(nextCtx);
if (result) {
......@@ -134,7 +140,11 @@ export class RegistrarAspect<Ctx extends Context, T = any> {
this.obj,
key as string,
);
return this.runLayersWith(ctx, cb, layers);
return this.runLayersWith(
ctx,
cb,
layers as RegisterMeta<Registrar.ContextCallbackLayer<Ctx>>[],
);
}
registerFor(ctx: Ctx, key: keyof T & string) {
......@@ -169,6 +179,8 @@ export class RegistrarAspect<Ctx extends Context, T = any> {
this.registrar.reflector.getArray('CordisTopLevelAction', this.obj),
);
const renderer = generateRenderer({ ...this.view, ...extraView });
actions.forEach((action) => action(ctx, this.obj, renderer));
actions.forEach((action) =>
action.run({ ...this.view, ...extraView }, ctx, this.obj, renderer),
);
}
}
This diff is collapsed.
import { renderObject } from './render-object';
import { FunctionParams, FunctionReturn } from '../def';
export class RegisterMeta<F extends (...args: any[]) => any, I = any> {
constructor(public action: F, public args: any[], public info?: I) {}
run(view: any, ...extras: FunctionParams<F>): FunctionReturn<F> {
return this.action(...extras, ...renderObject(this.args, view));
}
}
......@@ -14,8 +14,8 @@ declare module 'cordis' {
}
interface Events {
'pang'(message: string): Promise<string>;
'pong'(message: string): Promise<string>;
'pang'(message: string): string;
'pong'(message: string): string;
}
}
......@@ -101,14 +101,14 @@ class MyPartialConsumer {
@UsingService('dummyProvider')
@UseEvent('pang')
async onPang(content: string) {
onPang(content: string) {
const msg = `pang: ${content}`;
console.log(msg);
return msg;
}
@UseEvent('pong')
async onPong(content: string) {
onPong(content: string) {
const msg = `pong: ${content}`;
console.log(msg);
return msg;
......@@ -157,16 +157,16 @@ describe('On service', () => {
await app.start();
app.plugin(MyPartialConsumer);
expect(app.myPartialConsumer).toBeDefined();
expect(await app.parallel('pang', 'hello')).toEqual('hello');
expect(await app.parallel('pong', 'hello')).toEqual('pong: hello');
expect(app.bail('pang', 'hello')).toBeUndefined();
expect(app.bail('pong', 'hello')).toEqual('pong: hello');
app.dummyProvider = { foo: 'bar' };
expect(await app.parallel('pang', 'hello')).toEqual('pang: hello');
expect(await app.parallel('pong', 'hello')).toEqual('pong: hello');
expect(app.bail('pang', 'hello')).toEqual('pang: hello');
expect(app.bail('pong', 'hello')).toEqual('pong: hello');
app.dummyProvider = undefined;
expect(await app.parallel('pang', 'hi')).toEqual('hi');
expect(await app.parallel('pong', 'hi')).toEqual('pong: hi');
expect(app.bail('pang', 'hi')).toBeUndefined();
expect(app.bail('pong', 'hi')).toEqual('pong: hi');
app.dummyProvider = { foo: 'baz' };
expect(await app.parallel('pang', 'hi')).toEqual('pang: hi');
expect(await app.parallel('pong', 'hi')).toEqual('pong: hi');
expect(app.bail('pang', 'hi')).toEqual('pang: hi');
expect(app.bail('pong', 'hi')).toEqual('pong: hi');
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment