UNPKG

ayanami

Version:
75 lines (74 loc) 2.89 kB
import { InjectableFactory, Inject } from '@asuka/di'; import { SameScopeMetadataKey } from './same-scope-decorator'; import { CleanupSymbol } from '../../ssr/constants'; import { isSSREnabled } from '../../ssr/flag'; import { reqMap } from '../../ssr/express'; const map = new Map(); export const ayanamiInstances = new Map(); export function createOrGetInstanceInScope(constructor, scope) { const instanceAtScope = getInstanceFrom(constructor, scope); return instanceAtScope ? instanceAtScope : createInstanceInScope(constructor, scope); } function createInstanceInScope(constructor, scope) { const paramTypes = Reflect.getMetadata('design:paramtypes', constructor) || []; // parameters decorated by @Inject const paramAnnotations = Reflect.getMetadata('parameters', constructor) || []; const sameScopeParams = Reflect.getMetadata(SameScopeMetadataKey, constructor) || []; const deps = paramTypes.map((type, index) => { if (sameScopeParams[index]) { return createOrGetInstanceInScope(type, scope); } if (paramAnnotations[index] !== null) { let metadata = paramAnnotations[index]; metadata = Array.isArray(metadata) ? metadata : [metadata]; const inject = metadata.find((factory) => factory instanceof Inject); if (inject && inject.token) { return InjectableFactory.getInstanceByToken(inject.token); } } return InjectableFactory.getInstance(type); }); const newInstance = new constructor(...deps); setInstanceInScope(constructor, scope, newInstance); return newInstance; } function setInstanceInScope(constructor, scope, newInstance) { const scopeMap = map.get(constructor) || new Map(); scopeMap.set(scope, newInstance); map.set(constructor, scopeMap); newInstance[CleanupSymbol] = () => { newInstance.destroy(); scopeMap.delete(scope); }; if (isSSREnabled()) { ayanamiInstances.set(scope, (ayanamiInstances.get(scope) || []).concat(newInstance)); } } function getInstanceFrom(constructor, scope) { const scopeMap = map.get(constructor); return scopeMap && scopeMap.get(scope); } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function createScopeWithRequest(req, scope) { if (!scope) { return req; } if (reqMap.has(req)) { const scopes = reqMap.get(req); if (scopes.has(scope)) { return scopes.get(scope); } else { const reqScope = { req, scope }; scopes.set(scope, reqScope); return reqScope; } } else { const reqScopeMap = new Map(); const reqScope = { req, scope }; reqScopeMap.set(scope, reqScope); reqMap.set(req, reqScopeMap); return reqScope; } }