mylas
Mylas is a Node.js filesystem convenience wrapper with grouped helpers for UTF-8 text, JSON, Buffers, directories, and locating ancestor `node_modules` folders. Each data family offers Promise methods, several have synchronous forms, and text, JSON, and Buffer operations also have worker-thread variants. Saves create missing parent directories automatically, JSON reads can strip comments and trailing commas, and TypeScript declarations are included. It is a small API over Node's built-in `fs`, not a transactional storage layer, database, cross-runtime file abstraction, or general filesystem toolbox.
Mylas is defensible for a codebase that values its exact grouped API, automatic parent creation, and node_modules search. Most new projects should start with `node:fs/promises`; add a focused JSONC or filesystem package only when a concrete gap appears.
Use it if
- You repeatedly read and write small UTF-8 or JSON files and specifically want missing parent directories created automatically
- You need one typed wrapper that handles strings, JSON, Buffers, directory creation, and recursive directory removal
- You consume JSON-with-comments configuration and accept Mylas's limited comment-stripping grammar
- You need to discover `node_modules` directories while walking from a nested working directory toward the filesystem root
- You only need ordinary file I/O; `node:fs/promises`, `mkdir({ recursive: true })`, `readFile`, and `writeFile` already cover the core API without another package
- You need crash-safe or concurrent-safe persistence; the shipped source writes directly with `writeFile` or `writeFileSync` and does not use a temporary file, fsync, rename, locking, or compare-and-swap
- You expect workers to make small reads faster; each `loadW` or `saveW` call constructs a new `Worker`, and Buffer saves first copy data into a `SharedArrayBuffer`, so startup and copying can cost more than the I/O
- You want standards-based JSONC or JSON5 parsing; Mylas uses a handwritten comment and trailing-comma remover before `JSON.parse`, with no syntax-preserving edits or configurable parser behavior
- You plan to import `mylas/register`; its source adds methods to global `JSON`, the `String` constructor, and `String.prototype`, creating collision and test-isolation risks for process-wide convenience
Setup reality
Run `npm install mylas`; there are no runtime dependencies, peer packages, native addons, credentials, or config files. Version 2.1.14 declares Node 16 or newer and ships CommonJS plus declaration files. Prefer named imports such as `import { File, Json, Buf, Dir } from 'mylas'` in native ESM. The README's `import mylas from 'mylas'` works through some TypeScript and bundler interop paths, but the published CommonJS module sets an `exports.default` property. In native Node ESM, the default binding is the whole CommonJS exports object, so the helper you expect is at `mylas.default`; in CommonJS it is likewise `require('mylas').default`. Named imports avoid that ambiguity. Every save first creates missing parent directories recursively, which is convenient but also means a typo can create an unexpected tree before writing. String files are always UTF-8, JSON output is compact `JSON.stringify` output with no indentation, replacer, schema validation, or atomic replacement, and TypeScript generics only assert the parsed shape. The comment flag is the third argument of asynchronous `Json.load(path, callback, hasComments)`, so Promise callers must pass `undefined` as the callback to reach it. Worker methods spawn a fresh thread for each operation rather than using a pool; use them only after measuring large CPU-heavy JSON work, not by default. Directory removal is recursive and forced in the shipped source, with no trash or scope guard. Avoid `mylas/register` in libraries because its global and prototype changes affect every module in the process. The security page also claims support for older Node releases that conflicts with the package's `>=16` engine field; treat the published manifest as the install contract.
Patterns
Read a UTF-8 text fileread-text-file
import { File } from 'mylas';
const text = await File.load('./notes/message.txt');
console.log(text);String reads are fixed to UTF-8. Use `Buf.load()` or `node:fs/promises.readFile()` when you need another encoding or raw bytes.
Write text and create parent directorieswrite-text-file
import { File } from 'mylas';
await File.save('./output/reports/latest.txt', 'ready
');Mylas creates missing parent directories before writing. The write is direct, not atomic, so interruption can leave a partial file.
Access the default helper from CommonJSuse-commonjs-default
const mylas = require('mylas').default;
const configText = await mylas.load('./config/app.json');
const sameMethod = mylas.file.load === mylas.load;
console.log(sameMethod, configText.length);The published module stores the aggregate helper on `.default`. Named exports such as `require('mylas').File` are clearer and avoid interop surprises.
Read JSON with a TypeScript typeread-typed-json
import { Json } from 'mylas';
type AppConfig = { port: number; features: string[] };
const config = await Json.load<AppConfig>('./config/app.json');
console.log(config.port, config.features);The generic is a compile-time assertion only. Mylas calls `JSON.parse` but performs no runtime schema validation.
Read JSON containing comments and trailing commasread-json-comments
import { Json } from 'mylas';
type ToolConfig = { include: string[] };
const config = await Json.load<ToolConfig>(
'./tool.config.jsonc',
undefined,
true,
);
console.log(config.include);For the Promise API, `hasComments` is the third argument, so `undefined` must occupy the optional callback slot. This is a custom stripper, not full JSON5.
Write a JSON valuewrite-json
import { Json } from 'mylas';
await Json.save('./state/session.json', {
userId: 'u_42',
updatedAt: new Date().toISOString(),
});Output is compact `JSON.stringify` text with no indentation or replacer option. The direct write can expose partial content to concurrent readers.
Copy binary data as a Bufferread-write-buffer
import { Buf } from 'mylas';
const input = await Buf.load('./assets/source.bin');
await Buf.save('./output/copy.bin', input);
console.log(input.byteLength);Buffer methods are asynchronous only. Parent directories are created automatically before the destination is written.
Parse a large JSON file in a workerworker-json-load
import { Json } from 'mylas';
type RecordSet = { rows: unknown[] };
const data = await Json.loadW<RecordSet>('./data/large.json');
console.log(data.rows.length);Each worker call creates and tears down a new Worker. Measure end-to-end latency and memory before using this for routine small files.
Write a Buffer through a workerworker-buffer-save
import { Buf } from 'mylas';
const payload = Buffer.from('binary payload');
await Buf.saveW('./output/payload.bin', payload);The source copies the Buffer into a new SharedArrayBuffer before posting to a fresh worker, so this path adds allocation and copying.
Create and check a directorymanage-directory
import { Dir } from 'mylas';
const cacheDir = './var/cache/thumbnails';
await Dir.mk(cacheDir);
if (!(await Dir.check(cacheDir))) {
throw new Error('cache directory was not created');
}Directory creation is recursive. `Dir.check()` reports path existence, not whether the path is writable or actually a directory.
Remove a known generated directoryremove-directory
import { Dir } from 'mylas';
import path from 'node:path';
const allowed = path.resolve('./var/cache/thumbnails');
if (allowed === path.resolve('.') || !allowed.endsWith('/var/cache/thumbnails')) {
throw new Error('refusing unsafe directory removal');
}
await Dir.rm(allowed);The implementation removes recursively with force and offers no trash or recovery. Resolve and constrain every path before calling it with variable input.
Find ancestor node_modules directoriesfind-node-modules
import { Dir } from 'mylas';
const locations = Dir.nodeModules({
cwd: process.cwd(),
relative: false,
});
for (const location of locations) console.log(location);The search walks upward and may also consider global npm locations for special input forms. Do not treat discovered package directories as trusted data.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| fs-extra | npm | Choose it for a broader, established set of copy, move, ensure-directory, remove, and JSON filesystem helpers |
| jsonfile | npm | Choose it when reading and writing JSON is the whole job and formatting options matter |
| strip-json-comments | npm | Choose it with built-in `fs/promises` when comments are the only feature missing from native JSON file handling |