@unshared/decorators 0.0.15 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- {"version":3,"file":"Debounce.cjs","sources":["../Debounce.ts"],"sourcesContent":["import { Function, MethodDecorator } from '@unshared/types'\nimport { debounce } from '@unshared/functions/debounce'\n\n/**\n * Debounce a method so that it will only execute after the specified delay. If the method\n * is called multiple times before the delay has passed, the method will only execute once\n * after the delay has passed. The method will be called with the parameters of the last call.\n *\n * **Note:** This decorator will omit the return value of the method and return `undefined`.\n *\n * @param delay The delay in milliseconds to wait before executing the method.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a debounced method.\n * class Greeter {\n * ->@Debounce(100)\n * greet(name: string) { return `Hello, ${name}! - ${Date.now()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice')\n * instance.greet('Bob')\n * instance.greet('Charlie')\n *\n * // After 100ms the method will be called with the parameters of the last call.\n * // => Hello, Charlie!\n */\nexport function Debounce<T extends Function<void>>(delay: number): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = debounce(method, delay) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n beforeAll(() => {\n vi.useFakeTimers()\n })\n\n test('should not call the function if the delay has not passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(50)\n expect(fn).not.toHaveBeenCalled()\n })\n\n test('should call the function once after the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should call the function once with the parameters of the last call', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn(name: string) { fn(name) } }\n const instance = new Greeter()\n instance.fn('Alice')\n instance.fn('Bob')\n instance.fn('Charlie')\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledWith('Charlie')\n })\n\n test('should call the function multiple times if the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(3)\n })\n\n test('should return undefined', () => {\n const fn = vi.fn(() => 'foobar')\n class Greeter { @Debounce(10) fn() { return fn() } }\n const instance = new Greeter()\n const result = instance.fn()\n expect(result).toBeUndefined()\n })\n}\n"],"names":["debounce"],"mappings":";;AA4BO,SAAS,SAAmC,OAAmC;AAC7E,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQA,SAAAA,SAAS,QAAQ,KAAK,GAClC;AAAA,EAAA;AAEX;;"}
1
+ {"version":3,"file":"Debounce.cjs","sources":["../Debounce.ts"],"sourcesContent":["import { debounce } from '@unshared/functions/debounce'\nimport { Function, MethodDecorator } from '@unshared/types'\n\n/**\n * Debounce a method so that it will only execute after the specified delay. If the method\n * is called multiple times before the delay has passed, the method will only execute once\n * after the delay has passed. The method will be called with the parameters of the last call.\n *\n * **Note:** This decorator will omit the return value of the method and return `undefined`.\n *\n * @param delay The delay in milliseconds to wait before executing the method.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a debounced method.\n * class Greeter {\n * ->@Debounce(100)\n * greet(name: string) { return `Hello, ${name}! - ${Date.now()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice')\n * instance.greet('Bob')\n * instance.greet('Charlie')\n *\n * // After 100ms the method will be called with the parameters of the last call.\n * // => Hello, Charlie!\n */\nexport function Debounce<T extends Function<void>>(delay: number): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = debounce(method, delay) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n beforeAll(() => {\n vi.useFakeTimers()\n })\n\n test('should not call the function if the delay has not passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(50)\n expect(fn).not.toHaveBeenCalled()\n })\n\n test('should call the function once after the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should call the function once with the parameters of the last call', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn(name: string) { fn(name) } }\n const instance = new Greeter()\n instance.fn('Alice')\n instance.fn('Bob')\n instance.fn('Charlie')\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledWith('Charlie')\n })\n\n test('should call the function multiple times if the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(3)\n })\n\n test('should return undefined', () => {\n const fn = vi.fn(() => 'foobar')\n class Greeter { @Debounce(10) fn() { return fn() } }\n const instance = new Greeter()\n const result = instance.fn()\n expect(result).toBeUndefined()\n })\n}\n"],"names":["debounce"],"mappings":";;AA4BO,SAAS,SAAmC,OAAmC;AAC7E,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQA,SAAAA,SAAS,QAAQ,KAAK,GAClC;AAAA,EAAA;AAEX;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Debounce.js","sources":["../Debounce.ts"],"sourcesContent":["import { Function, MethodDecorator } from '@unshared/types'\nimport { debounce } from '@unshared/functions/debounce'\n\n/**\n * Debounce a method so that it will only execute after the specified delay. If the method\n * is called multiple times before the delay has passed, the method will only execute once\n * after the delay has passed. The method will be called with the parameters of the last call.\n *\n * **Note:** This decorator will omit the return value of the method and return `undefined`.\n *\n * @param delay The delay in milliseconds to wait before executing the method.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a debounced method.\n * class Greeter {\n * ->@Debounce(100)\n * greet(name: string) { return `Hello, ${name}! - ${Date.now()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice')\n * instance.greet('Bob')\n * instance.greet('Charlie')\n *\n * // After 100ms the method will be called with the parameters of the last call.\n * // => Hello, Charlie!\n */\nexport function Debounce<T extends Function<void>>(delay: number): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = debounce(method, delay) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n beforeAll(() => {\n vi.useFakeTimers()\n })\n\n test('should not call the function if the delay has not passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(50)\n expect(fn).not.toHaveBeenCalled()\n })\n\n test('should call the function once after the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should call the function once with the parameters of the last call', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn(name: string) { fn(name) } }\n const instance = new Greeter()\n instance.fn('Alice')\n instance.fn('Bob')\n instance.fn('Charlie')\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledWith('Charlie')\n })\n\n test('should call the function multiple times if the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(3)\n })\n\n test('should return undefined', () => {\n const fn = vi.fn(() => 'foobar')\n class Greeter { @Debounce(10) fn() { return fn() } }\n const instance = new Greeter()\n const result = instance.fn()\n expect(result).toBeUndefined()\n })\n}\n"],"names":[],"mappings":";AA4BO,SAAS,SAAmC,OAAmC;AAC7E,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQ,SAAS,QAAQ,KAAK,GAClC;AAAA,EAAA;AAEX;"}
1
+ {"version":3,"file":"Debounce.js","sources":["../Debounce.ts"],"sourcesContent":["import { debounce } from '@unshared/functions/debounce'\nimport { Function, MethodDecorator } from '@unshared/types'\n\n/**\n * Debounce a method so that it will only execute after the specified delay. If the method\n * is called multiple times before the delay has passed, the method will only execute once\n * after the delay has passed. The method will be called with the parameters of the last call.\n *\n * **Note:** This decorator will omit the return value of the method and return `undefined`.\n *\n * @param delay The delay in milliseconds to wait before executing the method.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a debounced method.\n * class Greeter {\n * ->@Debounce(100)\n * greet(name: string) { return `Hello, ${name}! - ${Date.now()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice')\n * instance.greet('Bob')\n * instance.greet('Charlie')\n *\n * // After 100ms the method will be called with the parameters of the last call.\n * // => Hello, Charlie!\n */\nexport function Debounce<T extends Function<void>>(delay: number): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = debounce(method, delay) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n beforeAll(() => {\n vi.useFakeTimers()\n })\n\n test('should not call the function if the delay has not passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(50)\n expect(fn).not.toHaveBeenCalled()\n })\n\n test('should call the function once after the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should call the function once with the parameters of the last call', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn(name: string) { fn(name) } }\n const instance = new Greeter()\n instance.fn('Alice')\n instance.fn('Bob')\n instance.fn('Charlie')\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledWith('Charlie')\n })\n\n test('should call the function multiple times if the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Debounce(10) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(3)\n })\n\n test('should return undefined', () => {\n const fn = vi.fn(() => 'foobar')\n class Greeter { @Debounce(10) fn() { return fn() } }\n const instance = new Greeter()\n const result = instance.fn()\n expect(result).toBeUndefined()\n })\n}\n"],"names":[],"mappings":";AA4BO,SAAS,SAAmC,OAAmC;AAC7E,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQ,SAAS,QAAQ,KAAK,GAClC;AAAA,EAAA;AAEX;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Memoize.cjs","sources":["../Memoize.ts"],"sourcesContent":["import { Function, MethodDecorator } from '@unshared/types'\nimport { MemoizeOptions, memoize } from '@unshared/functions/memoize'\n\n/**\n * Decorate a method to memoize it's result based on the arguments. Meaning\n * that it will return the same result without executing the method again,\n * **unless the arguments change**.\n *\n * @param options The memoization options.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a memoized method.\n * class Greeter {\n * ->@Memoize()\n * greet(name: string) { return `Hello, ${name}! - ${Math.random()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Bob') // 'Hello, Bob! - 0.987654321'\n */\nexport function Memoize<T extends Function>(options?: MemoizeOptions<T>): MethodDecorator<T> {\n return function(_target, _propertyName, descriptor) {\n const method = descriptor.value!\n descriptor.value = memoize(method, options) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\n\nif (import.meta.vitest) {\n test('should memoize the method', () => {\n const fn = vi.fn(Math.random)\n class MyClass { @Memoize() getId() { return fn() } }\n const instance = new MyClass()\n const id1 = instance.getId()\n const id2 = instance.getId()\n expect(id1).toStrictEqual(id2)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith()\n })\n\n test('should memoize the method by parameter', () => {\n const fn = vi.fn((n = 0) => (n as number) + Math.random())\n class MyClass { @Memoize() getId(n: number) { return fn(n) } }\n const instance = new MyClass()\n const id1 = instance.getId(1)\n const id2 = instance.getId(1)\n const id3 = instance.getId(2)\n expect(id1).toStrictEqual(id2)\n expect(id1).not.toStrictEqual(id3)\n expect(fn).toHaveBeenCalledTimes(2)\n expect(fn).toHaveBeenCalledWith(1)\n expect(fn).toHaveBeenCalledWith(2)\n })\n\n test('should preserve the method context', () => {\n class MyClass { value = { foo: 42 }; @Memoize() getValue() { return this?.value } }\n const instance = new MyClass()\n const result1 = instance.getValue()\n const result2 = instance.value\n expect(result1).toBe(result2)\n })\n}\n"],"names":["memoize"],"mappings":";;AAuBO,SAAS,QAA4B,SAAiD;AACpF,SAAA,SAAS,SAAS,eAAe,YAAY;AAClD,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQA,QAAAA,QAAQ,QAAQ,OAAO,GACnC;AAAA,EAAA;AAEX;;"}
1
+ {"version":3,"file":"Memoize.cjs","sources":["../Memoize.ts"],"sourcesContent":["import { memoize, MemoizeOptions } from '@unshared/functions/memoize'\nimport { Function, MethodDecorator } from '@unshared/types'\n\n/**\n * Decorate a method to memoize it's result based on the arguments. Meaning\n * that it will return the same result without executing the method again,\n * **unless the arguments change**.\n *\n * @param options The memoization options.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a memoized method.\n * class Greeter {\n * ->@Memoize()\n * greet(name: string) { return `Hello, ${name}! - ${Math.random()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Bob') // 'Hello, Bob! - 0.987654321'\n */\nexport function Memoize<T extends Function>(options?: MemoizeOptions<T>): MethodDecorator<T> {\n return function(_target, _propertyName, descriptor) {\n const method = descriptor.value!\n descriptor.value = memoize(method, options) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\n\nif (import.meta.vitest) {\n test('should memoize the method', () => {\n const fn = vi.fn(Math.random)\n class MyClass { @Memoize() getId() { return fn() } }\n const instance = new MyClass()\n const id1 = instance.getId()\n const id2 = instance.getId()\n expect(id1).toStrictEqual(id2)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith()\n })\n\n test('should memoize the method by parameter', () => {\n const fn = vi.fn((n = 0) => (n as number) + Math.random())\n class MyClass { @Memoize() getId(n: number) { return fn(n) } }\n const instance = new MyClass()\n const id1 = instance.getId(1)\n const id2 = instance.getId(1)\n const id3 = instance.getId(2)\n expect(id1).toStrictEqual(id2)\n expect(id1).not.toStrictEqual(id3)\n expect(fn).toHaveBeenCalledTimes(2)\n expect(fn).toHaveBeenCalledWith(1)\n expect(fn).toHaveBeenCalledWith(2)\n })\n\n test('should preserve the method context', () => {\n class MyClass { value = { foo: 42 }; @Memoize() getValue() { return this?.value } }\n const instance = new MyClass()\n const result1 = instance.getValue()\n const result2 = instance.value\n expect(result1).toBe(result2)\n })\n}\n"],"names":["memoize"],"mappings":";;AAuBO,SAAS,QAA4B,SAAiD;AACpF,SAAA,SAAS,SAAS,eAAe,YAAY;AAClD,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQA,QAAAA,QAAQ,QAAQ,OAAO,GACnC;AAAA,EAAA;AAEX;;"}
package/dist/Memoize.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Function, MethodDecorator } from '@unshared/types';
2
1
  import { MemoizeOptions } from '@unshared/functions/memoize';
2
+ import { Function, MethodDecorator } from '@unshared/types';
3
3
 
4
4
  /**
5
5
  * Decorate a method to memoize it's result based on the arguments. Meaning
@@ -1 +1 @@
1
- {"version":3,"file":"Memoize.js","sources":["../Memoize.ts"],"sourcesContent":["import { Function, MethodDecorator } from '@unshared/types'\nimport { MemoizeOptions, memoize } from '@unshared/functions/memoize'\n\n/**\n * Decorate a method to memoize it's result based on the arguments. Meaning\n * that it will return the same result without executing the method again,\n * **unless the arguments change**.\n *\n * @param options The memoization options.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a memoized method.\n * class Greeter {\n * ->@Memoize()\n * greet(name: string) { return `Hello, ${name}! - ${Math.random()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Bob') // 'Hello, Bob! - 0.987654321'\n */\nexport function Memoize<T extends Function>(options?: MemoizeOptions<T>): MethodDecorator<T> {\n return function(_target, _propertyName, descriptor) {\n const method = descriptor.value!\n descriptor.value = memoize(method, options) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\n\nif (import.meta.vitest) {\n test('should memoize the method', () => {\n const fn = vi.fn(Math.random)\n class MyClass { @Memoize() getId() { return fn() } }\n const instance = new MyClass()\n const id1 = instance.getId()\n const id2 = instance.getId()\n expect(id1).toStrictEqual(id2)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith()\n })\n\n test('should memoize the method by parameter', () => {\n const fn = vi.fn((n = 0) => (n as number) + Math.random())\n class MyClass { @Memoize() getId(n: number) { return fn(n) } }\n const instance = new MyClass()\n const id1 = instance.getId(1)\n const id2 = instance.getId(1)\n const id3 = instance.getId(2)\n expect(id1).toStrictEqual(id2)\n expect(id1).not.toStrictEqual(id3)\n expect(fn).toHaveBeenCalledTimes(2)\n expect(fn).toHaveBeenCalledWith(1)\n expect(fn).toHaveBeenCalledWith(2)\n })\n\n test('should preserve the method context', () => {\n class MyClass { value = { foo: 42 }; @Memoize() getValue() { return this?.value } }\n const instance = new MyClass()\n const result1 = instance.getValue()\n const result2 = instance.value\n expect(result1).toBe(result2)\n })\n}\n"],"names":[],"mappings":";AAuBO,SAAS,QAA4B,SAAiD;AACpF,SAAA,SAAS,SAAS,eAAe,YAAY;AAClD,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQ,QAAQ,QAAQ,OAAO,GACnC;AAAA,EAAA;AAEX;"}
1
+ {"version":3,"file":"Memoize.js","sources":["../Memoize.ts"],"sourcesContent":["import { memoize, MemoizeOptions } from '@unshared/functions/memoize'\nimport { Function, MethodDecorator } from '@unshared/types'\n\n/**\n * Decorate a method to memoize it's result based on the arguments. Meaning\n * that it will return the same result without executing the method again,\n * **unless the arguments change**.\n *\n * @param options The memoization options.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a memoized method.\n * class Greeter {\n * ->@Memoize()\n * greet(name: string) { return `Hello, ${name}! - ${Math.random()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Bob') // 'Hello, Bob! - 0.987654321'\n */\nexport function Memoize<T extends Function>(options?: MemoizeOptions<T>): MethodDecorator<T> {\n return function(_target, _propertyName, descriptor) {\n const method = descriptor.value!\n descriptor.value = memoize(method, options) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\n\nif (import.meta.vitest) {\n test('should memoize the method', () => {\n const fn = vi.fn(Math.random)\n class MyClass { @Memoize() getId() { return fn() } }\n const instance = new MyClass()\n const id1 = instance.getId()\n const id2 = instance.getId()\n expect(id1).toStrictEqual(id2)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith()\n })\n\n test('should memoize the method by parameter', () => {\n const fn = vi.fn((n = 0) => (n as number) + Math.random())\n class MyClass { @Memoize() getId(n: number) { return fn(n) } }\n const instance = new MyClass()\n const id1 = instance.getId(1)\n const id2 = instance.getId(1)\n const id3 = instance.getId(2)\n expect(id1).toStrictEqual(id2)\n expect(id1).not.toStrictEqual(id3)\n expect(fn).toHaveBeenCalledTimes(2)\n expect(fn).toHaveBeenCalledWith(1)\n expect(fn).toHaveBeenCalledWith(2)\n })\n\n test('should preserve the method context', () => {\n class MyClass { value = { foo: 42 }; @Memoize() getValue() { return this?.value } }\n const instance = new MyClass()\n const result1 = instance.getValue()\n const result2 = instance.value\n expect(result1).toBe(result2)\n })\n}\n"],"names":[],"mappings":";AAuBO,SAAS,QAA4B,SAAiD;AACpF,SAAA,SAAS,SAAS,eAAe,YAAY;AAClD,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQ,QAAQ,QAAQ,OAAO,GACnC;AAAA,EAAA;AAEX;"}
package/dist/Once.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Once.cjs","sources":["../Once.ts"],"sourcesContent":["import { Function, MethodDecorator } from '@unshared/types'\nimport { once } from '@unshared/functions/once'\n\n/**\n * Decorate a method to memoize it's result. Meaning that if the method is called,\n * it will return the same result without executing the method again, **even if the\n * method is called with different arguments**.\n *\n * @returns The method descriptor.\n * @example\n * // Declare a class with a onced method.\n * class Greeter {\n * ->@Once()\n * greet(name: string) { return `Hello, ${name}! - ${Math.random()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Bob') // 'Hello, Alice! - 0.123456789'\n */\nexport function Once<T extends Function>(): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = once(method) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\n\nif (import.meta.vitest) {\n test('should return the same value if no arguments are passed', () => {\n const fn = vi.fn(Math.random)\n class MyClass { @Once() getId() { return fn() } }\n const instance = new MyClass()\n const id1 = instance.getId()\n const id2 = instance.getId()\n expect(id1).toStrictEqual(id2)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith()\n })\n\n test('should return the same values if different arguments are passed', () => {\n const fn = vi.fn((n = 0) => (n as number) + Math.random())\n class MyClass { @Once() getId(n: number) { return fn(n) } }\n const instance = new MyClass()\n const id1 = instance.getId(1)\n const id2 = instance.getId(1)\n const id3 = instance.getId(2)\n expect(id1).toStrictEqual(id2)\n expect(id1).toStrictEqual(id3)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith(1)\n expect(fn).not.toHaveBeenCalledWith(2)\n })\n\n test('should preserve the method context', () => {\n class MyClass { value = { foo: 42 }; @Once() getValue() { return this?.value } }\n const instance = new MyClass()\n const result1 = instance.getValue()\n const result2 = instance.value\n expect(result1).toBe(result2)\n })\n\n test('should have different results for different instances', () => {\n class MyClass { @Once() getValue() { return Math.random() } }\n const instance1 = new MyClass()\n const instance2 = new MyClass()\n const result1 = instance1.getValue()\n const result2 = instance2.getValue()\n expect(result1).not.toStrictEqual(result2)\n })\n}\n"],"names":["once"],"mappings":";;AAqBO,SAAS,OAA+C;AACtD,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AACf,WAAA,WAAA,QAAQA,KAAK,KAAA,MAAM,GACvB;AAAA,EAAA;AAEX;;"}
1
+ {"version":3,"file":"Once.cjs","sources":["../Once.ts"],"sourcesContent":["import { once } from '@unshared/functions/once'\nimport { Function, MethodDecorator } from '@unshared/types'\n\n/**\n * Decorate a method to memoize it's result. Meaning that if the method is called,\n * it will return the same result without executing the method again, **even if the\n * method is called with different arguments**.\n *\n * @returns The method descriptor.\n * @example\n * // Declare a class with a onced method.\n * class Greeter {\n * ->@Once()\n * greet(name: string) { return `Hello, ${name}! - ${Math.random()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Bob') // 'Hello, Alice! - 0.123456789'\n */\nexport function Once<T extends Function>(): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = once(method) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\n\nif (import.meta.vitest) {\n test('should return the same value if no arguments are passed', () => {\n const fn = vi.fn(Math.random)\n class MyClass { @Once() getId() { return fn() } }\n const instance = new MyClass()\n const id1 = instance.getId()\n const id2 = instance.getId()\n expect(id1).toStrictEqual(id2)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith()\n })\n\n test('should return the same values if different arguments are passed', () => {\n const fn = vi.fn((n = 0) => (n as number) + Math.random())\n class MyClass { @Once() getId(n: number) { return fn(n) } }\n const instance = new MyClass()\n const id1 = instance.getId(1)\n const id2 = instance.getId(1)\n const id3 = instance.getId(2)\n expect(id1).toStrictEqual(id2)\n expect(id1).toStrictEqual(id3)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith(1)\n expect(fn).not.toHaveBeenCalledWith(2)\n })\n\n test('should preserve the method context', () => {\n class MyClass { value = { foo: 42 }; @Once() getValue() { return this?.value } }\n const instance = new MyClass()\n const result1 = instance.getValue()\n const result2 = instance.value\n expect(result1).toBe(result2)\n })\n\n test('should have different results for different instances', () => {\n class MyClass { @Once() getValue() { return Math.random() } }\n const instance1 = new MyClass()\n const instance2 = new MyClass()\n const result1 = instance1.getValue()\n const result2 = instance2.getValue()\n expect(result1).not.toStrictEqual(result2)\n })\n}\n"],"names":["once"],"mappings":";;AAqBO,SAAS,OAA+C;AACtD,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AACf,WAAA,WAAA,QAAQA,KAAK,KAAA,MAAM,GACvB;AAAA,EAAA;AAEX;;"}
package/dist/Once.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Once.js","sources":["../Once.ts"],"sourcesContent":["import { Function, MethodDecorator } from '@unshared/types'\nimport { once } from '@unshared/functions/once'\n\n/**\n * Decorate a method to memoize it's result. Meaning that if the method is called,\n * it will return the same result without executing the method again, **even if the\n * method is called with different arguments**.\n *\n * @returns The method descriptor.\n * @example\n * // Declare a class with a onced method.\n * class Greeter {\n * ->@Once()\n * greet(name: string) { return `Hello, ${name}! - ${Math.random()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Bob') // 'Hello, Alice! - 0.123456789'\n */\nexport function Once<T extends Function>(): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = once(method) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\n\nif (import.meta.vitest) {\n test('should return the same value if no arguments are passed', () => {\n const fn = vi.fn(Math.random)\n class MyClass { @Once() getId() { return fn() } }\n const instance = new MyClass()\n const id1 = instance.getId()\n const id2 = instance.getId()\n expect(id1).toStrictEqual(id2)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith()\n })\n\n test('should return the same values if different arguments are passed', () => {\n const fn = vi.fn((n = 0) => (n as number) + Math.random())\n class MyClass { @Once() getId(n: number) { return fn(n) } }\n const instance = new MyClass()\n const id1 = instance.getId(1)\n const id2 = instance.getId(1)\n const id3 = instance.getId(2)\n expect(id1).toStrictEqual(id2)\n expect(id1).toStrictEqual(id3)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith(1)\n expect(fn).not.toHaveBeenCalledWith(2)\n })\n\n test('should preserve the method context', () => {\n class MyClass { value = { foo: 42 }; @Once() getValue() { return this?.value } }\n const instance = new MyClass()\n const result1 = instance.getValue()\n const result2 = instance.value\n expect(result1).toBe(result2)\n })\n\n test('should have different results for different instances', () => {\n class MyClass { @Once() getValue() { return Math.random() } }\n const instance1 = new MyClass()\n const instance2 = new MyClass()\n const result1 = instance1.getValue()\n const result2 = instance2.getValue()\n expect(result1).not.toStrictEqual(result2)\n })\n}\n"],"names":[],"mappings":";AAqBO,SAAS,OAA+C;AACtD,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AACf,WAAA,WAAA,QAAQ,KAAK,MAAM,GACvB;AAAA,EAAA;AAEX;"}
1
+ {"version":3,"file":"Once.js","sources":["../Once.ts"],"sourcesContent":["import { once } from '@unshared/functions/once'\nimport { Function, MethodDecorator } from '@unshared/types'\n\n/**\n * Decorate a method to memoize it's result. Meaning that if the method is called,\n * it will return the same result without executing the method again, **even if the\n * method is called with different arguments**.\n *\n * @returns The method descriptor.\n * @example\n * // Declare a class with a onced method.\n * class Greeter {\n * ->@Once()\n * greet(name: string) { return `Hello, ${name}! - ${Math.random()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice') // 'Hello, Alice! - 0.123456789'\n * instance.greet('Bob') // 'Hello, Alice! - 0.123456789'\n */\nexport function Once<T extends Function>(): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = once(method) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\n\nif (import.meta.vitest) {\n test('should return the same value if no arguments are passed', () => {\n const fn = vi.fn(Math.random)\n class MyClass { @Once() getId() { return fn() } }\n const instance = new MyClass()\n const id1 = instance.getId()\n const id2 = instance.getId()\n expect(id1).toStrictEqual(id2)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith()\n })\n\n test('should return the same values if different arguments are passed', () => {\n const fn = vi.fn((n = 0) => (n as number) + Math.random())\n class MyClass { @Once() getId(n: number) { return fn(n) } }\n const instance = new MyClass()\n const id1 = instance.getId(1)\n const id2 = instance.getId(1)\n const id3 = instance.getId(2)\n expect(id1).toStrictEqual(id2)\n expect(id1).toStrictEqual(id3)\n expect(fn).toHaveBeenCalledTimes(1)\n expect(fn).toHaveBeenCalledWith(1)\n expect(fn).not.toHaveBeenCalledWith(2)\n })\n\n test('should preserve the method context', () => {\n class MyClass { value = { foo: 42 }; @Once() getValue() { return this?.value } }\n const instance = new MyClass()\n const result1 = instance.getValue()\n const result2 = instance.value\n expect(result1).toBe(result2)\n })\n\n test('should have different results for different instances', () => {\n class MyClass { @Once() getValue() { return Math.random() } }\n const instance1 = new MyClass()\n const instance2 = new MyClass()\n const result1 = instance1.getValue()\n const result2 = instance2.getValue()\n expect(result1).not.toStrictEqual(result2)\n })\n}\n"],"names":[],"mappings":";AAqBO,SAAS,OAA+C;AACtD,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AACf,WAAA,WAAA,QAAQ,KAAK,MAAM,GACvB;AAAA,EAAA;AAEX;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Throttle.cjs","sources":["../Throttle.ts"],"sourcesContent":["import { Function, MethodDecorator } from '@unshared/types'\nimport { throttle } from '@unshared/functions/throttle'\n\n/**\n * Throttle a method so that it will only execute once every specified delay.\n * Useful for implementing spam protection. When the method is called, it will\n * execute immediately and then wait for the specified delay before it can be\n * called again.\n *\n * **Note:** This decorator will omit the return value of the method and return `undefined`.\n *\n * @param delay The delay in milliseconds to wait before executing the method.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a debounced method.\n * class Greeter {\n * ->@Throttle(100)\n * greet(name: string) { return `Hello, ${name}! - ${Date.now()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice')\n * instance.greet('Bob')\n * instance.greet('Charlie')\n *\n * // The method will be called immediately and can only be called again after 100ms.\n * // => Hello, Alice!\n */\nexport function Throttle<T extends Function<void>>(delay: number): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = throttle(method, delay) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n beforeEach(() => vi.useFakeTimers)\n\n test('should call the function immediately', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should not call the function more than once within the delay', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should pass the parameters of the first call to the function', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(10) fn(name: string) { fn(name) } }\n const instance = new Greeter()\n instance.fn('Alice')\n instance.fn('Bob')\n instance.fn('Charlie')\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledWith('Alice')\n })\n\n test('should call the function again after the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(2)\n })\n\n test('should return undefined', () => {\n const fn = vi.fn(() => 'foobar')\n class Greeter { @Throttle(100) fn() { return fn() } }\n const instance = new Greeter()\n const result = instance.fn()\n expect(result).toBeUndefined()\n })\n}\n"],"names":["throttle"],"mappings":";;AA6BO,SAAS,SAAmC,OAAmC;AAC7E,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQA,SAAAA,SAAS,QAAQ,KAAK,GAClC;AAAA,EAAA;AAEX;;"}
1
+ {"version":3,"file":"Throttle.cjs","sources":["../Throttle.ts"],"sourcesContent":["import { throttle } from '@unshared/functions/throttle'\nimport { Function, MethodDecorator } from '@unshared/types'\n\n/**\n * Throttle a method so that it will only execute once every specified delay.\n * Useful for implementing spam protection. When the method is called, it will\n * execute immediately and then wait for the specified delay before it can be\n * called again.\n *\n * **Note:** This decorator will omit the return value of the method and return `undefined`.\n *\n * @param delay The delay in milliseconds to wait before executing the method.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a debounced method.\n * class Greeter {\n * ->@Throttle(100)\n * greet(name: string) { return `Hello, ${name}! - ${Date.now()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice')\n * instance.greet('Bob')\n * instance.greet('Charlie')\n *\n * // The method will be called immediately and can only be called again after 100ms.\n * // => Hello, Alice!\n */\nexport function Throttle<T extends Function<void>>(delay: number): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = throttle(method, delay) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n beforeEach(() => vi.useFakeTimers)\n\n test('should call the function immediately', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should not call the function more than once within the delay', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should pass the parameters of the first call to the function', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(10) fn(name: string) { fn(name) } }\n const instance = new Greeter()\n instance.fn('Alice')\n instance.fn('Bob')\n instance.fn('Charlie')\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledWith('Alice')\n })\n\n test('should call the function again after the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(2)\n })\n\n test('should return undefined', () => {\n const fn = vi.fn(() => 'foobar')\n class Greeter { @Throttle(100) fn() { return fn() } }\n const instance = new Greeter()\n const result = instance.fn()\n expect(result).toBeUndefined()\n })\n}\n"],"names":["throttle"],"mappings":";;AA6BO,SAAS,SAAmC,OAAmC;AAC7E,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQA,SAAAA,SAAS,QAAQ,KAAK,GAClC;AAAA,EAAA;AAEX;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Throttle.js","sources":["../Throttle.ts"],"sourcesContent":["import { Function, MethodDecorator } from '@unshared/types'\nimport { throttle } from '@unshared/functions/throttle'\n\n/**\n * Throttle a method so that it will only execute once every specified delay.\n * Useful for implementing spam protection. When the method is called, it will\n * execute immediately and then wait for the specified delay before it can be\n * called again.\n *\n * **Note:** This decorator will omit the return value of the method and return `undefined`.\n *\n * @param delay The delay in milliseconds to wait before executing the method.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a debounced method.\n * class Greeter {\n * ->@Throttle(100)\n * greet(name: string) { return `Hello, ${name}! - ${Date.now()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice')\n * instance.greet('Bob')\n * instance.greet('Charlie')\n *\n * // The method will be called immediately and can only be called again after 100ms.\n * // => Hello, Alice!\n */\nexport function Throttle<T extends Function<void>>(delay: number): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = throttle(method, delay) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n beforeEach(() => vi.useFakeTimers)\n\n test('should call the function immediately', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should not call the function more than once within the delay', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should pass the parameters of the first call to the function', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(10) fn(name: string) { fn(name) } }\n const instance = new Greeter()\n instance.fn('Alice')\n instance.fn('Bob')\n instance.fn('Charlie')\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledWith('Alice')\n })\n\n test('should call the function again after the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(2)\n })\n\n test('should return undefined', () => {\n const fn = vi.fn(() => 'foobar')\n class Greeter { @Throttle(100) fn() { return fn() } }\n const instance = new Greeter()\n const result = instance.fn()\n expect(result).toBeUndefined()\n })\n}\n"],"names":[],"mappings":";AA6BO,SAAS,SAAmC,OAAmC;AAC7E,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQ,SAAS,QAAQ,KAAK,GAClC;AAAA,EAAA;AAEX;"}
1
+ {"version":3,"file":"Throttle.js","sources":["../Throttle.ts"],"sourcesContent":["import { throttle } from '@unshared/functions/throttle'\nimport { Function, MethodDecorator } from '@unshared/types'\n\n/**\n * Throttle a method so that it will only execute once every specified delay.\n * Useful for implementing spam protection. When the method is called, it will\n * execute immediately and then wait for the specified delay before it can be\n * called again.\n *\n * **Note:** This decorator will omit the return value of the method and return `undefined`.\n *\n * @param delay The delay in milliseconds to wait before executing the method.\n * @returns The method descriptor.\n * @example\n * // Declare a class with a debounced method.\n * class Greeter {\n * ->@Throttle(100)\n * greet(name: string) { return `Hello, ${name}! - ${Date.now()}` }\n * }\n *\n * // The first call to the method will be executed.\n * const instance = new Greeter()\n * instance.greet('Alice')\n * instance.greet('Bob')\n * instance.greet('Charlie')\n *\n * // The method will be called immediately and can only be called again after 100ms.\n * // => Hello, Alice!\n */\nexport function Throttle<T extends Function<void>>(delay: number): MethodDecorator<T> {\n return (target, propertyName, descriptor) => {\n const method = descriptor.value!\n descriptor.value = throttle(method, delay) as unknown as T\n return descriptor\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n beforeEach(() => vi.useFakeTimers)\n\n test('should call the function immediately', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should not call the function more than once within the delay', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n instance.fn()\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(1)\n })\n\n test('should pass the parameters of the first call to the function', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(10) fn(name: string) { fn(name) } }\n const instance = new Greeter()\n instance.fn('Alice')\n instance.fn('Bob')\n instance.fn('Charlie')\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledWith('Alice')\n })\n\n test('should call the function again after the delay has passed', () => {\n const fn = vi.fn()\n class Greeter { @Throttle(100) fn() { fn() } }\n const instance = new Greeter()\n instance.fn()\n vi.advanceTimersByTime(100)\n instance.fn()\n vi.advanceTimersByTime(100)\n expect(fn).toHaveBeenCalledTimes(2)\n })\n\n test('should return undefined', () => {\n const fn = vi.fn(() => 'foobar')\n class Greeter { @Throttle(100) fn() { return fn() } }\n const instance = new Greeter()\n const result = instance.fn()\n expect(result).toBeUndefined()\n })\n}\n"],"names":[],"mappings":";AA6BO,SAAS,SAAmC,OAAmC;AAC7E,SAAA,CAAC,QAAQ,cAAc,eAAe;AAC3C,UAAM,SAAS,WAAW;AAC1B,WAAA,WAAW,QAAQ,SAAS,QAAQ,KAAK,GAClC;AAAA,EAAA;AAEX;"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@unshared/decorators",
3
3
  "type": "module",
4
- "version": "0.0.15",
4
+ "version": "0.0.16",
5
5
  "license": "MIT",
6
6
  "sideEffects": false,
7
7
  "author": "Stanley Horwood <stanley@hsjm.io>",
@@ -48,7 +48,7 @@
48
48
  "LICENSE.md"
49
49
  ],
50
50
  "dependencies": {
51
- "@unshared/functions": "0.0.15",
52
- "@unshared/types": "0.0.15"
51
+ "@unshared/functions": "0.0.16",
52
+ "@unshared/types": "0.0.16"
53
53
  }
54
54
  }