Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x 146x 146x 146x 146x 146x 146x 146x 146x 146x 283x 168x 283x 116x 168x 167x 168x 167x 167x 910x 910x 910x 6328x 6480x 6479x 6479x 6479x 2x 6477x 108x 108x 108x 108x 108x 108x 6480x 6480x 6480x 422x 422x 270x 152x 152x 152x 152x 152x 152x 151x 421x 6479x 168x 168x 168x 168x 13870x 13870x | import { assert, ConstructorType } from '@aspectjs/common/utils';
/**
* Returns an object to store global values across the framework
*/
import { ANNOTATION_CONTEXT_REGISTRY_PROVIDERS } from '../annotation/context/registry/annotation-context-registry.provider';
import { ANNOTATION_HOOK_REGISTRY_PROVIDERS } from '../annotation/factory/annotation-factory.provider';
import { ANNOTATION_REGISTRY_PROVIDERS } from '../annotation/registry/annotation-registry.provider';
import { ANNOTATION_TARGET_FACTORY_PROVIDERS } from '../annotation/target/annotation-target-factory.provider';
import { ReflectModuleConfiguration } from './module/reflect-module-config.type';
import { ReflectModule } from './module/reflect-module.type';
import type { ReflectProvider } from './reflect-provider.type';
import { RUNTIME_STATE_PROVIDER } from './runtime-state.provider';
@ReflectModule({
providers: [
RUNTIME_STATE_PROVIDER,
...ANNOTATION_REGISTRY_PROVIDERS,
...ANNOTATION_CONTEXT_REGISTRY_PROVIDERS,
...ANNOTATION_HOOK_REGISTRY_PROVIDERS,
...ANNOTATION_TARGET_FACTORY_PROVIDERS,
],
})
class AnnotationsModule {}
const DEFAULT_MODULES = [AnnotationsModule];
/**
* @internal
*
* The ReflectContext is a container for the global values and services of the framework.
* The services are added to the context in the form of {@link ReflectProvider}s,
* through the use of {@link ReflectModuleConfiguration}s.
*/
export class ReflectContext {
protected providersToResolve: Map<string, ReflectProvider[]> = new Map();
protected providersRegistry: Map<
string,
{ component: unknown; provider: ReflectProvider }[]
> = new Map();
protected addedProviders: Set<ReflectProvider> = new Set();
protected modules: Set<ConstructorType> = new Set();
/**
* @internal
* @param context
*/
constructor(context?: ReflectContext) {
this.providersToResolve = new Map(context?.providersToResolve);
this.providersRegistry = new Map(context?.providersRegistry);
this.addedProviders = new Set(context?.addedProviders);
this.modules = new Set(context?.modules);
this.registerModules(...DEFAULT_MODULES);
}
/**
* Adds a module to the context. Modules are unique by their name.
* Adding the same module twice has no effect.
* @param module The module to add
*/
registerModules(...modules: ConstructorType<unknown>[]): ReflectContext {
// dedupe modules
modules = [...new Set(modules).values()].filter(
(m) => !this.modules.has(m),
);
if (!modules.length) {
return this;
}
const providers = modules.flatMap((m) => getProviders(m));
this.addProviders(providers);
modules.forEach((m) => this.modules.add(m));
return this;
}
private addProviders(providers: ReflectProvider[]) {
providers.forEach((p) => {
const providerName = getProviderName(p.provide);
this.addedProviders.add(p);
this.providersToResolve.set(
providerName,
(this.providersToResolve.get(providerName) ?? []).concat(p),
);
});
}
/**
* Get a provider by its name or type.
* @param provider The provider name or type.
* @param T the provider type
* @return The provider, if registered, undefined otherwise.
*/
get<T>(providerType: ReflectProvider<T>['provide']): T {
return this._get(getProviderName(providerType));
}
private _get<T>(providerName: string, neededBy: string[] = []): T {
this._tryResolveProvider(providerName, neededBy);
const candidates = this.providersRegistry.get(providerName);
const provider = candidates?.[candidates?.length - 1]?.component;
// if provider not found
if (!provider) {
throw new Error(
`No ReflectContext provider found for ${providerName}${
neededBy?.length ? `. Needed by ${neededBy.join(' -> ')}` : ''
}`,
);
}
return provider as T;
}
/**
* Know if a provider is registered.
* @param providerType The provider name or type.
* @param T the provider type
* @returns true if the provider is registered, false otherwise.
*/
has<T>(providerType: ReflectProvider<T>['provide']): boolean {
return !!this.get(providerType);
}
protected assign(context: ReflectContext) {
assert(!!context);
this.modules = context.modules;
this.addedProviders = context.addedProviders;
this.providersRegistry = context.providersRegistry;
this.providersToResolve = context.providersToResolve;
return this;
}
private _tryResolveProvider(
providerType: string,
neededBy: string[] = [],
): void {
const providerName = getProviderName(providerType);
const providers = this.providersToResolve.get(providerName);
let component: unknown;
while (providers?.length) {
const provider = providers.shift()!; // remove p from the resolution list
// if provider has no deps
if (!provider.deps?.length) {
component = provider.factory();
} else {
const deps: any[] = provider.deps.map((dep) => {
// provider already resolved ?
const depName = getProviderName(dep);
try {
neededBy.push(providerName);
return this._get(depName, neededBy);
} finally {
neededBy.pop();
}
});
component = provider.factory(...deps);
}
this.providersRegistry.set(
providerName,
(this.providersRegistry.get(providerName) ?? []).concat({
component,
provider,
}),
);
}
this.providersToResolve.delete(providerName);
}
}
function getProviders(m: unknown): ReflectProvider[] {
assert(!!m);
const config: ReflectModuleConfiguration = (m as any)[Symbol.for('@ajs:rmd')];
Iif (!config) {
throw new TypeError(`object ${m} is not a module`);
}
return config.providers;
}
function getProviderName<T>(
providerType: ReflectProvider<T>['provide'],
): string {
assert(!!providerType);
return typeof providerType === 'string'
? providerType
: providerType.__providerName ?? providerType.name;
}
|