Skip to content

Commit

Permalink
feat: simplify (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
siyul-park committed Mar 20, 2021
1 parent d4b885e commit 49014ef
Show file tree
Hide file tree
Showing 18 changed files with 125 additions and 207 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const katanaProvider = () => new Katana();

const shurikenProvider = () => new Shuriken();

const ninjaProvider = async (lookUp: LookUp) => {
const ninjaProvider = async (lookUp: LookUpInterface) => {
return new Ninja(
await lookUp.fetch<Weapon>(Types.Weapon),
await lookUp.fetch<ThrowableWeapon>(Types.ThrowableWeapon)
Expand All @@ -55,15 +55,15 @@ const ninjaProvider = async (lookUp: LookUp) => {

const container = new Container();

container.bind(Types.Weapon).to(katanaProvider);
container.bind(Types.ThrowableWeapon).to(shurikenProvider);
container.bind(Types.Warrior).to(ninjaProvider);
container.bind(Types.Weapon).to(asSingleton(katanaProvider));
container.bind(Types.ThrowableWeapon).to(asSingleton(shurikenProvider));
container.bind(Types.Warrior).to(asSingleton(ninjaProvider));

const warrior = await container.fetch<Warrior>(Types.Warrior);
const throwableWeapon = await container.fetch<ThrowableWeapon>(
const warrior = await container.resolveOrThrow<Warrior>(Types.Warrior);
const throwableWeapon = await container.resolveOrThrow<ThrowableWeapon>(
Types.ThrowableWeapon
);
const weapon = await container.fetch<Weapon>(Types.Weapon);
const weapon = await container.resolveOrThrow<Weapon>(Types.Weapon);

expect(warrior.fight()).toEqual(weapon.hit());
expect(warrior.sneak()).toEqual(throwableWeapon.throw());
Expand Down
14 changes: 7 additions & 7 deletions packages/cheeket/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const katanaProvider = () => new Katana();

const shurikenProvider = () => new Shuriken();

const ninjaProvider = async (lookUp: LookUp) => {
const ninjaProvider = async (lookUp: LookUpInterface) => {
return new Ninja(
await lookUp.fetch<Weapon>(Types.Weapon),
await lookUp.fetch<ThrowableWeapon>(Types.ThrowableWeapon)
Expand All @@ -55,15 +55,15 @@ const ninjaProvider = async (lookUp: LookUp) => {

const container = new Container();

container.bind(Types.Weapon).to(katanaProvider);
container.bind(Types.ThrowableWeapon).to(shurikenProvider);
container.bind(Types.Warrior).to(ninjaProvider);
container.bind(Types.Weapon).to(asSingleton(katanaProvider));
container.bind(Types.ThrowableWeapon).to(asSingleton(shurikenProvider));
container.bind(Types.Warrior).to(asSingleton(ninjaProvider));

const warrior = await container.fetch<Warrior>(Types.Warrior);
const throwableWeapon = await container.fetch<ThrowableWeapon>(
const warrior = await container.resolveOrThrow<Warrior>(Types.Warrior);
const throwableWeapon = await container.resolveOrThrow<ThrowableWeapon>(
Types.ThrowableWeapon
);
const weapon = await container.fetch<Weapon>(Types.Weapon);
const weapon = await container.resolveOrThrow<Weapon>(Types.Weapon);

expect(warrior.fight()).toEqual(weapon.hit());
expect(warrior.sneak()).toEqual(throwableWeapon.throw());
Expand Down
2 changes: 0 additions & 2 deletions packages/cheeket/lib/binding/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import Binding from "./binding";
import BindingToSyntax from "./binding-to-syntax";
import Identifier from "../identifier/identifier";
import Storage from "../storage/storage";
import Lifecycle from "../contrant/lifecycle";
import AccessLimiter from "../contrant/access-limiter";

class Binder implements BinderInterface {
Expand All @@ -12,7 +11,6 @@ class Binder implements BinderInterface {
bind<T>(id: Identifier<T>): BindingToSyntax<T> {
const binding = new Binding<T>({
id,
lifecycle: Lifecycle.Singleton,
accessLimiter: AccessLimiter.Public,
});
this.storage.add(binding);
Expand Down
48 changes: 0 additions & 48 deletions packages/cheeket/lib/binding/binding-in-and-for-syntax.ts

This file was deleted.

20 changes: 20 additions & 0 deletions packages/cheeket/lib/binding/binding-in-syntax.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import AccessLimiter from "../contrant/access-limiter";
import Binding from "./binding";

class BindingInSyntax<T> {
constructor(private readonly binding: Binding<T>) {}

inPrivate(): void {
return this.in(AccessLimiter.Private);
}

inPublic(): void {
return this.in(AccessLimiter.Public);
}

in(accessLimiter: AccessLimiter): void {
this.binding.accessLimiter = accessLimiter;
}
}

export default BindingInSyntax;
5 changes: 1 addition & 4 deletions packages/cheeket/lib/binding/binding-info.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import Identifier from "../identifier/identifier";
import Lifecycle from "../contrant/lifecycle";
import AccessLimiter from "../contrant/access-limiter";
import ValueProvider from "./value-provider";
import ValueProvider from "../provider/value-provider";

interface BindingInfo<T> {
id: Identifier<T>;
lifecycle: Lifecycle;
accessLimiter: AccessLimiter;
valueProvider?: ValueProvider<T>;
value?: T;
}

export default BindingInfo;
8 changes: 4 additions & 4 deletions packages/cheeket/lib/binding/binding-to-syntax.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import Binding from "./binding";
import ValueProvider from "./value-provider";
import BindingInAndForSyntax from "./binding-in-and-for-syntax";
import ValueProvider from "../provider/value-provider";
import BindingInSyntax from "./binding-in-syntax";

class BindingToSyntax<T> {
constructor(private readonly binding: Binding<T>) {}

to(provider: ValueProvider<T>): BindingInAndForSyntax<T> {
to(provider: ValueProvider<T>): BindingInSyntax<T> {
this.binding.valueProvider = provider;
return new BindingInAndForSyntax(this.binding);
return new BindingInSyntax(this.binding);
}
}

Expand Down
23 changes: 3 additions & 20 deletions packages/cheeket/lib/binding/binding.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,27 @@
import LookUpInterface from "../look-up/look-up";
import Lifecycle from "../contrant/lifecycle";
import LookUp from "../look-up/look-up.interface";
import Identifier from "../identifier/identifier";
import AccessLimiter from "../contrant/access-limiter";
import ValueProvider from "./value-provider";
import ValueProvider from "../provider/value-provider";
import BindingInfo from "./binding-info";

class Binding<T> {
id: Identifier<T>;

lifecycle: Lifecycle;

accessLimiter: AccessLimiter;

valueProvider?: ValueProvider<T>;

value?: T;

constructor(bindingInfo: BindingInfo<T>) {
this.id = bindingInfo.id;
this.lifecycle = bindingInfo.lifecycle;
this.accessLimiter = bindingInfo.accessLimiter;
this.valueProvider = bindingInfo.valueProvider;
this.value = bindingInfo.value;
}

async resolve(lookUp: LookUpInterface): Promise<T> {
async resolve(lookUp: LookUp): Promise<T> {
if (this.valueProvider === undefined) {
throw new Error("ValueProvider is not undefined");
}

if (this.lifecycle === Lifecycle.Singleton) {
if (this.value !== undefined) {
return this.value;
}

const value = await this.valueProvider(lookUp);
this.value = value;
return value;
}

return this.valueProvider(lookUp);
}
}
Expand Down
46 changes: 12 additions & 34 deletions packages/cheeket/lib/container/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,25 @@ import BinderInterface from "../binding/binder.interface";
import Binder from "../binding/binder";
import BindingToSyntax from "../binding/binding-to-syntax";
import Storage from "../storage/storage";
import Lifecycle from "../contrant/lifecycle";
import AccessLimiter from "../contrant/access-limiter";
import LookUp from "../look-up/look-up";
import LookUpInterface from "../look-up/look-up.interface";
import AccessLimitedLookUp from "../look-up/access-limited-look-up";

class Container implements LookUp, BinderInterface {
private readonly storage = new Storage();

private readonly children = new Set<Container>();
class Container implements LookUpInterface, BinderInterface {
readonly #storage = new Storage();

private readonly privateLookup = new AccessLimitedLookUp(
this.storage,
AccessLimiter.Private,
this.children
this.#storage,
AccessLimiter.Private
);

private readonly publicLookup = new AccessLimitedLookUp(
this.storage,
this.#storage,
AccessLimiter.Public,
this.children,
this.privateLookup
);

private readonly binder = new Binder(this.storage);
private readonly binder = new Binder(this.#storage);

bind<T>(id: Identifier<T>): BindingToSyntax<T> {
return this.binder.bind(id);
Expand All @@ -36,33 +31,16 @@ class Container implements LookUp, BinderInterface {
return this.binder.unbind(id);
}

async fetch<T>(id: Identifier<T>): Promise<T> {
return this.publicLookup.fetch(id);
}

async get<T>(id: Identifier<T>): Promise<T | undefined> {
return this.publicLookup.get(id);
async resolveOrThrow<T>(id: Identifier<T>): Promise<T> {
return this.publicLookup.resolveOrThrow(id);
}

async resolveAll(): Promise<void> {
const bindings = this.storage.getAll();
await Promise.all(
bindings
.filter((binding) => binding.lifecycle === Lifecycle.Singleton)
.map((binding) => binding.resolve(this.privateLookup))
);

await Promise.all(
Array.from(this.children.values()).map((child) => child.resolveAll())
);
async resolve<T>(id: Identifier<T>): Promise<T | undefined> {
return this.publicLookup.resolve(id);
}

imports<T>(...containers: Container[]): void {
containers.forEach((container) => this.children.add(container));
}

unImports<T>(...containers: Container[]): void {
containers.forEach((container) => this.children.delete(container));
containers.forEach((container) => this.#storage.concat(container.#storage));
}
}

Expand Down
6 changes: 0 additions & 6 deletions packages/cheeket/lib/contrant/lifecycle.ts

This file was deleted.

9 changes: 2 additions & 7 deletions packages/cheeket/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
export {
default as BindingInAndForSyntax,
BindingInSyntax,
BindingForSyntax,
} from "./binding/binding-in-and-for-syntax";
export { default as BindingInSyntax } from "./binding/binding-in-syntax";
export { default as BindingToSyntax } from "./binding/binding-to-syntax";
export { default as AccessLimiter } from "./contrant/access-limiter";
export { default as Lifecycle } from "./contrant/lifecycle";
export { default as LookUp } from "./look-up/look-up";
export { default as LookUp } from "./look-up/look-up.interface";
export { default as Container } from "./container/container";
export { default } from "./container/container";
29 changes: 4 additions & 25 deletions packages/cheeket/lib/look-up/access-limited-look-up.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import LookUp from "./look-up";
import LookUp from "./look-up.interface";
import Identifier from "../identifier/identifier";
import AccessLimiter from "../contrant/access-limiter";
import FetchError from "./fetch-error";
Expand All @@ -11,7 +11,6 @@ class AccessLimitedLookUp implements LookUp {
constructor(
private readonly storage: Storage,
private readonly accessLimiter: AccessLimiter,
private readonly children: Set<LookUp>,
binderLookup?: LookUp
) {
if (binderLookup === undefined) {
Expand All @@ -21,24 +20,16 @@ class AccessLimitedLookUp implements LookUp {
}
}

async fetch<T>(id: Identifier<T>): Promise<T> {
const value = await this.get(id);
async resolveOrThrow<T>(id: Identifier<T>): Promise<T> {
const value = await this.resolve(id);
if (value === undefined) {
throw new FetchError(`${id.toString()} is not found`);
}

return value;
}

async get<T>(id: Identifier<T>): Promise<T | undefined> {
const value = await this.getByCurrent(id);
if (value !== undefined) {
return value;
}
return this.getByChildren(id);
}

private async getByCurrent<T>(id: Identifier<T>): Promise<T | undefined> {
async resolve<T>(id: Identifier<T>): Promise<T | undefined> {
const binding = this.storage.get(id);
if (
binding === undefined ||
Expand All @@ -60,18 +51,6 @@ class AccessLimitedLookUp implements LookUp {

return undefined;
}

private async getByChildren<T>(id: Identifier<T>): Promise<T | undefined> {
// eslint-disable-next-line no-restricted-syntax
for (const child of this.children) {
// eslint-disable-next-line no-await-in-loop
const childValue = await child.get(id);
if (childValue !== undefined) {
return childValue;
}
}
return undefined;
}
}

export default AccessLimitedLookUp;
8 changes: 8 additions & 0 deletions packages/cheeket/lib/look-up/look-up.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Identifier from "../identifier/identifier";

interface LookUp {
resolve<T>(id: Identifier<T>): Promise<T | undefined>;
resolveOrThrow<T>(id: Identifier<T>): Promise<T>;
}

export default LookUp;
Loading

0 comments on commit 49014ef

Please sign in to comment.