My utility library. Because some wheels still need to be reinvented.
import{isBrowser}from'@jsepia/utils'if(isBrowser()){document.createElement('canvas')}import{IDGenerator}from'@jsepia/utils'constcatIDGenerator=newIDGenerator()constdogIDGenerator=newIDGenerator()functioncreateCat(name){return{id: catIDGenerator.generateID()name: name,toy: 'scratcher'}}functioncreateDog(name){return{id: dogIDGenerator.generateID()name: name,toy: 'ball'}}import{generateID}from'@jsepia/utils'constentities=[]functionspawnMonster(){entities[generateID()]=newMonster()}functionspawnNPC(){entities[generateID()]=newNPC()}functiongetEntityType(id){if(entities[id]instanceofMonster){return'monster'}elseif(entities[id]instanceofNPC){return'npc'}return'unknown'}Recursively merges the properties of an object into another.
import{deepExtend}from'@jsepia/utils'constdefaults={targets: {'app.js': 'src/**/*.js','tests.js': 'test/**/*.js'},verbose: false}constuserPreferences={targets: {'libs.js': 'lib/**/*.js'}}constcommandLineParams={verbose: true}constoptions=deepExtend(defaults,userPreferences,commandLineParams)Output:
{
"targets": {
"app.js": "src/**/*.js",
"tests.js": "test/**/*.js",
"libs.js": "lib/**/*.js",
},
"verbose": true
}Overrides the top-level properties of an object with another's.
import{extend}from'@jsepia/utils'constconfig={env: 'development',entry: ['app.js','test.js']}constparams={env: 'production',entry: 'lib/**/*.js'}constoptions=extend(config,params)Output:
{
"env": "production",
"entry": "lib/**/*.js"
}import{indexOfRegex}from'@jsepia/utils'indexOfRegex('umm',/m/g)// 1indexOfRegex('umm',/m/g,2)// 2Finds the index at the last occurrence of a regular expression.
import{lastIndexOfRegex}from'@jsepia/utils'lastIndexOfRegex('umm',/m/g)// 2lastIndexOfRegex('umm',/m/g,2)// 1Determines whether a value is an array.
import{isArray}from'@jsepia/utils'isArray([])// trueisArray({})// falseisArray('')// falseimport{isDefined}from'@jsepia/utils'isDefined(null)// trueisDefined(undefined)// falseconstkitty={ears: 2,paws: 4,status: 'cute'}isDefined(kitty.status)// trueisDefined(kitty.wings)// falseimport{isIterable}from'@jsepia/utils'isIterable()// trueisIterable([])// trueisIterable('meow')// trueisIterable(null)// falseisIterable({})// falseDetermines if a value is numeric. All numbers are considered numeric. Strings are numeric only if they begin with a number (e.g. 5px).
Another way of looking at it is: isNumeric(foo) === true implies parseInt(foo) will return a valid number.
import{isNumeric}from'@jsepia/utils'isNumeric(-95)// trueisNumeric('5.6')// trueisNumeric('-5.6')// trueisNumeric('5px')// trueisNumeric('five')// falseisNumeric('E79')// falseisNumeric()// falseisNumeric(null)// falseisNumeric(true)// falseisNumeric({})// falseisNumeric([])// falseReturns true if a value has the type object and is not null. This function helps you determine if it's safe to query a value's properties or perform any other object-specific operations on it.
import{isObject}from'@jsepia/utils'isObject()// falseisObject(null)// false (even though typeof null === 'object')isObject(function(){})// falseisObject({})// trueisObject([])// true// gotchasisObject(true)// falseisObject(newBoolean())// falseisObject(1)// falseisObject(newNumber())// falseisObject('')// falseisObject(newString())// falseDetermines whether a value is a plain object - i.e. an object that is not an instance of a prototype or class, or otherwise does not have a constructor
import{isPlainObject}from'@jsepia/utils'isPlainObject()// falseisPlainObject([])// false (even though typeof [] === 'object')isPlainObject(NaN)// false (even though NaN is a Number type)isPlainObject(newDate())// falseisPlainObject({})// trueimport{buildUri}from'@jsepia/utils'buildUri({// it supports the basic options you would expectprotocol: 'http',host: 'juliosepia.com',port: '8080',path: '/posts/util.html',anchor: 'introduction',// hash// you can pass credentials separatelyuser: 'jsepia',password: 'hunter2',// or as a single stringuserInfo: 'jsepia:hunter2',// you can pass query params separatelyqueryKey: {version: '1.0',format: 'html'},// or as a single stringquery: 'version=1.0&format=html',})Output:
http://jsepia:hunter2@juliosepia.com:8080/posts/util.html?version=1.0&format=html#introduction
parseUri('http://jsepia:hunter2@juliosepia.com/posts/util.html?version=1.0&format=html#introduction')Output:
{
"anchor": "introduction",
"authority": "jsepia:hunter2@juliosepia.com",
"directory": "/posts/",
"file": "util.html",
"host": "juliosepia.com",
"password": "hunter2",
"path": "/posts/util.html",
"port": "",
"protocol": "http",
"query": "version=1.0&format=html",
"queryKey": {
"format": "html",
"version": "1.0",
},
"relative": "/posts/util.html?version=1.0&format=html#introduction",
"source": "http://jsepia:hunter2@juliosepia.com/posts/util.html?version=1.0&format=html#introduction",
"user": "jsepia",
"userInfo": "jsepia:hunter2"
}import{isValidUrl}from'@jsepia/utils'consturl=prompt('enter URL here')if(isValidUrl(url)){request(url).then((response)=>handleResponse,(err)=>handleError)}else{handleError(newError(`Invalid URL: ${url}`))}- Test the exported library
- Split into bundles
# unit test
yarn test# integ test (for CI and stuff)
yarn build && yarn test:integ