0.7.1 • Published 6 years ago

practikal-library v0.7.1

Weekly downloads
2
License
MIT
Repository
github
Last release
6 years ago

npm version Build Status Coverage Status License: MIT

practikal-library

Functional library which contains a useful set of functions for building small-size/mid-size web applications.

Goals

The library is built targeting some goals:

  • provide essential functions for building modern web applications.
  • 0 dependencies - 3rd party framework and library agnostic: you don't need any module from React, Angular, Vue, Aurelia, Ember, etc. but you can use it with any of them.
  • everything is pluggable/extensible (loggers, fetch middlewares, validators, validation languages so).
  • functions are written following functional programming principles (immutability, purity, composability - currying, partial-applications, high-order functions).
  • each module is completely independent and does not refer any other library module.
  • tiny: the unminified code is 13 KB (ES2015/ES6).
  • functions should be as simple as possible.
  • FP on/off OOP.

Description

The library contains functions for:

  • logging messages.
  • fetching data.
  • validating objects.
  • publishing/subscribing to events.
  • caching data.

All modules are stateless. Each module contains just pure functions. Index.ts file contains just impure functions (working with cache make them impure).

All modules are totally independent of each other; the only place where modules are glued together is index.ts file.

There are 2 different ways to use library:

  • recommended and simplest way (using useLibrary function).
  • without calling useLibrary (see the logging usage paragraph).

Install

npm i practikal-library --save
npm i https://git@github.com/dragos-tudor/practikal-library#master --save

Usage

Start using library

import { useLibrary } from 'practikal-library';

useLibrary();

useLibrary({ logLevel: 'TRACE' }); // or with other log level

Using useLibrary function will initialize the library with all required plumbing.

The implicit log level is 'INFO'.

Logging

Functions for:

  • logging different kind of messages: trace, debug, info, warn, error.
  • adding new loggers;
  • changing current logging level;

Simple logging calls

import { trace, debug, info, warn, error } from 'practikal-library';

trace('msg');
debug('msg');
info('msg');
warn('WARN', ['msg1', 'msg2']);
error('msg');
error(Error('msg'));

Using useLibrary will automatically add console logger and will set provided current log level.

Adding a new logger

import { addLogger } from 'practikal-library';

const popupLogger = (logLevel, ...data) => { switch(logLevel) { case 'INFO': /*...*/ }; };

addLogger(popupLogger);

Changing current log level

import { setLogLevel } from 'practikal-library';

setLogLevel('WARN');

Using logging without calling useLibrary (not recommanded)

import { info, consoleLogger } from 'practikal-library/logging';

info('INFO', [consoleLogger])('msg');

Fetch

Functions for:

  • fetching (json) data (using Fetch API).
  • adding new middlewares.

Simple json fetch calls

import { getJson, putJson, postJson, deleteJson } from 'practikal-library';

getJson('http://foo.com/bar');
getJson('http://foo.com/bar', { barName: 'test bar' });
putJson('http://foo.com/bar', { barName: 'test bar' });
postJson('http://foo.com/bar', { barId: 1, barName: 'test bar' });
deleteJson('http://foo.com/bar', { barId: 1 });

Simple generic fetch call

import { fetchData, getJsonRequest } from 'practikal-library';

const request = getJsonRequest('GET', { barName: 'test bar' });

fetchData('http://foo.com/bar', request);

Using useLibrary will automatically add logger middleware, request middleware (request settings uniformization) and retry middleware (apply retry policy in case of network error - 5 times at 200ms interval).

Middlewares (see Asp.Net Core middlewares) are additional layers on top of fetchData function. The middlewares are added (and chained) at runtime ensuring that all http requests will pass through them until to reach fetchData function.

Adding base url middleware

import { addMiddleware, getAbsoluteUrl, getJson } from 'practikal-library';

const baseUrlMiddleware = (next) => (url, request) => 
    next(getAbsoluteUrl(url, 'http://foo.com'), request)

addMiddleware(baseUrlMiddleware);

getJson('/bar', null); // fetch json from url 'http://foo.com/bar'

In the same way could be added other kind of middlewares (antiforgery header middleware).

Validation

Functions for:

  • validating objects and values.
  • using new validation languages.
  • using custom validators.
  • adding/changing validation messages (for custom validators or changing existing validator message).

Validating object

import { validate, isRequired } from 'practikal-library';

const validObj = { field1: 'a' };
const invalidObj = { field1: '' };
const validations = { field1: [ isRequired ] }

validate(validObj, validations); // output: { field1: '', isValid: true }
validate(invalidObj, validations); // output: { field1: 'Value is required', isValid: false }

Using new validation language

import { setValidationLanguage } from 'practikal-library';

const frValidation = { required: 'Valeur est requise' /* ... other validators */ };

setValidationLanguage(frValidation);

Adding/changing validator message for current language

import { getValidationLanguage, setValidationLanguage, setValidatorMessage } from 'practikal-library';

let language = getValidationLanguage();

language = setValidatorMessage('required', 'custom message', language);

setValidationLanguage(language);

Using new custom validator

import { setValidationLanguage, getValidationLanguage, isEmpty } from 'practikal-library';

// define contains validator
const contains = (val: string, elem: string) => 
    !isEmpty(val) && val.indexOf(elem) >= 0 ? null : getValidationLanguage()['contains'].replace('#elem', elem) 

// set english contains validator message
setValidatorMessage('contains', 'Value not contains "#elem"', language);    

Publisher-Subscriber

Functions for:

  • publishing events.
  • subscribing to events.
  • unsubscribing from events.

Using publisher-subscriber functions

import { publish, subscribe, unsubscribe } from './practikal-library';

subscribe('event1', 'subscriber1', (data) => console.log(data));

publish('event1', "test"); // output: "test"

unsubscribe('event1', 'subscriber1');

publish('event1', "test"); // output: 

Subscribing to one event will not return an subscription id (like usual).

Unsubscribing from one event is made based on subscription name.

Caching

Functions for:

  • adding data to cache.
  • removing data from cache.
  • getting data from cache.

Using caching functions

import { addToCache, removeFromCache, getFromCache } from './practikal-library';

addToCache('k1', { val: 1 })

getFromCache('k1') // output: { val: 1 }

removeFromCache('k1')

getFromCache('k1') // output: null

Development

Clone

git clone https://github.com/dragos-tudor/practikal-library.git

Install

npm install

Build

npm run build

Test

npm run test

/* or for continous testing (CT) */
npm run test.watchAll
npm run test.watch "validation\.spec\.ts"
npx jest --watchAll  
/*...*/

Rules:

  • As a general defining rules:

    • interfaces define structures.
    • types are used to define functions or union types.
    • functions are declared as arrow functions.
    • object literals declare structures.
    • classes are NOT used.
  • As a general naming rule interfaces and types are uppercases, functions and literal objects are lowercases.

  • As a general positioning rule each module start with exported interfaces and types definitions, functions and object literals declarations and then the private ones.

ES2015/ES6 and CommonJs supported module systems (default ES2015/ES6).

0.7.1

6 years ago

0.7.0

6 years ago

0.5.0

6 years ago

0.4.1

6 years ago

0.4.0

6 years ago

0.3.2

6 years ago

0.3.1

6 years ago

0.3.0

6 years ago

0.2.1

6 years ago

0.2.0

6 years ago

0.1.2

6 years ago

0.1.1

6 years ago