Skip to content

Commit c69cd6b

Browse files
committed
refactor: boyscout rules
1 parent 8d7aef0 commit c69cd6b

File tree

1 file changed

+23
-18
lines changed

1 file changed

+23
-18
lines changed

src/container.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,52 +41,57 @@ export function createContainer(): Container {
4141
return binding;
4242
};
4343

44-
const verifyCircularDependencies = (key: DependencyKey) => {
45-
if (resolutionStack.includes(key)) {
46-
const cycle = [...resolutionStack, key].map((k) => k.toString()).join(' -> ');
44+
const isCircularDependency = (key: DependencyKey): boolean => resolutionStack.includes(key);
45+
46+
const buildCycleOf = (key: DependencyKey) => [...resolutionStack, key].map((k) => k.toString()).join(' -> ');
47+
48+
const startCircularDependencyDetectionFor = (dependencyKey: DependencyKey) => resolutionStack.push(dependencyKey);
49+
50+
const endCircularDependencyDetection = () => resolutionStack.pop();
51+
52+
const get = <T>(dependencyKey: DependencyKey): T => {
53+
if (isCircularDependency(dependencyKey)) {
54+
const cycle = buildCycleOf(dependencyKey);
4755
throw new Error(`Circular dependency detected: ${cycle}`);
4856
}
49-
};
50-
51-
const get = <T>(key: DependencyKey): T => {
52-
verifyCircularDependencies(key);
5357

54-
resolutionStack.push(key);
58+
startCircularDependencyDetectionFor(dependencyKey);
5559

5660
try {
57-
const binding = getLastBinding(key);
61+
const binding = getLastBinding(dependencyKey);
5862

5963
const {factory, scope} = binding;
6064

6165
if (scope === 'singleton') {
62-
if (!singletonInstances.has(key)) {
63-
singletonInstances.set(key, factory(resolveDependency));
66+
if (!singletonInstances.has(dependencyKey)) {
67+
singletonInstances.set(dependencyKey, factory(resolveDependency));
6468
}
65-
return singletonInstances.get(key) as T;
69+
return singletonInstances.get(dependencyKey) as T;
6670
}
6771

6872
if (scope === 'transient') {
6973
return factory(resolveDependency) as T;
7074
}
7175

7276
if (scope === 'scoped') {
73-
if (!currentScopeId)
74-
throw new Error(`Cannot resolve scoped binding outside of a scope: ${key.toString()}`);
77+
if (!currentScopeId) {
78+
throw new Error(`Cannot resolve scoped binding outside of a scope: ${dependencyKey.toString()}`);
79+
}
7580

7681
if (!scopedInstances.has(currentScopeId)) {
7782
scopedInstances.set(currentScopeId, new Map<DependencyKey, unknown>());
7883
}
7984
const scopeMap = scopedInstances.get(currentScopeId)!;
80-
if (!scopeMap.has(key)) {
81-
scopeMap.set(key, factory(resolveDependency));
85+
if (!scopeMap.has(dependencyKey)) {
86+
scopeMap.set(dependencyKey, factory(resolveDependency));
8287
}
8388

84-
return scopeMap.get(key) as T;
89+
return scopeMap.get(dependencyKey) as T;
8590
}
8691

8792
throw new Error(`Unknown scope: ${scope}`);
8893
} finally {
89-
resolutionStack.pop();
94+
endCircularDependencyDetection();
9095
}
9196
};
9297

0 commit comments

Comments
 (0)