Comparing version 0.0.3 to 0.0.4
import { LinkedAbortController } from 'linked-abort-controller'; | ||
import { Class } from 'yummies/utils/types'; | ||
import { ContainerConfig, InjectRegisterConfig } from './container.types.js'; | ||
import { ContainerConfig } from './container.types.js'; | ||
import { Tag } from './tag.js'; | ||
import { TagConfig } from './tag.types.js'; | ||
import { TagConfig, TagDetailedConfig } from './tag.types.js'; | ||
export declare class Container { | ||
@@ -10,3 +10,3 @@ private config?; | ||
protected abortController: LinkedAbortController; | ||
protected dependencies: Map<Class<any>, any>; | ||
protected dependencies: Map<Tag<any>, any>; | ||
protected children: Container[]; | ||
@@ -20,3 +20,4 @@ protected parent?: Container; | ||
inject<TConstructor extends Class<any>>(Constructor: TConstructor, ...args: TConstructor extends Class<any, infer TArgs> ? TArgs : []): TConstructor extends Class<infer TInstance> ? TInstance : never; | ||
register<TConstructor extends Class<any>>(Constructor: TConstructor, config?: InjectRegisterConfig): Tag<TConstructor extends Class<infer TInstance> ? TInstance : never>; | ||
inject<TTag extends Tag<any>>(tag: TTag extends Tag<infer TTarget> ? TTarget : never, ...args: TTag extends Tag<any, infer TArgs> ? TArgs : []): TTag extends Tag<infer TTarget> ? TTarget : never; | ||
register<TConstructor extends Class<any>>(Constructor: TConstructor, config?: Omit<TagDetailedConfig<TConstructor>, 'token'>): Tag<TConstructor extends Class<infer TInstance> ? TInstance : never>; | ||
register<TTarget>(target: TagConfig<TTarget>): Tag<TTarget>; | ||
@@ -26,5 +27,5 @@ get<TConstructor extends Class<any>>(Constructor: TConstructor): (TConstructor extends Class<infer TInstance> ? TInstance : never) | null; | ||
protected extend(config?: Partial<Omit<ContainerConfig, 'parent' | 'id'>>): Container; | ||
protected getInjectConfig(Constructor: Class<any>): InjectRegisterConfig | null; | ||
protected getTag(value: any): Tag<any, any[]> | null; | ||
protected getContainerFromInstance(instance: any): Container | null; | ||
protected createInstance(Constructor: Class<any, any[]>, args: any[], parent: Container, config?: Partial<ContainerConfig>): any; | ||
protected createInstance(tag: Tag<any>, args: any[], parent: Container, config?: Partial<ContainerConfig>): any; | ||
destroy(instance?: any): void; | ||
@@ -31,0 +32,0 @@ } |
@@ -6,5 +6,2 @@ /* eslint-disable no-prototype-builtins */ | ||
const mark = Symbol('di'); | ||
const defaultInjectRegisterConfig = { | ||
scope: 'transient', | ||
}; | ||
export class Container { | ||
@@ -37,8 +34,8 @@ config; | ||
inject(Constructor, ...args) { | ||
const injectConfig = this.getInjectConfig(Constructor); | ||
const tag = this.getTag(Constructor); | ||
const currentContainer = this.path.at(-1) ?? this; | ||
if (!injectConfig) { | ||
if (!tag) { | ||
throw new Error(`Class ${Constructor.name} is not registered for DI`); | ||
} | ||
switch (injectConfig.scope) { | ||
switch (tag.injectConfig.scope) { | ||
case 'singleton': { | ||
@@ -49,3 +46,3 @@ const resolved = rootContainer.get(Constructor); | ||
} | ||
const instance = rootContainer.createInstance(Constructor, args, rootContainer, injectConfig.__); | ||
const instance = rootContainer.createInstance(tag, args, rootContainer, tag.injectConfig.__); | ||
return instance; | ||
@@ -69,3 +66,3 @@ } | ||
} | ||
const instance = this.createInstance(Constructor, args, currentContainer, injectConfig.__); | ||
const instance = this.createInstance(tag, args, currentContainer, tag.injectConfig.__); | ||
return instance; | ||
@@ -75,20 +72,20 @@ } | ||
if (typeof constructorOrTagConfig === 'function') { | ||
Object.assign(constructorOrTagConfig, { | ||
[mark]: config || defaultInjectRegisterConfig, | ||
}); | ||
return Tag.create({ | ||
value: Symbol(), | ||
metaData: constructorOrTagConfig, | ||
}); | ||
const tag = Tag.create(constructorOrTagConfig, { ...config }); | ||
return tag; | ||
} | ||
return Tag.create(constructorOrTagConfig); | ||
const { token, ...tagConfig } = constructorOrTagConfig || {}; | ||
return Tag.create(token, tagConfig); | ||
} | ||
get(Constructor) { | ||
if (this.dependencies.has(Constructor)) { | ||
return this.dependencies.get(Constructor); | ||
const tag = Tag.research(Constructor); | ||
if (!tag) { | ||
return null; | ||
} | ||
if (this.dependencies.has(tag)) { | ||
return this.dependencies.get(tag); | ||
} | ||
let instance = null; | ||
for (const child of this.children) { | ||
if (child.dependencies.has(Constructor)) { | ||
instance = child.dependencies.get(Constructor); | ||
if (child.dependencies.has(tag)) { | ||
instance = child.dependencies.get(tag); | ||
} | ||
@@ -99,3 +96,3 @@ } | ||
isInjectable(Constructor) { | ||
return !!this.getInjectConfig(Constructor); | ||
return !!this.getTag(Constructor); | ||
} | ||
@@ -124,7 +121,4 @@ extend(config) { | ||
} | ||
getInjectConfig(Constructor) { | ||
if (mark in Constructor) { | ||
return Constructor[mark]; | ||
} | ||
return null; | ||
getTag(value) { | ||
return Tag.research(value); | ||
} | ||
@@ -137,8 +131,10 @@ getContainerFromInstance(instance) { | ||
} | ||
createInstance(Constructor, args, parent, config) { | ||
createInstance(tag, args, parent, config) { | ||
const container = parent.extend(config); | ||
const index = this.path.push(container) - 1; | ||
const instance = new Constructor(...args); | ||
instance[mark] = container; | ||
container.dependencies.set(Constructor, instance); | ||
const instance = tag.createValue(...args); | ||
if (tag.strategy === 'class-constructor') { | ||
instance[mark] = container; | ||
} | ||
container.dependencies.set(tag, instance); | ||
this.path.splice(index); | ||
@@ -145,0 +141,0 @@ return instance; |
@@ -141,2 +141,13 @@ import { LinkedAbortController } from 'linked-abort-controller'; | ||
}); | ||
it('tag (simple)', () => { | ||
const ContainerMock = createContainerMock(); | ||
const container = new ContainerMock({ | ||
containerConstructor: ContainerMock, | ||
}); | ||
const { register, inject } = container; | ||
const tag = register({ | ||
value: () => 1, | ||
}); | ||
expect(inject(tag)).toBe(1); | ||
}); | ||
}); |
import { Tag } from './tag.js'; | ||
export declare const container: import("./container.js").Container; | ||
export declare const inject: <TConstructor extends import("yummies/utils/types.js").Class<any>>(Constructor: TConstructor, ...args: TConstructor extends import("yummies/utils/types.js").Class<any, infer TArgs> ? TArgs : []) => TConstructor extends import("yummies/utils/types.js").Class<infer TInstance> ? TInstance : never, register: { | ||
<TConstructor extends import("yummies/utils/types.js").Class<any>>(Constructor: TConstructor, config?: import("./container.types.js").InjectRegisterConfig): Tag<TConstructor extends import("yummies/utils/types.js").Class<infer TInstance> ? TInstance : never>; | ||
export declare const inject: { | ||
<TConstructor extends import("yummies/utils/types.js").Class<any>>(Constructor: TConstructor, ...args: TConstructor extends import("yummies/utils/types.js").Class<any, infer TArgs> ? TArgs : []): TConstructor extends import("yummies/utils/types.js").Class<infer TInstance> ? TInstance : never; | ||
<TTag extends Tag<any>>(tag: TTag extends Tag<infer TTarget> ? TTarget : never, ...args: TTag extends Tag<any, infer TArgs> ? TArgs : []): TTag extends Tag<infer TTarget> ? TTarget : never; | ||
}, register: { | ||
<TConstructor extends import("yummies/utils/types.js").Class<any>>(Constructor: TConstructor, config?: Omit<import("./tag.types.js").TagDetailedConfig<TConstructor>, "token">): Tag<TConstructor extends import("yummies/utils/types.js").Class<infer TInstance> ? TInstance : never>; | ||
<TTarget>(target: import("./tag.types.js").TagConfig<TTarget>): Tag<TTarget>; | ||
@@ -6,0 +9,0 @@ }, destroy: (instance?: any) => void; |
{ | ||
"name": "mobidic", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"keywords": [], | ||
@@ -5,0 +5,0 @@ "author": "js2me", |
15
tag.d.ts
@@ -1,7 +0,12 @@ | ||
import { TagConfig } from './tag.types'; | ||
export declare class Tag<TTarget> { | ||
private config; | ||
protected constructor(config: TagConfig<TTarget>); | ||
static create<TTarget>(config: TagConfig<TTarget>): Tag<TTarget>; | ||
import { InjectRegisterConfig } from './container.types'; | ||
import { TagConfig, TagDetailedConfig } from './tag.types'; | ||
export declare class Tag<TTarget, TArgs extends any[] = any[]> { | ||
injectConfig: InjectRegisterConfig; | ||
strategy: 'class-constructor' | 'token'; | ||
config: TagDetailedConfig<TTarget>; | ||
protected constructor(configOrToken: TagConfig<TTarget, TArgs>); | ||
createValue(...args: any[]): TTarget; | ||
static create<TTarget>(token?: Exclude<TagDetailedConfig<TTarget>['token'], undefined>, config?: Omit<TagDetailedConfig<TTarget>, 'token'>): Tag<TTarget, any[]>; | ||
static research<TTarget = any>(value: any): Tag<TTarget> | null; | ||
} | ||
//# sourceMappingURL=tag.d.ts.map |
53
tag.js
@@ -0,9 +1,54 @@ | ||
const mark = Symbol('di'); | ||
export class Tag { | ||
injectConfig; | ||
strategy; | ||
config; | ||
constructor(config) { | ||
this.config = config; | ||
constructor(configOrToken) { | ||
this.config = | ||
typeof configOrToken === 'object' | ||
? configOrToken | ||
: { | ||
token: configOrToken, | ||
}; | ||
this.strategy = | ||
(this.config.strategy ?? typeof this.config.token === 'function') | ||
? 'class-constructor' | ||
: 'token'; | ||
this.injectConfig = { | ||
__: this.config.__, | ||
scope: this.config.scope ?? 'transient', | ||
}; | ||
if (this.strategy === 'class-constructor' && | ||
typeof this.config.token === 'function') { | ||
Object.assign(this.config.token, { | ||
[mark]: this, | ||
}); | ||
} | ||
} | ||
static create(config) { | ||
return new Tag(config); | ||
createValue(...args) { | ||
if (this.strategy === 'class-constructor') { | ||
return new this.config.token(...args); | ||
} | ||
if (this.config.value) { | ||
return this.config.value(...args); | ||
} | ||
return this.config.token; | ||
} | ||
static create(token, config) { | ||
return new Tag({ | ||
...config, | ||
token, | ||
}); | ||
} | ||
static research(value) { | ||
if (value instanceof Tag) { | ||
return value; | ||
} | ||
if (typeof value === 'function' && | ||
mark in value && | ||
value[mark] instanceof Tag) { | ||
return value[mark]; | ||
} | ||
return null; | ||
} | ||
} |
@@ -1,10 +0,13 @@ | ||
import { AnyObject } from 'yummies/utils/types'; | ||
import { Class } from 'yummies/utils/types'; | ||
import { InjectRegisterConfig } from './container.types'; | ||
export type TagSimpleConfig<TTarget> = (string | symbol) & { | ||
__REF__?: TTarget; | ||
}; | ||
export interface TagDetailedConfig<TTarget> { | ||
value?: TagSimpleConfig<TTarget>; | ||
metaData?: AnyObject; | ||
export interface TagDetailedConfig<TTarget, TArgs extends any[] = any[]> extends InjectRegisterConfig { | ||
token?: TagSimpleConfig<TTarget> | Class<TTarget>; | ||
meta?: any; | ||
value?: (...args: TArgs) => TTarget; | ||
strategy?: 'class-constructor' | 'token'; | ||
} | ||
export type TagConfig<TTarget> = TagSimpleConfig<TTarget> | TagDetailedConfig<TTarget>; | ||
export type TagConfig<TTarget, TArgs extends any[] = any[]> = TagDetailedConfig<TTarget, TArgs> | TagSimpleConfig<TTarget>; | ||
//# sourceMappingURL=tag.types.d.ts.map |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
25743
447
0