Commit c584a517 authored by nanahira's avatar nanahira

mid

parent adbfce6d
......@@ -11,42 +11,59 @@ import {
const ServiceClassPrefix = 'class:';
const ProvidePrefix = 'provide:';
export class AppContextCore<T = Empty, Req = Empty> {
private __current: T;
export class AppContextCore<Cur = Empty, Req = Empty> {
private __current: Cur;
private __required: Req;
registry = new Map<string, any>();
loadSeq: any[] = [];
provide<
C extends AppServiceClass<T>,
C extends AppServiceClass<Cur>,
const P extends string = '',
const M extends (keyof InstanceType<C>)[] = [],
>(
cls: C,
...args: AppProvideArgs<T, C, P, M>
): AppProvidedMerged<T, Req, C, P, M> {
...args: AppProvideArgs<Cur, Req, C, P, M>
): AppProvidedMerged<Cur, Req, C, P, M> {
const options = args[args.length - 1] as
| AppProvideOptions<T, C, P, M>
| AppProvideOptions<Cur, Req, C, P, M>
| undefined;
const _args: ConstructorParameters<C> = args;
const inst =
options?.useValue ??
(options?.useFactory
? options.useFactory(this as any, ..._args)
: new (options?.useClass ?? cls)(this as any, _args));
this.registry.set(ServiceClassPrefix + cls.name, inst);
return this as any;
}
get<R>(cls: AppServiceClass<T, any, R>): R {}
get<R>(cls: AppServiceClass<Cur, Req, any, R>): R {}
getAsync<R>(cls: AppServiceClass<Cur, Req, any, R>): Promise<R> {}
use<T2>(ctx: AppContext<T2, T>): AppContext<Prettify<T & T2>, Req> {
use<const Ctxes extends AppContext<any, any>[]>(
...ctxes: Ctxes
): AppContextUsed<Cur, Req, Ctxes> {
return this as any;
}
define(): AppContext<T, Req> {
define(): AppContext<Cur, Req> {
return this as any;
}
async start(): Promise<AppContext<T, Req>> {
async start(): Promise<Empty extends Req ? AppContext<Cur, Req> : never> {
return this as any;
}
}
export const createAppContext = <Req = Empty>() =>
new AppContextCore<Req, Req>() as AppContext<Req, Req>;
new AppContextCore<Empty, Req>() as AppContext<Empty, Req>;
// testing code below
......@@ -86,7 +103,6 @@ async function test() {
.provide(Bar, 5, {
merge: ['getBar'],
})
.provide(Foo, 3, { provide: 'foo22' })
.define();
const ctx2 = createAppContext<{ foo: Foo }>()
......@@ -95,5 +111,11 @@ async function test() {
})
.define();
const ctx = await createAppContext().use(ctx2).define().start();
const ctx2Used = await createAppContext().use(ctx2).define().start();
const final = await createAppContext().use(ctx1).use(ctx2).define().start();
const reversed = await createAppContext()
.use(ctx2)
.use(ctx1)
.define()
.start();
}
import { Empty } from '../types';
import { AppContext } from './types';
export class AppServiceBase<T = Empty, Config extends any[] = []> {
export class AppServiceBase<Cur = Empty, Config extends any[] = []> {
constructor(
public ctx: AppContext<T>,
public ctx: AppContext<Cur>,
...args: Config
) {}
......
import { Awaitable, Empty, Prettify } from '../types';
import { AppContextCore } from './app-context';
export type AppContext<T = Empty, Req = Empty> = AppContextCore<T, Req> & T;
type CurAndReq<Cur, Req> = {
[K in keyof Cur | keyof Req]: K extends keyof Cur
? Cur[K]
: K extends keyof Req
? Req[K]
: never;
};
export type AppContext<Cur = Empty, Req = Empty> = AppContextCore<Cur, Req> &
CurAndReq<Cur, Req>;
export type AppServiceClass<T = Empty, A extends any[] = any[], R = any> = new (
ctx: AppContext<T>,
...args: A
) => R;
export type AppServiceClass<
Cur = Empty,
Req = Empty,
A extends any[] = any[],
R = any,
> = new (ctx: AppContext<Cur, Req>, ...args: A) => R;
export type AppServiceConfig<C extends AppServiceClass> = C extends new (
first: any,
......@@ -16,39 +27,77 @@ export type AppServiceConfig<C extends AppServiceClass> = C extends new (
: never;
export type AppProvideOptions<
T,
C extends AppServiceClass<T>,
Cur,
Req,
C extends AppServiceClass<Cur>,
P extends string,
M extends (keyof InstanceType<C>)[],
> = {
provide?: P;
merge?: M;
useValue?: InstanceType<C>;
useValue?: Awaitable<InstanceType<C>>;
useFactory?: (
ctx: AppContext<T>,
ctx: AppContext<Cur, Req>,
...args: ConstructorParameters<C>
) => Awaitable<InstanceType<C>>;
useClass?: new (...args: ConstructorParameters<C>) => InstanceType<C>;
};
export type AppProvideArgs<
T,
C extends AppServiceClass<T>,
Cur,
Req,
C extends AppServiceClass<Cur>,
P extends string,
M extends (keyof InstanceType<C>)[],
> = [...args: AppServiceConfig<C>, options?: AppProvideOptions<T, C, P, M>];
> = [
...args: AppServiceConfig<C>,
options?: AppProvideOptions<Cur, Req, C, P, M>,
];
type CurResolved<Cur, Req, Cur2, Req2> = Prettify<Cur & Cur2>;
type ResolveReq<Provided, Req> = {
[K in keyof Req as K extends keyof Provided
? Provided[K] extends Req[K]
? never // ✅ 满足 → 删除
: K // ❌ 类型不匹配 → 保留
: K]: Req[K]; // ❌ 没提供 → 保留
};
type ReqResolved<Cur, Req, Cur2, Req2> = Prettify<
ResolveReq<Cur & Cur2, Req & Req2>
>;
type AppContextResolved<Cur, Req, Cur2, Req2> = AppContext<
CurResolved<Cur, Req, Cur2, Req2>,
ReqResolved<Cur, Req, Cur2, Req2>
>;
export type AppProvidedMerged<
T,
Cur,
Req,
C extends AppServiceClass<any>,
C extends AppServiceClass<any, any>,
P extends string,
M extends (keyof InstanceType<C>)[],
> = AppContext<
Prettify<
T & {
[K in M[number]]: InstanceType<C>[K];
} & (P extends '' ? Empty : { [K in P]: InstanceType<C> })
>,
Req
> = AppContextResolved<
Cur,
Req,
{
[K in M[number]]: InstanceType<C>[K];
} & (P extends '' ? Empty : { [K in P]: InstanceType<C> }),
Empty
>;
export type AppContextUsed<
Cur,
Req,
Ctxes extends AppContext<any, any>[],
> = Ctxes extends []
? AppContext<Cur, Req>
: Ctxes extends [infer First, ...infer Rest extends AppContext<any, any>[]]
? First extends AppContext<infer Cur2, infer Req2>
? AppContextUsed<
CurResolved<Cur, Req, Cur2, Req2>,
ReqResolved<Cur, Req, Cur2, Req2>,
Rest
>
: never
: never;
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