Skip to content

Commit

Permalink
Merge pull request #152 from inversify/refactor/update-bindings-with-…
Browse files Browse the repository at this point in the history
…consistent-activated-generic

Update bindings with consistent activated generic
  • Loading branch information
notaphplover authored Dec 3, 2024
2 parents 74eb6d6 + 933539e commit 67c4491
Show file tree
Hide file tree
Showing 19 changed files with 94 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { stringifyServiceIdentifier } from '@inversifyjs/common';
import { Binding } from '../models/Binding';
import { bindingTypeValues } from '../models/BindingType';

export function stringifyBinding(binding: Binding<unknown>): string {
export function stringifyBinding(binding: Binding): string {
switch (binding.type) {
case bindingTypeValues.Instance:
return `[ type: "${binding.type}", serviceIdentifier: "${stringifyServiceIdentifier(binding.serviceIdentifier)}", scope: "${binding.scope}", implementationType: "${binding.implementationType.name}" ]`;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { ConstantValueBinding } from './ConstantValueBinding';
import { DynamicValueBinding } from './DynamicValueBinding';
import { Factory } from './Factory';
import { FactoryBinding } from './FactoryBinding';
import { InstanceBinding } from './InstanceBinding';
import { Provider } from './Provider';
import { ProviderBinding } from './ProviderBinding';
import { ServiceRedirectionBinding } from './ServiceRedirectionBinding';

export type Binding<TActivated> =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type Binding<TActivated = any> =
| ConstantValueBinding<TActivated>
| DynamicValueBinding<TActivated>
| FactoryBinding<TActivated>
| (TActivated extends Factory<unknown> ? FactoryBinding<TActivated> : never)
| InstanceBinding<TActivated>
| ProviderBinding<TActivated>
| (TActivated extends Provider<unknown> ? ProviderBinding<TActivated> : never)
| ServiceRedirectionBinding<TActivated>;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ResolutionContext } from '../../resolution/models/ResolutionContext';
import { Resolved } from '../../resolution/models/Resolved';

export type DynamicValueBuilder<T> = (
context: ResolutionContext,
) => T | Promise<T>;
) => Resolved<T>;
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { bindingTypeValues } from './BindingType';
import { Factory } from './Factory';
import { ScopedBinding } from './ScopedBinding';

export interface FactoryBinding<TActivated>
export interface FactoryBinding<TActivated extends Factory<unknown>>
extends ScopedBinding<
typeof bindingTypeValues.Factory,
typeof bindingScopeValues.Singleton,
Factory<TActivated>
TActivated
> {
readonly factory: (context: ResolutionContext) => Factory<TActivated>;
readonly factory: (context: ResolutionContext) => TActivated;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { bindingTypeValues } from './BindingType';
import { Provider } from './Provider';
import { ScopedBinding } from './ScopedBinding';

export interface ProviderBinding<TActivated>
export interface ProviderBinding<TActivated extends Provider<unknown>>
extends ScopedBinding<
typeof bindingTypeValues.Provider,
typeof bindingScopeValues.Singleton,
Provider<TActivated>
TActivated
> {
readonly provider: (context: ResolutionContext) => Provider<TActivated>;
readonly provider: (context: ResolutionContext) => TActivated;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Either } from '@inversifyjs/common';

import { Resolved } from '../../resolution/models/Resolved';
import { BaseBinding } from './BaseBinding';
import { BindingActivation } from './BindingActivation';
import { BindingDeactivation } from './BindingDeactivation';
Expand All @@ -11,7 +12,7 @@ export interface ScopedBinding<
TScope extends BindingScope,
TActivated,
> extends BaseBinding<TType, TActivated> {
cache: Either<undefined, TActivated>;
cache: Either<undefined, Resolved<TActivated>>;
readonly onActivation: BindingActivation<TActivated> | undefined;
readonly onDeactivation: BindingDeactivation<TActivated> | undefined;
readonly scope: TScope;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import { bindingScopeValues } from '../../binding/models/BindingScope';
import { bindingTypeValues } from '../../binding/models/BindingType';
import { ConstantValueBinding } from '../../binding/models/ConstantValueBinding';
import { DynamicValueBinding } from '../../binding/models/DynamicValueBinding';
import { Factory } from '../../binding/models/Factory';
import { FactoryBinding } from '../../binding/models/FactoryBinding';
import { InstanceBinding } from '../../binding/models/InstanceBinding';
import { Provider } from '../../binding/models/Provider';
import { ProviderBinding } from '../../binding/models/ProviderBinding';
import { ServiceRedirectionBinding } from '../../binding/models/ServiceRedirectionBinding';
import { BindingService } from '../../binding/services/BindingService';
Expand Down Expand Up @@ -54,8 +56,8 @@ function buildLeafBindingPlanResult(
binding:
| ConstantValueBinding<unknown>
| DynamicValueBinding<unknown>
| FactoryBinding<unknown>
| ProviderBinding<unknown>,
| FactoryBinding<Factory<unknown>>
| ProviderBinding<Provider<unknown>>,
): PlanResult {
const planServiceNode: PlanServiceNode = {
bindings: [],
Expand All @@ -81,15 +83,15 @@ function buildSimpleInstancePlanResult(
constructorParameterBinding:
| ConstantValueBinding<unknown>
| DynamicValueBinding<unknown>
| FactoryBinding<unknown>
| ProviderBinding<unknown>,
| FactoryBinding<Factory<unknown>>
| ProviderBinding<Provider<unknown>>,
propertyKeyBindingPair: [
string | symbol,
(
| ConstantValueBinding<unknown>
| DynamicValueBinding<unknown>
| FactoryBinding<unknown>
| ProviderBinding<unknown>
| FactoryBinding<Factory<unknown>>
| ProviderBinding<Provider<unknown>>
),
],
instanceBinding: InstanceBinding<unknown>,
Expand Down Expand Up @@ -126,8 +128,8 @@ function buildSimpleInstancePlanResult(
(
| ConstantValueBinding<unknown>
| DynamicValueBinding<unknown>
| FactoryBinding<unknown>
| ProviderBinding<unknown>
| FactoryBinding<Factory<unknown>>
| ProviderBinding<Provider<unknown>>
),
] = propertyKeyBindingPair;

Expand Down Expand Up @@ -159,8 +161,8 @@ function buildServiceRedirectionToLeafBindingPlanResult(
leafBinding:
| ConstantValueBinding<unknown>
| DynamicValueBinding<unknown>
| FactoryBinding<unknown>
| ProviderBinding<unknown>,
| FactoryBinding<Factory<unknown>>
| ProviderBinding<Provider<unknown>>,
serviceRedirectionBinding: ServiceRedirectionBinding<unknown>,
): PlanResult {
const planServiceNode: PlanServiceNode = {
Expand Down Expand Up @@ -195,9 +197,9 @@ function buildServiceRedirectionToLeafBindingPlanResult(
describe(plan.name, () => {
let constantValueBinding: ConstantValueBinding<unknown>;
let dynamicValueBinding: DynamicValueBinding<unknown>;
let factoryBinding: FactoryBinding<unknown>;
let factoryBinding: FactoryBinding<Factory<unknown>>;
let instanceBinding: InstanceBinding<unknown>;
let providerBinding: ProviderBinding<unknown>;
let providerBinding: ProviderBinding<Provider<unknown>>;
let serviceRedirectionBinding: ServiceRedirectionBinding<unknown>;
let serviceRedirectionToNonExistentBinding: ServiceRedirectionBinding<unknown>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { ConstantValueBinding } from '../../binding/models/ConstantValueBinding';
import { DynamicValueBinding } from '../../binding/models/DynamicValueBinding';
import { Factory } from '../../binding/models/Factory';
import { FactoryBinding } from '../../binding/models/FactoryBinding';
import { Provider } from '../../binding/models/Provider';
import { ProviderBinding } from '../../binding/models/ProviderBinding';
import { BaseBindingNode } from './BaseBindingNode';

export type LeafBindingNode = BaseBindingNode<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
| ConstantValueBinding<any>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
| DynamicValueBinding<any>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
| FactoryBinding<any>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
| ProviderBinding<any>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type LeafBindingNode<TActivated = any> = BaseBindingNode<
| ConstantValueBinding<TActivated>
| DynamicValueBinding<TActivated>
| (TActivated extends Factory<unknown> ? FactoryBinding<TActivated> : never)
| (TActivated extends Provider<unknown> ? ProviderBinding<TActivated> : never)
>;
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { InstanceBinding } from '../../binding/models/InstanceBinding';
import { InstanceBindingNode } from './InstanceBindingNode';

export type PlanServiceNodeParent = InstanceBindingNode;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type PlanServiceNodeParent<TActivated = any> = InstanceBindingNode<
InstanceBinding<TActivated>
>;
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
import { BindingType } from '../../binding/models/BindingType';
import { ScopedBinding } from '../../binding/models/ScopedBinding';
import { ResolutionParams } from '../models/ResolutionParams';
import { Resolved } from '../models/Resolved';

export function resolveScoped<
TActivated,
Expand All @@ -14,9 +15,9 @@ export function resolveScoped<
TBinding extends ScopedBinding<TType, BindingScope, TActivated>,
>(
getBinding: (arg: TArg) => TBinding,
resolve: (params: ResolutionParams, arg: TArg) => TActivated,
): (params: ResolutionParams, arg: TArg) => TActivated {
return (params: ResolutionParams, arg: TArg): TActivated => {
resolve: (params: ResolutionParams, arg: TArg) => Resolved<TActivated>,
): (params: ResolutionParams, arg: TArg) => Resolved<TActivated> {
return (params: ResolutionParams, arg: TArg): Resolved<TActivated> => {
const binding: TBinding = getBinding(arg);

switch (binding.scope) {
Expand All @@ -25,7 +26,7 @@ export function resolveScoped<
return binding.cache.value;
}

const resolvedValue: TActivated = resolve(params, arg);
const resolvedValue: Resolved<TActivated> = resolve(params, arg);

binding.cache = {
isRight: true,
Expand All @@ -36,10 +37,12 @@ export function resolveScoped<
}
case bindingScopeValues.Request: {
if (params.requestScopeCache.has(binding.id)) {
return params.requestScopeCache.get(binding.id) as TActivated;
return params.requestScopeCache.get(
binding.id,
) as Resolved<TActivated>;
}

const resolvedValue: TActivated = resolve(params, arg);
const resolvedValue: Resolved<TActivated> = resolve(params, arg);

params.requestScopeCache.set(binding.id, resolvedValue);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,25 @@ import { BindingType } from '../../binding/models/BindingType';
import { ScopedBinding } from '../../binding/models/ScopedBinding';
import { getSelf } from '../../common/calculations/getSelf';
import { ResolutionParams } from '../models/ResolutionParams';
import { Resolved } from '../models/Resolved';
import { resolveScoped } from './resolveScoped';

export const resolveScopedBinding: <
TActivated,
TType extends BindingType,
TBinding extends ScopedBinding<TType, BindingScope, TActivated>,
>(
resolve: (params: ResolutionParams, binding: TBinding) => TActivated,
) => (params: ResolutionParams, binding: TBinding) => TActivated = <
resolve: (
params: ResolutionParams,
binding: TBinding,
) => Resolved<TActivated>,
) => (params: ResolutionParams, binding: TBinding) => Resolved<TActivated> = <
TActivated,
TType extends BindingType,
TBinding extends ScopedBinding<TType, BindingScope, TActivated>,
>(
resolve: (params: ResolutionParams, binding: TBinding) => TActivated,
resolve: (
params: ResolutionParams,
binding: TBinding,
) => Resolved<TActivated>,
) => resolveScoped(getSelf, resolve);
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ import { InstanceBinding } from '../../binding/models/InstanceBinding';
import { InstanceBindingNode } from '../../planning/models/InstanceBindingNode';
import { getInstanceNodeBinding } from '../calculations/getInstanceNodeBinding';
import { ResolutionParams } from '../models/ResolutionParams';
import { Resolved } from '../models/Resolved';
import { resolveScoped } from './resolveScoped';

export const resolveScopedInstanceBindingNode: <TActivated>(
resolve: (
params: ResolutionParams,
node: InstanceBindingNode<InstanceBinding<TActivated>>,
) => TActivated,
) => Resolved<TActivated>,
) => (
params: ResolutionParams,
node: InstanceBindingNode<InstanceBinding<TActivated>>,
) => TActivated = <TActivated>(
) => Resolved<TActivated> = <TActivated>(
resolve: (
params: ResolutionParams,
node: InstanceBindingNode<InstanceBinding<TActivated>>,
) => TActivated,
) => Resolved<TActivated>,
) => resolveScoped(getInstanceNodeBinding, resolve);
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { bindingScopeValues } from '../../binding/models/BindingScope';
import { BindingType } from '../../binding/models/BindingType';
import { ScopedBinding } from '../../binding/models/ScopedBinding';
import { ResolutionParams } from '../models/ResolutionParams';
import { Resolved } from '../models/Resolved';

export function resolveSingletonScopedBinding<
TActivated,
Expand All @@ -12,14 +13,20 @@ export function resolveSingletonScopedBinding<
TActivated
>,
>(
resolve: (params: ResolutionParams, binding: TBinding) => TActivated,
): (params: ResolutionParams, binding: TBinding) => TActivated {
return (params: ResolutionParams, binding: TBinding): TActivated => {
resolve: (
params: ResolutionParams,
binding: TBinding,
) => Resolved<TActivated>,
): (params: ResolutionParams, binding: TBinding) => Resolved<TActivated> {
return (
params: ResolutionParams,
binding: TBinding,
): Resolved<TActivated> => {
if (binding.cache.isRight) {
return binding.cache.value;
}

const resolvedValue: TActivated = resolve(params, binding);
const resolvedValue: Resolved<TActivated> = resolve(params, binding);

binding.cache = {
isRight: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { DynamicValueBinding } from '../../binding/models/DynamicValueBinding';
import { ResolutionParams } from '../models/ResolutionParams';
import { Resolved } from '../models/Resolved';

export function resolveDynamicValueBindingCallback<TActivated>(
params: ResolutionParams,
binding: DynamicValueBinding<TActivated>,
): TActivated | Promise<TActivated> {
): Resolved<TActivated> {
return binding.value(params.context);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import { beforeAll, describe, expect, it, jest } from '@jest/globals';

import { bindingScopeValues } from '../../binding/models/BindingScope';
import { bindingTypeValues } from '../../binding/models/BindingType';
import { Factory } from '../../binding/models/Factory';
import { FactoryBinding } from '../../binding/models/FactoryBinding';
import { ResolutionParams } from '../models/ResolutionParams';
import { resolveFactoryBindingCallback } from './resolveFactoryBindingCallback';

describe(resolveFactoryBindingCallback.name, () => {
let resolutionParamsFixture: ResolutionParams;

let factoryValueBindingMock: jest.Mocked<FactoryBinding<unknown>>;
let factoryValueBindingMock: jest.Mocked<FactoryBinding<Factory<unknown>>>;

beforeAll(() => {
resolutionParamsFixture = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import { Factory } from '../../binding/models/Factory';
import { FactoryBinding } from '../../binding/models/FactoryBinding';
import { ResolutionParams } from '../models/ResolutionParams';

export function resolveFactoryBindingCallback(
params: ResolutionParams,
binding: FactoryBinding<unknown>,
): Factory<unknown> {
export function resolveFactoryBindingCallback<
TActivated extends Factory<unknown>,
>(params: ResolutionParams, binding: FactoryBinding<TActivated>): TActivated {
return binding.factory(params.context);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { resolveProviderBindingCallback } from './resolveProviderBindingCallback
describe(resolveProviderBindingCallback.name, () => {
let resolutionParamsFixture: ResolutionParams;

let providerBindingMock: jest.Mocked<ProviderBinding<unknown>>;
let providerBindingMock: jest.Mocked<ProviderBinding<Provider<unknown>>>;

beforeAll(() => {
resolutionParamsFixture = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import { Provider } from '../../binding/models/Provider';
import { ProviderBinding } from '../../binding/models/ProviderBinding';
import { ResolutionParams } from '../models/ResolutionParams';

export function resolveProviderBindingCallback<TActivated>(
params: ResolutionParams,
binding: ProviderBinding<TActivated>,
): Provider<TActivated> {
export function resolveProviderBindingCallback<
TActivated extends Provider<unknown>,
>(params: ResolutionParams, binding: ProviderBinding<TActivated>): TActivated {
return binding.provider(params.context);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type Resolved<TActivated> =
| SyncResolved<TActivated>
| Promise<SyncResolved<TActivated>>;

export type SyncResolved<TActivated> = Awaited<TActivated>;

0 comments on commit 67c4491

Please sign in to comment.