Arrow keys: ← previous · → next 31 of 35
@nodedk/tools
0.4.4 stable

tools#

File, process, string, and object utilities, with a selected Lodash build.

Install#

npm i @nodedk/tools

Usage#

var tools = require('@nodedk/tools')

async function main() {
  var config = await tools.read('./config.json')
  var files = await tools.tree('./app')

  console.log(tools.get(config, 'server.port', 3000))
  console.log(files)
  console.log(tools.slug('Hello, world!'))
}

main().catch(console.error)

Functions are synchronous unless described as returning a Promise.

Files and paths#

Paths passed to file helpers are resolved with resolve(). Methods that write or append resolve without a value.

  • resolve(...parts): joins path parts and returns an absolute path. A leading ~ expands to the home directory; @ expands to the current directory.
  • basext(file): returns [base, extension, filename]; the extension has no dot.
  • exist(file): Promise of whether stat succeeds.
  • isDir(file), isFile(file): Promises of directory/file checks; false on stat errors. Follow symbolic links.
  • isSymlink(file): Promise of a symbolic-link check using lstat.
  • read(file, encoding): Promise of file contents or a loaded module. With no encoding, .js, .json, .mjs, .cjs, .wasm, and .node use require(), .yml uses yaml.load, and other files return UTF-8 text. Pass 'utf8' to read source text instead of loading a module. Module caching and runtime module-format support apply.
  • write(file, content): creates parent directories and overwrites the file. Objects/arrays are serialized for .json and .yml; other content is passed to fs.writeFile. Directory creation uses a shell command, so use trusted paths without shell metacharacters.
  • append(file, content): appends text or bytes; does not create parent directories.
  • edit(file, fn): reads UTF-8 text, calls synchronous fn(text), then writes its result. A falsy result writes an empty string.
  • dir(file): Promise of entry names, or an Error object if reading fails.
  • walk(directory, fn): recursively calls fn(file, parentDirectory) for files. Returns a Promise after traversal; callback Promises are not awaited.
  • tree(root): Promise of an array of absolute file paths; [] for a missing root.
  • env(file, mode): Promise of configuration loaded from file, merged with name.<mode>.ext when present. Nested objects merge; arrays concatenate. Missing files contribute {}.
var tools = require('@nodedk/tools')

async function main() {
  var config = await tools.env('./config.json', 'production')
  await tools.write('./data/config.json', config)
  await tools.append('./data/events.log', 'Started\n')
  await tools.edit('./data/events.log', function (text) {
    return text.replace('Started', 'Ready')
  })

  await tools.walk('./data', function (file, directory) {
    console.log(directory, file)
  })
}

main().catch(console.error)

Commands and terminal input#

These helpers execute local commands. run, cap, and pass return Promises of combined, trimmed stdout and stderr. A nonzero command exit still resolves; the result does not include an exit code.

  • run(command = '', options = {}): executes a command and prints its output. Options: shell (default true), stdio (default 'pipe'), and quiet (default false). Keep stdout and stderr piped so output can be collected.
  • cap(command = '', options = {}): sets options.quiet = true, then calls run.
  • pass(command = '', options = {}): inherits stdin, pipes output, and calls run. Updates options.stdio in place.
  • ask(prompt = '> ', options = {}): Promise of one input line. Options are passed to readline.createInterface, overriding stdin/stdout defaults.
  • key(fn): enables raw terminal input and adds a keypress listener fn(text, key). Returns no value; requires a TTY and leaves raw mode enabled.
  • print(value): replaces the current terminal line, without a newline. Objects are JSON-stringified. Returns no value.
  • exit(message, code = 0): optionally logs a message, then exits the process.
  • sleep(seconds = 1): Promise that resolves after the delay.
var tools = require('@nodedk/tools')

async function main() {
  var version = await tools.cap('node --version')
  var name = await tools.ask('Name: ')
  tools.print(tools.format('%s uses %s', name, version))
  await tools.sleep(1)
}

main().catch(console.error)

IDs and hashes#

  • uuid(): UUID version 4 string, supplied by uuid.v4. Also accepts that function’s options, output buffer, and byte offset arguments.
  • cuid(): CUID2 string, supplied by createId().
  • hex(size = 20): random hexadecimal string of size characters.
  • md5(value): hexadecimal MD5 digest of a string or supported byte input.
  • hash(value, saltRounds = 10): Promise of a bcrypt hash; coerces input to a string.
  • compare(plain, hash): Promise of a bcrypt match boolean; coerces both to strings.
var tools = require('@nodedk/tools')

async function main() {
  var hash = await tools.hash('example-password')
  console.log(await tools.compare('example-password', hash))
  console.log(tools.uuid(), tools.cuid(), tools.hex(32))
}

main().catch(console.error)

Type checks and conversion#

Every check below takes one value and returns a boolean.

  • isEmail(value): simple non-whitespace name@domain.suffix pattern.
  • isId(value): at least 24 lowercase letters or digits.
  • isURL(value): matches an HTTP(S) or www. address within the string.
  • isDateString(value): matches the library’s timestamp pattern; this is a format check, not full calendar validation.
  • isDateObject(value): Lodash Date-object check, including invalid Dates.
  • isDate(value): accepts a Date object or a matching date string.
  • isRegExpString(value): matches %r/pattern/flags, with i and g flags.
  • isRegExpObject(value): Lodash RegExp-object check.
  • isRegExp(value): accepts a RegExp object or encoded regex string.
  • isBool(value): boolean conversion. The strings 'false', 'null', 'NaN', 'undefined', and '0' become false; all others use !!value.

type(value) returns the lowercase object-tag name, such as 'array', 'date', 'null', or 'undefined'.

convert(value, type) supports 'string' and 'id' via String, 'integer' via parseInt, 'float' via parseFloat, 'date' via new Date, and 'boolean' via isBool. Unknown types pass through unchanged.

unstring(value, options = {}) recursively restores encoded RegExps and parseable timestamp strings. Objects/arrays are updated in place; a primitive returns its converted value. options is currently unused. Timestamp 0 is not converted because the parser result is tested for truthiness.

tools.convert('42', 'integer') // 42
tools.isBool('false') // false
tools.unstring({ pattern: '%r/hello/i', at: '2026-09-11T10:00:00Z' })

Strings and display#

  • format(template, ...values): replaces one %s per value, in order. Arrays join with ', '; plain objects become 'key: value' pairs.
  • strip(text, separator = '\n'): trims each segment and rejoins with the separator.
  • slug(value): lowercases, transliterates common accented characters, replaces separators with hyphens, and removes unsupported characters.
  • shorten(name, max = 20): trims and collapses whitespace. When longer than max, abbreviates every word except the last to an initial. max is a trigger, not a guaranteed output length.
  • json(value): JSON.stringify(value, null, 2).
  • colorize(): random pale HSL color string.
  • inspect(value, options = {}): deep-clones the value, returns util.inspect output, and prints it unless quiet is true. Inspection options are forwarded to util.inspect. exclude sets listed object paths to null in the clone; the current implementation replaces the options variable while processing exclusions, so do not combine it with other options.
tools.format('Members: %s', ['Ada', 'Kim']) // 'Members: Ada, Kim'
tools.strip('  one  \n  two  ') // 'one\ntwo'
tools.shorten('Ada Augusta Lovelace', 15) // 'A. A. Lovelace'
var text = tools.inspect({ name: 'Ada' }, { quiet: true, depth: null })

Objects and arrays#

  • deepTrim(object, characters = ''): trims the selected characters from every nested string in place; returns no value. The default empty character set leaves strings unchanged. Pass ' ' to trim spaces.
  • dot(object, separator = '.'): returns flattened paths for nested plain objects. Arrays remain leaf values.
  • undot(object, separator = '.'): rebuilds nested values using Lodash set. separator joins nested source keys; Lodash still interprets dots/brackets in the resulting paths.
  • clean(data, ...types): removes nullish leaf values by default, or leaf values matching type() names when provided. Mutates and returns data. Arrays are spliced during traversal; adjacent removable elements can be skipped.
  • traverse(object, fn, path = []): awaits fn(key, value, parent, path) for each leaf. path describes the parent; append key for the full leaf path. Adds a non-enumerable _parent reference to nested objects. Resolves without a value.
  • sortByNumber(array, comparator): sorts in place and returns the array. Defaults to comparing leading numbers in strings. Pass a standard (a, b) => number comparator to override it.
var data = { user: { name: ' Ada ' }, roles: ['editor'] }
tools.deepTrim(data, ' ')
var flat = tools.dot(data)
// { 'user.name': 'Ada', roles: ['editor'] }
var nested = tools.undot(flat)

await tools.traverse(nested, function (key, value, parent, path) {
  console.log(path.concat(key), value)
})

Lodash functions#

The selected Lodash build is available as tools.lodash and copied onto tools. Root isDate and isRegExp are the extended checks above; use tools.lodash.isDate and tools.lodash.isRegExp for object-only checks.

  • cloneDeep(value): recursively clones a value.
  • get(object, path, defaultValue): reads a dot/bracket path or path array.
  • set(object, path, value): writes a path in place and returns the object.
  • pick(object, ...paths), omit(object, ...paths): return selected or excluded properties; paths may be arrays.
  • merge(object, ...sources): recursively merges into the first object and returns it; arrays merge by index.
  • mergeWith(object, ...sources, customizer): merges with customizer(objectValue, sourceValue, key, object, source, stack). Returning undefined uses the default merge behavior.
  • sortBy(collection, ...iteratees): returns values in stable ascending order. Iteratees may be property paths, functions, or supported Lodash shorthands.
  • transform(object, iteratee, accumulator): builds and returns an accumulator; iteratee(accumulator, value, key, object) may return false to stop. An omitted accumulator uses a matching empty container.
  • trim(string = '', characters): trims whitespace by default or selected characters when supplied.
  • isArray, isBoolean, isEmpty, isFunction, isInteger, isNil, isNumber, isPlainObject, isString, isUndefined: single-value Lodash predicates. isNil accepts null/undefined; isNumber includes NaN and boxed numbers; isEmpty checks collection contents rather than truthiness.

The build also exposes these Lodash helpers:

  • constant(value): returns a function that always returns value.
  • identity(value): returns its argument.
  • property(path): returns a function that reads the path from an object.
  • iteratee(value): creates a callback from a function, property path, [path, expectedValue], or object matcher.
  • flatten(array): flattens one array level.
  • last(array): returns the final item or undefined.
  • keys(object), keysIn(object): enumerable string keys, own-only or also inherited.
  • hasIn(object, path): checks a path, including inherited properties.
  • toPlainObject(value): copies enumerable own and inherited properties.
  • memoize(fn, resolver): caches function results. The optional resolver receives the same arguments and chooses a cache key; otherwise the first argument is the key. The returned function exposes .cache.
  • eq(value, other): SameValueZero equality, including NaN equal to NaN.
  • toNumber(value), toFinite(value), toInteger(value), toString(value): Lodash conversions to the named type. Finite/integer conversion maps NaN to 0 and bounds infinities; string conversion maps nullish values to ''.
  • isArguments, isArrayLike, isArrayLikeObject, isBuffer, isLength, isMap, isObject, isObjectLike, isSet, isSymbol, isTypedArray: single-value Lodash predicates. Array-like values have a valid .length and are not functions; the object variant also requires an object.
  • stubArray(), stubFalse(): return a fresh [] or false.
  • _: reference to the custom Lodash export.

Other exports#

  • mode: NODE_ENV captured when the module loads.
  • NODE_EXTENSIONS: ['js', 'json', 'mjs', 'cjs', 'wasm', 'node'].
  • regexp: regular expressions named email, id, reg, date, url, slug, ip, image, domain, and subdomain. Use .test(value) for a match.
  • yaml: the js-yaml module, including load(source, options) and dump(value, options).
  • lazy(moduleName): returns a proxy that loads a module on its first call or property access. Calls forward arguments and this to the module’s exported function. Resolution is based on the working directory captured when tools loads.
var tools = require('@nodedk/tools')
var path = tools.lazy('node:path')
console.log(path.basename('/app/index.js'))

Development#

Rebuild the selected Lodash functions listed in scripts/build.js:

npm run build

The generated file is lib/lodash.js.

Created by Vidar Eldøy