flydrive
is a framework-agnostic package which provides a powerful wrapper to manage file Storage in Node.js.
There are currently 3 drivers available:
'local'
: Stores files on the local file system.'s3'
: Amazon S3 and other compatible services
- You need to install the
@slynova/flydrive-s3
package to be able to use this driver. - This driver is compatible with DigitalOcean Spaces and Scaleway Object Storage.
'gcs'
: Google Cloud Storage
- You need to install the
@slynova/flydrive-gcs
package to be able to use this driver.
Getting Started
This package is available in the npm registry.
It can easily be installed with npm
or yarn
.
$ npm i @slynova/flydrive
$ yarn add @slynova/flydrive
When you require the package in your file, it will give you access to the StorageManager
class.
This class is a facade for the package and should be instantiated with a configuration object.
const { StorageManager } = require('@slynova/flydrive');
const storage = new StorageManager(...);
Once you instantiated the manager, you can use the StorageManager#disk()
method to retrieve a disk an use it.
storage.disk();
storage.disk('awsCloud');
storage.disk('awsCloud', customConfig);
Registering External Driver
After installing any external driver, like @slynova/flydrive-gcs
, you need to register it inside our manager to be able to use it.
The following is done by using the method storage.registerDriver(name: string, Driver)
.
const { GoogleCloudStorage } = require('@slynova/flydrive-gcs');
const { StorageManager } = require('@slynova/flydrive');
const storage = new StorageManager(...);
storage.registerDriver('gcs', GoogleCloudStorage);
Driver's API
Each driver extends the abstract class Storage
. This class will throw an exception for each methods by default. The driver needs to overwrite the methods it supports.
The following method doesn't exist on the LocalFileSystemStorage
driver, therefore, it will throw an exception.
storage.disk('local').getSignedUrl();
Since we are using TypeScript, you can make use of casting to get the real interface:
import { LocalFileSystemStorage } from '@slynova/flydrive';
storage.disk<LocalFileSystemStorage>('local');
Response interface
Asynchronous methods will always return a Promise which resolves with a Response
object. The response object may contain relevant data in its properties (for
example, the ExistsResponse
object for the exists
method contains a boolean
exists
property).
All responses additionally have a raw
property which is driver-specific and
contains the result from the original call made by the driver.
Exceptions
In case of runtime errors, flydrive
will try to throw driver-agnostic exceptions.
Exceptions also have a raw
property which contains the original error.
Methods
append(location: string, content: Buffer | Stream | string, options: object): Promise<Response>
This method will append the content to the file at the location.
If the file doesn't exist yet, it will be created.
await storage.disk('local').append('foo.txt', 'bar');
copy(src: string, dest: string, options: object): Promise<Response>
This method will copy a file to another location.
await storage.disk('local').copy('foo.txt', 'bar.txt');
delete(location: string): Promise<DeleteResponse>
This method will delete the file at the given location.
const { wasDeleted } = await storage.disk('local').delete('foo.txt');
The value returned by this method will have a wasDeleted
property that
can be either a boolean (true
if a file was deleted, false
if there was
no file to delete) or null
(if no information about the file is available).
driver()
This method returns the driver used if you need to do anything specific not supported by default.
storage.disk('local').driver();
storage.disk('awsCloud').driver();
storage.disk('googleCloud').driver();
exists(location: string): Promise<ExistsResponse>
This method will determine if a file exists at the given location.
const { exists } = await storage.disk('local').exists('foo.txt');
get(location: string, encoding: string = 'utf-8'): Promise<ContentResponse<string>>
This method will return the file's content as a string for the given location.
const { content } = await storage.disk('local').get('foo.txt');
getBuffer(location: string): Promise<ContentResponse<Buffer>>
This method will return the file's content as a Buffer for the given location.
const { content } = await storage.disk('local').exists('foo.txt');
getSignedUrl(location: string, options: SignedUrlOptions = { expiry: 900 }): Promise<SignedUrlResponse>
This method will return the signed url for an existing file.
const { signedUrl } = await storage.disk('awsCloud').getSignedUrl('foo.txt');
getStat(location: string): Promise<StatResponse>
This method will return the file's size (in bytes) and last modification date.
const { size, modified } = await storage.disk('local').getStat('foo.txt');
getStream(location: string, options: object | string): Stream
This method will return a Node.js readable stream for the given file.
const stream = storage.disk('local').getStream('foo.txt');
getUrl(location: string): string
This method will return a public URL for a given file.
const uri = storage.disk('awsCloud').getUrl('foo.txt');
move(src: string, dest: string): Promise<Response>
This method will move the file to a new location.
await storage.disk('local').move('foo.txt', 'newFolder/foo.txt');
put(location: string, content: Buffer | Stream | string, options: object): Promise<Response>
This method will create a new file with the provided content.
await storage.disk('local').put('bar.txt', 'Foobar');
prepend(location: string, content: Buffer | string, options: object): Promise<Response>
This method will prepend content to a file.
await storage.disk('local').prepend('foo.txt', 'bar');
flatList(prefix?: string): AsyncIterable<FileListResponse>
This method will return an async iterator over all file names that start with prefix
(recursive).
const disk = storage.disk('local');
for await (const filename of disk.flatList('a/b')) {
console.log(filename);
}
Contribution Guidelines
Any pull requests or discussions are welcome.
Note that every pull request providing new feature or correcting a bug should be created with appropriate unit tests.