Handle your application files in Node.js
The intention behind this repository is to always maintain a Storage
class to manipulate files using any driver.
To use the high potential from this package you need to install first this other packages from SecJS, it keeps as dev dependency because one day
@secjs/core
will install everything once.
npm install @secjs/env @secjs/utils @secjs/contracts @secjs/exceptions
Then you can install the package using:
npm install @secjs/storage
First you need to create the configuration file filesystem in the config folder on project root path. Is extremely important to use export default in these configurations.
import { Env } from '@secjs/env'
import { Path } from '@secjs/utils'
export default {
/*
|--------------------------------------------------------------------------
| Default Filesystem Disk
|--------------------------------------------------------------------------
|
| Here you may specify the default filesystem disk that should be used
| by the framework. The "local" disk, as well as a variety of cloud
| based disks are available to your application.
|
*/
default: Env('FILESYSTEM_DISK', 'local'),
/*
|--------------------------------------------------------------------------
| Filesystem Disks
|--------------------------------------------------------------------------
|
| Here you may configure as many filesystem "disks" as you wish, and you
| may even configure multiple disks of the same driver. Defaults have
| been setup for each driver as an example of the required options.
|
*/
disks: {
local: {
driver: 'local',
root: Path.noBuild().storage('app'),
url: `${Env('APP_URL', '')}/storage`,
},
public: {
driver: 'local',
root: Path.noBuild().storage('app/public'),
url: `${Env('APP_URL', '')}/storage/public`,
},
s3: {
driver: 's3',
key: Env('AWS_KEY', ''),
secret: Env('AWS_SECRET', ''),
region: Env('AWS_REGION', ''),
bucket: Env('AWS_BUCKET', ''),
endpoint: Env('AWS_ENDPOINT', '')
},
gcs: {
driver: 'gcs',
project: Env('GCS_PROJECT', ''),
secret: Env('GCS_SECRET', ''),
bucket: Env('GCS_BUCKET', ''),
endpoint: Env('GCS_ENDPOINT', ''),
},
},
}
With the config/filesystem file created you can use Storage class to start storing your files.
import { Storage } from '@secjs/storage'
const storage = new Storage()
// Storage class will always use the default value set in config/filesystem to store the files, in this case, local.
await storage.put('file.txt', Buffer.from('hello world!'))
// The file will be saved in the root storage/app/file.txt, according to config/filesystem.
// You can use putFile method to create a file "without name", an unique id will be generated for him.
const path = await storage.putFile('folder', 'txt', Buffer.from('hello world!')) // returns the path -> folder/DASdsakdjas912831jhdasnm.txt
// The file will be saved in the root storage/app/folder/DASdsakdjas912831jhdasnm.txt, according to config/filesystem.
// You can use exists and missing too
console.log(await storage.exists('folder/DASdsakdjas912831jhdasnm.txt')) // true
console.log(await storage.missing('folder/DASdsakdjas912831jhdasnm.txt')) // false
// You can get only the content of the file in Buffer using get
await storage.get('folder/DASdsakdjas912831jhdasnm.txt') // Buffer<6c 6c 6c 6c...>
// You can generate an url and a temporaryUrl to your file based on config/filesystem.
await storage.url('folder/DASdsakdjas912831jhdasnm.txt') // https://cdn.secjs.io/storage/folder/DASdsakdjas912831jhdasnm.txt
// 10 minutes = 600000ms
await storage.temporaryUrl('folder/DASdsakdjas912831jhdasnm.txt', 600000) // https://cdn.secjs.io/storage/folder/temp/30219310391sadlksa12039.txt
// You can delete the file using delete
const force = true
// You can use force to not throw exceptions if file does not exist
await storage.delete('folder/DASdsakdjas912831jhdasnm.txt', force)
// You can use copy and move
// In this case folder/DASdsakdjas912831jhdasnm.txt will still exists
await storage.copy('folder/DASdsakdjas912831jhdasnm.txt', 'folder/test/copy.txt')
// In this case folder/DASdsakdjas912831jhdasnm.txt will be removed
await storage.move('folder/DASdsakdjas912831jhdasnm.txt', 'folder/test/move.txt')
You can subscribe the disks configs in runtime using in Storage constructor or disk method
// Using disk method approach
// File created on storage/newAppFolder/file.txt
storage
.disk('local', { root: Path.noBuild().storage('newAppFolder') })
.put('file.txt', Buffer.from('Hello World'))
// Using constructor method approach
const newStorage = new Storage({ root: Path.noBuild().storage('newAppFolder') })
// File created on storage/newAppFolder/file2.txt
newStorage.put('file2.txt', Buffer.from('Hello World'))
// You can reset configs using an empty object in the disk method
storage.disk('local', {}) // Clear the runtime configuration
You can use s3 or gcs disk to make all this actions inside buckets
// Saves to S3
storage.disk('s3').put('folder/file.txt', Buffer.from('Hello world!'))
// Saves to GCS
storage.disk('gcs').put('folder/file.txt', Buffer.from('Hello world!'))
Nowadays, @secjs/storage has only LocalDriver, S3Driver and GCSDriver support, but you can extend the drivers for Storage class if you implement DriverContract interface
import { DriverContract } from '@secjs/storage'
class CustomDriver implements DriverContract {
private readonly _url: string
private readonly _root: string
constructor(disk: string) {
this._url = Config.get(`filesystem.disks.${disk}.url`)
this._root = Config.get(`filesystem.disks.${disk}.root`)
}
// all the methods implemented from DriverContract...
}
Constructor is extremely important in your CustomDriver class, it's the constructor that will use the values from config/filesystem disks to manipulate your CustomDriver using
disk
method from storage. So if you are building a CustomDriver, and you want to use it, you can create a new disk inside config/filesystem disks or change the driver from an existing disk.
// extending disks
// config/filesystem file
export default {
// default etc...
disks: {
mydisk: {
driver: 'custom',
root: Path.storage('app/mydisk'),
url: `${Env('APP_URL', '')}/storage/mydisk`,
}
// ... other disks
}
}
Build you new driver using build static method
const name = 'custom'
const driver = CustomDriver
Storage.build(name, driver)
console.log(Storage.drivers) // ['s3', 'local', 'public', 'custom']
Now, if you have implemented your disk in config/filesystem, you can use him inside storage
// Will use CustomDriver to handle the file actions
storage.disk('mydisk').put('file.txt', Buffer.from('my custom driver'))
Made with 🖤 by jlenon7 👋