-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from SeanLuis/feature/adding_accesors_utilities
feature: adding accessors (getters & setters) decorators utilities and documentation
- Loading branch information
Showing
13 changed files
with
268 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { IAccessors } from "../../interfaces/accessors/IAccessors"; | ||
|
||
/** | ||
* Decorator function that automatically creates getters and setters for properties. | ||
* @param options - Optional. The options for the Accessors decorator. | ||
* @returns A decorator function. | ||
*/ | ||
export function Accessors(options?: IAccessors) { | ||
return function <T extends { new (...args: any[]): {} }>(constructor: T) { | ||
const instance = new constructor(); | ||
|
||
const instanceProperties = Object.getOwnPropertyNames(instance); | ||
|
||
instanceProperties.forEach(propertyName => { | ||
if (propertyName === 'constructor' || (!options?.includePrivate && propertyName.startsWith('_'))) { | ||
return; | ||
} | ||
|
||
const baseName = propertyName.startsWith('_') ? propertyName.slice(1) : propertyName; | ||
const capitalizedBaseName = baseName.charAt(0).toUpperCase() + baseName.slice(1); | ||
|
||
const getterName = `get${capitalizedBaseName}`; | ||
if (typeof constructor.prototype[getterName] === 'undefined') { | ||
Object.defineProperty(constructor.prototype, getterName, { | ||
get() { return this[propertyName]; }, | ||
enumerable: options?.enumerable ?? false, | ||
configurable: true, | ||
}); | ||
} | ||
|
||
const setterName = `set${capitalizedBaseName}`; | ||
if (typeof constructor.prototype[setterName] === 'undefined') { | ||
Object.defineProperty(constructor.prototype, setterName, { | ||
set(newValue) { this[propertyName] = newValue; }, | ||
enumerable: options?.enumerable ?? false, | ||
configurable: true, | ||
}); | ||
} | ||
}); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { IGetter } from "../../interfaces/accessors/IGetter"; | ||
|
||
/** | ||
* Decorator function that automatically creates a getter for a property. | ||
* @param options - Optional. The options for the Getter decorator. | ||
* @returns A decorator function. | ||
*/ | ||
export function Getter(options?: IGetter) { | ||
return function (target: any, propertyName: string) { | ||
const baseName = propertyName.startsWith('_') ? propertyName.slice(1) : propertyName; | ||
const capitalizedBaseName = baseName.charAt(0).toUpperCase() + baseName.slice(1); | ||
|
||
Object.defineProperty(target, `get${capitalizedBaseName}`, { | ||
get() { return this[propertyName]; }, | ||
enumerable: options?.enumerable ?? true, | ||
configurable: true, | ||
}); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { ISetter } from "../../interfaces/accessors/ISetter"; | ||
|
||
/** | ||
* Decorator function that automatically creates a setter for a property. | ||
* @param options - Optional. The options for the Setter decorator. | ||
* @returns A decorator function. | ||
*/ | ||
export function Setter(options?: ISetter) { | ||
return function (target: any, propertyName: string) { | ||
const baseName = propertyName.startsWith('_') ? propertyName.slice(1) : propertyName; | ||
const capitalizedBaseName = baseName.charAt(0).toUpperCase() + baseName.slice(1); | ||
|
||
Object.defineProperty(target, `set${capitalizedBaseName}`, { | ||
set(newValue) { this[propertyName] = newValue; }, | ||
enumerable: options?.writable ?? true, | ||
configurable: true, | ||
}); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { Accessors } from './Accessors'; | ||
export { Getter } from './Getter'; | ||
export { Setter } from './Setter'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* `IAccessors` interface for AutoAccessors decorator options. | ||
* | ||
* @property {boolean} includePrivate - Optional. Determines if the private properties should be included in the accessor. | ||
* If set to true, private properties are included. | ||
* If set to false or omitted, private properties are not included. | ||
* @property {boolean} enumerable - Optional. Determines if the property shows up during enumeration of the properties on the corresponding object. | ||
* If set to true, the property appears during enumeration. | ||
* If set to false or omitted, the property does not appear. | ||
* @property {boolean} writable - Optional. Determines if the property should be writable. | ||
* If set to true, the property can be changed. | ||
* If set to false or omitted, the property is read-only. | ||
*/ | ||
export interface IAccessors { | ||
includePrivate?: boolean; | ||
enumerable?: boolean; | ||
writable?: boolean; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** | ||
* `IGetter` interface for AutoGetter decorator options. | ||
* | ||
* @property {boolean} enumerable - Optional. Determines if the property shows up during enumeration of the properties on the corresponding object. | ||
* If set to true, the property appears during enumeration. | ||
* If set to false or omitted, the property does not appear. | ||
*/ | ||
export interface IGetter { | ||
enumerable?: boolean; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** | ||
* `ISetter` interface for AutoSetter decorator options. | ||
* | ||
* @property {boolean} writable - Optional. Determines if the property should be writable. | ||
* If set to true, the property can be changed. | ||
* If set to false or omitted, the property is read-only. | ||
*/ | ||
export interface ISetter { | ||
writable?: boolean; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// @ts-nocheck | ||
|
||
import { Accessors } from '../../../src'; | ||
|
||
interface AccessorsMethods { | ||
getProp(): string; | ||
setProp(value: string): void; | ||
} | ||
|
||
@Accessors({ includePrivate: true }) | ||
class TestClass { | ||
private _prop: string = 'test'; | ||
|
||
constructor(prop: string) { | ||
this._prop = prop; | ||
} | ||
} | ||
|
||
describe('AutoAccessors', () => { | ||
it('should create a setter for the property', () => { | ||
const testInstance = new TestClass('initial') as TestClass & AccessorsMethods; | ||
|
||
expect(testInstance).toHaveProperty('setProp'); | ||
expect(testInstance).toHaveProperty('getProp'); | ||
expect(testInstance.getProp).toBeDefined(); | ||
|
||
testInstance. _prop = 'new value'; | ||
expect(testInstance._prop).toBe('new value'); | ||
}); | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// @ts-nocheck | ||
|
||
import { Getter } from '../../../src'; | ||
|
||
interface GetterMethod { | ||
getProp(): string; | ||
} | ||
|
||
class TestClass { | ||
@Getter() private _prop: string = 'test'; | ||
} | ||
|
||
describe('AutoGetter', () => { | ||
it('should create a getter for the property', () => { | ||
const testInstance = new TestClass() as TestClass & GetterMethod; | ||
expect(testInstance).toHaveProperty('getProp'); | ||
expect(testInstance.getProp).toBeDefined(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// @ts-nocheck | ||
|
||
import { Setter } from '../../../src'; | ||
|
||
interface SetterMethod { | ||
setProp(value: string): void; | ||
} | ||
|
||
class TestClass { | ||
@Setter() private _prop: string = 'test'; | ||
} | ||
|
||
describe('AutoSetter', () => { | ||
it('should create a setter for the property', () => { | ||
const testInstance = new TestClass() as TestClass & SetterMethod; | ||
expect(testInstance).toHaveProperty('setProp'); | ||
|
||
testInstance._prop = 'new value'; | ||
expect(testInstance._prop).toBe('new value'); | ||
}); | ||
}); |