google-cloud-tasks
Version:
Nodejs package to push tasks to Google Cloud Tasks (beta). Include pushing batches.
244 lines (213 loc) • 6.61 kB
JavaScript
/**
* Copyright (c) 2018, Neap Pty Ltd.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
const shortid = require('shortid')
const newId = (options={}) => {
const id = shortid.generate().replace(/-/g, 'r').replace(/_/g, '9')
return options.short ? id.slice(0,-4) : id
}
const getDateUtc = (date) => {
const now_utc = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds())
return new Date(now_utc)
}
const addZero = nbr => ('0' + nbr).slice(-2)
const getTimestamp = (options={ short:true }) => {
const d = getDateUtc(new Date())
const main = `${d.getUTCFullYear()}${addZero(d.getUTCMonth()+1)}${addZero(d.getUTCDate())}`
if (options.short)
return main
else
return `${main}-${addZero(d.getUTCHours())}${addZero(d.getUTCMinutes())}${addZero(d.getUTCSeconds())}`
}
const _objectSortBy = (obj, fn = x => x, dir='asc') => Object.keys(obj || {})
.map(key => ({ key, value: obj[key] }))
.sort((a,b) => {
const vA = fn(a.value)
const vB = fn(b.value)
if (dir == 'asc') {
if (vA < vB)
return -1
else if (vA > vB)
return 1
else
return 0
} else {
if (vA > vB)
return -1
else if (vA < vB)
return 1
else
return 0
}
}).reduce((acc,v) => {
acc[v.key] = v.value
return acc
}, {})
const _arraySortBy = (arr, fn = x => x, dir='asc') => (arr || []).sort((a,b) => {
const vA = fn(a)
const vB = fn(b)
if (dir == 'asc') {
if (vA < vB)
return -1
else if (vA > vB)
return 1
else
return 0
} else {
if (vA > vB)
return -1
else if (vA < vB)
return 1
else
return 0
}
})
const sortBy = (obj, fn = x => x, dir='asc') => Array.isArray(obj) ? _arraySortBy(obj, fn, dir) : _objectSortBy(obj, fn, dir)
const newSeed = (size=0) => Array.apply(null, Array(size))
const mergeObj = (...objs) => objs.reduce((acc, obj) => { //Object.assign(...objs.map(obj => JSON.parse(JSON.stringify(obj))))
obj = obj || {}
if (typeof(obj) != 'object' || Array.isArray(obj) || (obj instanceof Date))
return acc
Object.keys(obj).forEach(property => {
const val = obj[property]
const originVal = acc[property]
const readyToMerge = !originVal || !val || typeof(val) != 'object' || Array.isArray(val) || typeof(originVal) != 'object' || Array.isArray(originVal)
acc[property] = readyToMerge ? val : mergeObj(originVal, val)
})
return acc
}, {})
const isEmptyObj = obj => {
if (!obj)
return true
try {
const o = JSON.stringify(obj)
return o == '{}'
} catch(e) {
return (() => false)(e)
}
}
const isObj = obj => {
if (!obj || typeof(obj) != 'object')
return false
try {
const o = JSON.stringify(obj) || ''
return o.match(/^\{(.*?)\}$/)
} catch(e) {
return (() => false)(e)
}
}
const getDiff = (orig={}, current={}) => {
return Object.keys(current).reduce((acc, key) => {
const val = current[key]
const origVal = orig[key]
if (val == undefined || origVal == val)
return acc
const origValIsObj = isObj(origVal)
if (!origValIsObj && origVal != val) {
acc[key] = val
return acc
}
const valIsObj = isObj(val)
if (origValIsObj && valIsObj) {
const objDiff = getDiff(origVal, val)
if (!isEmptyObj(objDiff))
acc[key] = objDiff
return acc
}
if (origVal != val) {
acc[key] = val
return acc
}
return acc
}, {})
}
const objAreSame = (obj1, obj2) => {
const o = getDiff(obj1, obj2)
return Object.keys(o || {}).length == 0
}
const arrayObjAreDiff = (objArr_01, objArr_02) => {
objArr_01 = objArr_01 || []
objArr_02 = objArr_02 || []
if (objArr_01.length != objArr_02.length)
return false
return objArr_01.some(h1 => !objArr_02.some(h2 => objAreSame(h1, h2)))
}
const mergeCollection = (...collections) => {
if (collections.length == 0)
return []
const lengths = collections.filter(col => col && col.length).map(col => col.length)
if (lengths.length == 0)
return collections
const maxLength = Math.max(...collections.filter(col => col && col.length).map(col => col.length))
return collections.map(col => {
const l = (col || []).length
if (l == 0) {
return newSeed(maxLength)
}
if (l == maxLength)
return col
const diff = maxLength - l
return [...col, ...newSeed(diff)]
})
}
/**
* Breaks down an array in a collection of array of size 'batchSize'.
*
* @param {Array} col Initial collection (e.g. [1,2,3,4,5])
* @param {Number} batchSize Size of each batch (e.g. 2)
* @return {Array} collection of array of size 'batchSize' (e.g. [[1,2], [3,4], [5]]).
*/
const batch = (col, batchSize=1) => {
const l = (col || []).length-1
return l < 0 ? [] : col.reduce((acc,item,idx) => {
acc.current.value.push(item)
acc.current.size++
if (acc.current.size == batchSize || idx == l) {
acc.result.push(acc.current.value)
acc.current = { value:[], size:0 }
}
return acc
},{ result:[], current: { value:[], size:0 } }).result
}
const validateUrl = (value='') =>
/^(http:\/\/|https:\/\/)localhost(:[0-9]+){0,1}(?!([a-zA-Z]|:(?![0-9])))/.test(value) || // localhost case
/^(http:\/\/|https:\/\/)[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(:[0-9]+){0,1}(?!([a-zA-Z]|:(?![0-9])))/.test(value) || // IPV4 case
/^(http:\/\/|https:\/\/)[a-zA-Z0-9]{1,4}:[a-zA-Z0-9]{1,4}:[a-zA-Z0-9]{1,4}:[a-zA-Z0-9]{1,4}:[a-zA-Z0-9]{1,4}:[a-zA-Z0-9]{1,4}:[a-zA-Z0-9]{1,4}:[a-zA-Z0-9]{1,4}(:[0-9]+){0,1}(?!([a-zA-Z]|:(?![0-9])))/.test(value) || // IPV6 case
/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(value)
const getRandomNumber = (start, end) => {
const size = end == undefined ? start : (end - start)
const offset = end == undefined ? 0 : start
return offset + Math.floor(Math.random() * size)
}
module.exports = {
identity: {
'new': newId
},
math: {
randomNumber: getRandomNumber
},
date: {
timestamp: getTimestamp
},
collection: {
batch,
sortBy,
seed: newSeed,
merge: mergeCollection
},
obj: {
merge: mergeObj,
isEmpty: isEmptyObj,
isObj,
diff: getDiff,
same: objAreSame,
arrayAreDiff: arrayObjAreDiff
},
validate: {
url: validateUrl
}
}