{"id":15732301,"url":"https://github.com/stopsopa/nlab","last_synced_at":"2026-03-01T18:31:43.138Z","repository":{"id":57311141,"uuid":"164500312","full_name":"stopsopa/nlab","owner":"stopsopa","description":"Various libs","archived":false,"fork":false,"pushed_at":"2025-05-07T01:40:50.000Z","size":1420,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-30T06:41:46.169Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://stopsopa.github.io/nlab/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stopsopa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-01-07T21:38:10.000Z","updated_at":"2025-05-07T01:40:53.000Z","dependencies_parsed_at":"2024-06-21T20:23:46.143Z","dependency_job_id":"904f9603-9bf1-44d4-92c2-b3d38c49f0d9","html_url":"https://github.com/stopsopa/nlab","commit_stats":{"total_commits":331,"total_committers":3,"mean_commits":"110.33333333333333","dds":0.5347432024169184,"last_synced_commit":"45a48cf691c7a5bf7491613b1f80638885d19cd2"},"previous_names":[],"tags_count":145,"template":false,"template_full_name":null,"purl":"pkg:github/stopsopa/nlab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stopsopa%2Fnlab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stopsopa%2Fnlab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stopsopa%2Fnlab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stopsopa%2Fnlab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stopsopa","download_url":"https://codeload.github.com/stopsopa/nlab/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stopsopa%2Fnlab/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29978506,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T16:35:47.903Z","status":"ssl_error","status_checked_at":"2026-03-01T16:35:44.899Z","response_time":124,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-04T00:08:53.622Z","updated_at":"2026-03-01T18:31:43.129Z","avatar_url":"https://github.com/stopsopa.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Tests](https://github.com/stopsopa/nlab/actions/workflows/tests.yml/badge.svg)](https://github.com/stopsopa/nlab/actions/workflows/tests.yml)\n[![npm version](https://badge.fury.io/js/nlab.svg)](https://badge.fury.io/js/nlab)\n[![npm version](https://shields.io/npm/v/nlab)](https://www.npmjs.com/package/nlab)\n[![NpmLicense](https://img.shields.io/npm/l/nlab.svg)](https://github.com/stopsopa/nlab/blob/master/LICENSE)\n![jest coverage](https://stopsopa.github.io/nlab/coverage/coverage-badge.svg)\n[![dependencies](https://depx.co/api/badge/nlab)](https://depx.co/pkg/nlab)\n\n# Go to\n\nVisit http://stopsopa.github.io/nlab/\n\n# Table of Contents\n\n\u003c!-- toc --\u003e\n\n- [Promise delay](#promise-delay)\n- [promiseall](#promiseall)\n- [lightFetch](#lightfetch)\n- [promiseany](#promiseany)\n- [parallel](#parallel)\n- [md5](#md5)\n- [CachePromise](#cachepromise)\n- [isObject()](#isobject)\n- [isArray()](#isarray)\n- [isAsyncFunction()](#isasyncfunction)\n- [isDate()](#isdate)\n- [trim()](#trim)\n- [alphaid()](#alphaid)\n- [xor](#xor)\n- [curry](#curry)\n- [generateSalt](#generatesalt)\n- [all](#all)\n- [serializeError](#serializeerror)\n- [aes256](#aes256)\n- [sha256](#sha256)\n- [color](#color)\n- [get](#get)\n- [set](#set)\n- [del](#del)\n- [pregQuote](#pregquote)\n- [stringToRegex](#stringtoregex)\n- [incrementSlug](#incrementslug)\n- [negotiatePort](#negotiateport)\n- [ms](#ms)\n- [cachePromiseInterval](#cachepromiseinterval)\n\n\u003c!-- tocstop --\u003e\n\n_(TOC generated using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_\n\n# Promise delay\n\n```javascript\nconst delay = require(\"nlab/delay\");\n\ndelay(3000, \"ok\").then((data) =\u003e console.log(\"then:\", data));\n// prints 'then: ok' after 3 sek\n```\n\n```javascript\nconst delay = require(\"nlab/delay\");\n\nPromise.resolve(\"all good\")\n  .then(\n    (data) =\u003e delay(3000, data),\n    (data) =\u003e delay.reject(3000, data),\n  )\n  .then(\n    (ok) =\u003e console.log(\"ok:\", ok),\n    (error) =\u003e console.log(\"catch:\", error),\n  );\n// 'ok: all good' - after 3 sec\n```\n\n```javascript\nconst delay = require(\"nlab/delay\");\n\nPromise.reject(\"all wrong\")\n  .then(\n    (data) =\u003e delay(3000, data),\n    (data) =\u003e delay.reject(3000, data),\n  )\n  .then(\n    (ok) =\u003e console.log(\"ok:\", ok),\n    (error) =\u003e console.log(\"catch:\", error),\n  );\n// 'catch: all wrong' - after 3 sec\n```\n\n```javascript\nconst then = require(\"nlab/delay\").then;\n\nconst { then } = require(\"nlab/delay\");\n\nPromise.resolve(\"resolved\")\n  .then(...then(1000))\n  .then((data) =\u003e console.log(\"then:\", data));\n// 'then: resolved' - after 1 sec\n\nPromise.reject(\"rejected\")\n  .then(...then(1000))\n  .catch((data) =\u003e console.log(\"catch:\", data));\n// 'catch: rejected' - after 1 sec\n```\n\nUse of _delay()_ with es6:\n\n```javascript\nimport delay from \"nlab/delay\";\n\nconst delay = require(\"nlab/delay\");\n\n(async function () {\n  console.log(\"start\");\n\n  await delay(1000);\n\n  console.log(\"end\");\n})();\n\n// 'start'\n// 'end' - after 1 sec\n```\n\n# promiseall\n\nWorks like Promise.all but when one or more promises in array are rejected, it will still wait for all other promises to resolve or reject ( to finish their job ), and return array like:\n\n```javascript\nconst promiseall = require(\"nlab/promiseall\");\n\nimport promiseall from \"nlab/promiseall\";\n\nconst list = promiseall([\n  /* ... array of promises to wait ... */\n]);\n\n// example response (if at least one promise is rejected)\n\n[\n  {\n    resolved: true,\n    data: \"...\",\n  },\n  {\n    resolved: true,\n    data: \"...\",\n  },\n  {\n    resolved: false,\n    data: \"...\",\n  },\n  {\n    resolved: true,\n    data: \"...\",\n  },\n];\n```\n\nIf all promises are resolved then there is not difference in behaviour from native Promise.all().\nIt just return array of payloads from those resolved promises.\n\npromiseall in this variant is designed to address some particular issues with race condition\n\n# lightFetch\n\n```javascript\nconst lightFetch = require(\"nlab/lightFetch\");\n\nimport lightFetch from \"nlab/lightFetch\";\n\n(async function () {\n  try {\n    const res = await lightFetch(\"/url\", {\n      method: \"POST\",\n      body: {\n        // because body is object it will be sent as json\n        some: \"data\",\n      },\n      timeout: 4000, // 4 sec\n    });\n  } catch (e) {\n    console.log(`general error: ${e}`);\n  }\n})();\n```\n\n[Doc](/src/lightFetch.js#L18)\n\n# promiseany\n\n```javascript\nconst promiseany = require(\"nlab/promiseany\");\n\nimport promiseany from \"nlab/promiseany\";\n\npromiseany([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]).then(console.log); // 1\n\npromiseany([new Promise((r) =\u003e setTimeout(() =\u003e r(1), 100)), Promise.resolve(2), Promise.resolve(3)]).then(console.log); // 2\n\npromiseany([Promise.reject(1), Promise.resolve(2), Promise.resolve(3)]).then(console.log); // 2\n\npromiseany([Promise.reject(1), Promise.reject(2), Promise.reject(3)]).catch(console.log); // [ 1, 2, 3 ]\n```\n\n# parallel\n\nAllows only to specific number of asynchronous action to be executed in parallel, rest is queued.\n\n```javascript\nconst parallel = require(\"nlab/parallel\");\n\nimport parallel from \"nlab/parallel\";\n\nconst instance = parallel({\n  numberOfThreads: 3,\n});\n\napp.all((req, res) =\u003e {\n  instance((slot, release) =\u003e {\n    console.log(`do some stuff ${slot}/${instance.getSetup().numberOfThreads}`);\n\n    setTimeout(() =\u003e {\n      console.log(`still in the queue: ${instance.getQueue().length}`);\n\n      release();\n    }, 100);\n  });\n});\n```\n\n# md5\n\n```javascript\n\nconst md5 = require('nlab/md5');\n\nimport md5 from 'nlab/md5';\n\nconsole.log(md5('str'));\n\n# echo -n 'str' | node_modules/nlab/src/md5.js\n\n```\n\n# CachePromise\n\n```javascript\nconst CachePromise = require(\"nlab/CachePromise\");\n\nimport CachePromise from \"nlab/CachePromise\";\n\nasync (done) =\u003e {\n  try {\n    const cachePromise = new CachePromise({\n      ttlms: 5,\n    });\n\n    let mainPromise = cachePromise.get({ a: \"b3\" }, () =\u003e new Promise((res) =\u003e setTimeout(res, 5, \"abc\")));\n\n    let data = await mainPromise;\n\n    expect(data).toEqual(\"abc\");\n\n    await delay(15);\n\n    mainPromise = cachePromise.get({ a: \"b3\" }, () =\u003e new Promise((res) =\u003e setTimeout(res, 5, \"abcd\")));\n\n    data = await mainPromise;\n\n    expect(data).toEqual(\"abcd\");\n\n    done();\n  } catch (e) {\n    done({\n      error: e,\n    });\n  }\n};\n```\n\n# isObject()\n\nIt's more strict method to test if given arg is an object - more strict than implementation from lodash or underscore.js\n\n```javascript\nimport isObject from \"nlab/isObject\";\n// or\n// const isObject = require('nlab/isObject');\n\n//  ✓isObject - {}                                                  -\u003e true\n//  ✓isObject - using with object that have implemented toString()  -\u003e true\n//  ✓isObject - extended object                                     -\u003e true\n//  ✓isObject - new function () {}                                  -\u003e true\n//  ✓isObject - []                                                  -\u003e false\n//  ✓isObject - function () {}                                      -\u003e false\n//  ✓isObject - async function () {}                                -\u003e false\n//  ✓isObject - () =\u003e {}                                            -\u003e false\n//  ✓isObject - null                                                -\u003e false\n//  ✓isObject - true                                                -\u003e false\n//  ✓isObject - false                                               -\u003e false\n//  ✓isObject - NaN                                                 -\u003e false\n//  ✓isObject - undefined                                           -\u003e false\n//  ✓isObject - no arg                                              -\u003e false\n//  ✓isObject - 4                                                   -\u003e false\n//  ✓isObject - string                                              -\u003e false\n//  ✓isObject - Symbol('test')                                      -\u003e false\n//  ✓isObject - new Date()                                          -\u003e false\n```\n\nTo se more details about what is considired an object and what is not see test cases coverage for this file:\n\n- [tests](https://github.com/stopsopa/nlab/blob/master/test/nlab/isObject.test.js)\n\n# isArray()\n\nIt's actually _Array.isArray_ with MDN polyfill.\n\n```javascript\nimport isArray from \"nlab/isArray\";\n// or\n// const isArray = require('nlab/isArray');\n\n//  ✓isArray - []                                                  -\u003e true\n//  ✓isArray - {}                                                  -\u003e false\n//  ✓isArray - using with object that have implemented toString()  -\u003e false\n//  ✓isArray - extended object                                     -\u003e false\n//  ✓isArray - new function () {}                                  -\u003e false\n//  ✓isArray - function () {}                                      -\u003e false\n//  ✓isArray - async function () {}                                -\u003e false\n//  ✓isArray - () =\u003e {}                                            -\u003e false\n//  ✓isArray - null                                                -\u003e false\n//  ✓isArray - true                                                -\u003e false\n//  ✓isArray - false                                               -\u003e false\n//  ✓isArray - NaN                                                 -\u003e false\n//  ✓isArray - undefined                                           -\u003e false\n//  ✓isArray - no arg                                              -\u003e false\n//  ✓isArray - 4                                                   -\u003e false\n//  ✓isArray - string                                              -\u003e false\n//  ✓isArray - Symbol('test')                                      -\u003e false\n```\n\n# isAsyncFunction()\n\n```javascript\nimport isAsyncFunction from \"nlab/isAsyncFunction\";\n// or\n// const isAsyncFunction = require('nlab/isAsyncFunction');\n\n//  ✓isAsyncFunction - []                                                  -\u003e false\n//  ✓isAsyncFunction - {}                                                  -\u003e false\n//  ✓isAsyncFunction - using with object that have implemented toString()  -\u003e false\n//  ✓isAsyncFunction - extended object                                     -\u003e false\n//  ✓isAsyncFunction - new function () {}                                  -\u003e false\n//  ✓isAsyncFunction - function () {}                                      -\u003e false\n//  ✓isAsyncFunction - async function () {}                                -\u003e true\n//  ✓isAsyncFunction - () =\u003e {}                                            -\u003e false\n//  ✓isAsyncFunction - null                                                -\u003e false\n//  ✓isAsyncFunction - true                                                -\u003e false\n//  ✓isAsyncFunction - false                                               -\u003e false\n//  ✓isAsyncFunction - NaN                                                 -\u003e false\n//  ✓isAsyncFunction - undefined                                           -\u003e false\n//  ✓isAsyncFunction - no arg                                              -\u003e false\n//  ✓isAsyncFunction - 4                                                   -\u003e false\n//  ✓isAsyncFunction - string                                              -\u003e false\n//  ✓isAsyncFunction - Symbol('test')                                      -\u003e false\n```\n\n# isDate()\n\n```javascript\nimport isDate from \"nlab/isDate\";\n// or\n// const isDate = require('nlab/isDate');\n\n//  ✓isDate - new Date()                                          -\u003e true\n//  ✓isDate - {}                                                  -\u003e false\n//  ✓isDate - using with object that have implemented toString()  -\u003e false\n//  ✓isDate - extended object                                     -\u003e false\n//  ✓isDate - new function () {}                                  -\u003e false\n//  ✓isDate - []                                                  -\u003e false\n//  ✓isDate - function () {}                                      -\u003e false\n//  ✓isDate - async function () {}                                -\u003e false\n//  ✓isDate - () =\u003e {}                                            -\u003e false\n//  ✓isDate - null                                                -\u003e false\n//  ✓isDate - true                                                -\u003e false\n//  ✓isDate - false                                               -\u003e false\n//  ✓isDate - NaN                                                 -\u003e false\n//  ✓isDate - undefined                                           -\u003e false\n//  ✓isDate - no arg                                              -\u003e false\n//  ✓isDate - 4                                                   -\u003e false\n//  ✓isDate - string                                              -\u003e false\n//  ✓isDate - Symbol('test')                                      -\u003e false\n```\n\n# trim()\n\n```javascript\nimport trim from \"nlab/trim\";\n// or\n// const trim = require('nlab/trim');\n\n/*!\n * direction : 'rl'|'r'|'l'   --\u003e   (undefined =\u003e 'rl')\n * charlist  : (undefined =\u003e \" \\n\")\n */\nfunction trim(string, charlist, direction) {\n  /* ... */\n}\n```\n\n# alphaid()\n\n```javascript\nimport alphaid from \"nlab/alphaid\";\n// or\n// const alphaid = require('nlab/alphaid');\n\nconst t = alphaid(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\");\n\nexpect(t.encode(1)).toEqual(\"b\");\nexpect(t.encode(2)).toEqual(\"c\");\nexpect(t.encode(3)).toEqual(\"d\");\nexpect(t.encode(61)).toEqual(\"9\");\nexpect(t.encode(62)).toEqual(\"ba\");\nexpect(t.encode(63)).toEqual(\"bb\");\n\nexpect(t.decode(t.encode(5))).toEqual(5);\nexpect(t.decode(t.encode(50))).toEqual(50);\nexpect(t.decode(t.encode(150))).toEqual(150);\n\nconst t = alphaid(\"01\");\n\nexpect(t.encode(1)).toEqual(\"1\");\nexpect(t.encode(2)).toEqual(\"10\");\nexpect(t.encode(3)).toEqual(\"11\");\nexpect(t.encode(4)).toEqual(\"100\");\nexpect(t.encode(5)).toEqual(\"101\");\nexpect(t.encode(24)).toEqual(\"11000\");\nexpect(t.encode(26)).toEqual(\"11010\");\nexpect(t.encode(40)).toEqual(\"101000\");\nexpect(t.encode(50)).toEqual(\"110010\");\nexpect(t.encode(60)).toEqual(\"111100\");\nexpect(t.encode(61)).toEqual(\"111101\");\nexpect(t.encode(62)).toEqual(\"111110\");\nexpect(t.encode(63)).toEqual(\"111111\");\n```\n\n# xor\n\n```javascript\nimport xor from \"nlab/xor\";\n\nconst key = \"mysecret key\";\n\nconst data = \"my data\";\n\nif (xor(xor(data, key), key) === data) {\n  // true\n}\n```\n\n# curry\n\n```javascript\nimport curry from \"nlab/curry\";\n\nconst curry = require(\"nlab/curry\");\n\nconst fn = curry((a, b, c) =\u003e a + b + c);\n\nexpect(fn(2, 4)(8)).toEqual(14);\n```\n\n# generateSalt\n\n```javascript\nimport generateSalt from \"nlab/generateSalt\";\n\nconst generateSalt = require(\"nlab/generateSalt\");\n\nconsole.log(generateSalt(12));\n\n// d87c3e2c5373\n```\n\n# all\n\n```javascript\nimport all from \"nlab/all\";\n\nconst all = require(\"nlab/all\");\n\nvar k = () =\u003e {\n  console.log(\"k\");\n  return [\"k1\", \"k2\"];\n};\n\nvar l = () =\u003e {\n  console.log(\"l\");\n  return [\"l1\", \"l2\"];\n};\n\n[k, l] = all([k, l], (data) =\u003e\n  console.log({\n    callback: data,\n  }),\n);\n\nsetTimeout(k, 1800);\nsetTimeout(l, 1000);\n\n// l\n// k\n// { callback: [ [ 'k1', 'k2' ], [ 'l1', 'l2' ] ] }\n```\n\n# serializeError\n\n```javascript\nimport serializeError from \"nlab/serializeError\";\nimport se from \"nlab/se\";\n\nconst serializeError = require(\"nlab/serializeError\");\nconst se = require(\"nlab/se\");\n\nconst log = require(\"inspc\");\n\ntry {\n  throw new Error(`naha you don't`);\n} catch (e) {\n  log.dump({\n    implicit_to_string: e,\n    serializeError: serializeError(e),\n    leave_stack_as_a_string: serializeError(e, true),\n  });\n}\n\n// Object {\n//   \u003cimplicit_to_string\u003e [Error]: \u003eError: naha you don't\u003c\n//   \u003cserializeError\u003e Object {\n//     \u003cname\u003e [String]: \u003eError\u003c len: 5\n//     \u003cmessage\u003e [String]: \u003enaha you don't\u003c len: 14\n//     \u003cstack\u003e Array [\n//       \u003c0\u003e [String]: \u003eError: naha you don't\u003c len: 21\n//       \u003c1\u003e [String]: \u003e    at Object.\u003canonymous\u003e (.../ttt.js:9:9)\u003c len: 80\n//       \u003c2\u003e [String]: \u003e    at Module._compile (module.js:653:30)\u003c len: 41\n//       \u003c3\u003e [String]: \u003e    at Object.Module._extensions..js (module.js:664:10)\u003c len: 55\n//       \u003c4\u003e [String]: \u003e    at Module.load (module.js:566:32)\u003c len: 37\n//       \u003c5\u003e [String]: \u003e    at tryModuleLoad (module.js:506:12)\u003c len: 39\n//       \u003c6\u003e [String]: \u003e    at Function.Module._load (module.js:498:3)\u003c len: 46\n//       \u003c7\u003e [String]: \u003e    at Function.Module.runMain (module.js:694:10)\u003c len: 49\n//       \u003c8\u003e [String]: \u003e    at startup (bootstrap_node.js:204:16)\u003c len: 41\n//       \u003c9\u003e [String]: \u003e    at bootstrap_node.js:625:3\u003c len: 30\n//     ]\n//   }\n//   \u003cleave_stack_as_a_string\u003e Object {\n//     \u003cname\u003e [String]: \u003eError\u003c len: 5\n//     \u003cmessage\u003e [String]: \u003enaha you don't\u003c len: 14\n//     \u003cstack\u003e [String]: \u003eError: naha you don't\n//     at Object.\u003canonymous\u003e (.../ttt.js:9:9)\n//     at Module._compile (module.js:653:30)\n//     at Object.Module._extensions..js (module.js:664:10)\n//     at Module.load (module.js:566:32)\n//     at tryModuleLoad (module.js:506:12)\n//     at Function.Module._load (module.js:498:3)\n//     at Function.Module.runMain (module.js:694:10)\n//     at startup (bootstrap_node.js:204:16)\n//     at bootstrap_node.js:625:3\u003c len: 448\n//   }\n// }\n```\n\n# aes256\n\n```javascript\nimport aes256 from \"nlab/aes256\";\n// or\n// const aes256 = require('nlab/aes256');\n\nconst c = aes256(`password`);\n\nlet msg = `message `;\n\nconst enc = c.encrypt(msg);\n\nconst dec = c.decrypt(enc);\n\n// dec === msg;\n```\n\n# sha256\n\n```javascript\nimport sha256 from \"nlab/sha256\";\n// or\n// const sha256 = require('nlab/sha256');\n\nsha256(\"test\"); // '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'\n```\n\n# color\n\n```javascript\nimport c from \"nlab/colors\";\n// or\n// const c = require('nlab/colors');\n\nconst glossary = {\n  Bright: \"\\x1b[1m\",\n  Dim: \"\\x1b[2m\",\n  Underscore: \"\\x1b[4m\",\n  Blink: \"\\x1b[5m\",\n  Reverse: \"\\x1b[7m\",\n  Hidden: \"\\x1b[8m\",\n  FgBlack: \"\\x1b[30m\",\n  FgRed: \"\\x1b[31m\", // red\n  FgGreen: \"\\x1b[32m\", // green\n  FgYellow: \"\\x1b[33m\", // yellow\n  FgBlue: \"\\x1b[34m\",\n  FgMagenta: \"\\x1b[35m\", // magenta\n  FgCyan: \"\\x1b[36m\", // cyan\n  FgWhite: \"\\x1b[37m\",\n  BgBlack: \"\\x1b[40m\",\n  BgRed: \"\\x1b[41m\",\n  BgGreen: \"\\x1b[42m\",\n  BgYellow: \"\\x1b[43m\",\n  BgBlue: \"\\x1b[44m\",\n  BgMagenta: \"\\x1b[45m\",\n  BgCyan: \"\\x1b[46m\",\n  BgWhite: \"\\x1b[47m\",\n  r: \"\\x1b[31m\", // red\n  g: \"\\x1b[32m\", // green\n  b: \"\\x1b[34m\", // blue\n  y: \"\\x1b[33m\", // yellow\n  m: \"\\x1b[35m\", // magenta\n  c: \"\\x1b[36m\", // cyan\n  reset: \"\\x1b[0m\",\n};\n\nconsole.log(c.r(`print in red`));\nconsole.log(c.g(`print in green`));\nconsole.log(c.BgGreen(`print in green`));\n\n// or\nc(`print`, `in`, `blue\\n`, `b`); // last arg will be use to choose color\nc(`print`, `in`, `green\\n`, `g`);\n// the difference is that it will also print it directly using one of\n// console.log() - in browser\n// process.stdout.write() - in node\n```\n\n![table of colors](https://i.imgur.com/mWzuQWP.png)\n\n# get\n\n```javascript\nimport get from \"nlab/get\";\n// or\n// const get = require('nlab/get');\n\nconst data = {\n  one: {\n    two: [\n      {\n        t: \"e\",\n      },\n      {\n        three: {\n          four: {\n            six: \"test\",\n          },\n        },\n      },\n    ],\n  },\n};\n\nconsole.log(get(data, \"one.two.1.three.four.six\"));\n// will print: 'test'\n\nconsole.log(get(data, \"one.two.1.three\"));\n// // will print: { four: { six: 'test' } }\n//\nconsole.log(get(data));\n// // will print: { one: { two: [ [Object], [Object] ] } }\n//\nconsole.log(get(data, \"one.two.1.nonexisting\"));\n// // will print: undefined\n//\nconsole.log(get(data, \"one.two.1.nonexisting\", \"defvalifnotexist\"));\n// // will print: 'defvalifnotexist'\n```\n\n# set\n\n```javascript\nimport set from \"nlab/set\";\n// or\n// const set = require('nlab/set');\n\nlet data = { one: \"two\" };\n\nset(data, \"three\", \"four\");\nconsole.log(JSON.stringify(data));\n// will print: {\"one\":\"two\",\"three\":\"four\"}\n\nset(data, \"three.a\", \"four\");\nconsole.log(JSON.stringify(data));\n// will print: {\"one\":\"two\",\"three\":{\"a\":\"four\"}}\n// -\u003e string 'four' has been replaced with object {a:'four'}\n\nset(data, \"six.seven.eight\", \"nine\");\nconsole.log(JSON.stringify(data, null, 4));\n// will print:\n// {\n//     \"one\": \"two\",\n//     \"three\": {\n//         \"a\": \"four\"\n//     },\n//     \"six\": {\n//         \"seven\": {\n//             \"eight\": \"nine\"\n//         }\n//     }\n// }\n\nset(data, \"three.bbb.ccc\", \"ddd\");\nconsole.log(JSON.stringify(data, null, 4));\n// will print:\n// {\n//     \"one\": \"two\",\n//     \"three\": {\n//         \"a\": \"four\",\n//         \"bbb\": {\n//             \"ccc\": \"ddd\"\n//         }\n//     },\n//     \"six\": {\n//         \"seven\": {\n//             \"eight\": \"nine\"\n//         }\n//     }\n// }\n\ndata = { one: \"two\" };\nset(data, \"arr\", []);\nconsole.log(JSON.stringify(data));\n// will print: {\"one\":\"two\",\"arr\":[]}\n\nset(data, \"arr.\", \"v1\"); // works like array.push();\nconsole.log(JSON.stringify(data));\n// will print: {\"one\":\"two\",\"arr\":[\"v1\"]}\n\nset(data, \"arr.\", \"v2\");\nconsole.log(JSON.stringify(data));\n// will print: {\"one\":\"two\",\"arr\":[\"v1\",\"v2\"]}\n\nset(data, \"arr..a.b..c\", \"v3\");\nconsole.log(JSON.stringify(data, null, 4));\n// will print:\n// {\n//     \"one\": \"two\",\n//     \"arr\": [\n//         \"v1\",\n//         \"v2\",\n//         {\n//             \"a\": {\n//                 \"b\": [\n//                     {\n//                         \"c\": \"v3\"\n//                     }\n//                 ]\n//             }\n//         }\n//     ]\n// }\n```\n\n# del\n\n```javascript\nimport del from \"nlab/del\";\n// or\n// const del = require('nlab/del');\n\nconst data = {\n  test: {\n    one: [\n      {\n        two: \"three\",\n      },\n      {\n        four: \"five\",\n      },\n      {\n        two: {\n          a: \"b\",\n          c: \"d\",\n        },\n      },\n      {\n        six: \"seven\",\n      },\n    ],\n    empty: false,\n  },\n};\n\ndel(data, `test.one`);\n\nexpect(data).toEqual({\n  test: {\n    empty: false,\n  },\n});\n```\n\n# pregQuote\n\nFunction to prefix in regex reserved characters.\n\n```javascript\nimport pregQuote from \"nlab/pregQuote\";\n// or\n// const pregQuote = require('nlab/pregQuote');\n\npregQuote(\"test\"); // 'test'\npregQuote(\"test[]test\"); // 'test\\[\\]test'\npregQuote(\"t?e(st\"); // 't\\?es\\(t'\n```\n\n# stringToRegex\n\nFunction to convert string to regex.\n\n```javascript\nimport stringToRegex from \"nlab/stringToRegex\";\n// or\n// const stringToRegex = require('nlab/stringToRegex');\n\nconst r = stringToRegex(\"/abc\\\\/abcf/i\");\n\nconsole.log(r);\n// {\n//   \"flags\": \"i\",\n//   \"source\": \"abc\\\\/abcf\",\n//   \"str\": \"/abc\\\\/abcf/i\"\n// }\n```\n\n# incrementSlug\n\nFunction to generate next possible value in db for unique key column.\n(In order to use it it's necessary to find 'last/biggest' slug in column):\n\n```jsx\nimport incrementSlug from \"nlab/incrementSlug\";\n\nimport slugify from \"nlab/slugify\";\n\nconst title = \"....\";\n\nconst prefix = slugify(title, { lower: true });\n\nlet newSlug = prefix;\n\nlet lastSlug = await this.queryColumn(\n  debug,\n  trx,\n  `SELECT slug FROM :table: WHERE slug LIKE :slug ORDER BY slug desc limit 1`,\n  {\n    slug: prefix + \"%\",\n  },\n);\n\nif (lastSlug) {\n  nextSlug = incrementSlug(lastSlug);\n}\n\nreturn nextSlug;\n```\n\n```javascript\nimport incrementSlug from \"nlab/incrementSlug\";\n// or\n// const incrementSlug = require('nlab/incrementSlug');\n\nincrementSlug(\"test\"); // 'test-1'\nincrementSlug(\"test-30\"); // 'test-31'\nincrementSlug(\"test-30\", \"_\"); // 'test-30_1'\nincrementSlug(\"test_30\", \"_\"); // 'test-31'\n```\n\n# negotiatePort\n\n```javascript\nimport negotiatePort from \"nlab/negotiatePort\";\n// or\n// const negotiatePort = require('nlab/negotiatePort');\n\nnegotiatePort(\"http\", 80); // ''\nnegotiatePort(\"http\", \"80\"); // ''\nnegotiatePort(\"http:\", \"80\"); // ''\nnegotiatePort(\"http://\", \"80\"); // ''\nnegotiatePort(\"http\", \"81\"); // '81'\nnegotiatePort(\"http\", \"81\", \":\"); // ':81'\nnegotiatePort(\"https\", \"80\"); // '80'\nnegotiatePort(\"https\", \"80\", \":\"); // ':80'\nnegotiatePort(\"https\", 443); // '443'\nnegotiatePort(\"https:\", 443); // '443'\nnegotiatePort(\"https:/\", 443); // '443'\nnegotiatePort(\"https://\", 443); // '443'\nnegotiatePort(\"https\", \"443\"); // '443'\nnegotiatePort(\"https\", \"443\", \":\"); // ':443'\n```\n\n# ms\n\nGenerate human readable version of time left based on given number of miliseconds (or other unit);\n\n```javascript\nimport ms from \"nlab/ms\";\n\nconst ms = require(\"nlab/ms\");\n\nconst generate = ms.generate;\n\nconst raw = ms.raw;\n\nconsole.log(ms(89754389233)); // number of miliseconds\n// 2y 308d 19h 46m 29s 233ms\n\nconsole.log(ms(89754389)); // number of miliseconds\n// 1d 55m 54s 389ms\n\nconsole.log(ms(89754389, \"s\")); // number of seconds\n// 2y 308d 19h 46m 29s\n// other units m,h,d,y - default 'ms'\n\nconsole.log(\n  ms(89754389, {\n    unit: \"s\",\n    dict: {\n      ms: \" ms\",\n      s: \" sec\",\n      m: \" min\",\n      h: \" hours\",\n      d: \" days\",\n      y: \" years\",\n    },\n  }),\n);\n// 2 years 308 days 19 hours 46 min 29 sec\n\nconst k = generate(\n  {\n    ms: 45,\n    s: 46,\n    m: 47,\n    h: 4,\n    d: 3,\n    y: 2,\n  } /* unit: default 'ms' */,\n);\n\nconsole.log(k); // 63348466045\n\nconsole.log(ms(k)); // 2y 3d 4h 47m 46s 45ms\n\nconsole.log(JSON.stringify(raw(k)));\n// {\"ms\":45,\"s\":46,\"m\":47,\"h\":4,\"d\":3,\"y\":2}\n```\n\n[see also](https://stackoverflow.com/a/50098261/5560682)\n\n# cachePromiseInterval\n\nLibrary for caching data and refreshing it periodicly using given async function to get the cache content,\nit is possible to cache multiple sets of data based on unique set of input arguments.\nIf new set arguments appear then it will fetch data on demand.\n\n```javascript\nimport cachePromiseInterval from \"nlab/cachePromiseInterval\";\n\nconst cachePromiseInterval = require(\"nlab/cachePromiseInterval\");\n\n// example\n\nconst log = require(\"inspc\");\n\nconst delay = require(\"nlab/delay\");\n\nconst cache = cachePromiseInterval(\"separatebucket\");\n\nconst fetch = (args, data) =\u003e {\n  return cache({\n    args,\n    create: () =\u003e\n      new Promise((res) =\u003e {\n        // console.log('fetch...')\n\n        setTimeout(res, 20, `res: ${data}`);\n      }),\n    refreshinterval: 20,\n  });\n};\n\n(async function () {\n  {\n    const { data } = await fetch([\"arg\"], \"dd\");\n\n    console.log(`data: ${data}`); // data: res: dd\n  }\n\n  {\n    // will server data from cache because args are the same\n    const { data } = await fetch([\"arg\"], \"ddd\");\n\n    console.log(`data: ${data}`); // data: res: dd\n  }\n\n  process.exit(0);\n})();\n\n// end of case 1\n\n(async function () {\n  {\n    const { data } = await fetch([\"arg\"], \"dd\");\n\n    console.log(`data: ${data}`); // data: res: dd\n  }\n\n  {\n    // arguments has changed so create will be called for this set of arguments\n    // and it will return different data\n    const { data } = await fetch([\"arg\", \"arg2\"], \"ddd\");\n\n    console.log(`data: ${data}`); // data: res: ddd\n  }\n\n  process.exit(0);\n})();\n\n// end of case 2\n\n// first failed cache will crash server (process.exit(1)) if create return rejected promise\n// it means library can't populate cache for this case\nconst fetchCrash = (args, data) =\u003e {\n  return cache({\n    args,\n    // firstcrach: true, it is true by defualt\n    create: () =\u003e\n      new Promise((res, rej) =\u003e {\n        // console.log('fetch...')\n\n        setTimeout(rej, 20, `rej: ${data}`);\n      }),\n    refreshinterval: 20,\n  });\n};\n\n(async function () {\n  {\n    const { data } = await fetchCrash([\"arg\"], \"dd\");\n\n    console.log(`data: ${data}`); // data: res: dd\n  }\n\n  // Object {\n  //     \u003ckey\u003e [String]: \u003eseparatebucket\u003c len: 14\n  //     \u003cckey\u003e [String]: \u003eseparatebucket_9b6bc915ce444bab0f263ac01bfb83b14c5a13d0351b22a7e5c748a6d594144f\u003c len: 79\n  //     \u003ccatch\u003e [String]: \u003ecachePromiseInterval error: promise catch\u003c len: 41\n  //     \u003co\u003e Object {\n  //     \u003cargs\u003e Array [\n  //         \u003c0\u003e [String]: \u003earg\u003c len: 3\n  //     ]\n  //     \u003ccreate\u003e [Function]: \u003e\u003c\n  //     \u003crefreshinterval\u003e [Integer]: \u003e20\u003c\n  //         \u003cfirstcrach\u003e [Boolean]: \u003etrue\u003c\n  //     }\n  //     \u003ce\u003e [String]: \u003erej: dd\u003c len: 7\n  //     \u003cfirstcrach\u003e [Undefined]: \u003eundefined\u003c\n  // }\n\n  // server will exit with status code: 1\n})();\n\n// end of case 3\n\n// first failed cache will crash server (process.exit(1)) if create return rejected promise\n// it means library can't populate cache for this case\nconst fetchCrash2 = (args, data) =\u003e {\n  return cache({\n    args,\n    firstcrach: false, // it is true by defualt\n    create: () =\u003e\n      new Promise((res, rej) =\u003e {\n        // console.log('fetch...')\n\n        setTimeout(rej, 20, `rej: ${data}`);\n      }),\n    refreshinterval: 200,\n  });\n};\n\n(async function () {\n  try {\n    const { data } = await fetchCrash2([\"arg\"], \"dd\");\n  } catch (e) {\n    log.dump({\n      catch_error: e, // rej: dd\n    });\n  }\n\n  try {\n    const { data } = await fetchCrash2([\"arg\"], \"ddd\");\n  } catch (e) {\n    log.dump({\n      catch_error2: e, // rej: dd - the same value\n    });\n  }\n\n  // It will just try and try to fetch it every interval given in refreshinterval\n  // Object {\n  //     \u003ckey\u003e [String]: \u003eseparatebucket\u003c len: 14\n  //     \u003cckey\u003e [String]: \u003eseparatebucket_9b6bc915ce444bab0f263ac01bfb83b14c5a13d0351b22a7e5c748a6d594144f\u003c len: 79\n  //     \u003cerror\u003e [String]: \u003eo.refreshinterval next call error\u003c len: 33\n  //     \u003ce\u003e [String]: \u003erej: dd\u003c len: 7\n  // }\n\n  // server will not crash\n})();\n\n// end of case 4\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstopsopa%2Fnlab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstopsopa%2Fnlab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstopsopa%2Fnlab/lists"}