├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test └── index.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "think" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | coverage.lcov 40 | 41 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | demo/ 4 | test/ 5 | src/ 6 | ISSUE_TEMPLATE.md 7 | appveyor.yml 8 | README_zh-CN.md -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '6' 4 | sudo: false 5 | script: 6 | - "npm test" 7 | after_success: 8 | - 'npm install coveralls && ./node_modules/.bin/nyc report --reporter=text-lcov | ./node_modules/.bin/coveralls' -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 ThinkJS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # think-helper 2 | [![Build Status](https://travis-ci.org/thinkjs/think-helper.svg?branch=master)](https://travis-ci.org/thinkjs/think-helper) 3 | [![Coverage Status](https://coveralls.io/repos/github/thinkjs/think-helper/badge.svg)](https://coveralls.io/github/thinkjs/think-helper) 4 | [![npm](https://img.shields.io/npm/v/think-helper.svg)](https://www.npmjs.com/package/think-helper) 5 | 6 | `think-helper` defines a set of helper functions for ThinkJS. 7 | 8 | ## Installation 9 | 10 | Using npm: 11 | 12 | ```sh 13 | npm install think-helper 14 | ``` 15 | 16 | In Node.js: 17 | 18 | ```js 19 | import helper from 'think-helper'; 20 | 21 | let md5 = helper.md5(''); 22 | 23 | ``` 24 | 25 | APIs: 26 | 27 | API | Param | Description 28 | ---|---|--- 29 | `isInt` | | check integer 30 | `isIP` | | check IP 31 | `isIPv4` | | check IPv4 32 | `isIPv6` | | check IPv6 33 | `isMaster` | |cluster.isMaster 34 | `isArray` | `arg`{mix}
`return`{Boolean} | check if a variable is an Array 35 | `isBoolean` | `arg`{mix}
`return`{Boolean} | check if a variable is an Boolean 36 | `isNull` | `arg`{mix}
`return`{Boolean} | check if a variable is an null 37 | `isNullOrUndefined` | `arg`{mix}
`return`{Boolean} | check if a variable is null or undefined 38 | `isNumber` | `arg`{mix}
`return`{Boolean} | check if a variable is an Number 39 | `isString` | `arg`{mix}
`return`{Boolean} | check if a variable is an String 40 | `isSymbol` | `arg`{mix}
`return`{Boolean} | check if a variable is an Symbol 41 | `isUndefined` | `arg`{mix}
`return`{Boolean} | check if a variable is an undefined 42 | `isRegExp` | `arg`{mix}
`return`{Boolean} | check if a variable is an RegExp 43 | `isObject` | `arg`{mix}
`return`{Boolean} | check if a variable is an Object 44 | `isDate` | `arg`{mix}
`return`{Boolean} | check if a variable is an Date 45 | `isError` | `arg`{mix}
`return`{Boolean} | check if a variable is an Error 46 | `isFunction` | `arg`{mix}
`return`{Boolean} | check if a variable is an Function 47 | `isPrimitive` | `arg`{mix}
`return`{Boolean} | check if a variable is an Primitive 48 | `isBuffer` | `arg`{mix}
`return`{Boolean} | check if a variable is an Buffer 49 | `promisify` | `function`{function}
`receiver`{object}
`return` Promise | make callback function to promise 50 | `extend` | `target`{object\|array}
`args`{Object\|Array}
`return`{Object} | extend object 51 | `camelCase` | `str`{string}
`return`{String} | make indexAction to index_action 52 | `isNumberString` | `str`{string}
`return`{Boolean} | check object is number string 53 | `isTrueEmpty` | `obj`{mixed}
`return`{Boolean}| truely 54 | `isEmpty` | `obj`{object}
`return`{Boolean}| check object is mepty 55 | `defer` | `return` defer | get deferred object 56 | `md5` | `str`{string}
`return`{string} | get content md5 57 | `timeout` | `time`{Number}
`return` Promise | get timeout Promise 58 | `escapeHtml` | `str`{String}
`return` {string} | escape html 59 | `datetime` | `date`{Date\|String}
`format`{String}
`return`{String} | get datetime 60 | `uuid` | `version`{String} v1 or v4 | generate uuid 61 | `isExist` | `dir`{String} | check path is exist 62 | `isFile` | `filePath`{String} | check filepath is file 63 | `isDirectory` | `filePath`{String} | check path is directory 64 | `chmod` | `path`{String}
`mode`{String} | change path mode 65 | `mkdir` | `dir`{String}
`mode`{String} | make dir 66 | `getdirFiles` | `dir`{String}
`prefix`{String} | get files in path 67 | `rmdir` | `path`{String}
`reserve`{Boolean}
`return`{Promise} | remove dir async 68 | `parseAdapterConfig` | `config`{Object}
`extConfig`{Object\|String} | parse adapter config 69 | `ms` | `time`{String} | transform humanize time to ms 70 | `omit` | `obj`{obj}
`prop` {String|Array} | omit object props 71 | 72 | 73 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for think-helper in ThinkJs 3.x 2 | // Project: https://thinkjs.org/ 3 | // Definitions by: SijieCai 4 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 5 | 6 | 7 | 8 | declare namespace ThinkHelper { 9 | interface Defer { 10 | promise: Promise, 11 | resolve: Function, 12 | reject: Function 13 | } 14 | export function camelCase(str: any): any; 15 | 16 | 17 | /** 18 | * change path mode 19 | * 20 | * @export 21 | * @param {string} p 22 | * @param {string} mode default is '0777' 23 | * @returns {*} 24 | */ 25 | export function chmod(p: string, mode?: string): any; 26 | 27 | /** 28 | * get datetime 29 | * 30 | * @export 31 | * @param {*} date 32 | * @param {*} format default is 'YYYY-MM-DD HH:mm:ss' 33 | * @returns {*} 34 | */ 35 | export function datetime(date?: Date | string | number, format?: string): string; 36 | 37 | /** 38 | * get deferred object 39 | * 40 | * @export 41 | * @returns {Defer} 42 | */ 43 | export function defer(): Defer; 44 | 45 | /** 46 | * escape html 47 | * 48 | * @export 49 | * @param {string} str 50 | * @returns {string} 51 | */ 52 | export function escapeHtml(str: string): string; 53 | 54 | export function extend(target: Object, ...args: Object[]): any; 55 | 56 | 57 | /** 58 | * 59 | * get files in path 60 | * @export 61 | * @param {string} dir 62 | * @param {string} prefix 63 | * @returns {string} 64 | */ 65 | export function getdirFiles(dir: string, prefix?: string): Array; 66 | 67 | export function isArray(arg: any): boolean; 68 | 69 | export function isBoolean(arg: any): boolean; 70 | 71 | export function isBuffer(b: any): boolean; 72 | 73 | export function isDate(d: any): boolean; 74 | 75 | export function isDirectory(filePath: any): boolean; 76 | 77 | export function isEmpty(obj: any): boolean; 78 | 79 | export function isError(e: any): boolean; 80 | 81 | export function isExist(dir: any): boolean; 82 | 83 | export function isFile(filePath: any): boolean; 84 | 85 | export function isFunction(arg: any): boolean; 86 | 87 | export function isInt(value: string): boolean; 88 | 89 | export function isIP(value: string): boolean; 90 | 91 | export function isIPv4(value: string): boolean; 92 | 93 | export function isIPv6(value: string): boolean; 94 | 95 | export var isMaster: boolean; 96 | 97 | export function isNull(arg: any): boolean; 98 | 99 | export function isNullOrUndefined(arg: any): boolean; 100 | 101 | export function isNumber(arg: any): boolean; 102 | 103 | export function isNumberString(obj: any): boolean; 104 | 105 | export function isObject(obj: any): boolean; 106 | 107 | export function isPrimitive(arg: any): boolean; 108 | 109 | export function isRegExp(re: any): boolean; 110 | 111 | export function isString(arg: any): boolean; 112 | 113 | export function isSymbol(arg: any): boolean; 114 | 115 | export function isTrueEmpty(obj: any): boolean; 116 | 117 | export function isUndefined(arg: any): boolean; 118 | 119 | export function md5(str: string): string; 120 | 121 | /** 122 | * 123 | * 124 | * @export 125 | * @param {string} dir 126 | * @param {string} mode default to '0777' 127 | * @returns {*} 128 | */ 129 | export function mkdir(dir: string, mode?: string): any; 130 | 131 | /** 132 | * transform humanize time to ms 133 | * 134 | * @export 135 | * @param {*} time 136 | * @returns {*} 137 | */ 138 | export function ms(time: any): number; 139 | 140 | 141 | /** 142 | * omit some props in object 143 | * 144 | * @export 145 | * @param {Object} obj 146 | * @param {(string | Array)} props ',' seperate string or array of props 147 | * @returns {Object} 148 | */ 149 | export function omit(obj: Object, props: string | Array): Object; 150 | 151 | 152 | export function parseAdapterConfig(config: Object, ...extConfig: Array): Object; 153 | 154 | /** 155 | * make callback function to promise 156 | * 157 | * @param {Function} fn [] 158 | * @param {Object} receiver [] 159 | * @return {Function} [] 160 | */ 161 | export function promisify(fn: Function, receiver: Object): Function; 162 | /** 163 | * remove dir aync 164 | * @param {String} p [path] 165 | * @param {Boolean} reserve [] 166 | * @return {Promise} [] 167 | */ 168 | export function rmdir(p: String, reserve?: Boolean): Promise; 169 | 170 | /** 171 | * snakeCase string 172 | * @param {String} str [] 173 | * @return {String} [] 174 | */ 175 | export function snakeCase(str: string): string; 176 | 177 | /** 178 | * get timeout Promise default 1000 179 | * @param {Number} time [] 180 | * @return {Promise} [] 181 | */ 182 | export function timeout(time?: Number): Promise; 183 | /** 184 | * generate uuid 185 | * @param {String} version [uuid RFC version defautl to v4, or v1] 186 | * @return {String} [] 187 | */ 188 | export function uuid(version?: string): string; 189 | 190 | export interface Think { 191 | 192 | camelCase(str: any): any; 193 | 194 | 195 | /** 196 | * change path mode 197 | * 198 | * @export 199 | * @param {string} p 200 | * @param {string} mode default is '0777' 201 | * @returns {*} 202 | */ 203 | chmod(p: string, mode?: string): any; 204 | 205 | /** 206 | * get datetime 207 | * 208 | * @export 209 | * @param {*} date 210 | * @param {*} format default is 'YYYY-MM-DD HH:mm:ss' 211 | * @returns {*} 212 | */ 213 | datetime(date: any, format?: string): any; 214 | 215 | /** 216 | * get deferred object 217 | * 218 | * @export 219 | * @returns {Defer} 220 | */ 221 | defer(): Defer; 222 | 223 | /** 224 | * escape html 225 | * 226 | * @export 227 | * @param {string} str 228 | * @returns {string} 229 | */ 230 | escapeHtml(str: string): string; 231 | 232 | extend(target: Object, ...args: Object[]): any; 233 | 234 | 235 | /** 236 | * 237 | * get files in path 238 | * @export 239 | * @param {string} dir 240 | * @param {string} prefix 241 | * @returns {string} 242 | */ 243 | getdirFiles(dir: string, prefix?: string): Array; 244 | 245 | isArray(arg: any): boolean; 246 | 247 | isBoolean(arg: any): boolean; 248 | 249 | isBuffer(b: any): boolean; 250 | 251 | isDate(d: any): boolean; 252 | 253 | isDirectory(filePath: any): boolean; 254 | 255 | isEmpty(obj: any): boolean; 256 | 257 | isError(e: any): boolean; 258 | 259 | isExist(dir: any): boolean; 260 | 261 | isFile(filePath: any): boolean; 262 | 263 | isFunction(arg: any): boolean; 264 | 265 | isIP(value: string): boolean; 266 | 267 | isIPv4(value: string): boolean; 268 | 269 | isIPv6(value: string): boolean; 270 | 271 | isMaster: boolean; 272 | 273 | isNull(arg: any): boolean; 274 | 275 | isNullOrUndefined(arg: any): boolean; 276 | 277 | isNumber(arg: any): boolean; 278 | 279 | isNumberString(obj: any): boolean; 280 | 281 | isObject(obj: any): boolean; 282 | 283 | isPrimitive(arg: any): boolean; 284 | 285 | isRegExp(re: any): boolean; 286 | 287 | isString(arg: any): boolean; 288 | 289 | isSymbol(arg: any): boolean; 290 | 291 | isTrueEmpty(obj: any): boolean; 292 | 293 | isUndefined(arg: any): boolean; 294 | 295 | md5(str: string): string; 296 | 297 | /** 298 | * 299 | * 300 | * @export 301 | * @param {string} dir 302 | * @param {string} mode default to '0777' 303 | * @returns {*} 304 | */ 305 | mkdir(dir: string, mode?: string): any; 306 | 307 | /** 308 | * transform humanize time to ms 309 | * 310 | * @export 311 | * @param {*} time 312 | * @returns {*} 313 | */ 314 | ms(time: any): number; 315 | 316 | 317 | /** 318 | * omit some props in object 319 | * 320 | * @export 321 | * @param {Object} obj 322 | * @param {(string | Array)} props ',' seperate string or array of props 323 | * @returns {Object} 324 | */ 325 | omit(obj: Object, props: string | Array): Object; 326 | 327 | 328 | parseAdapterConfig(config: Object, ...extConfig: Array): Object; 329 | 330 | /** 331 | * make callback function to promise 332 | * 333 | * @param {Function} fn [] 334 | * @param {Object} receiver [] 335 | * @return {Function} [] 336 | */ 337 | promisify(fn: Function, receiver: Object): Function; 338 | /** 339 | * remove dir aync 340 | * @param {String} p [path] 341 | * @param {Boolean} reserve [] 342 | * @return {Promise} [] 343 | */ 344 | rmdir(p: String, reserve?: Boolean): Promise; 345 | 346 | /** 347 | * snakeCase string 348 | * @param {String} str [] 349 | * @return {String} [] 350 | */ 351 | snakeCase(str: string): string; 352 | 353 | /** 354 | * get timeout Promise default 1000 355 | * @param {Number} time [] 356 | * @return {Promise} [] 357 | */ 358 | timeout(time?: Number): Promise; 359 | /** 360 | * generate uuid 361 | * @param {String} version [uuid RFC version defautl to v4, or v1] 362 | * @return {String} [] 363 | */ 364 | uuid(version?: string): string; 365 | 366 | } 367 | } 368 | 369 | export = ThinkHelper; 370 | 371 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const crypto = require('crypto'); 4 | const net = require('net'); 5 | const cluster = require('cluster'); 6 | const uuid = require('uuid'); 7 | const ms = require('ms'); 8 | const { 9 | isArray, 10 | isBoolean, 11 | isNull, 12 | isNullOrUndefined, 13 | isNumber, 14 | isString, 15 | isSymbol, 16 | isUndefined, 17 | isRegExp, 18 | isObject, 19 | isDate, 20 | isError, 21 | isFunction, 22 | isPrimitive, 23 | isBuffer 24 | } = require('core-util-is'); 25 | 26 | const fsRmdir = promisify(fs.rmdir, fs); 27 | const fsUnlink = promisify(fs.unlink, fs); 28 | const fsReaddir = promisify(fs.readdir, fs); 29 | 30 | const numberReg = /^((-?(\d+\.|\d+|\.\d)\d*(?:e[+-]?\d*(?:\d?\.?|\.?\d?)\d*)?)|(0[0-7]+)|(0x[0-9a-f]+))$/i; 31 | const toString = Object.prototype.toString; 32 | 33 | exports.isIP = net.isIP; 34 | exports.isIPv4 = net.isIPv4; 35 | exports.isIPv6 = net.isIPv6; 36 | exports.isMaster = cluster.isMaster; 37 | 38 | exports.isArray = isArray; 39 | exports.isBoolean = isBoolean; 40 | exports.isNull = isNull; 41 | exports.isNullOrUndefined = isNullOrUndefined; 42 | exports.isNumber = isNumber; 43 | exports.isString = isString; 44 | exports.isSymbol = isSymbol; 45 | exports.isUndefined = isUndefined; 46 | exports.isRegExp = isRegExp; 47 | exports.isObject = isObject; 48 | exports.isDate = isDate; 49 | exports.isError = isError; 50 | exports.isFunction = isFunction; 51 | exports.isPrimitive = isPrimitive; 52 | exports.isBuffer = isBuffer; 53 | 54 | /** 55 | * override isObject method in `core-util-is` module 56 | */ 57 | exports.isObject = obj => { 58 | return toString.call(obj) === '[object Object]'; 59 | }; 60 | 61 | /** 62 | * check value is integer 63 | */ 64 | function isInt(value) { 65 | if (isNaN(value) || exports.isString(value)) { 66 | return false; 67 | } 68 | var x = parseFloat(value); 69 | return (x | 0) === x; 70 | } 71 | 72 | exports.isInt = isInt; 73 | 74 | /** 75 | * make callback function to promise 76 | * @param {Function} fn [] 77 | * @param {Object} receiver [] 78 | * @return {Promise} [] 79 | */ 80 | function promisify(fn, receiver) { 81 | return (...args) => { 82 | return new Promise((resolve, reject) => { 83 | fn.apply(receiver, [...args, (err, res) => { 84 | return err ? reject(err) : resolve(res); 85 | }]); 86 | }); 87 | }; 88 | } 89 | 90 | exports.promisify = promisify; 91 | 92 | exports.extend = require('lodash.merge'); 93 | 94 | /** 95 | * camelCase string 96 | * @param {String} str [] 97 | * @return {String} [] 98 | */ 99 | function camelCase(str) { 100 | if (str.indexOf('_') > -1) { 101 | str = str.replace(/_(\w)/g, (a, b) => { 102 | return b.toUpperCase(); 103 | }); 104 | } 105 | return str; 106 | } 107 | exports.camelCase = camelCase; 108 | 109 | /** 110 | * snakeCase string 111 | * @param {String} str [] 112 | * @return {String} [] 113 | */ 114 | function snakeCase(str) { 115 | return str.replace(/([^A-Z])([A-Z])/g, function($0, $1, $2) { 116 | return $1 + '_' + $2.toLowerCase(); 117 | }); 118 | }; 119 | exports.snakeCase = snakeCase; 120 | 121 | /** 122 | * check object is number string 123 | * @param {Mixed} obj [] 124 | * @return {Boolean} [] 125 | */ 126 | function isNumberString(obj) { 127 | if (!obj) return false; 128 | return numberReg.test(obj); 129 | } 130 | exports.isNumberString = isNumberString; 131 | 132 | /** 133 | * true empty 134 | * @param {Mixed} obj [] 135 | * @return {Boolean} [] 136 | */ 137 | function isTrueEmpty(obj) { 138 | if (obj === undefined || obj === null || obj === '') return true; 139 | if (exports.isNumber(obj) && isNaN(obj)) return true; 140 | return false; 141 | } 142 | exports.isTrueEmpty = isTrueEmpty; 143 | 144 | /** 145 | * check object is mepty 146 | * @param {[Mixed]} obj [] 147 | * @return {Boolean} [] 148 | */ 149 | function isEmpty(obj) { 150 | if (isTrueEmpty(obj)) return true; 151 | if (exports.isRegExp(obj)) { 152 | return false; 153 | } else if (exports.isDate(obj)) { 154 | return false; 155 | } else if (exports.isError(obj)) { 156 | return false; 157 | } else if (exports.isArray(obj)) { 158 | return obj.length === 0; 159 | } else if (exports.isString(obj)) { 160 | return obj.length === 0; 161 | } else if (exports.isNumber(obj)) { 162 | return obj === 0; 163 | } else if (exports.isBoolean(obj)) { 164 | return !obj; 165 | } else if (exports.isObject(obj)) { 166 | for (const key in obj) { 167 | return false && key; // only for eslint 168 | } 169 | return true; 170 | } 171 | return false; 172 | } 173 | exports.isEmpty = isEmpty; 174 | 175 | /** 176 | * get deferred object 177 | * @return {Object} [] 178 | */ 179 | function defer() { 180 | const deferred = {}; 181 | deferred.promise = new Promise((resolve, reject) => { 182 | deferred.resolve = resolve; 183 | deferred.reject = reject; 184 | }); 185 | return deferred; 186 | } 187 | exports.defer = defer; 188 | 189 | /** 190 | * get content md5 191 | * @param {String} str [content] 192 | * @return {String} [content md5] 193 | */ 194 | function md5(str) { 195 | return crypto.createHash('md5').update(str + '', 'utf8').digest('hex'); 196 | } 197 | exports.md5 = md5; 198 | 199 | /** 200 | * get timeout Promise 201 | * @param {Number} time [] 202 | * @return {[type]} [] 203 | */ 204 | function timeout(time = 1000) { 205 | return new Promise((resolve) => { 206 | setTimeout(resolve, time); 207 | }); 208 | } 209 | exports.timeout = timeout; 210 | 211 | /** 212 | * escape html 213 | */ 214 | function escapeHtml(str) { 215 | return (str + '').replace(/[<>'"]/g, a => { 216 | switch (a) { 217 | case '<': 218 | return '<'; 219 | case '>': 220 | return '>'; 221 | case '"': 222 | return '"e;'; 223 | case '\'': 224 | return '''; 225 | } 226 | }); 227 | } 228 | exports.escapeHtml = escapeHtml; 229 | 230 | /** 231 | * get datetime 232 | * @param {Date} date [] 233 | * @return {String} [] 234 | */ 235 | function datetime(date = new Date(), format) { 236 | if (date && isString(date)) { 237 | const dateString = date; 238 | date = new Date(Date.parse(date)); 239 | 240 | if (isNaN(date.getTime()) && !format) { 241 | format = dateString; 242 | date = new Date(); 243 | } 244 | } 245 | format = format || 'YYYY-MM-DD HH:mm:ss'; 246 | 247 | const fn = d => { 248 | return ('0' + d).slice(-2); 249 | }; 250 | 251 | const d = new Date(date); 252 | const formats = { 253 | YYYY: d.getFullYear(), 254 | MM: fn(d.getMonth() + 1), 255 | DD: fn(d.getDate()), 256 | HH: fn(d.getHours()), 257 | mm: fn(d.getMinutes()), 258 | ss: fn(d.getSeconds()) 259 | }; 260 | 261 | return format.replace(/([a-z])\1+/ig, a => { 262 | return formats[a] || a; 263 | }); 264 | } 265 | exports.datetime = datetime; 266 | 267 | /** 268 | * generate uuid 269 | * @param {String} version [uuid RFC version] 270 | * @return {String} [] 271 | */ 272 | exports.uuid = function(version) { 273 | if (version === 'v1') return uuid.v1(); 274 | return uuid.v4(); 275 | }; 276 | 277 | /** 278 | * parse adapter config 279 | */ 280 | exports.parseAdapterConfig = (config = {}, ...extConfig) => { 281 | config = exports.extend({}, config); 282 | // {handle: ''} 283 | if (!config.type) config.type = '_'; 284 | // {type: 'xxx', handle: ''} 285 | if (config.handle) { 286 | const type = config.type; 287 | delete config.type; 288 | config = { type, [type]: config }; 289 | } 290 | extConfig = extConfig.map(item => { 291 | if (!item) return {}; 292 | // only change type 293 | // 'xxx' 294 | if (exports.isString(item)) { 295 | item = { type: item }; 296 | } 297 | // {handle: 'www'} 298 | // only add some configs 299 | if (!item.type) { 300 | item = { type: config.type, [config.type]: item }; 301 | } 302 | // {type: 'xxx', handle: 'www'} 303 | if (item.handle) { 304 | const type = item.type; 305 | delete item.type; 306 | item = { type, [type]: item }; 307 | } 308 | return item; 309 | }); 310 | // merge config 311 | config = exports.extend({}, config, ...extConfig); 312 | const value = config[config.type] || {}; 313 | // add type for return value 314 | value.type = config.type; 315 | return value; 316 | }; 317 | /** 318 | * transform humanize time to ms 319 | */ 320 | exports.ms = function(time) { 321 | if (typeof time === 'number') return time; 322 | const result = ms(time); 323 | if (result === undefined) { 324 | throw new Error(`think-ms('${time}') result is undefined`); 325 | } 326 | return result; 327 | }; 328 | 329 | /** 330 | * omit some props in object 331 | */ 332 | exports.omit = function(obj, props) { 333 | if (exports.isString(props)) { 334 | props = props.split(','); 335 | } 336 | const keys = Object.keys(obj); 337 | const result = {}; 338 | keys.forEach(item => { 339 | if (props.indexOf(item) === -1) { 340 | result[item] = obj[item]; 341 | } 342 | }); 343 | return result; 344 | }; 345 | 346 | /** 347 | * check path is exist 348 | */ 349 | function isExist(dir) { 350 | dir = path.normalize(dir); 351 | try { 352 | fs.accessSync(dir, fs.R_OK); 353 | return true; 354 | } catch (e) { 355 | return false; 356 | } 357 | } 358 | 359 | exports.isExist = isExist; 360 | 361 | /** 362 | * check filepath is file 363 | */ 364 | function isFile(filePath) { 365 | if (!isExist(filePath)) return false; 366 | try { 367 | const stat = fs.statSync(filePath); 368 | return stat.isFile(); 369 | } catch (e) { 370 | return false; 371 | } 372 | } 373 | exports.isFile = isFile; 374 | 375 | /** 376 | * check path is directory 377 | */ 378 | function isDirectory(filePath) { 379 | if (!isExist(filePath)) return false; 380 | try { 381 | const stat = fs.statSync(filePath); 382 | return stat.isDirectory(); 383 | } catch (e) { 384 | return false; 385 | } 386 | } 387 | exports.isDirectory = isDirectory; 388 | 389 | /** 390 | * change path mode 391 | * @param {String} p [path] 392 | * @param {String} mode [path mode] 393 | * @return {Boolean} [] 394 | */ 395 | function chmod(p, mode) { 396 | try { 397 | fs.chmodSync(p, mode); 398 | return true; 399 | } catch (e) { 400 | return false; 401 | } 402 | } 403 | exports.chmod = chmod; 404 | 405 | /** 406 | * make dir 407 | */ 408 | function mkdir(dir, mode) { 409 | if (isExist(dir)) { 410 | if (mode) return chmod(dir, mode); 411 | return true; 412 | } 413 | const pp = path.dirname(dir); 414 | if (isExist(pp)) { 415 | try { 416 | fs.mkdirSync(dir, mode); 417 | return true; 418 | } catch (e) { 419 | return false; 420 | } 421 | } 422 | if (mkdir(pp, mode)) return mkdir(dir, mode); 423 | return false; 424 | } 425 | exports.mkdir = mkdir; 426 | 427 | /** 428 | * get files in path 429 | * @param {} dir [] 430 | * @param {} prefix [] 431 | * @return {} [] 432 | */ 433 | function getdirFiles(dir, prefix = '') { 434 | dir = path.normalize(dir); 435 | if (!fs.existsSync(dir)) return []; 436 | const files = fs.readdirSync(dir); 437 | let result = []; 438 | files.forEach(item => { 439 | const currentDir = path.join(dir, item); 440 | const stat = fs.statSync(currentDir); 441 | if (stat.isFile()) { 442 | result.push(path.join(prefix, item)); 443 | } else if (stat.isDirectory()) { 444 | const cFiles = getdirFiles(currentDir, path.join(prefix, item)); 445 | result = result.concat(cFiles); 446 | } 447 | }); 448 | return result; 449 | }; 450 | 451 | exports.getdirFiles = getdirFiles; 452 | 453 | /** 454 | * remove dir aync 455 | * @param {String} p [path] 456 | * @param {Boolean} reserve [] 457 | * @return {Promise} [] 458 | */ 459 | function rmdir(p, reserve) { 460 | if (!isDirectory(p)) return Promise.resolve(); 461 | return fsReaddir(p).then(files => { 462 | const promises = files.map(item => { 463 | const filepath = path.join(p, item); 464 | if (isDirectory(filepath)) return rmdir(filepath, false); 465 | return fsUnlink(filepath); 466 | }); 467 | return Promise.all(promises).then(() => { 468 | if (!reserve) return fsRmdir(p); 469 | }); 470 | }); 471 | } 472 | exports.rmdir = rmdir; 473 | 474 | exports.isBuffer = Buffer.isBuffer; 475 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "think-helper", 3 | "description": "Helper for ThinkJS", 4 | "version": "1.1.4", 5 | "author": { 6 | "name": "songguangyu", 7 | "email": "522963130@qq.com" 8 | }, 9 | "scripts": { 10 | "test": "eslint index.js && nyc ava test/", 11 | "coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov", 12 | "lint": "eslint index.js", 13 | "lint-fix": "eslint --fix index.js" 14 | }, 15 | "ava": { 16 | "require": [ 17 | "babel-core/register" 18 | ] 19 | }, 20 | "contributors": [ 21 | { 22 | "name": "songguangyu", 23 | "email": "522963130@qq.com" 24 | } 25 | ], 26 | "main": "index.js", 27 | "types": "index.d.ts", 28 | "dependencies": { 29 | "core-util-is": "^1.0.2", 30 | "lodash.merge": "^4.6.2", 31 | "ms": "^1.0.0", 32 | "uuid": "^7.0.3" 33 | }, 34 | "devDependencies": { 35 | "ava": "^0.18.0", 36 | "codecov": "^3.7.1", 37 | "coveralls": "^2.11.16", 38 | "eslint": "^4.2.0", 39 | "eslint-config-think": "^1.0.1", 40 | "nyc": "^7.1.0" 41 | }, 42 | "keywords": [], 43 | "repository": { 44 | "type": "git", 45 | "url": "https://github.com/thinkjs/think-helper" 46 | }, 47 | "engines": { 48 | "node": ">=6.0.0" 49 | }, 50 | "readmeFilename": "README.md", 51 | "bugs": { 52 | "url": "https://github.com/thinkjs/think-helper/issues" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import { 3 | isInt, 4 | isFunction, 5 | isExist, 6 | isFile, 7 | isDirectory, 8 | extend, 9 | promisify, 10 | defer, 11 | md5, 12 | mkdir, 13 | rmdir, 14 | chmod, 15 | uuid, 16 | datetime, 17 | escapeHtml, 18 | isEmpty, 19 | isNumberString, 20 | camelCase, 21 | getdirFiles, 22 | isTrueEmpty, 23 | isIP, 24 | timeout, 25 | parseAdapterConfig, 26 | ms, 27 | snakeCase, 28 | isBuffer, 29 | omit 30 | } from '../index.js'; 31 | import fs from 'fs'; 32 | import path from 'path'; 33 | 34 | test('isInt', t => { 35 | t.is(isInt(42), true); 36 | }); 37 | 38 | test('isInt1', t => { 39 | t.is(isInt('42'), false); 40 | }); 41 | 42 | test('isInt2', t => { 43 | t.is(isInt(4e2), true); 44 | }); 45 | 46 | test('isInt3', t => { 47 | t.is(isInt('4e2'), false); 48 | }); 49 | 50 | test('isInt4', t => { 51 | t.is(isInt(' 1 '), false); 52 | }); 53 | 54 | test('isInt5', t => { 55 | t.is(isInt(''), false); 56 | }); 57 | 58 | test('isInt6', t => { 59 | t.is(isInt(' '), false); 60 | }); 61 | 62 | test('isInt7', t => { 63 | t.is(isInt('1a'), false); 64 | }); 65 | 66 | test('isInt8', t => { 67 | t.is(isInt('42e2a'), false); 68 | }); 69 | 70 | test('isInt9', t => { 71 | t.is(isInt(null), false); 72 | }); 73 | 74 | test('isInt10', t => { 75 | t.is(isInt(undefined), false); 76 | }); 77 | 78 | test('isInt11', t => { 79 | t.is(isInt(NaN), false); 80 | }); 81 | 82 | test('isInt12', t => { 83 | t.is(isInt(42.1), false); 84 | }); 85 | 86 | test('isExist', t => { 87 | t.is(isExist('/www/fasdfasfasdfa'), false); 88 | }); 89 | 90 | test('isExist 2', t => { 91 | t.is(isExist(__filename), true); 92 | }); 93 | 94 | test('isExist 3', t => { 95 | t.is(isExist(__dirname), true); 96 | }); 97 | 98 | test('isExist 4', t => { 99 | t.is(isExist('/root'), false); 100 | }); 101 | 102 | test('isFile', t => { 103 | t.is(isFile('/root'), false); 104 | }); 105 | 106 | test('isFile 2', t => { 107 | t.is(isFile(__filename), true); 108 | }); 109 | 110 | test('isDirectory', t => { 111 | t.is(isDirectory(__filename), false); 112 | }); 113 | 114 | test('isDirectory 2', t => { 115 | t.is(isDirectory(__dirname), true); 116 | }); 117 | 118 | test('extend 1', t => { 119 | const data = extend({}, {name: 'test'}); 120 | t.deepEqual(data, {name: 'test'}); 121 | }); 122 | 123 | test('extend 2', t => { 124 | const data = extend({ 125 | name: 'xd' 126 | }, {name: ['1', '2']}); 127 | t.deepEqual(data, {name: ['1', '2']}); 128 | }); 129 | 130 | test('extend 3', t => { 131 | const data = extend({ 132 | name: 'xd' 133 | }, {name: {value: '1'}}); 134 | t.deepEqual(data, {name: {value: '1'}}); 135 | }); 136 | 137 | test('extend 4', t => { 138 | const data = extend({ 139 | name: ['1'] 140 | }, {name: ['2']}); 141 | t.deepEqual(data, {name: ['2']}); 142 | }); 143 | 144 | test('extend 5', t => { 145 | const data = extend({}, {name: 'welefen'}, {name: 'suredy'}); 146 | t.deepEqual(data, {name: 'suredy'}); 147 | }); 148 | 149 | test('extend 6', t => { 150 | const data = extend({}, {name: 'welefen'}, {name2: 'suredy'}); 151 | t.deepEqual(data, {name: 'welefen', name2: 'suredy'}); 152 | }); 153 | 154 | test('extend 7', t => { 155 | const data = extend(null, {name: 'welefen'}, {name2: 'suredy'}); 156 | t.deepEqual(data, {name: 'welefen', name2: 'suredy'}); 157 | }); 158 | 159 | test('extend 8', t => { 160 | const data = extend({}, {name: [4, 5]}); 161 | t.deepEqual(data, {name: [4, 5]}); 162 | }); 163 | 164 | test('extend 9', t => { 165 | const data = extend({}, '', {name: 'sgy'}); 166 | t.deepEqual(data, {name: 'sgy'}); 167 | }); 168 | 169 | test('extend 10', t => { 170 | const data = extend({name: 'sgy'}, {name: 'sgy'}); 171 | t.deepEqual(data, {name: 'sgy'}); 172 | }); 173 | 174 | // test('extend getter', t => { 175 | // let source = { 176 | // get a(){ 177 | // return this.b(); 178 | // }, 179 | // b(){ 180 | // return 1; 181 | // } 182 | // } 183 | // let data = extend({name:'sgy'}, source); 184 | // t.deepEqual(data.a, 1); 185 | // }) 186 | 187 | // test('extend setter', t => { 188 | // let source = { 189 | // get a(){ 190 | // return this.xxx; 191 | // }, 192 | // set a(val){ 193 | // this.xxx = val; 194 | // }, 195 | // b(){ 196 | // return 1; 197 | // } 198 | // } 199 | // let data = extend({name:'sgy'}, source); 200 | // data.a = 222; 201 | // t.deepEqual(data.a, 222); 202 | // t.deepEqual(data.xxx, 222) 203 | // }) 204 | 205 | test('promisify', async(t) => { 206 | const fn = promisify(fs.readFile, fs); 207 | const data = await fn(__filename); 208 | t.is(data.length > 0, true); 209 | }); 210 | 211 | test('promisify 2', async(t) => { 212 | const fn = promisify(fs.readFile, fs); 213 | const data = await fn(path.join(__filename, 'dddd')).catch(() => false); 214 | t.is(data, false); 215 | }); 216 | 217 | test('defer', t => { 218 | const deferred = defer(); 219 | t.is(isFunction(deferred.promise.then), true); 220 | }); 221 | 222 | test('md5', t => { 223 | t.is(md5(''), 'd41d8cd98f00b204e9800998ecf8427e'); 224 | }); 225 | 226 | test('mkdir', t => { 227 | mkdir('welefen22'); 228 | t.is(isDirectory('welefen22'), true); 229 | fs.rmdirSync('welefen22'); 230 | }); 231 | 232 | test('mkdir 2', t => { 233 | mkdir('welefen/suredy/www'); 234 | t.is(isDirectory('welefen/suredy/www'), true); 235 | fs.rmdirSync('welefen/suredy/www'); 236 | fs.rmdirSync('welefen/suredy'); 237 | fs.rmdirSync('welefen'); 238 | }); 239 | 240 | test('mkdir 3', t => { 241 | mkdir('welefen44/suredy/www'); 242 | mkdir('welefen44/suredy/www'); 243 | t.is(isDirectory('welefen44/suredy/www'), true); 244 | fs.rmdirSync('welefen44/suredy/www'); 245 | fs.rmdirSync('welefen44/suredy'); 246 | fs.rmdirSync('welefen44'); 247 | }); 248 | 249 | test('mkdir 4', async(t) => { 250 | mkdir('songguangyu78'); 251 | t.is(mkdir('songguangyu78/smart', '9527'), false); 252 | await rmdir('songguangyu78'); 253 | }); 254 | 255 | test('mkdir 5', async(t) => { 256 | t.is(mkdir('songguangyu79/smart', '9527'), false); 257 | await rmdir('songguangyu79'); 258 | }); 259 | 260 | test('rmdir', async(t) => { 261 | mkdir('songguangyu75'); 262 | t.is(isDirectory('songguangyu75'), true); 263 | await rmdir('songguangyu75'); 264 | t.is(isDirectory('songguangyu75'), false); 265 | }); 266 | 267 | test('rmdir 1', async(t) => { 268 | mkdir('songguangyu76'); 269 | fs.writeFileSync('songguangyu76/abc.js', '123'); 270 | mkdir('songguangyu76/xiaoming'); 271 | t.is(isDirectory('songguangyu76'), true); 272 | await rmdir('songguangyu76'); 273 | t.is(isDirectory('songguangyu76'), false); 274 | }); 275 | 276 | test('rmdir 2', async(t) => { 277 | mkdir('songguangyu77'); 278 | fs.rmdirSync('songguangyu77'); 279 | chmod('songguangyu77'); 280 | await rmdir('songguangyu77'); 281 | }); 282 | 283 | test('uuid', t => { 284 | var uuid1 = uuid('v1'); 285 | t.is(uuid1.length > 1, true); 286 | var uuid2 = uuid(); 287 | t.is(uuid2.length > 1, true); 288 | }); 289 | 290 | test('ms 1200', t => { 291 | var value = ms(1200); 292 | t.is(value, 1200); 293 | }); 294 | test('ms 2 days', t => { 295 | var value = ms('2 days'); 296 | t.is(value, 172800000); 297 | }); 298 | test('ms 1d', t => { 299 | var value = ms('1d'); 300 | t.is(value, 86400000); 301 | }); 302 | test('ms 10h', t => { 303 | var value = ms('10h'); 304 | t.is(value, 36000000); 305 | }); 306 | test('ms 2.5 hrs', t => { 307 | var value = ms('2.5 hrs'); 308 | t.is(value, 9000000); 309 | }); 310 | test('ms 1y', t => { 311 | var value = ms('1y'); 312 | t.is(value, 31557600000); 313 | }); 314 | test('ms 1b', t => { 315 | try { 316 | const value = ms('1b'); 317 | t.is(1, value); 318 | } catch (e) { 319 | t.is(e.toString(), "Error: think-ms('1b') result is undefined"); 320 | } 321 | }); 322 | 323 | test('datetime', t => { 324 | datetime(); 325 | datetime('123'); 326 | }); 327 | 328 | test('datetime 1', t => { 329 | t.plan(4); 330 | const now = new Date(); 331 | t.is(datetime('2017-12-12 10:00:00', 'YYYY-MM-DD'), '2017-12-12'); 332 | t.is(datetime('', 'YYYY-MM-DD'), 'YYYY-aN-aN'); 333 | t.is( 334 | datetime(new Date('2017/10/10'), 'YYYY-MM-DD HH:mm:ss'), 335 | '2017-10-10 00:00:00' 336 | ); 337 | t.is( 338 | datetime('YYYY/MM/DD'), 339 | [ 340 | now.getFullYear(), 341 | ('0' + (now.getMonth() + 1)).slice(-2), 342 | now.getDate() 343 | ].join('/') 344 | ); 345 | }); 346 | 347 | test('escapeHtml', t => { 348 | t.deepEqual(escapeHtml('
'), '<div width='200'></div>'); 349 | }); 350 | test('escapeHtml 1', t => { 351 | t.deepEqual(escapeHtml(('
')), '<div width="e;200"e;></div>'); 352 | }); 353 | test('isEmpty', t => { 354 | t.is(isEmpty({}), true); 355 | t.is(isEmpty(NaN), true); 356 | t.is(isEmpty(1), false); 357 | t.is(isEmpty('sgy'), false); 358 | t.is(isEmpty(false), true); 359 | t.is(isEmpty(null), true); 360 | t.is(isEmpty(undefined), true); 361 | t.is(isEmpty(''), true); 362 | t.is(isEmpty({'a': 1}), false); 363 | var date = new Date(); 364 | t.is(isEmpty(date), false); 365 | var func = function() {}; 366 | t.is(isEmpty(func), false); 367 | t.is(isEmpty([]), true); 368 | t.is(isEmpty(new Error('errror')), false); 369 | t.is(isEmpty(/test/), false); 370 | }); 371 | test('isNumberString', t => { 372 | t.is(isNumberString(''), false); 373 | t.is(isNumberString('111d111'), false); 374 | t.is(isNumberString('111111'), true); 375 | t.is(isNumberString('.1'), true); 376 | t.is(isNumberString('.e1'), false); 377 | t.is(isNumberString('.1e1'), true); 378 | t.is(isNumberString('1.e1'), true); 379 | t.is(isNumberString('e1'), false); 380 | t.is(isNumberString('1e1'), true); 381 | t.is(isNumberString('1.1e1'), true); 382 | t.is(isNumberString('e1499451'), false); 383 | t.is(isNumberString('149e9451'), true); 384 | }); 385 | 386 | test('camelCase', t => { 387 | t.deepEqual(camelCase('index_test'), 'indexTest'); 388 | }); 389 | 390 | test('getdirFiles', t => { 391 | mkdir('songguangyu79'); 392 | mkdir('songguangyu79/songguangyu80'); 393 | fs.writeFileSync('songguangyu79/abc.js', '123'); 394 | fs.writeFileSync('songguangyu79/songguangyu80/abc.js', '123'); 395 | getdirFiles('songguangyu79'); 396 | getdirFiles('songguangyu80'); 397 | rmdir('songguangyu79'); 398 | }); 399 | 400 | test('isTrueEmpty', t => { 401 | t.deepEqual(isTrueEmpty(null), true); 402 | }); 403 | 404 | test('chmod', t => { 405 | mkdir('songguangyu81'); 406 | chmod('songguangyu81', '0777'); 407 | t.is(chmod('songguangyu82', '0777'), false); 408 | rmdir('songguangyu81'); 409 | }); 410 | 411 | test('isIP', t => { 412 | t.deepEqual(isIP('127.0.0.1') === 4, true); 413 | }); 414 | 415 | test('timeout', t => { 416 | timeout(1000).then(() => { 417 | t.pass('success'); 418 | }); 419 | }); 420 | 421 | test('snakeCase', t => { 422 | var value = snakeCase('wwwTest'); 423 | t.deepEqual(value, 'www_test'); 424 | }); 425 | 426 | test('isBuffer', t => { 427 | var value = isBuffer('wwwTest'); 428 | t.deepEqual(value, false); 429 | }); 430 | 431 | test('isBuffer 2', t => { 432 | var value = isBuffer(Buffer.from('test')); 433 | t.deepEqual(value, true); 434 | }); 435 | 436 | test('parseAdapterConfig', t => { 437 | const config = { 438 | type: 'nunjucks', 439 | common: { 440 | viewPath: 'thinkjs', 441 | extname: '.html', 442 | sep: '_' // seperator between controller and action 443 | }, 444 | nunjucks: { 445 | handle: 'nunjucks' 446 | }, 447 | ejs: { 448 | handle: 'ejs' 449 | } 450 | }; 451 | const extConfig = 'ejs'; 452 | const extConfig2 = { 453 | handle: 'ejs' 454 | }; 455 | t.deepEqual(parseAdapterConfig(config).handle, 'nunjucks'); 456 | t.deepEqual(parseAdapterConfig(config, extConfig).handle, 'ejs'); 457 | t.deepEqual(parseAdapterConfig(config, extConfig2).handle, 'ejs'); 458 | }); 459 | 460 | test('parseAdapterConfig 2', t => { 461 | const config = { 462 | type: 'nunjucks', 463 | common: { 464 | viewPath: 'thinkjs', 465 | extname: '.html', 466 | sep: '_' // seperator between controller and action 467 | }, 468 | nunjucks: { 469 | handle: 'nunjucks' 470 | }, 471 | ejs: { 472 | handle: 'ejs' 473 | } 474 | }; 475 | // const extConfig = 'ejs'; 476 | const extConfig2 = { 477 | type: 'ejs', 478 | handle: 'ejs' 479 | }; 480 | t.deepEqual(parseAdapterConfig(config, extConfig2).type, 'ejs'); 481 | }); 482 | 483 | test('parseAdapterConfig 3', t => { 484 | const config = { 485 | type: 'nunjucks', 486 | common: { 487 | viewPath: 'thinkjs', 488 | extname: '.html', 489 | sep: '_' // seperator between controller and action 490 | }, 491 | nunjucks: { 492 | handle: 'nunjucks' 493 | }, 494 | ejs: { 495 | handle: 'ejs' 496 | } 497 | }; 498 | // const extConfig = 'ejs'; 499 | const extConfig2 = { 500 | type: 'ejs', 501 | handle: 'ejs' 502 | }; 503 | const value = parseAdapterConfig(config); 504 | t.deepEqual(parseAdapterConfig(value, extConfig2).type, 'ejs'); 505 | }); 506 | 507 | test('parseAdapterConfig 3', t => { 508 | const value = parseAdapterConfig({}); 509 | t.deepEqual(parseAdapterConfig(value).type, '_'); 510 | }); 511 | 512 | test('parseAdapterConfig 4', t => { 513 | const value = parseAdapterConfig({handle: 'www', value: '222'}); 514 | t.deepEqual(parseAdapterConfig(value).value, '222'); 515 | }); 516 | 517 | test('parseAdapterConfig 5', t => { 518 | const value = parseAdapterConfig({ 519 | type: 'www', 520 | www: { 521 | handle: 'www', value: '222' 522 | }, 523 | aaa: { 524 | value: 333 525 | } 526 | }, 'test', 'aaa'); 527 | t.deepEqual(value.value, 333); 528 | }); 529 | 530 | test('parseAdapterConfig 6', t => { 531 | const value = parseAdapterConfig({ 532 | type: 'www', 533 | www: { 534 | handle: 'www', value: '222' 535 | }, 536 | aaa: { 537 | value: 333 538 | } 539 | }, 'test', {timeout: 20}); 540 | t.deepEqual(value.timeout, 20); 541 | }); 542 | 543 | test('omit 1', t => { 544 | const value = omit({ 545 | a: 1, 546 | b: 2 547 | }, 'test'); 548 | t.deepEqual(value, {a: 1, b: 2}); 549 | }); 550 | 551 | test('omit 1', t => { 552 | const value = omit({ 553 | a: 1, 554 | b: 2 555 | }, 'a'); 556 | t.deepEqual(value, {b: 2}); 557 | }); 558 | 559 | test('omit 2', t => { 560 | const value = omit({ 561 | a: 1, 562 | b: 2 563 | }, 'a,b'); 564 | t.deepEqual(value, {}); 565 | }); 566 | 567 | test('omit 3', t => { 568 | const value = omit({ 569 | a: 1, 570 | b: 2 571 | }, ['a', 'b']); 572 | t.deepEqual(value, {}); 573 | }); 574 | --------------------------------------------------------------------------------