Commit 6e4df9a2 authored by nanahira's avatar nanahira

rework typing system

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