nodejs-shared
v2.0.1
Published
Batteries-included Node.js utility belt for files, images, validation, and more.
Maintainers
Readme
nodejs-shared
Batteries-included Node.js utility belt for files, images, validation, and more.
Install
npm install nodejs-sharedAPI
Browser
Parses user agent strings to extract browser, OS, and platform info.
| Method | Description |
|--------|-------------|
| parse(ua) | Parses a UA string. Returns {platform, osName, osVersion, browserName} or null for bots/unknown. |
import {Browser} from 'nodejs-shared';
// Mobile browser
const mobile = Browser.parse(
'Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36'
);
// {platform: 'mobile', osName: 'Android', osVersion: 13, browserName: 'Chrome'}
// Desktop browser
const desktop = Browser.parse(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
);
// {platform: 'desktop', osName: 'Windows', osVersion: 10, browserName: 'Chrome'}
// Bot or unknown UA → null
Browser.parse('Googlebot/2.1'); // nullFileUtils
File system operations: read, write, copy, delete, permissions, and more.
| Method | Description |
|--------|-------------|
| basename(filePath, withExtension?) | Extracts the file name from a path. withExtension: include extension in result (default false). |
| changePermission(filePath, mode?) | Changes file permissions (default 0o755). |
| changeOwner(filePath, username, groupName?) | Changes owner and/or group. |
| copy(source, destination) | Copies a file or directory recursively. |
| deleteDirectory(dirPath) | Deletes a directory and all contents. |
| deleteFile(filePath) | Deletes a file. No-op if it doesn't exist. |
| exists(filePath) | Checks if a file or directory exists. |
| getExtension(filePath) | Returns the file extension without the dot. |
| getFilemtime(filePath) | Returns last modification time as Unix timestamp. |
| getTmpDirectory() | Returns the system temp directory path. |
| getTmpPath(extension?) | Generates a unique temp file path with the given extension. |
| glob(pattern, options?) | Finds files matching a glob pattern. cwd: base directory. ignore: patterns to exclude. |
| isBase64(str) | Checks if a string is valid base64. |
| isDirectory(path) | Checks if a path is a directory. |
| isFile(path) | Checks if a path is a file. |
| isPath(str) | Checks if a string is a valid file system path (format only, not existence). |
| makeDirectory(dirPath, options?) | Creates a directory recursively. mode: permissions (default 0o755). owner: {username, groupName}. |
| makeTmpDirectory(options?) | Creates a unique temp directory. Same options as makeDirectory. |
| readAsBase64(filePath) | Reads a file as a base64 string. |
| readAsDataUrl(filePath) | Reads a file as a data URL string (MIME type auto-detected). |
| readAsJson(filePath) | Reads and parses a JSON file. |
| readAsString(filePath) | Reads a file as a UTF-8 string. |
| rename(source, destination) | Renames (moves) a file or directory. |
| write(filePath, content?, options?) | Writes content to a file. Creates parent dirs automatically. mode: permissions (default 0o755). owner: {username, groupName}. |
import {FileUtils} from 'nodejs-shared';
// File name extraction
FileUtils.basename('/home/user/report.pdf'); // 'report'
FileUtils.basename('/home/user/report.pdf', true); // 'report.pdf'
// Read files in various formats
const config = FileUtils.readAsJson('/etc/app/config.json');
const text = FileUtils.readAsString('/etc/hosts');
const base64 = FileUtils.readAsBase64('/uploads/photo.jpg');
const dataUrl = FileUtils.readAsDataUrl('/uploads/photo.png');
// 'data:image/png;base64,iVBORw0KGgo...'
// Write with file permissions and ownership
FileUtils.write('/var/log/app.log', 'started', {
mode: 0o644,
owner: {username: 'nginx', groupName: 'nginx'},
});
// Create directory with permissions and ownership
FileUtils.makeDirectory('/var/www/uploads', {
mode: 0o755,
owner: {username: 'nginx', groupName: 'nginx'},
});
// Find files by glob pattern
const images = FileUtils.glob('/uploads/**/*.{jpg,png}');
// Search relative to a base directory
FileUtils.glob('**/*.txt', {cwd: '/var/data'});
// Exclude specific patterns
FileUtils.glob('/uploads/**/*', {ignore: ['/uploads/tmp/**']});
// Generate a unique temp file path
const tmpPath = FileUtils.getTmpPath('jpg'); // '/tmp/a1b2c3d4.jpg'ImageUtils
Image manipulation powered by Sharp and ImageMagick.
| Method | Description |
|--------|-------------|
| cropImage(input, output, options) | Crops a rectangular region. left, top, width, height in pixels. Negative offsets are clamped to 0. |
| mergeImages(inputs, output, options?) | Merges multiple images. direction: 'vertical'/'horizontal' (default 'vertical'). color: canvas background (default black). align: 'start'/'center'/'end' (default 'start'). offset: spacing in px between images (default 0). margin: number, CSS shorthand string, or {top, right, bottom, left} object (default 0). |
| resizeImage(input, options?) | Resizes an image. width, height: target size. output: save path (omit to overwrite original). contain: fit within bounds instead of cropping (default false, crops to cover). |
| getGifFrameCount(input) | Returns the number of frames in a GIF. Accepts file path or data URL. |
| extractFirstGifFrame(input, output?) | Extracts the first frame of an animated GIF. Accepts file path or data URL. |
| getImageDimensions(filePath) | Returns {width, height} or null. |
| convertImageFormat(input, output?, options?) | Converts between formats (JPEG, PNG, BMP, etc.) via ImageMagick. Accepts file path or data URL. margin: border size in pixels. background: border color (default 'white'). bmpVersion: 'bmp2'/'bmp3'/'bmp4' (default 'bmp3'). trueColor: use TrueColor for BMP (default true). Returns data URL. |
import {ImageUtils} from 'nodejs-shared';
// Crop a 200x200 region starting at (100, 50)
await ImageUtils.cropImage('photo.jpg', 'cropped.jpg', {
left: 100, top: 50, width: 200, height: 200,
});
// Merge side by side, centered vertically, 10px gap between images
await ImageUtils.mergeImages(
['left.png', 'right.png'],
'combined.png',
{direction: 'horizontal', align: 'center', offset: 10},
);
// Stack vertically with white background and margin
await ImageUtils.mergeImages(
['header.png', 'body.png', 'footer.png'],
'stacked.png',
{
direction: 'vertical',
color: 'white', // canvas background color
margin: '20 30', // CSS shorthand: top/bottom 20px, left/right 30px
// margin: 10, // uniform 10px on all sides
// margin: {top: 5, right: 10, bottom: 15, left: 20}, // per-side
},
);
// Resize to width (height auto-calculated to keep aspect ratio)
await ImageUtils.resizeImage('photo.jpg', {width: 800, output: 'thumb.jpg'});
// Fit within 400x300 without cropping (letterboxed)
await ImageUtils.resizeImage('photo.jpg', {
width: 400, height: 300, contain: true, output: 'fitted.jpg',
});
// Omit output to overwrite original file
await ImageUtils.resizeImage('photo.jpg', {width: 800});
// GIF frame count (accepts file path or data URL)
const frames = await ImageUtils.getGifFrameCount('animation.gif'); // 35
// Extract first frame from animated GIF
await ImageUtils.extractFirstGifFrame('animation.gif', 'first-frame.jpg');
// Get image dimensions
ImageUtils.getImageDimensions('photo.jpg'); // {width: 1920, height: 1080}
// Convert format (returns data URL of the converted image)
const dataUrl = await ImageUtils.convertImageFormat('photo.jpg', 'photo.png');
// Convert with 10px black border around the image
await ImageUtils.convertImageFormat('photo.jpg', 'photo.bmp', {
margin: 10, background: 'black',
});MediaUtils
Data URL handling and image file writing.
| Method | Description |
|--------|-------------|
| isDataUrl(str) | Checks if a string is a valid base64 data URL. |
| parseDataUrl(str) | Extracts mimeType, base64, extension, and bytesize from a data URL. Returns null if invalid. |
| writeImage(path, data, options?) | Writes an image from a data URL, Buffer, or SVG string. mode: file permissions (default 0o755). owner: {username, groupName}. |
import {MediaUtils} from 'nodejs-shared';
// Validate data URL format
MediaUtils.isDataUrl('data:image/png;base64,iVBORw0KGgo='); // true
MediaUtils.isDataUrl('https://example.com/image.png'); // false
// Parse data URL into components
const parts = MediaUtils.parseDataUrl('data:image/jpeg;base64,/9j/4AAQ...');
// {mimeType: 'image/jpeg', base64: '/9j/4AAQ...', extension: 'jpg', bytesize: 45056}
// Write image from data URL (base64 decoded automatically)
MediaUtils.writeImage('/uploads/photo.jpg', 'data:image/jpeg;base64,...');
// Write image from Buffer
MediaUtils.writeImage('/uploads/photo.png', buffer);
// Write raw SVG string directly
MediaUtils.writeImage('/uploads/icon.svg', '<svg>...</svg>');
// Write with file permissions and ownership
MediaUtils.writeImage('/uploads/photo.png', buffer, {
mode: 0o644,
owner: {username: 'nginx', groupName: 'nginx'},
});ProcessUtils
System user and group lookup (Unix/Linux).
| Method | Description |
|--------|-------------|
| getUid(username) | Returns the UID for a username. |
| getGid(groupName) | Returns the GID for a group name. |
import {ProcessUtils} from 'nodejs-shared';
ProcessUtils.getUid('www-data'); // 33
ProcessUtils.getGid('www-data'); // 33Reflect
Reflection utilities for inspecting class methods.
| Method | Description |
|--------|-------------|
| getStaticMethods(clazz) | Returns a Set<string> of static method names. |
| getMethods(instance) | Returns a Set<string> of instance method names. |
import {Reflect} from 'nodejs-shared';
class UserService {
static create(name) { /* ... */ }
static findById(id) { /* ... */ }
save() { /* ... */ }
delete() { /* ... */ }
}
Reflect.getStaticMethods(UserService); // Set {'create', 'findById'}
Reflect.getMethods(new UserService()); // Set {'constructor', 'save', 'delete'}Regex
Regular expression utilities.
| Method | Description |
|--------|-------------|
| escape(str, replace?) | Escapes RegExp special characters. replace: {char: replacement} map to customize escaping per character. |
import {Regex} from 'nodejs-shared';
// Escape special chars for safe use in new RegExp()
Regex.escape('price: $9.99 (USD)');
// 'price: \\$9\\.99 \\(USD\\)'
// Custom replacements: '.' → character class, '*' → wildcard
Regex.escape('file.*.txt', {'.': '[.]', '*': '.*'});
// 'file[.].*[.]txt'Validators
30 validation functions wrapping validator.js. All follow the pattern (value, options?) => boolean.
import {validators} from 'nodejs-shared';
// Basic usage
validators.isEmail('[email protected]'); // true
validators.isURL('https://example.com'); // true
validators.isIP('192.168.1.1'); // true
validators.isJSON('{"key": "value"}'); // true
// Range / bounds
validators.isInt('42', {min: 1, max: 100}); // true
validators.isFloat('3.14', {gt: 0, lt: 10}); // true
// Date format
validators.isDate('15-03-2025', {format: 'DD-MM-YYYY'}); // true
// Whitespace-only string → empty
validators.isEmpty(' ', {ignoreWhitespace: true}); // true
// Allow spaces in alpha check
validators.isAlpha('hello world', {ignore: ' '}); // true
// Must have a decimal point
validators.isDecimal('3.50', {forceDecimal: true}); // true
// Reject +, -, . symbols
validators.isNumeric('+123', {noSymbols: true}); // false
// Accept "yes"/"no"/"1"/"0" as boolean
validators.isBoolean('yes', {loose: true}); // true
// "Name <addr>" format
validators.isEmail('"User" <[email protected]>', {allowDisplayName: true}); // true
// Allow # fragment in URL
validators.isURL('https://example.com#section', {allowFragments: true}); // true
// UUID v4 only
validators.isUUID('550e8400-e29b-41d4-a716-446655440000', 4); // true
// Accept bare strings/numbers as valid JSON
validators.isJSON('"hello"', {allowPrimitives: true}); // true
// CIDR notation (192.168.1.0/24)
validators.isIP('192.168.1.0/24', {version: 4, allowRange: true}); // true| Validator | Description |
|-----------|-------------|
| isAfter(value, date?) | Date is after the comparison date (default: now). |
| isAlpha(value, options?) | Contains only letters. ignore: chars/regex to skip. |
| isAlphanumeric(value, options?) | Contains only letters and numbers. ignore: chars/regex to skip. |
| isBefore(value, date?) | Date is before the comparison date (default: now). |
| isBoolean(value, options?) | Is a boolean string. loose: also accept 'yes'/'no', '0'/'1'. |
| isDataURI(value) | Is a valid data URI. |
| isDate(value, options?) | Is a valid date. format (default 'YYYY/MM/DD'), strictMode, delimiters. |
| isDecimal(value, options?) | Is a decimal number. forceDecimal: require decimal point. decimalDigits: allowed digits (e.g. '1,3'). |
| isEmail(value, options?) | Is a valid email. allowDisplayName, requireDisplayName, allowUtf8LocalPart, requireTld, hostBlacklist, hostWhitelist. |
| isEmpty(value, options?) | Is empty (null, undefined, NaN, [], false, ''). ignoreWhitespace: treat whitespace-only as empty. |
| isFQDN(value, options?) | Is a fully qualified domain name. requireTld, allowWildcard. |
| isFQDNorIP(value, options?) | Is an FQDN or IP address. requireTld, allowWildcard (FQDN), version, allowRange (IP). |
| isFloat(value, options?) | Is a float. min, max, gt, lt. |
| isHash(value, algorithm) | Is a hash. algorithm: 'md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', etc. |
| isHexadecimal(value) | Is a hexadecimal value. |
| isHexColor(value) | Is a hex color code. |
| isHSL(value) | Is an HSL color. |
| isIn(value, values) | Is in the specified array, string, or object. |
| isInt(value, options?) | Is an integer. min, max, gt, lt, allowLeadingZeroes. |
| isIP(value, options?) | Is an IP address. version (4/6), allowRange (CIDR). |
| isJSON(value, options?) | Is valid JSON. allowPrimitives: accept "true", "123", etc. |
| isJWT(value) | Is a valid JWT. |
| isLength(value, options?) | String length is within bounds. min (default 0), max. |
| isLowercase(value) | Is all lowercase. |
| isNumeric(value, options?) | Contains only numbers. noSymbols: disallow +, -, .. |
| isPort(value) | Is a valid port number (0-65535). |
| isRGBColor(value, options?) | Is an RGB/RGBA color. includePercentValues: allow rgb(100%,0%,0%). |
| isUppercase(value) | Is all uppercase. |
| isURL(value, options?) | Is a valid URL. requireTld, allowWildcard, allowFragments, allowQueryComponents. |
| isUUID(value, version?) | Is a valid UUID. version: 1|2|3|4|5|'all' (default 'all'). |
Requirements
- Node.js 18+
- ImageMagick — required by
ImageUtilsfor GIF frame operations and format conversion
Testing
npm testChangelog
See CHANGELOG.md for all release notes.
Author
shumatsumonobu GitHub / X / Facebook
