@enstore/fs
v0.0.2
Published
File system utilities for Enstore storage system
Downloads
98
Maintainers
Readme
@enstore/fs
@enstore/fs
is a Node.js–style file system interface that seamlessly mounts a remote EnStore server as if it were a local filesystem. It provides APIs similar to Node.js fs
—both stream-based (createWriteStream
) and promise-based (readFile
, writeFile
).
It introduces the following classes:
EnstoreFs
- Offers a
createWriteStream
method analogous tofs.createWriteStream
in Node.js, allowing you to stream file uploads chunk-by-chunk to an EnStore server. - Exposes a static property
EnstoreFs.promises
pointing to anEnstorePromiseFs
instance for promise-based operations.
- Offers a
EnstorePromiseFs
- Provides
readFile
andwriteFile
methods that follow Node.js’s promise-basedfs.promises
API signatures. - Use these methods to read or write remote files asynchronously.
- Provides
Both classes extend a common BaseFs
abstract class which handles credential resolution and root directory mapping.
Installation
npm install @enstore/fs
Usage Overview
Instantiate an
EnstoreFs
orEnstorePromiseFs
object with configuration for:- Root directory (a local path you treat as
"/"
on the EnStore server) - Credentials (endpoint, username, password) either directly, via environment variables, or via a credential file.
- Root directory (a local path you treat as
Use the familiar
fs
-like methods:readFile
/writeFile
(Promise-based inEnstorePromiseFs
)createWriteStream
(inEnstoreFs
) for streaming writes- The static property
EnstoreFs.promises
is a convenience instance for promise-based operations.
Quick Example
import { EnstoreFs } from '@enstore/fs';
// Create an instance pointing "rootDirectory" to /var/logs (on your local system)
const enFs = new EnstoreFs({
rootDirectory: '/var/logs',
// credentials can come from environment or credentials file
});
// 1) Use the static promise-based API
await EnstoreFs.promises.writeFile('/var/logs/nginx/access.log', 'Hello, world\n', 'utf-8');
const content = await EnstoreFs.promises.readFile('/var/logs/nginx/access.log', 'utf-8');
console.log('Remote content:', content);
// 2) Or use createWriteStream for streaming
const writeStream = enFs.createWriteStream('/var/logs/app/streamed.log');
writeStream.write('Some chunk of data\n');
writeStream.write('Another chunk\n');
writeStream.end(() => {
console.log('Stream upload complete!');
});
In this example, local file paths like "/var/logs/nginx/access.log"
map to remote EnStore paths like "/nginx/access.log"
.
Configuration and Credential Resolution
BaseFs
Constructor Config
interface EnstoreFsConfig {
endpoint?: string;
username?: string;
password?: string;
credentialsFilePath?: string;
rootDirectory: string; // required
}
rootDirectory
(required)- A local path you consider as root. For instance,
"/var/logs"
in your code maps to"/"
on the EnStore server.
- A local path you consider as root. For instance,
Credentials can be resolved in three steps:
- Constructor config: if
endpoint
,username
,password
are explicitly provided, these take priority. - Environment Variables:
ENSTORE_ENDPOINT
,ENSTORE_USERNAME
,ENSTORE_PASSWORD
. - Credentials File: A JSON file (by default at
~/.enstore/credentials.json
) or a custom path specified bycredentialsFilePath
.
- Constructor config: if
If any required credential (endpoint
, username
, password
) remains missing after these steps, the constructor throws an error.
EnstoreFs
EnstoreFs
extends BaseFs
and provides:
createWriteStream(path, [options])
Returns aWritable
Node.js stream that uploads data to EnStore in real time. As you write chunks, they are streamed chunk-by-chunk to the remote server using multipart form-data.Static:
EnstoreFs.promises
(instance ofEnstorePromiseFs
)
A convenient way to access promise-based methods without instantiatingEnstorePromiseFs
separately.
Streaming Example
const enFs = new EnstoreFs({ rootDirectory: '/data/logs' });
const writeStream = enFs.createWriteStream('/data/logs/giantFile.log');
writeStream.on('uploaded', () => {
console.log('Upload success');
});
writeStream.on('error', err => {
console.error('Upload failed:', err);
});
// Write data in chunks
writeStream.write('chunk 1...');
writeStream.write('chunk 2...');
writeStream.end();
Your EnStore server (e.g. Express + Multer) can handle this multipart chunked upload. This approach is memory-efficient for large files.
EnstorePromiseFs
EnstorePromiseFs
extends BaseFs
and implements:
readFile(path, [options])
→Promise<Buffer | string>
Just likefs.promises.readFile
, supports anencoding
option to return a string.writeFile(path, data, [options])
→Promise<void>
Similar tofs.promises.writeFile
, supports string or buffer data.
Example:
import { EnstorePromiseFs } from '@enstore/fs';
(async function main() {
const promiseFs = new EnstorePromiseFs({ rootDirectory: '/home/user/files' });
await promiseFs.writeFile('/home/user/files/note.txt', 'Hello from EnStore!', 'utf-8');
const content = await promiseFs.readFile('/home/user/files/note.txt', 'utf-8');
console.log(content);
})();
Root Directory Mapping
- If
rootDirectory = "/some/local/path"
, then passing"/some/local/path/foo/bar.txt"
toreadFile
orwriteFile
automatically translates to"/foo/bar.txt"
on the remote server. - If you pass a local path outside of
rootDirectory
, the library throws an error (e.g.,Path /home/outside is outside the rootDirectory /some/local/path
).
Credentials File
By default, credentials are read from:
~/.enstore/credentials.json
A typical credentials.json
:
{
"endpoint": "http://my-enstore-server:3000",
"username": "admin",
"encryptedPassword": "base64encodedString..."
}
If you prefer a different path, specify credentialsFilePath
in the constructor config:
new EnstoreFs({
rootDirectory: '/mnt',
credentialsFilePath: '/path/to/mycreds.json'
});
Installation & Example
Install:
npm install @enstore/fs
Create an instance:
import { EnstoreFs } from '@enstore/fs'; const enFs = new EnstoreFs({ rootDirectory: '/mnt/myfiles' // endpoint, username, password can come from ENV or credentialsFile }); // Stream upload const ws = enFs.createWriteStream('/mnt/myfiles/someLargeFile.bin'); ws.write(...); ws.end();
Promise-based:
await EnstoreFs.promises.writeFile('/mnt/myfiles/report.txt', 'Report data', 'utf-8'); const content = await EnstoreFs.promises.readFile('/mnt/myfiles/report.txt', 'utf-8'); console.log(content);
Limitations & Notes
- Chunked Streaming: The
createWriteStream
method uses a multipart approach to chunk data. Ensure your EnStore server supports streaming multipart uploads (e.g. with Multer, Busboy, etc.). - Root Directory: Strictly enforces paths under the specified root. Trying to read/write outside will throw an error.
- File listing / other
fs
methods (likereaddir
,stat
) are not yet implemented. You can add them following a similar pattern (use/files/ls
or/files/stat
EnStore endpoints). - Large Files: For truly large files, ensure your server and network settings allow streaming without memory constraints. The streaming approach helps avoid loading the entire file in memory at once.
- Error Handling: The library throws standard JavaScript errors if the EnStore server responds with an error, or if credentials are missing.
Contributing
PRs are welcome for additional features such as:
readdir
,stat
,unlink
, etc.- Improved streaming error-handling or partial uploads.
- Enhanced credential management or token-based authentication.