Skip to content
This repository has been archived by the owner on Mar 3, 2024. It is now read-only.

A Utility Library for Typescript which contains a variety of Decorators, that solve different Cross-Cutting concerns. This includes common functionality like retries, validation, logging and caching, hence the name lib of commons.

License

Templum/lib-of-commons

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

94 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lib of Common

This library is a utility library for Typescript which provides functionality for addressing cross-concerns e.g. Logging, Caching or Validation. For a list of available decorators see.

Installation

  1. Installation via yarn or npm with: $ npm install lib-of-commons or $ yarn add lib-of-commons.
  2. Enable experimentalDecorators:true & emitDecoratorMetadata:true in tslint.json.

Note: Some of the Decorators e.g. Measure currently rely on Node API's and won't work in the browser.

Decorators

Logging

    // Also compatible with Winston default logger.
    const logger: IToolboxLogger = console; // Fallback value

    class Example {
        @Log(Level.Info, logger)
        public login(username: string, @Hide() secret: string, privs: string[]) {
            // Generate token based on input
        }
    }

    const instance = new Example();
    instance.login('username', 'geheim', ['history_read', 'history_write']);
    // => Call: login("username",*****,["history_read","history_write"])

Caching

    const logger: ICache = new MemoryCache(); // Fallback value
    const ONE_MINUTE = 60 * 1000; // Fallback value

    class Example {
        @Cache(ONE_MINUTE)
        add(a: number, b: number){
            return a + b;
        }

        @Cache()
        validate(@CacheKey token: string, timestamp: number, debug: boolean){
            // Validate
        }
    }

    const instance = new Example();
    instance.add(1,2); // => 3 calculated
    instance.add(1,2); // => 3 from Cache
    instance.add(2,2); // => 4 calculated

    instance.validate('supersecret', Date.now(), false); // validated
    instance.validate('supersecret', 1343, true); // cached
    instance.validate('othersecret', Date.now(), false); // validated

Validation

    class Example {
        @Validate()
        div(@isInteger() a: number, @isInteger() @isGreater(0) b: number){
            return a / b;
        }

        @Validate()
        addPriv(userUUID: string, @isOneOf(["Read", "Write", "Update", "Delete"]) newPriv: string) {
            // Add Priv to userUUID
            return true;
        }

        @Validate()
        discount(price:number, @isSmaller(0.20) discountFactor: number){
            return price - ((price / 100) * discountFactor);
        }
    }

    const instance = new Example();

    instance.div('0', 2); // => Error div: Parameter 0 was not an Integer
    instance.div(0, '2'); // => Error div: Parameter 1 was not an Integer

    instance.div(2, 0); // => Error div: Parameter 1 was not greater then 0
    instance.div(2, -1); // => Error div: Parameter 1 was not greater then 0

    instance.addPriv('2d776ba0-5fca-409f-9181-388a7f76e260', 'root'); // => Error addPriv: Parameter 1 was not in whitelist

    instance.discount(100, 0.5); // => Error discount: Parameter 1 was not smaller then 0.2

Execution

    // Predicat that should return true if the error is retriable
    const isNetworkError = error => !!error && error instanceof NetworkError;
    const retries = 3; // Default Value

    class Example {
        @AsyncRetry(isNetworkError, retries)
        async backgroundTask(input: any) {
            // Can fail with NetworkError
            await client.sendData(input);
        }

        @Retry(isNetworkError, retries)
        task() {
            // Can fail with NetworkError
            await client.sendData(input);
        }
    }

    const instance = new Example();

    instance.backgroundTask('data'); // => Will retry up to 3 times as long as error is an NetworkError
    instance.task(); // => Will retry up to 3 times as long as error is an NetworkError
    // Debounce Window in MS
    const DEBOUNCE_WINDOW_MS = 500;

    class Example {
        @Debounce(DEBOUNCE_WINDOW_MS)
        sync(input: any) {
            console.log('Synced with input:', input);
        }
    }

    const instance = new Example();

    instance.sync('I will be synced'); // => Synced with input: I will be synced
    instance.sync('I will not be synced'); // => dropped

    await new Promise(resolve => setTimeout(resolve, 600));

    instance.sync('I will be synced again'); // => Synced with input: I will be synced again
    instance.sync('I still will not be synced'); // => dropped

Metrics

    //#### Following Code is required to obtain reported Metrics ####//

    // Could also choose a less specialized type e.g. any
    class MyMonitor implements IMonitor<number> {
        getIdentifier(): string {
            return 'MyMonitor';
        }

        handleAnnouncement(announcement: Announcement<number>): void {
            if (announcement.key === 'Timings') {
                console.info('Execution Time', announcement.data);
            }
        }
    }

    // Register MyMonitor
    const globalAnnouncer = libOfCommons.getAnnouncerInstance();
    globalAnnouncer.register(new MyMonitor());

    //#### Usage of the Measure Decorator ####//
    class Example {
        @Measure(TimeUnit.Nanosecond, 'Timings')
        async sleep(time: number) {
            return await new Promise(resolve => setTimeout(resolve, time));
        }
    }

    const instance = new Example();

    await instance.sleep(100); // => Execution Time 100963100 (~ 100,96 ms)
    await instance.sleep(100); // => Execution Time 101334900 (~ 101,33 ms)
    await instance.sleep(100); // => Execution Time 101105000 (~ 101,10 ms)
    //#### Following Code is required to obtain reported Metrics ####//

    // Could also choose a less specialized type e.g. any
    class MyMonitor implements IMonitor<number> {
        getIdentifier(): string {
            return 'MyMonitor';
        }

        handleAnnouncement(announcement: Announcement<number>): void {
            if (announcement.key === 'User_Subscribed') {
                console.info('Current Value', announcement.data);
            }
        }
    }

    // Register MyMonitor
    const globalAnnouncer = libOfCommons.getAnnouncerInstance();
    globalAnnouncer.register(new MyMonitor());

    //#### Usage of the Measure Decorator ####//
    class Example {
        @Counter('User_Subscribed')
        subscribed(email: string) {
            // Do something
            return true;
        }
    }

    const instance = new Example();

    instance.subscribed('user@sample.com'); // => Current Value 1

About

A Utility Library for Typescript which contains a variety of Decorators, that solve different Cross-Cutting concerns. This includes common functionality like retries, validation, logging and caching, hence the name lib of commons.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published