UNPKG

@coolgk/utils

Version:

javascript, typescript utility and wrapper functions and classes: array, string, base64, ampq, bcrypt, cache, captcha, csv, email, jwt, number, pdf, tmp, token, unit conversion, url params, session, form data, google sign in, facebook sign in

1,624 lines (1,263 loc) 58 kB
[![Build Status](https://travis-ci.org/coolgk/node-utils.svg?branch=master)](https://travis-ci.org/coolgk/node-utils) [![dependencies Status](https://david-dm.org/coolgk/node-utils/status.svg)](https://david-dm.org/coolgk/node-utils) [![Coverage Status](https://coveralls.io/repos/github/coolgk/node-utils/badge.svg)](https://coveralls.io/github/coolgk/node-utils) [![Known Vulnerabilities](https://snyk.io/test/github/coolgk/node-utils/badge.svg)](https://snyk.io/test/github/coolgk/node-utils) `npm install @coolgk/utils` You can install and use the modules below as standalone packages. If you wish to use @coolgk/utils as an all-in-one package, replace @coolgk/[module] with @coolgk/**utils**/[module] in the require() or import statements in the examples below. Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) Also see: [@coolgk/mongo](https://www.npmjs.com/package/@coolgk/mongo) A javascript / typescript MongoDB modelling library which enables joins in collections, simplifies CRUD operations for sub / nested documents and implements schema based data validation. [@coolgk/mvc](https://www.npmjs.com/package/@coolgk/mvc) A simple, lightweight javascript / typescript MxC framework that helps you to create object oriented, modular and testable code. - [amqp](#coolgkamqp) - [array](#coolgkarray) - [base64](#coolgkbase64) - [bcrypt](#coolgkbcrypt) - [cache](#coolgkcache) - [captcha](#coolgkcaptcha) - [csv](#coolgkcsv) - [email](#coolgkemail) - [facebook-sign-in](#coolgkfacebook-sign-in) - [formdata](#coolgkformdata) - [google-sign-in](#coolgkgoogle-sign-in) - [jwt](#coolgkjwt) - [number](#coolgknumber) - [pdf](#coolgkpdf) - [session](#coolgksession) - [queue](#coolgkqueue) - [string](#coolgkstring) - [tmp](#coolgktmp) - [token](#coolgktoken) - [unit](#coolgkunit) - [url](#coolgkurl) ## @coolgk/array a javascript / typescript module `npm install @coolgk/array` array utilities Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { toArray } from '@coolgk/array'; // OR // const { toArray } = require('@coolgk/array'); const a = undefined; const b = false; const c = ''; const d = [1,2,3]; const e = {a:1}; console.log(toArray(a)); // [] console.log(toArray(b)); // [ false ] console.log(toArray(c)); // [ '' ] console.log(toArray(d)); // [ 1, 2, 3 ] console.log(toArray(e)); // [ { a: 1 } ] ``` <a name="toArray"></a> ## toArray(data) ⇒ <code>array</code> **Kind**: global function | Param | Type | Description | | --- | --- | --- | | data | <code>\*</code> | any data to be type cast to array | ## @coolgk/amqp a javascript / typescript module `npm install @coolgk/amqp` a simple RabbitMQ (amqp wrapper) class for publishing and consuming messages Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { Amqp } from '@coolgk/amqp'; // OR // const { Amqp } = require('@coolgk/amqp'); const amqp = new Amqp({ url: 'amqp://localhost/vhost' }); const message = { a: 1, b: 'b' }; // CONSUMER MUST BE STARTED FIRST BEFORE PUSHLISHING ANY MESSAGE // consumer.js // consume message and return (send) a response back to publisher amqp.consume(({rawMessage, message}) => { console.log('consumer received', message); // consumer received ignore response // consumer received { a: 1, b: 'b' } return { response: 'response message' } }); // publisher.js // publish a message, no response from consumer amqp.publish('ignore response'); // publish a message and handle response from consumer amqp.publish(message, ({rawResponseMessage, responseMessage}) => { console.log('response from consumer', responseMessage); // response from consumer { response: 'response message' } }); // example to add: // consume from (multiple) routes // round robin consumers // direct route + a catch all consumer ``` <a name="Amqp"></a> ## Amqp **Kind**: global class * [Amqp](#Amqp) * [new Amqp(options)](#new_Amqp_new) * [.closeConnection()](#Amqp+closeConnection) ⇒ <code>void</code> * [.publish(message, [callback], [options])](#Amqp+publish) ⇒ <code>promise.&lt;Array.&lt;boolean&gt;&gt;</code> * [.getChannel()](#Amqp+getChannel) ⇒ <code>promise</code> <a name="new_Amqp_new"></a> ### new Amqp(options) | Param | Type | Description | | --- | --- | --- | | options | <code>object</code> | | | options.url | <code>string</code> | connection string e.g. amqp://localhost | | [options.sslPem] | <code>string</code> | pem file path | | [options.sslCa] | <code>string</code> | sslCa file path | | [options.sslPass] | <code>string</code> | password | <a name="Amqp+closeConnection"></a> ### amqp.closeConnection() ⇒ <code>void</code> **Kind**: instance method of [<code>Amqp</code>](#Amqp) <a name="Amqp+publish"></a> ### amqp.publish(message, [callback], [options]) ⇒ <code>promise.&lt;Array.&lt;boolean&gt;&gt;</code> **Kind**: instance method of [<code>Amqp</code>](#Amqp) | Param | Type | Default | Description | | --- | --- | --- | --- | | message | <code>\*</code> | | message any type that can be JSON.stringify'ed | | [callback] | <code>function</code> | | callback(message) for processing response from consumers | | [options] | <code>object</code> | | | | [options.routes] | <code>string</code> \| <code>Array.&lt;string&gt;</code> | <code>&quot;[&#x27;#&#x27;]&quot;</code> | route names | | [options.exchangeName] | <code>string</code> | <code>&quot;&#x27;defaultExchange&#x27;&quot;</code> | exchange name | <a name="Amqp+getChannel"></a> ### amqp.getChannel() ⇒ <code>promise</code> **Kind**: instance method of [<code>Amqp</code>](#Amqp) **Returns**: <code>promise</code> - - promise<channel> ## @coolgk/base64 a javascript / typescript module `npm install @coolgk/base64` base64 encoded decode functions Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { encode, decode, encodeUrl, decodeUrl } from '@coolgk/base64'; // OR // const { encode, decode, encodeUrl, decodeUrl } = require('@coolgk/base64'); const a = 'https://www.google.co.uk/?a=b' const hash = encode(a); const urlHash = encodeUrl(a); console.log(a); // https://www.google.co.uk/?a=b console.log(hash); // aHR0cHM6Ly93d3cuZ29vZ2xlLmNvLnVrLz9hPWI= console.log(decode(hash)); // https://www.google.co.uk/?a=b console.log(urlHash); // aHR0cHM6Ly93d3cuZ29vZ2xlLmNvLnVrLz9hPWI console.log(decodeUrl(urlHash)); // https://www.google.co.uk/?a=b ``` ## Functions <dl> <dt><a href="#encode">encode(data)</a> ⇒ <code>string</code></dt> <dd></dd> <dt><a href="#decode">decode(data)</a> ⇒ <code>string</code></dt> <dd></dd> <dt><a href="#encodeUrl">encodeUrl(data)</a> ⇒ <code>string</code></dt> <dd></dd> <dt><a href="#decodeUrl">decodeUrl(data)</a> ⇒ <code>string</code></dt> <dd></dd> </dl> <a name="encode"></a> ## encode(data) ⇒ <code>string</code> **Kind**: global function | Param | Type | Description | | --- | --- | --- | | data | <code>string</code> | string to encode | <a name="decode"></a> ## decode(data) ⇒ <code>string</code> **Kind**: global function | Param | Type | Description | | --- | --- | --- | | data | <code>string</code> | encoded hash | <a name="encodeUrl"></a> ## encodeUrl(data) ⇒ <code>string</code> **Kind**: global function | Param | Type | Description | | --- | --- | --- | | data | <code>string</code> | string to encode | <a name="decodeUrl"></a> ## decodeUrl(data) ⇒ <code>string</code> **Kind**: global function | Param | Type | Description | | --- | --- | --- | | data | <code>string</code> | base64 encoded url to decode | ## @coolgk/bcrypt a javascript / typescript module `npm install @coolgk/bcrypt` just a promise wrapper Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { encrypt, verify } from '@coolgk/bcrypt'; // OR // const { encrypt, verify } = require('@coolgk/bcrypt'); const password = 'abc123'; encrypt(password).then((hash) => { verify(password, hash).then(console.log); // true verify(password, 'invalidhash').then(console.log, console.error); // Not a valid BCrypt hash. verify('invalidpass', hash).then(console.log); // false }); ``` ## Functions <dl> <dt><a href="#encrypt">encrypt(value, salt)</a> ⇒ <code>promise.&lt;string&gt;</code></dt> <dd></dd> <dt><a href="#verify">verify(value, hashedString)</a> ⇒ <code>promise.&lt;boolean&gt;</code></dt> <dd></dd> </dl> <a name="encrypt"></a> ## encrypt(value, salt) ⇒ <code>promise.&lt;string&gt;</code> **Kind**: global function | Param | Type | Description | | --- | --- | --- | | value | <code>string</code> | string to encrypt | | salt | <code>string</code> | salt | <a name="verify"></a> ## verify(value, hashedString) ⇒ <code>promise.&lt;boolean&gt;</code> **Kind**: global function | Param | Type | Description | | --- | --- | --- | | value | <code>string</code> | string to check | | hashedString | <code>string</code> | encrypted hash | ## @coolgk/cache a javascript / typescript module `npm install @coolgk/cache` a redis wrapper Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { Cache } from '@coolgk/cache'; import { createClient } from 'redis'; // OR // const { Cache } = require('@coolgk/cache'); // const { createClient } = require('redis'); const client = createClient({ host: 'localhost', port: 12869, password: '----' }); const cache = new Cache({ redisClient: client }); cache.set('abc', {a: 1}, 1).then(console.log); // 'OK' cache.get('abc').then(console.log); // { a: 1 } setTimeout(() => { cache.get('abc').then(console.log); // null client.quit(); }, 1500); cache.getSetIfNull( 'abc', () => Promise.resolve('data'), 10 ).then((v) => { console.log(v); // { a: 1 } }); Promise.all([ cache.set('x', 'val x'), cache.set('y', 'val y'), cache.set('z', 'val z') ]).then( () => Promise.all([ cache.get('x').then(console.log), // val x cache.get('y').then(console.log), // val y cache.get('z').then(console.log) // val z ]) ).then( () => Promise.all([ cache.delete('x'), cache.delete('y'), cache.delete('z') ]) ).then( () => Promise.all([ cache.get('x').then(console.log), // null cache.get('y').then(console.log), // null cache.get('z').then(console.log) // null ]) ); ``` <a name="Cache"></a> ## Cache **Kind**: global class * [Cache](#Cache) * [new Cache(options)](#new_Cache_new) * [.set(name, value, [expiry])](#Cache+set) ⇒ <code>promise</code> * [.get(name)](#Cache+get) ⇒ <code>promise</code> * [.delete(name)](#Cache+delete) ⇒ <code>promise</code> * [.getSetIfNull(name, callback, [expiry])](#Cache+getSetIfNull) ⇒ <code>promise</code> * [.command(command, ...params)](#Cache+command) ⇒ <code>promise</code> <a name="new_Cache_new"></a> ### new Cache(options) | Param | Type | Description | | --- | --- | --- | | options | <code>object</code> | | | [options.redisClient] | <code>object</code> | redis client from redis.createClient() redisClient needs to be passed in so the same connection can be used elsewhere and get closed outside this class | <a name="Cache+set"></a> ### cache.set(name, value, [expiry]) ⇒ <code>promise</code> **Kind**: instance method of [<code>Cache</code>](#Cache) | Param | Type | Default | Description | | --- | --- | --- | --- | | name | <code>string</code> | | name of the variable | | value | <code>\*</code> | | value is always JSON.stringify'ed | | [expiry] | <code>number</code> | <code>0</code> | expire time in seconds. 0 = never expire | <a name="Cache+get"></a> ### cache.get(name) ⇒ <code>promise</code> **Kind**: instance method of [<code>Cache</code>](#Cache) **Returns**: <code>promise</code> - - cached value | Param | Type | Description | | --- | --- | --- | | name | <code>string</code> | name of the variable | <a name="Cache+delete"></a> ### cache.delete(name) ⇒ <code>promise</code> **Kind**: instance method of [<code>Cache</code>](#Cache) | Param | Type | Description | | --- | --- | --- | | name | <code>string</code> \| <code>Array.&lt;string&gt;</code> | name(s) of the variable | <a name="Cache+getSetIfNull"></a> ### cache.getSetIfNull(name, callback, [expiry]) ⇒ <code>promise</code> get the cached value, if not set, resolve "callback()" and save the value then return it **Kind**: instance method of [<code>Cache</code>](#Cache) **Returns**: <code>promise</code> - - cached value | Param | Type | Default | Description | | --- | --- | --- | --- | | name | <code>string</code> | | name of the variable | | callback | <code>function</code> | | a callback function which returns a value or a promise | | [expiry] | <code>number</code> | <code>0</code> | expire time in seconds. 0 = never expire | <a name="Cache+command"></a> ### cache.command(command, ...params) ⇒ <code>promise</code> **Kind**: instance method of [<code>Cache</code>](#Cache) | Param | Type | Description | | --- | --- | --- | | command | <code>string</code> | redis command to run | | ...params | <code>array</code> | params for the command | ## @coolgk/captcha a javascript / typescript module `npm install @coolgk/captcha` recapcha wrapper Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript const { verify } = require('@coolgk/captcha'); const secret = '-------'; verify(secret, captchaResponse).then((response) => { console.log(response); // { success: true, challenge_ts: '2017-12-03T08:19:48Z', hostname: 'www.google.com' } // { success: false, 'error-codes': [ 'invalid-input-response' ] } }); // OR import { Captcha } from '@coolgk/captcha'; // OR // const { Captcha } = require('@coolgk/captcha'); const captcha = new Captcha({ secret }); const captchaResponse = '---------'; captcha.verify(captchaResponse).then((response) => { console.log(response); // { success: true, challenge_ts: '2017-12-03T08:19:48Z', hostname: 'www.google.com' } // { success: false, 'error-codes': [ 'invalid-input-response' ] } }); ``` <a name="Captcha"></a> ## Captcha **Kind**: global class * [Captcha](#Captcha) * [new Captcha(options)](#new_Captcha_new) * [.verify(response, [remoteip])](#Captcha+verify) <a name="new_Captcha_new"></a> ### new Captcha(options) | Param | Type | Description | | --- | --- | --- | | options | <code>object</code> | | | options.secret | <code>object</code> | google captcha secret https://www.google.com/recaptcha/admin#site/337294176 | <a name="Captcha+verify"></a> ### captcha.verify(response, [remoteip]) **Kind**: instance method of [<code>Captcha</code>](#Captcha) | Param | Type | Description | | --- | --- | --- | | response | <code>string</code> | repsonse from recaptcha | | [remoteip] | <code>string</code> | ip address | | | <code>promise</code> | | ## @coolgk/csv a javascript / typescript module `npm install @coolgk/csv` read and write csv files Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { Csv } from '@coolgk/csv'; // OR // const { Csv } = require('@coolgk/csv'); const csv = new Csv({ tmpConfig: { dir: '/tmp/csv' } // optional }); const arrayData = [ [1,2,3,4,5], [6,7,7,8,9], [0,5,8,90,65] ]; const objectData = [ {col1: 'ab', col2: 'cd', col3: 'ef'}, {col1: '2ab', col2: '2cd', col3: '2ef'}, {col1: '3ab', col2: '3cd', col3: '3ef'} ]; csv.createFile( arrayData, { columns: ['column 1', 'column 2', 'column 3', 'h4', 'h5'], formatter: (row) => { return row.map((value) => 'formatted-' + value); } } ).then((csvFilePath) => { console.log(csvFilePath); // /tmp/csv/151229255018910356N9qKqUgrpzG2.csv read(csvFilePath, ['column 1', 'column 2', 'column 3', 'h4', 'h5']); }); csv.createFile( objectData, { columns: ['col1', 'col2', 'col3'], formatter: (row) => { return [row.col1 + '+format', row.col2 + '+format', row.col3 + '+format']; } } ).then((csvFilePath) => { console.log(csvFilePath); // /tmp/csv/151229255019910356AlO9kbzkdqjq.csv read(csvFilePath, ['col1', 'col2', 'col3']); }); function read (file, columns) { // with columns/headers // read lines as object const lines = csv.readFile(file, {columns: columns}); lines.forEach( (lineArray, index) => { console.log(lineArray, index); // { // 'column 1': 'formatted-1', // 'column 2': 'formatted-2', // 'column 3': 'formatted-3', // h4: 'formatted-4', // h5: 'formatted-5' // } 1 }, (total) => { console.log('read done, total:', total); // read done, total: 4 } ); // without columns/headers // read lines as array const lines2 = csv.readFile(file); lines2.forEach( (lineArray, index) => { console.log(lineArray, index); // [ 'formatted-1', 'formatted-2', 'formatted-3', 'formatted-4', 'formatted-5' ] 1 }, (total) => { console.log('read done, total:', total); // read done, total: 4 } ); } ``` ## @coolgk/email a javascript / typescript module `npm install @coolgk/email` a email sender wrapper class Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { Email } from '@coolgk/email'; // OR // const { Email } = require('@coolgk/email'); const email = new Email({host: 'localhost'}); email.send({ subject: 'hello this is email subject', from: { name: 'Daniel Gong', email: 'daniel.k.gong@example.com' }, to: [ { name: 'Dan Go', email: 'dan@example.com' }, 'gong@example.com' ], message: '<html><body><h1>test</h1>some message here <img src="cid:my-image" width="500" height="250"></body></html>', attachments: [ { path: '/tmp/test.png', name: 'screenshot.png' }, { path:"/tmp/test.png", headers:{"Content-ID": "<my-image>"} } ] }).then((sentMessage) => { console.log(sentMessage); }).catch((error) => { console.log(error); }); ``` <a name="Email"></a> ## Email **Kind**: global class **See**: https://www.npmjs.com/package/emailjs#emailserverconnectoptions * [Email](#Email) * [new Email(options)](#new_Email_new) * [.send(options, [attachments])](#Email+send) ⇒ <code>promise</code> <a name="new_Email_new"></a> ### new Email(options) | Param | Type | Default | Description | | --- | --- | --- | --- | | options | <code>object</code> | | | | [options.user] | <code>string</code> | | username for logging into smtp | | [options.password] | <code>string</code> | | password for logging into smtp | | [options.host] | <code>string</code> | <code>&quot;&#x27;localhost&#x27;&quot;</code> | smtp host | | [options.port] | <code>string</code> | | smtp port (if null a standard port number will be used) | | [options.ssl] | <code>boolean</code> | | boolean (if true or object, ssl connection will be made) | | [options.tls] | <code>boolean</code> | | boolean (if true or object, starttls will be initiated) | | [options.domain] | <code>string</code> | | domain to greet smtp with (defaults to os.hostname) | | [options.authentication] | <code>Array.&lt;string&gt;</code> | | authentication methods | <a name="Email+send"></a> ### email.send(options, [attachments]) ⇒ <code>promise</code> **Kind**: instance method of [<code>Email</code>](#Email) **Returns**: <code>promise</code> - - message sent | Param | Type | Description | | --- | --- | --- | | options | <code>object</code> | | | options.subject | <code>string</code> | email subject | | [options.message] | <code>string</code> | html email message | | options.to | <code>Array.&lt;(string\|object)&gt;</code> | to email address | | options.to[].name | <code>string</code> | name of the recipient | | options.to[].email | <code>string</code> | email address of the recipient | | [options.from] | <code>string</code> \| <code>object</code> | see options.to | | [options.cc] | <code>Array.&lt;(string\|object)&gt;</code> | see options.to | | [options.bcc] | <code>Array.&lt;(string\|object)&gt;</code> | see options.to | | [attachments] | <code>Array.&lt;object&gt;</code> | email attachments | | attachments.path | <code>string</code> | file path | | [attachments.name] | <code>string</code> | file name | | [attachments.type] | <code>string</code> | file mime type | | [attachments.method] | <code>string</code> | method to send attachment as (used by calendar invites) | | [attachments.headers] | <code>object</code> | attachment headers, header: value pairs, e.g. {"Content-ID":"<my-image>"} | ## @coolgk/facebook-sign-in a javascript / typescript module `npm install @coolgk/facebook-sign-in` facebook sign in module which verifies client access token and returns account data Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript const { FacebookSignIn } = require('@coolgk/facebook-sign-in'); // OR // import { FacebookSignIn } from '@coolgk/facebook-sign-in'; const facebookSignIn = new FacebookSignIn({ clientId: '...', secret: '...' }); const invalidToken = '...'; const validToken = '...'; (async () => { const account1 = await facebookSignIn.verify(invalidToken); console.log(account1); // false const account2 = await facebookSignIn.verify(validToken); console.log(account2); // { email: 'abc@example.com', id: '123123123123123123' } })() ``` <a name="FacebookSignIn"></a> ## FacebookSignIn **Kind**: global class * [FacebookSignIn](#FacebookSignIn) * _instance_ * [.verify(token, [fields])](#FacebookSignIn+verify) ⇒ <code>Promise.&lt;(false\|object)&gt;</code> * _static_ * [.FacebookSignIn](#FacebookSignIn.FacebookSignIn) * [new FacebookSignIn(options)](#new_FacebookSignIn.FacebookSignIn_new) <a name="FacebookSignIn+verify"></a> ### facebookSignIn.verify(token, [fields]) ⇒ <code>Promise.&lt;(false\|object)&gt;</code> verify access token from clients and return false or account data **Kind**: instance method of [<code>FacebookSignIn</code>](#FacebookSignIn) **Returns**: <code>Promise.&lt;(false\|object)&gt;</code> - - false if access token is invalid otherwise returns account data | Param | Type | Default | Description | | --- | --- | --- | --- | | token | <code>string</code> | | facebook user's token string | | [fields] | <code>string</code> | <code>&quot;&#x27;email&#x27;&quot;</code> | fields to fetch from user's facebook account. comma separated value e.g. id,name,email | <a name="FacebookSignIn.FacebookSignIn"></a> ### FacebookSignIn.FacebookSignIn **Kind**: static class of [<code>FacebookSignIn</code>](#FacebookSignIn) <a name="new_FacebookSignIn.FacebookSignIn_new"></a> #### new FacebookSignIn(options) | Param | Type | Description | | --- | --- | --- | | options | <code>object</code> | | | options.clientId | <code>string</code> | facebook app id | | options.secret | <code>string</code> | facebook app secret | ## @coolgk/formdata a javascript / typescript module `npm install @coolgk/formdata` A http request form data parser (large file friendly) for 'application/json', 'application/x-www-form-urlencoded' and 'multipart/form-data'. It only parses form data when you ask for it. Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) #### Example Form ```html <form method="POST" enctype="multipart/form-data"> <input type="text" name="name"> <input type="text" name="age"> <input type="file" name="photo"> <input type="file" name="photo"> <input type="file" name="id"> </form> ``` #### Express Middleware ```javascript // express middleware const app = require('express')(); const formdata = require('@coolgk/formdata'); app.use(formdata.express()); app.post('/id-only', async (request, response, next) => { const post = await request.formdata.getData('id'); // upload 3 files but only parse 1, ignore others console.log(post); response.json(post); // output // { // "name": "Tim", // "age": "33", // "id": { // "error": null, // "fieldname": "id", // "filename": "test.txt", // "encoding": "7bit", // "mimetype": "text/plain", // "size": 13, // "path": "/tmp/151605931497716067xZGgxPUdNvoj" // } // } }); app.post('/all-files', async (request, response, next) => { const post = await request.formdata.getData(['id', 'photo']); // parse all files console.log(post); response.json(post); // output // { // "name": "Tim", // "age": "33", // "photo": [ // { // "error": null, // "fieldname": "photo", // "filename": "test.png", // "encoding": "7bit", // "mimetype": "image/png", // "size": 604, // "path": "/tmp/151605931497716067xZGgxPUdNvoj" // }, // { // "error": null, // "fieldname": "photo", // "filename": "test.svg", // "encoding": "7bit", // "mimetype": "image/svg+xml", // "size": 2484, // "path": "/tmp/151605931497916067EAUAa3yB4q42" // } // ], // "id": { // "error": null, // "fieldname": "id", // "filename": "test.txt", // "encoding": "7bit", // "mimetype": "text/plain", // "size": 13, // "path": "/tmp/151605931498016067zqZe6dlhidQ5" // } // } }); app.listen(8888); ``` #### Native Node App ```javascript const { formData, express, getFormData, FormDataError } = require('@coolgk/formdata'); const http = require('http'); http.createServer(async (request, response) => { const data = await getFormData(request, { fileFieldNames: ['id', 'photo'] }); // OR // const formdata = formData(request); // ... some middelware // ... in some routes // const data = formdata.getData(['id', 'photo']); console.log(data); response.end(JSON.stringify(data)); // { // "name": "Tim", // "age": "33", // "photo": [ // { // "error": null, // "fieldname": "photo", // "filename": "test.png", // "encoding": "7bit", // "mimetype": "image/png", // "size": 604, // "path": "/tmp/151605931497716067xZGgxPUdNvoj" // }, // { // "error": null, // "fieldname": "photo", // "filename": "test.svg", // "encoding": "7bit", // "mimetype": "image/svg+xml", // "size": 2484, // "path": "/tmp/151605931497916067EAUAa3yB4q42" // } // ], // "id": { // "error": null, // "fieldname": "id", // "filename": "test.txt", // "encoding": "7bit", // "mimetype": "text/plain", // "size": 13, // "path": "/tmp/151605931498016067zqZe6dlhidQ5" // } // } }).listen(8888); ``` ## @coolgk/google-sign-in a javascript / typescript module `npm install @coolgk/google-sign-in` google sign in module which verifies id token and returns account data Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript const { GoogleSignIn } = require('@coolgk/google-sign-in'); // OR // import { GoogleSignIn } from '@coolgk/google-sign-in'; const googleSignIn = new GoogleSignIn({ clientId: '......' }); const invalidToken = '...'; const validToken = '...'; (async () => { const account1 = await googleSignIn.verify(invalidToken); console.log(account1); // false const account2 = await googleSignIn.verify(validToken); console.log(account2); // { // azp: '...', // aud: '...', // sub: '123123123', // email: 'abc@exmaple.com', // email_verified: true, // at_hash: 'asdfasdfasdfasdfa', // exp: 1520633389, // iss: 'accounts.google.com', // jti: 'qfwfasdfasdfasdfasdfasdfasdfadsf', // iat: 1520629789, // name: 'first last', // picture: 'https://lh6.googleusercontent.com/.../photo.jpg', // given_name: 'first', // family_name: 'last', // locale: 'en-GB' // } })() ``` <a name="GoogleSignIn"></a> ## GoogleSignIn **Kind**: global class * [GoogleSignIn](#GoogleSignIn) * _instance_ * [.verify(token)](#GoogleSignIn+verify) ⇒ <code>Promise.&lt;(boolean\|object)&gt;</code> * _static_ * [.GoogleSignIn](#GoogleSignIn.GoogleSignIn) * [new GoogleSignIn(options)](#new_GoogleSignIn.GoogleSignIn_new) <a name="GoogleSignIn+verify"></a> ### googleSignIn.verify(token) ⇒ <code>Promise.&lt;(boolean\|object)&gt;</code> **Kind**: instance method of [<code>GoogleSignIn</code>](#GoogleSignIn) **Returns**: <code>Promise.&lt;(boolean\|object)&gt;</code> - - false if id token is invalid otherwise returns account data | Param | Type | Description | | --- | --- | --- | | token | <code>string</code> | google id token string | <a name="GoogleSignIn.GoogleSignIn"></a> ### GoogleSignIn.GoogleSignIn **Kind**: static class of [<code>GoogleSignIn</code>](#GoogleSignIn) <a name="new_GoogleSignIn.GoogleSignIn_new"></a> #### new GoogleSignIn(options) | Param | Type | Description | | --- | --- | --- | | options | <code>object</code> | | | options.clientId | <code>string</code> | google client id | ## @coolgk/jwt a javascript / typescript module `npm install @coolgk/jwt` a simple jwt token class Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { Jwt } from '@coolgk/jwt'; // OR // const { Jwt } = require('@coolgk/jwt'); const jwt = new Jwt({secret: 'abc'}); const string = 'http://example.com/a/b/c?a=1'; const token = jwt.generate(string); console.log( jwt.verify(token), // { exp: 0, iat: 1512307492763, rng: 0.503008668963175, data: 'http://example.com/a/b/c?a=1' } jwt.verify(token+'1') // false ); const token2 = jwt.generate(string, 200); console.log( jwt.verify(token2), // { exp: 1512307493026, iat: 1512307492826, rng: 0.5832258275608753, data: 'http://example.com/a/b/c?a=1' } jwt.verify(token+'1') // false ); setTimeout(() => { console.log(jwt.verify(token2)); // false }, 250); ``` <a name="Jwt"></a> ## Jwt **Kind**: global class * [Jwt](#Jwt) * [new Jwt(options)](#new_Jwt_new) * [.generate(data, [expiry])](#Jwt+generate) ⇒ <code>string</code> * [.verify(token)](#Jwt+verify) ⇒ <code>boolean</code> \| <code>object</code> <a name="new_Jwt_new"></a> ### new Jwt(options) | Param | Type | Description | | --- | --- | --- | | options | <code>object</code> | | | options.secret | <code>string</code> | for encryption | <a name="Jwt+generate"></a> ### jwt.generate(data, [expiry]) ⇒ <code>string</code> **Kind**: instance method of [<code>Jwt</code>](#Jwt) | Param | Type | Default | Description | | --- | --- | --- | --- | | data | <code>\*</code> | | any data can be JSON.stringify'ed | | [expiry] | <code>number</code> | <code>0</code> | in milliseconds 0 = never expire | <a name="Jwt+verify"></a> ### jwt.verify(token) ⇒ <code>boolean</code> \| <code>object</code> **Kind**: instance method of [<code>Jwt</code>](#Jwt) **Returns**: <code>boolean</code> \| <code>object</code> - - false or the payload of the token | Param | Type | Description | | --- | --- | --- | | token | <code>string</code> | token to verify | ## @coolgk/number a javascript / typescript module `npm install @coolgk/number` number utitlies Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { round } from '@coolgk/number'; // OR // const { round } = require('@coolgk/number'); console.log(round(1.3923, 2)); // 1.39 console.log(round(100, 2)); // 100 console.log(round(100.1264, 2)); // 100.13 console.log(round(100.958747, 4)); // 100.9587 ``` <a name="round"></a> ## round(value, precision) ⇒ <code>number</code> **Kind**: global function | Param | Type | Default | Description | | --- | --- | --- | --- | | value | <code>number</code> | | number to round | | precision | <code>number</code> | <code>2</code> | precision | ## @coolgk/pdf a javascript / typescript module `npm install @coolgk/pdf` html to PDF module. create PDF files from html string or file. Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript // for "error while loading shared libraries: libfontconfig.so" run "sudo apt-get -y install libfontconfig" import { Pdf, Format, Orientation } from '@coolgk/pdf'; // OR // const { Pdf, Format, Orientation } = require('@coolgk/pdf'); const pdf = new Pdf({ tmpConfig: { dir: '/tmp/pdf' } // optional }); pdf.createFromHtmlFile( '/tmp/test.html', { header: { height: '1cm', contents: "<strong style='color: red'>Page ${pageNumber} of ${numberOfPages} - ${pageNumber}</strong>" }, footer: { height: '1cm', contents: 'footer <strong>Page ${pageNumber} of ${numberOfPages}</strong>' }, margin: '0.5cm' } ).then((pdfFile) => { console.log(pdfFile); }); const htmlCode = `<!DOCTYPE html><html><head> <title>CCES</title> <style> .pagebreak { page-break-after: always; } h2, h1 { color: red } </style> </head> <body> <div> <h1>page 1</h1> <p>some text <img src='https://dummyimage.com/600x400/3bbda9/f516ae.jpg'></p> </div> <div class="pagebreak"></div> <div> <h2>page 2</h2> <table> <tr> <td>texgt</td> <td>text</td> </tr> </table> </div> </body> </html>`; pdf.createFromHtmlString(htmlCode).then((pdfFile) => { console.log(pdfFile); }); ``` ## @coolgk/session a javascript / typescript module `npm install @coolgk/session` An session handler that works without cookie (and with cookie too). Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) When working without cookie, this class reads the session token from the **"Authorization"** header. e.g. **Authorization : Bearer cn389ncoiwuencr...** #### Express Middleware Example ```javascript // express middleware const session = require('@coolgk/session'); const app = require('express')(); app.use( session.express({ redisClient: require('redis').createClient({ host: process.env.REDIS_HOST, port: process.env.REDIS_PORT, password: process.env.REDIS_PASSWORD }), secret: '123' // secret is required for creating the session token / id }) ); app.use(async (request, response, next) => { // allow access if it's the login page or the request has a valid session if ('/login' === request.url || await request.session.verifyAndRenew()) { // if session is verified, renew session next(); } else { // deny access response.send('Please Login'); // output // 'Please Login' } }); app.get('/login', async (request, response, next) => { // start a new session (create a new session id) const accessToken = await request.session.init(); // set session variables await request.session.set('user', { id: 1, username: 'abc' }); // send session token/id back response.json({ accessToken }); // output // {"accessToken":"eyJleHAiOjAsIml..."} }); app.get('/user', async (request, response, next) => { // get session variable response.json(await request.session.get('user')); // output // {"id":1,"username":"abc"} }); app.get('/session', async (request, response, next) => { // get all session values response.json(await request.session.getAll()); // output // {"user":{"id":1,"username":"abc"}} }); app.get('/logout', async (request, response, next) => { // destroy current session await request.session.destroy(); response.json(await request.session.getAll()); // output // {} }); app.listen(8888); ``` #### Native Node App Example ```javascript import { Session } from '@coolgk/session'; // OR // const { Session } = require('@coolgk/session'); const http = require('http'); http.createServer(async (request, response) => { const session = new Session({ redisClient: require('redis').createClient({ host: process.env.REDIS_HOST, port: process.env.REDIS_PORT, password: process.env.REDIS_PASSWORD }), secret: '123', request, response }); // ... some middelware // ... in some routes // set sesstion await session.start(); await session.set('user', {id: 1, username: 'user@example.com'}); // check session and renew if verified const verified = await session.verifyAndRenew(); if (verified) { // session exists, logged in, do something } else { // deny access or show login screen } // show session data response.end( JSON.stringify( await session.getAll() ) ); // {"user":{"id":1,"username":"user@example.com"}} }).listen(8888); ``` #### To use without cookie Create a session without the **"response"** property and the sessoin object will read the session id from the **"Authorization"** header i.e. **Authorization : Bearer cn389ncoiwuencr...** ```javascript const session = new Session({ redisClient: require('redis').createClient({ host: process.env.REDIS_HOST, port: process.env.REDIS_PORT, password: process.env.REDIS_PASSWORD }), secret: '123', request }); ``` <a name="Session"></a> ## Session This class extends @coolgk/token see set(), get(), delete(), getAll() in @coolgk/token **Kind**: global class * [Session](#Session) * [.destroy()](#Session+destroy) ⇒ <code>promise</code> * [.renew([expiry])](#Session+renew) ⇒ <code>promise</code> <a name="Session+destroy"></a> ### session.destroy() ⇒ <code>promise</code> destory the current session **Kind**: instance method of [<code>Session</code>](#Session) <a name="Session+renew"></a> ### session.renew([expiry]) ⇒ <code>promise</code> renew session optionally with a different expiry time **Kind**: instance method of [<code>Session</code>](#Session) **Returns**: <code>promise</code> - - false if session has not been started or has a invalid token string | Param | Type | Description | | --- | --- | --- | | [expiry] | <code>number</code> | in seconds | ## @coolgk/queue a javascript / typescript module `npm install @coolgk/queue` This is a super lightweight function that limits the number of async functions run concurrently and run them in order. Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) 1. Put async functions in a queue and limit the number of async functions that run concurrently. 2. Run async functions in order 3. Run x number of functions in parallel per batch in order. similar to async / await when the second parameter is 1. ## Examples ```javascript import { queue } from '@coolgk/queue'; // OR // const { queue } = require('@coolgk/queue'); function a (x) { console.log('start a'); return new Promise((resolve) => setTimeout(() => { console.log('end a', x); resolve('a') }, 1300)); } function b (x) { console.log('start b'); return new Promise((resolve) => setTimeout(() => { console.log('end b', x); resolve('b') }, 1200)); } function c (x) { console.log('start c'); return new Promise((resolve) => setTimeout(() => { console.log('end c', x); resolve('c') }, 100)); } // call a, b, c in order i.e. b does not start until a resolves queue(a); queue(b); queue(c); // call a 5 times, each waits until the previous call resolves [1,2,3,4,5].forEach(() => { queue(a) }); // run 3 jobs at a time [1,2,3,4,5,6,7,8,9,10].forEach(() => { queue(a, 3) }); ``` <a name="queue"></a> ## queue(callback, [limit]) ⇒ <code>promise</code> **Kind**: global function | Param | Type | Default | Description | | --- | --- | --- | --- | | callback | <code>function</code> | | callback function that returns a promise or any other types | | [limit] | <code>number</code> | <code>1</code> | number of callback to run at the same time, by default one callback at a time | ## @coolgk/string a javascript / typescript module `npm install @coolgk/string` string utility functions Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { stripTags, escapeHtml, unescapeHtml, prepad0 } from '@coolgk/string'; // OR // const { stripTags, escapeHtml, unescapeHtml, prepad0 } = require('@coolgk/string'); const str = '<h1>test</h1><script>alert(1)</script>' console.log(stripTags(str)); // test alert(1) console.log(escapeHtml(str)); // &lt;h1&gt;test&lt;/h1&gt;&lt;script&gt;alert(1)&lt;/script&gt; console.log(unescapeHtml(escapeHtml(str))); // <h1>test</h1><script>alert(1)</script> console.log(prepad0(7, 2)); // 07 console.log(prepad0(70, 3)); // 070 console.log(prepad0(70, 4)); // 0070 console.log(prepad0(1, 4)); // 0001 console.log(prepad0(1000, 2)); // 1000 ``` ## Functions <dl> <dt><a href="#stripTags">stripTags(a)</a> ⇒ <code>string</code></dt> <dd><p>strip html tags e.g. &quot;&lt;h1&gt;header&lt;/h1&gt;&lt;p&gt;message&lt;/p&gt;&quot; becomes &quot;header message&quot;</p> </dd> <dt><a href="#escapeHtml">escapeHtml(value)</a> ⇒ <code>string</code></dt> <dd><p>escaping user input e.g. html code in a message box</p> </dd> <dt><a href="#unescapeHtml">unescapeHtml(string)</a> ⇒ <code>string</code></dt> <dd><p>unescaping strings escaped by escapeHtml()</p> </dd> <dt><a href="#prepad0">prepad0(value, length)</a> ⇒ <code>string</code></dt> <dd><p>use padStart instead</p> </dd> </dl> <a name="stripTags"></a> ## stripTags(a) ⇒ <code>string</code> strip html tags e.g. "&lt;h1&gt;header&lt;/h1&gt;&lt;p&gt;message&lt;/p&gt;" becomes "header message" **Kind**: global function **Returns**: <code>string</code> - - string with tags stripped | Param | Type | Description | | --- | --- | --- | | a | <code>string</code> | string | <a name="escapeHtml"></a> ## escapeHtml(value) ⇒ <code>string</code> escaping user input e.g. html code in a message box **Kind**: global function | Param | Type | Description | | --- | --- | --- | | value | <code>string</code> | string to escape | <a name="unescapeHtml"></a> ## unescapeHtml(string) ⇒ <code>string</code> unescaping strings escaped by escapeHtml() **Kind**: global function | Param | Type | Description | | --- | --- | --- | | string | <code>string</code> | string to unescape | <a name="prepad0"></a> ## prepad0(value, length) ⇒ <code>string</code> use padStart instead **Kind**: global function **See**: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart | Param | Type | Default | Description | | --- | --- | --- | --- | | value | <code>number</code> | | an integer in string or number format | | length | <code>number</code> | <code>2</code> | length of the output e.g. length = 2, 8 becomes 08. length = 3, 70 = 070. | ## @coolgk/tmp a javascript / typescript module `npm install @coolgk/tmp` wrapper functions, generate tmp file or folders Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { generateFile, generateDir, generateTmpName } from '@coolgk/tmp'; // OR // const { generateFile, generateDir, generateTmpName } = require('@coolgk/tmp'); generateFile({dir: '/tmp/test'}).then((r) => console.log('file', r)); // file { path: '/tmp/test/1512307052908140480ZZj6J0LOIJb.tmp' } generateDir({dir: '/tmp/test'}).then((r) => console.log('dir',r)); // dir { path: '/tmp/test/1512307052918140484Pnv1m95ZS2b' } generateTmpName({dir: '/tmp/test'}).then((r) => console.log('name', r)); // name { path: '/tmp/test/151230705292114048hb3XIds0FO9Y' } ``` ## Functions <dl> <dt><a href="#generateFile">generateFile([options])</a> ⇒ <code>promise</code></dt> <dd></dd> <dt><a href="#generateDir">generateDir([options])</a> ⇒ <code>promise</code></dt> <dd></dd> <dt><a href="#generateTmpName">generateTmpName([options])</a> ⇒ <code>promise</code></dt> <dd></dd> </dl> <a name="generateFile"></a> ## generateFile([options]) ⇒ <code>promise</code> **Kind**: global function **Returns**: <code>promise</code> - - { path: ..., cleanupCallback: ... } calling cleanupCallback() removes the generated file | Param | Type | Default | Description | | --- | --- | --- | --- | | [options] | <code>object</code> | | | | [options.mode] | <code>number</code> | <code>0600</code> | the file mode to create with, defaults to 0600 on file and 0700 on directory | | [options.prefix] | <code>string</code> | <code>&quot;Date.now()&quot;</code> | the optional prefix, fallbacks to tmp- if not provided | | [options.postfix] | <code>string</code> | <code>&quot;&#x27;.tmp&#x27;&quot;</code> | the optional postfix, fallbacks to .tmp on file creation | | [options.dir] | <code>string</code> | <code>&quot;/tmp&quot;</code> | the optional temporary directory, fallbacks to system default | | [options.keep] | <code>boolean</code> | <code>false</code> | if to keep the file | <a name="generateDir"></a> ## generateDir([options]) ⇒ <code>promise</code> **Kind**: global function **Returns**: <code>promise</code> - - { path: ..., cleanupCallback: ... } calling cleanupCallback() removes the generated file | Param | Type | Default | Description | | --- | --- | --- | --- | | [options] | <code>object</code> | | | | [options.mode] | <code>number</code> | <code>0600</code> | the file mode to create with, defaults to 0600 on file and 0700 on directory | | [options.prefix] | <code>string</code> | <code>&quot;Date.now()&quot;</code> | the optional prefix, fallbacks to tmp- if not provided | | [options.postfix] | <code>string</code> | <code>&quot;&#x27;.tmp&#x27;&quot;</code> | the optional postfix, fallbacks to .tmp on file creation | | [options.dir] | <code>string</code> | <code>&quot;/tmp&quot;</code> | the optional temporary directory, fallbacks to system default | | [options.keep] | <code>boolean</code> | <code>false</code> | if to keep the file | <a name="generateTmpName"></a> ## generateTmpName([options]) ⇒ <code>promise</code> **Kind**: global function **Returns**: <code>promise</code> - - { path: ... } | Param | Type | Default | Description | | --- | --- | --- | --- | | [options] | <code>object</code> | | | | [options.mode] | <code>number</code> | <code>0600</code> | the file mode to create with, defaults to 0600 on file and 0700 on directory | | [options.prefix] | <code>string</code> | <code>&quot;Date.now()&quot;</code> | the optional prefix, fallbacks to tmp- if not provided | | [options.postfix] | <code>string</code> | <code>&quot;&#x27;.tmp&#x27;&quot;</code> | the optional postfix, fallbacks to .tmp on file creation | | [options.dir] | <code>string</code> | <code>&quot;/tmp&quot;</code> | the optional temporary directory, fallbacks to system default | ## @coolgk/token a javascript / typescript module `npm install @coolgk/token` an expirable, revocable, renewable token with data storage Report bugs here: [https://github.com/coolgk/node-utils/issues](https://github.com/coolgk/node-utils/issues) ## Examples ```javascript import { Token } from '@coolgk/token'; import { createClient } from 'redis'; // OR // const { Token } = require('@coolgk/token'); // const createClient = require('redis').createClient; (async () => { const redisClient = createClient({ host: 'localhost', port: 6379, password: '----' }); const token = new Token({ redisClient: redisClient, expiry: 5, token: 'abcde' }); console.log( await token.verify() ) // false await token.renew(); console.log( await token.verify() ) // true console.log( await token.get('var1'); ); // null console.log( await token.getAll() ); // {} await token.set('var1', {a: 'var1', b: false}); console.log( await token.get('var1'); ); // {a: 'var1', b: false} await token.set('var2', 'string var 2'); console.log( await token.getAll() ); // { var1: { a: 'var1', b: false }, var2: 'string var 2' }