@dooboostore/core-node

NPM versionBuild and TestLicense: MIT

A comprehensive Node.js-specific utility library extending@dooboostore/corewith file system operations, process management, memory profiling, and batch HTTP downloading capabilities. Perfect for backend services, CLI tools, SSR applications, and DevOps workflows.


✨ Key Features

  • 📁 Rich File System Operations:FileUtils.File<E>class with copy/move/delete/rename operations plus promise/sync read/write helpers—no raw fs callbacks
  • 📄 Buffer & Data Conversion: String ↔ Buffer conversions with Base64 support (data URLs compatible)
  • 🌐 Batch URL Processing:HttpPageDownloaderfor SSR to static HTML generation (pre-rendering workflows)
  • ⚙️ Process & Environment Access: PID, platform, architecture, environment variables, CLI argv
  • 💾 Memory Profiling & Monitoring: Heap snapshots, memory usage tracking, SIGUSR2 debugging signal handler
  • 🛣️ Path Operations: Thin, typed wrapper around Node.js'spathmodule
  • 🔌 Node.js Built-ins Only: Implemented on top offs/path/process/v8/os— no third-party runtime deps
  • 🎯 TypeScript Support: Full TypeScript definitions with generics and advanced types
  • 📦 Entry Points: import everything from the package root; the only otherexportsentry is./bundle-entry

Installation

@dooboostore/core-nodedepends on@dooboostore/core(installed automatically) and peer-depends onreflect-metadata:

# pnpm (recommended)pnpm add @dooboostore/core-node reflect-metadata# npmnpm install @dooboostore/core-node reflect-metadata# yarnyarn add @dooboostore/core-node reflect-metadata

📚 Module Organization

@dooboostore/core-nodeincludes6 focused modules:

ModulePurposeKey Exports
fileFile system operationsFileUtils,FileUtils.File<E>class
fetchHTTP page downloadingHttpPageDownloader
processProcess informationProcessUtils(PID, platform, env)
memoryMemory profilingMemoryUtils(heap snapshots, monitoring)
pathPath operationsPathUtils(join, resolve, normalize)
convertData conversionConvertUtils(Buffer ↔ String, Base64)

🎯 Core Modules Deep Dive

1️⃣File System Operations(FileUtils)

File system helpers plus an object-orientedFileUtils.File<E>class (a namespace member, not a top-level export).

File Class

// FileUtils.FileclassFile<E =any> {constructor(data: { path:string; originalName?:string; etcData?: E })// Note: the constructor calls updateStats() without awaiting it, so `size` is filled asynchronously.// Call `await file.updateStats()` before reading `size` on a freshly constructed File.// Propertiesgetpath():string// Full file pathgetfileName():string// Just the filename (substring after the last '/')getdirectory():string// Directory path (substring before the last '/')getextension():string|undefined// Text after the last '.' (undefined only if the path ends in '.')getoriginalName():string|undefined// Original filename passed in when constructedsize:number|undefined// File size in bytes (populated by updateStats())etcData: E// Generic metadata// MethodsasyncupdateStats():Promise<void>// Refresh file statsasyncdelete():Promise<void>// Delete the fileasynccopy(newPath:string):Promise<void>// Copy to newPath; this File then points at the copyasyncmove(newPath:string):Promise<void>// Move to newPath (a full path incl. file name; creates dirs if needed)asyncrename(newName:string):Promise<void>// Rename within the same directory}

FileUtils Namespace

PathParamTypeaccepted throughout isstring | string[]— an array is joined viapath.join(...).

// Write a Buffer to a file (auto-generates an OS temp path if config.path is omitted)writeFile<E =any>(buffer:Buffer,config?: {path?:string// defaults to `${os.tmpdir()}/${uuid4()}_${Date.now()}`originalName?:string// original filename, stored as File.originalNameetcData?: E// generic metadata, stored as File.etcData}):Promise<File<E>>// ReadreadSync(path:PathParamType,config?: {option?: fs.readFileSync2nd arg }):BufferreadAsync(path:PathParamType,config?: {option?: fs.promises.readFile2nd arg }):Promise<Buffer>read(path:PathParamType,config: {option: fs.readFile2nd arg }):Promise<Buffer>// callback-style fs.readFile, promisified by returnreadJsonSync<T =any>(path:PathParamType): T
readJsonAsync<T =any>(path:PathParamType):Promise<T>readStringSync(path:PathParamType):string// reads as 'utf-8'readStringAsync(path:PathParamType):Promise<string>// reads as 'utf-8'// Writewrite(data:string|Buffer,config: {path:PathParamType,options?: fs.WriteFileOptions}):string// returns the resolved pathwriteAppend(data:string|Buffer,config: {path:PathParamType,options?: fs.WriteFileOptions}):string// DeletedeleteSync(path:PathParamType,config?: {options?: fs.RmOptions}):void// fs.rmSync, only if it existsdeleteDirSync(path:PathParamType,config?: {options?: fs.RmDirOptions}):void// fs.rmdirSync, only if it existsdeleteFileSync(path:PathParamType):void// fs.unlinkSync, only if it exists// CopycopySync(source:PathParamType,destination:PathParamType,options?: fs.cpSync3rd arg):void// Directory operationsmkdirSync(path:PathParamType,config?:MakeDirectoryOptions):voidmkdir(path:PathParamType,config?:MakeDirectoryOptions):Promise<string>// Note: the callback keys are spelled `existes`/`noExistes` (typo preserved from the source), not `exists`/`noExists`existsSync(path:PathParamType,config?: {existes?:(path:string) =>void,noExistes?:(path:string) =>void}):boolean// Path handlingpath(pathParam:PathParamType):string// joins an array with path.join(...), or returns the string as-is

Example: File Upload Handler

import{FileUtils}from'@dooboostore/core-node';interfaceUploadMetadata{userId:string;uploadedAt:Date;mimeType?:string;
}asyncfunctionhandleFileUpload(buffer:Buffer,metadata:UploadMetadata) {// Save file with metadataconstfile =awaitFileUtils.writeFile<UploadMetadata>(buffer, {path:'./uploads/user-files/document.pdf',originalName:'my-document.pdf',etcData: metadata
  });awaitfile.updateStats();// size is filled asynchronously by the constructorconsole.log(`File saved:${file.path}`);console.log(`Size:${file.size}bytes`);console.log(`User ID:${file.etcData?.userId}`);// Rename after processing (in ./uploads/user-files)awaitfile.rename('document-processed.pdf');// Copy to backup — note: `file` now points at the backup copyawaitfile.copy('./backups/document-processed.pdf');returnfile;
}

2️⃣HTTP Page Downloading(fetch module)

Batch download HTML pages from a running server for SSR pre-rendering workflows.

HttpPageDownloader Class

classHttpPageDownloader{constructor(baseUrl:string,// e.g., 'http://localhost:3000'httpFetcher:HttpFetcher=newHttpFetcher()// Optional custom fetcher)// Methodsasyncdownload(route:string):Promise<string>// GET `${baseUrl}${route}` and return the body textasyncdownloadAndSave(outputDir:string,route:string):Promise<void>// writes <outputDir>/<route>/index.html ('/' -> <outputDir>/index.html); logs and swallows errorsasyncdownloadAndSaveAll(outputDir:string,routes:string[]):Promise<void>// calls downloadAndSave for each route sequentially}

BecausedownloadAndSavecatches and logs errors instead of throwing,downloadAndSaveAllnever rejects on a failed route — check the console output.

Example: SSR Static Site Generation

import{HttpPageDownloader}from'@dooboostore/core-node';asyncfunctiongenerateStaticSite() {constdownloader =newHttpPageDownloader('http://localhost:3000');constroutes = ['/','/about','/products','/products/1','/contact'];// Generate all static HTML filesawaitdownloader.downloadAndSaveAll('./dist', routes);console.log('✅ Static site generated in ./dist');
}generateStaticSite();

3️⃣Process & Environment(ProcessUtils)

Access to Node.js process information and environment variables.

ProcessUtils Namespace

A thin, directly-named wrapper around Node's globalprocessobject.

// Runtime identityProcessUtils.getPid():number// process.pidProcessUtils.getPlatform():NodeJS.Platform// process.platform ('darwin' | 'linux' | 'win32' | ...)ProcessUtils.getArch():string// process.archProcessUtils.getNodeVersion():string// process.versionProcessUtils.getVersions():NodeJS.ProcessVersions// process.versions (node, v8, openssl, ...)ProcessUtils.getTitle():string// process.titleProcessUtils.getCwd():string// process.cwd()ProcessUtils.getUptime():number// process.uptime()ProcessUtils.getCpuUsage():NodeJS.CpuUsage// process.cpuUsage()ProcessUtils.getArgv():string[]// process.argv (NOT sliced — includes the node binary and script path)// EnvironmentProcessUtils.getEnv(key:string):string|undefined// process.env[key]ProcessUtils.setEnv(key:string,value:string):void// process.env[key] = valueProcessUtils.isProduction():boolean// process.env.NODE_ENV === 'production'ProcessUtils.isDevelopment():boolean// process.env.NODE_ENV === 'development' || NODE_ENV is unsetProcessUtils.isTest():boolean// process.env.NODE_ENV === 'test'// Process controlProcessUtils.exit(code:number=0):void// process.exit(code)

Example: Environment Configuration

import{ProcessUtils}from'@dooboostore/core-node';constconfig = {isDev:ProcessUtils.isDevelopment(),port:Number(ProcessUtils.getEnv('PORT')) ||3000,database:ProcessUtils.getEnv('DATABASE_URL') ||'localhost:5432'};console.log('🚀 Starting server...');console.log(`  PID:${ProcessUtils.getPid()}`);console.log(`  Platform:${ProcessUtils.getPlatform()}(${ProcessUtils.getArch()})`);console.log(`  Environment:${ProcessUtils.isProduction() ?'Production':'Development'}`);

4️⃣Memory Profiling & Monitoring(memory module)

Monitor heap usage and generate memory snapshots for debugging.

MemoryUtils Namespace

// Raw memory usage (bytes — same shape as process.memoryUsage())MemoryUtils.memoryUsage():NodeJS.MemoryUsage// { rss, heapTotal, heapUsed, external, arrayBuffers }// Logs memory usage to the console, converted to MBMemoryUtils.logMemoryUsage():void// Writes a V8 heap snapshot into `logPath` (a directory), filename is heap-<ISO timestamp>.heapsnapshot// Returns the written file path, or null if v8.writeHeapSnapshot threwMemoryUtils.writeHeapSnapshot(logPath:string):string|null// Registers a SIGUSR2 handler that calls writeHeapSnapshot(logPath) when the process receives SIGUSR2// (e.g. `kill -SIGUSR2 <pid>`, or `pm2 sendSignal SIGUSR2 <app-name>`)MemoryUtils.registerHeapDumpSignal(logPath:string):void// Starts a setInterval that calls logMemoryUsage() every `intervalMs`, and if `thresholdMB`// is exceeded, warns and (if `logPath` is given) writes an automatic heap snapshot.// Returns the interval handle so you can clearInterval() it later.MemoryUtils.startMemoryMonitoring(intervalMs?:number/* default 5 min */,thresholdMB?:number,logPath?:string):NodeJS.Timeout

Example: Memory Monitoring

import{MemoryUtils}from'@dooboostore/core-node';// Log memory every 30s, and auto-dump a heap snapshot into ./heaps if usage exceeds 500MBMemoryUtils.startMemoryMonitoring(30_000,500,'./heaps');// Also dump on demand via `kill -SIGUSR2 <pid>`MemoryUtils.registerHeapDumpSignal('./heaps');

5️⃣Path Operations(PathUtils)

Wrapper around Node.jspathmodule with type-safe handling.

PathUtils Namespace

A direct, one-to-one wrapper around Node'spathmodule (plusprocessCwd()forprocess.cwd()). Every function takes plain string arguments — unlikeFileUtils'sPathParamType, it doesnotaccept an array in place of the rest-args.

PathUtils.processCwd():string// process.cwd()PathUtils.join(...paths:string[]):string// path.join(...)PathUtils.resolve(...paths:string[]):string// path.resolve(...)PathUtils.normalize(path:string):string// path.normalize(path)PathUtils.dirname(path:string):string// path.dirname(path)PathUtils.basename(path:string,suffix?:string):string// path.basename(path, suffix)PathUtils.extname(path:string):string// path.extname(path)PathUtils.isAbsolute(path:string):boolean// path.isAbsolute(path)PathUtils.relative(from:string,to:string):string// path.relative(from, to)PathUtils.parse(path:string): path.ParsedPath// path.parse(path)PathUtils.format(pathObject: path.FormatInputPathObject):string// path.format(pathObject)

Example: Path Handling

import{PathUtils}from'@dooboostore/core-node';constconfigPath =PathUtils.join('./config','env','production.json');// Parse file partsconstparsed =PathUtils.parse('/app/src/index.ts');// { root: '/', dir: '/app/src', base: 'index.ts', ext: '.ts', name: 'index' }

6️⃣Data Conversion(ConvertUtils)

Convert between Buffers, strings, and handle Base64 encoding/decoding.

ConvertUtils Namespace

// Buffer (or string, passed through unchanged) to StringConvertUtils.toString(data:string|Buffer,config?: {encoding?:BufferEncoding// default: 'utf-8'; forwarded to Buffer#toString(encoding, start, end)start?:numberend?:number}):string// String to BufferConvertUtils.toBuffer(data:string,config?: {encoding:BufferEncoding}):Buffer

toBufferonly special-casesconfig.encoding === 'base64': it strips an optional Data URL prefix (everything up to and including;base64,, e.g."data:image/png;base64,iVBORw0KGgo...") and decodes the rest as base64. For any other (or missing)encoding, it returnsBuffer.from(data)(UTF-8) — other encoding values are not applied.

Example: Image Processing

import{ConvertUtils,FileUtils}from'@dooboostore/core-node';asyncfunctionsaveBase64Image(dataUrl:string) {// Handle data URLs: "data:image/png;base64,iVBORw0KGgo..."constbuffer =ConvertUtils.toBuffer(dataUrl, {encoding:'base64'});constfile =awaitFileUtils.writeFile(buffer, {path:'./uploads/image.png',originalName:'avatar.png'});returnfile.path;
}

📖 Usage Examples

Example 1: Complete File Upload Workflow

import{FileUtils}from'@dooboostore/core-node';interfaceUploadMetadata{userId:string;uploadedAt:Date;fileSize:number;
}asyncfunctionhandleUpload(buffer:Buffer,userId:string) {constfile =awaitFileUtils.writeFile<UploadMetadata>(buffer, {path:`./uploads/${userId}/document.pdf`,originalName:'resume.pdf',etcData: {
      userId,uploadedAt:newDate(),fileSize: buffer.length}
  });awaitfile.updateStats();console.log(`✅ Saved:${file.fileName}(${file.size}bytes)`);awaitfile.copy(`./backups/${userId}-${Date.now()}.pdf`);// `file` now points at the backupreturnfile;
}

Example 2: SSR Static Generation

import{HttpPageDownloader}from'@dooboostore/core-node';import{ProcessUtils}from'@dooboostore/core-node';asyncfunctionbuildStaticSite() {constbaseUrl =ProcessUtils.getEnv('BUILD_URL') ||'http://localhost:3000';constdownloader =newHttpPageDownloader(baseUrl);constroutes = ['/','/about','/products','/contact'];awaitdownloader.downloadAndSaveAll('./dist', routes);console.log(`✨ Generated${routes.length}static pages`);
}

Example 3: Environment-based Configuration

import{ProcessUtils}from'@dooboostore/core-node';constconfig = {environment:ProcessUtils.isProduction() ?'production':'development',port:Number(ProcessUtils.getEnv('PORT')) ||3000,debug:ProcessUtils.getEnv('DEBUG') ==='true'};

Example 4: Memory Monitoring

import{MemoryUtils}from'@dooboostore/core-node';// Enable SIGUSR2 heap profiling — `kill -SIGUSR2 <pid>` dumps a snapshot into ./heap-dumpsMemoryUtils.registerHeapDumpSignal('./heap-dumps');// Also log + auto-dump every 30s if heap usage exceeds 500MBMemoryUtils.startMemoryMonitoring(30_000,500,'./heap-dumps');

🔗 Relationship to @dooboostore/core

core-nodedepends on@dooboostore/corefor two things specifically:HttpPageDownloaderusescore'sHttpFetcher/HttpFetcherRequestto perform the actual HTTP GET, andFileUtils.writeFileusescore'sRandomUtils.uuid4()to generate a temp file name when nopathis given. Everything else in this package (file, process, memory, path, convert) is implemented directly on Node.js built-ins and has no further dependency oncore.

Feature@dooboostore/core-node
File I/O✅
Process/Env✅
Memory Profiling✅
Buffer/Base64 Conversion✅
Path Operations✅
HTTP page fetching✅ (viacore'sHttpFetcher)

🎓 Best Practices

  1. UseFileUtils.File<E>for type-safe metadata—etcDatacarries whatever metadata you need alongside the file.
  2. Register a SIGUSR2 heap dump handler in production—MemoryUtils.registerHeapDumpSignal(dir)lets you trigger a heap snapshot on demand viakill -SIGUSR2 <pid>, without restarting the process.
  3. UseProcessUtilsfor environment checks—isProduction()/isDevelopment()/isTest()readNODE_ENVconsistently.
  4. UsePathUtilsfor cross-platform path handlinginstead of string concatenation.

License

This package is licensed under theMIT License.