Commit c584a517 authored by nanahira's avatar nanahira

mid

parent adbfce6d
...@@ -11,42 +11,59 @@ import { ...@@ -11,42 +11,59 @@ import {
const ServiceClassPrefix = 'class:'; const ServiceClassPrefix = 'class:';
const ProvidePrefix = 'provide:'; const ProvidePrefix = 'provide:';
export class AppContextCore<T = Empty, Req = Empty> { export class AppContextCore<Cur = Empty, Req = Empty> {
private __current: T; private __current: Cur;
private __required: Req; private __required: Req;
registry = new Map<string, any>();
loadSeq: any[] = [];
provide< provide<
C extends AppServiceClass<T>, C extends AppServiceClass<Cur>,
const P extends string = '', const P extends string = '',
const M extends (keyof InstanceType<C>)[] = [], const M extends (keyof InstanceType<C>)[] = [],
>( >(
cls: C, cls: C,
...args: AppProvideArgs<T, C, P, M> ...args: AppProvideArgs<Cur, Req, C, P, M>
): AppProvidedMerged<T, Req, C, P, M> { ): AppProvidedMerged<Cur, Req, C, P, M> {
const options = args[args.length - 1] as const options = args[args.length - 1] as
| AppProvideOptions<T, C, P, M> | AppProvideOptions<Cur, Req, C, P, M>
| undefined; | 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; 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; return this as any;
} }
define(): AppContext<T, Req> { define(): AppContext<Cur, Req> {
return this as any; return this as any;
} }
async start(): Promise<AppContext<T, Req>> { async start(): Promise<Empty extends Req ? AppContext<Cur, Req> : never> {
return this as any; return this as any;
} }
} }
export const createAppContext = <Req = Empty>() => export const createAppContext = <Req = Empty>() =>
new AppContextCore<Req, Req>() as AppContext<Req, Req>; new AppContextCore<Empty, Req>() as AppContext<Empty, Req>;
// testing code below // testing code below
...@@ -86,7 +103,6 @@ async function test() { ...@@ -86,7 +103,6 @@ async function test() {
.provide(Bar, 5, { .provide(Bar, 5, {
merge: ['getBar'], merge: ['getBar'],
}) })
.provide(Foo, 3, { provide: 'foo22' })
.define(); .define();
const ctx2 = createAppContext<{ foo: Foo }>() const ctx2 = createAppContext<{ foo: Foo }>()
...@@ -95,5 +111,11 @@ async function test() { ...@@ -95,5 +111,11 @@ async function test() {
}) })
.define(); .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 { Empty } from '../types';
import { AppContext } from './types'; import { AppContext } from './types';
export class AppServiceBase<T = Empty, Config extends any[] = []> { export class AppServiceBase<Cur = Empty, Config extends any[] = []> {
constructor( constructor(
public ctx: AppContext<T>, public ctx: AppContext<Cur>,
...args: Config ...args: Config
) {} ) {}
......
import { Awaitable, Empty, Prettify } from '../types'; import { Awaitable, Empty, Prettify } from '../types';
import { AppContextCore } from './app-context'; 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 ( export type AppServiceClass<
ctx: AppContext<T>, Cur = Empty,
...args: A Req = Empty,
) => R; A extends any[] = any[],
R = any,
> = new (ctx: AppContext<Cur, Req>, ...args: A) => R;
export type AppServiceConfig<C extends AppServiceClass> = C extends new ( export type AppServiceConfig<C extends AppServiceClass> = C extends new (
first: any, first: any,
...@@ -16,39 +27,77 @@ export type AppServiceConfig<C extends AppServiceClass> = C extends new ( ...@@ -16,39 +27,77 @@ export type AppServiceConfig<C extends AppServiceClass> = C extends new (
: never; : never;
export type AppProvideOptions< export type AppProvideOptions<
T, Cur,
C extends AppServiceClass<T>, Req,
C extends AppServiceClass<Cur>,
P extends string, P extends string,
M extends (keyof InstanceType<C>)[], M extends (keyof InstanceType<C>)[],
> = { > = {
provide?: P; provide?: P;
merge?: M; merge?: M;
useValue?: InstanceType<C>; useValue?: Awaitable<InstanceType<C>>;
useFactory?: ( useFactory?: (
ctx: AppContext<T>, ctx: AppContext<Cur, Req>,
...args: ConstructorParameters<C> ...args: ConstructorParameters<C>
) => Awaitable<InstanceType<C>>; ) => Awaitable<InstanceType<C>>;
useClass?: new (...args: ConstructorParameters<C>) => InstanceType<C>; useClass?: new (...args: ConstructorParameters<C>) => InstanceType<C>;
}; };
export type AppProvideArgs< export type AppProvideArgs<
T, Cur,
C extends AppServiceClass<T>, Req,
C extends AppServiceClass<Cur>,
P extends string, P extends string,
M extends (keyof InstanceType<C>)[], 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< export type AppProvidedMerged<
T, Cur,
Req, Req,
C extends AppServiceClass<any>, C extends AppServiceClass<any, any>,
P extends string, P extends string,
M extends (keyof InstanceType<C>)[], M extends (keyof InstanceType<C>)[],
> = AppContext< > = AppContextResolved<
Prettify< Cur,
T & { Req,
[K in M[number]]: InstanceType<C>[K]; {
} & (P extends '' ? Empty : { [K in P]: InstanceType<C> }) [K in M[number]]: InstanceType<C>[K];
>, } & (P extends '' ? Empty : { [K in P]: InstanceType<C> }),
Req 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