Skip to content

Commit

Permalink
Use new Concern Constructor interface
Browse files Browse the repository at this point in the history
  • Loading branch information
aedart committed Feb 22, 2024
1 parent bfa7eff commit 030721a
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 143 deletions.
13 changes: 8 additions & 5 deletions packages/contracts/src/support/concerns/Injector.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Constructor } from "@aedart/contracts";
import Concern from "./Concern";
import ConcernConstructor from "./ConcernConstructor";
import Configuration from "./Configuration";
import MustUseConcerns from "./MustUseConcerns";

Expand Down Expand Up @@ -36,20 +37,21 @@ export default interface Injector<T = object>
* @template T = object The target class that concern classes must be injected into
* @template C = {@link Concern}
*
* @param {Constructor<C> | Configuration<C>} concerns List of concern classes / injection configurations
* @param {ConcernConstructor<C> | Configuration<C>} concerns List of concern classes / injection configurations
*
* @returns {MustUseConcerns<T>} The modified target class
*
* @throws {InjectionException}
*/
inject<C = Concern>(...concerns: (Constructor<C>|Configuration<C>)[]): MustUseConcerns<T>;
inject<C extends Concern>(...concerns: (ConcernConstructor<C>|Configuration<C>)[]): MustUseConcerns<T>;

/**
* Defines the concern classes that must be used by the target class.
*
* **Note**: _Method changes the target class, such that it implements and respects the
* {@link MustUseConcerns} interface. The original target class' constructor remains the untouched!_
*
* @template C extends Concern
* @template T = object
*
* @param {T} target The target class that must define the concern classes to be used
Expand All @@ -60,7 +62,7 @@ export default interface Injector<T = object>
* @throws {InjectionException} If given concern classes conflict with target class' parent concern classes,
* e.g. in case of duplicates. Or, if unable to modify target class.
*/
defineConcerns<T = object>(target: T, concerns: Constructor<Concern>[]): MustUseConcerns<T>;
defineConcerns<C extends Concern, T = object>(target: T, concerns: ConcernConstructor<C>[]): MustUseConcerns<T>;

/**
* Defines a concerns {@link Container} in target class' prototype.
Expand Down Expand Up @@ -102,6 +104,7 @@ export default interface Injector<T = object>
* **Note**: _Method will do nothing, if a property or method already exists in the target class' prototype
* chain, with the same name as given "alias"._
*
* @template C extends Concern
* @template T = object
*
* @param {MustUseConcerns<T>} target The target in which "alias" must be defined in
Expand All @@ -115,10 +118,10 @@ export default interface Injector<T = object>
* @throws {InjectionException} If unable to define "alias" in target class, e.g. due to failure when obtaining
* or defining [property descriptors]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor#description}.
*/
defineAlias<T = object>(
defineAlias<C extends Concern, T = object>(
target: MustUseConcerns<T>,
alias: PropertyKey,
key: PropertyKey,
source: Constructor<Concern>
source: ConcernConstructor<C>
): boolean;
}
4 changes: 2 additions & 2 deletions packages/contracts/src/support/concerns/MustUseConcerns.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ConstructorOrAbstractConstructor } from "@aedart/contracts";
import type { ConcernClasses } from "./index";
import type { ConcernClasses, Concern } from "./index";
import { CONCERN_CLASSES } from "./index";
import Owner from "./Owner";

Expand Down Expand Up @@ -35,5 +35,5 @@ export default interface MustUseConcerns<T = object>
*
* @return {ConcernClasses}
*/
[CONCERN_CLASSES](): ConcernClasses;
[CONCERN_CLASSES](): ConcernClasses<Concern>;
}
9 changes: 5 additions & 4 deletions packages/contracts/src/support/concerns/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Constructor, ConstructorOrAbstractConstructor } from "@aedart/contracts";
import { ConstructorOrAbstractConstructor } from "@aedart/contracts";
import Concern from "./Concern";
import ConcernConstructor from "./ConcernConstructor";

/**
* An alias for a property or method in a {@link Concern} class
Expand All @@ -21,8 +22,8 @@ export type Aliases<T extends Concern> = {
/**
* Array that holds a {@link Concern} class / Owner class pair.
*/
export type ConcernOwnerClassPair = [
Constructor<Concern>, // Concern Class
export type ConcernOwnerClassPair<T extends Concern> = [
ConcernConstructor<T>, // Concern Class
ConstructorOrAbstractConstructor // Owner class that must use the concern class
];

Expand All @@ -32,4 +33,4 @@ export type ConcernOwnerClassPair = [
*
* @see ConcernOwnerClassPair
*/
export type ConcernClasses = ConcernOwnerClassPair[];
export type ConcernClasses<T extends Concern> = ConcernOwnerClassPair<T>[];
268 changes: 136 additions & 132 deletions packages/support/src/concerns/ConcernsInjector.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
Concern,
ConcernConstructor,
Injector,
MustUseConcerns,
Configuration
Expand Down Expand Up @@ -46,137 +47,140 @@ export default class ConcernsInjector<T = object> implements Injector<T>
{
return this.#target;
}

/**
* Injects concern classes into the target class and return the modified target.
*
* **Note**: _Method performs injection in the following way:_
*
* _**A**: Defines the concern classes in target class, via {@link defineConcerns}._
*
* _**B**: Defines a concerns container in target class' prototype, via {@link defineContainer}._
*
* _**C**: Defines "aliases" (proxy properties and methods) in target class' prototype, via {@link defineAliases}._
*
* @template T = object The target class that concern classes must be injected into
* @template C = {@link Concern}
*
* @param {Constructor<C> | Configuration<C>} concerns List of concern classes / injection configurations
*
* @returns {MustUseConcerns<T>} The modified target class
*
* @throws {InjectionException}
*/
public inject<C = Concern>(...concerns: (Constructor<C>|Configuration<C>)[]): MustUseConcerns<T>
{
// TODO: implement this method...

// Resolve arguments, such that they are of type "concern injection configuration".

// A) Define the concern classes in target class

// B) Define a concerns container in target class' prototype

// C) Define "aliases" (proxy properties and methods) in target class' prototype

return this.target as MustUseConcerns<T>;
}

/**
* Defines the concern classes that must be used by the target class.
*
* **Note**: _Method changes the target class, such that it implements and respects the
* {@link MustUseConcerns} interface. The original target class' constructor remains the untouched!_
*
* @template T = object
*
* @param {T} target The target class that must define the concern classes to be used
* @param {Constructor<Concern>[]} concerns List of concern classes
*
* @returns {MustUseConcerns<T>} The modified target class
*
* @throws {InjectionException} If given concern classes conflict with target class' parent concern classes,
* e.g. in case of duplicates. Or, if unable to modify target class.
*/
public defineConcerns<T = object>(target: T, concerns: Constructor<Concern>[]): MustUseConcerns<T>
{
// TODO: implement this method...

return target as MustUseConcerns<T>;
}

/**
* Defines a concerns {@link Container} in target class' prototype.
*
* **Note**: _Method changes the target class, such that it implements and respects the
* [Owner]{@link import('@aedart/contracts/support/concerns').Owner} interface!_
*
* @template T = object
*
* @param {MustUseConcerns<T>} target The target in which a concerns container must be defined
*
* @returns {MustUseConcerns<T>} The modified target class
*
* @throws {InjectionException} If unable to define concerns container in target class
*/
public defineContainer<T = object>(target: MustUseConcerns<T>): MustUseConcerns<T>
{
// TODO: implement this method...

return target;
}

/**
* Defines "aliases" (proxy properties and methods) in target class' prototype, such that they
* point to the properties and methods available in the concern classes.
*
* **Note**: _Method defines each alias using the {@link defineAlias} method!_
*
* @template T = object
*
* @param {MustUseConcerns<T>} target The target in which "aliases" must be defined in
* @param {Configuration<Concern>[]} configurations List of concern injection configurations
*
* @returns {MustUseConcerns<T>} The modified target class
*
* @throws {InjectionException} If case of alias naming conflicts. Or, if unable to define aliases in target class.
*/
public defineAliases<T = object>(target: MustUseConcerns<T>, configurations: Configuration<Concern>[]): MustUseConcerns<T>
{
// TODO: implement this method...

return target;
}

/**
* Defines an "alias" (proxy property or method) in target class' prototype, to a property or method
* in given concern.
*
* **Note**: _Method will do nothing, if a property or method already exists in the target class' prototype
* chain, with the same name as given "alias"._
*
* @template T = object
*
* @param {MustUseConcerns<T>} target The target in which "alias" must be defined in
* @param {PropertyKey} alias Name of the "alias" in the target class (name of the proxy property or method)
* @param {PropertyKey} key Name of the property or method that the "alias" is for, in the concern class (`source`)
* @param {Constructor<Concern>} source The concern class that holds the property or methods (`key`)
*
* @returns {boolean} `true` if "alias" was in target class. `false` if not, e.g. a property or method already
* exists in target class' prototype chain, with the same name as the alias.
*
* @throws {InjectionException} If unable to define "alias" in target class, e.g. due to failure when obtaining
* or defining [property descriptors]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor#description}.
*/
public defineAlias<T = object>(
target: MustUseConcerns<T>,
alias: PropertyKey,
key: PropertyKey,
source: Constructor<Concern>
): boolean
{
// TODO: implement this method...

return false;
}
// TODO: INCOMPLETE...

//
// /**
// * Injects concern classes into the target class and return the modified target.
// *
// * **Note**: _Method performs injection in the following way:_
// *
// * _**A**: Defines the concern classes in target class, via {@link defineConcerns}._
// *
// * _**B**: Defines a concerns container in target class' prototype, via {@link defineContainer}._
// *
// * _**C**: Defines "aliases" (proxy properties and methods) in target class' prototype, via {@link defineAliases}._
// *
// * @template T = object The target class that concern classes must be injected into
// * @template C = {@link Concern}
// *
// * @param {Constructor<C> | Configuration<C>} concerns List of concern classes / injection configurations
// *
// * @returns {MustUseConcerns<T>} The modified target class
// *
// * @throws {InjectionException}
// */
// public inject<C = Concern>(...concerns: (Constructor<C>|Configuration<C>)[]): MustUseConcerns<T>
// {
// // TODO: implement this method...
//
// // Resolve arguments, such that they are of type "concern injection configuration".
//
// // A) Define the concern classes in target class
//
// // B) Define a concerns container in target class' prototype
//
// // C) Define "aliases" (proxy properties and methods) in target class' prototype
//
// return this.target as MustUseConcerns<T>;
// }
//
// /**
// * Defines the concern classes that must be used by the target class.
// *
// * **Note**: _Method changes the target class, such that it implements and respects the
// * {@link MustUseConcerns} interface. The original target class' constructor remains the untouched!_
// *
// * @template T = object
// *
// * @param {T} target The target class that must define the concern classes to be used
// * @param {Constructor<Concern>[]} concerns List of concern classes
// *
// * @returns {MustUseConcerns<T>} The modified target class
// *
// * @throws {InjectionException} If given concern classes conflict with target class' parent concern classes,
// * e.g. in case of duplicates. Or, if unable to modify target class.
// */
// public defineConcerns<T = object>(target: T, concerns: Constructor<Concern>[]): MustUseConcerns<T>
// {
// // TODO: implement this method...
//
// return target as MustUseConcerns<T>;
// }
//
// /**
// * Defines a concerns {@link Container} in target class' prototype.
// *
// * **Note**: _Method changes the target class, such that it implements and respects the
// * [Owner]{@link import('@aedart/contracts/support/concerns').Owner} interface!_
// *
// * @template T = object
// *
// * @param {MustUseConcerns<T>} target The target in which a concerns container must be defined
// *
// * @returns {MustUseConcerns<T>} The modified target class
// *
// * @throws {InjectionException} If unable to define concerns container in target class
// */
// public defineContainer<T = object>(target: MustUseConcerns<T>): MustUseConcerns<T>
// {
// // TODO: implement this method...
//
// return target;
// }
//
// /**
// * Defines "aliases" (proxy properties and methods) in target class' prototype, such that they
// * point to the properties and methods available in the concern classes.
// *
// * **Note**: _Method defines each alias using the {@link defineAlias} method!_
// *
// * @template T = object
// *
// * @param {MustUseConcerns<T>} target The target in which "aliases" must be defined in
// * @param {Configuration<Concern>[]} configurations List of concern injection configurations
// *
// * @returns {MustUseConcerns<T>} The modified target class
// *
// * @throws {InjectionException} If case of alias naming conflicts. Or, if unable to define aliases in target class.
// */
// public defineAliases<T = object>(target: MustUseConcerns<T>, configurations: Configuration<Concern>[]): MustUseConcerns<T>
// {
// // TODO: implement this method...
//
// return target;
// }
//
// /**
// * Defines an "alias" (proxy property or method) in target class' prototype, to a property or method
// * in given concern.
// *
// * **Note**: _Method will do nothing, if a property or method already exists in the target class' prototype
// * chain, with the same name as given "alias"._
// *
// * @template T = object
// *
// * @param {MustUseConcerns<T>} target The target in which "alias" must be defined in
// * @param {PropertyKey} alias Name of the "alias" in the target class (name of the proxy property or method)
// * @param {PropertyKey} key Name of the property or method that the "alias" is for, in the concern class (`source`)
// * @param {Constructor<Concern>} source The concern class that holds the property or methods (`key`)
// *
// * @returns {boolean} `true` if "alias" was in target class. `false` if not, e.g. a property or method already
// * exists in target class' prototype chain, with the same name as the alias.
// *
// * @throws {InjectionException} If unable to define "alias" in target class, e.g. due to failure when obtaining
// * or defining [property descriptors]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor#description}.
// */
// public defineAlias<T = object>(
// target: MustUseConcerns<T>,
// alias: PropertyKey,
// key: PropertyKey,
// source: Constructor<Concern>
// ): boolean
// {
// // TODO: implement this method...
//
// return false;
// }
}

0 comments on commit 030721a

Please sign in to comment.