@file-storage/core
Advanced tools
Comparing version
@@ -13,4 +13,13 @@ /// <reference types="node" /> | ||
defaultDisk: Driver; | ||
/** | ||
* All plugin instances. | ||
*/ | ||
private pluginInstances; | ||
constructor(diskName?: string); | ||
get name(): string; | ||
/** | ||
* Initialize a storage. | ||
*/ | ||
private initialize; | ||
/** | ||
* Config for storage methods supported in the application. | ||
@@ -21,4 +30,8 @@ */ | ||
* Get disk instance by diskName. | ||
* | ||
* @param diskName Disk name. | ||
* @param asStorage Return a storage instance. | ||
*/ | ||
disk<U extends Driver>(diskName?: string): U; | ||
disk<U extends Driver>(diskName: string): U; | ||
disk(diskName: string, asStorage: true): StorageClass; | ||
url(path: string): string; | ||
@@ -28,10 +41,11 @@ exists(path: string): Promise<boolean>; | ||
lastModified(path: string): Promise<number>; | ||
put(stream: Stream, path: string): Promise<any>; | ||
put(data: Stream | Buffer, path: string): Promise<any>; | ||
get(path: string): Stream | Promise<Stream>; | ||
delete(path: string): Promise<any>; | ||
uploadImageFromExternalUri(uri: string, path: string, ignoreHeaderContentType?: boolean): Promise<any>; | ||
makeDir(dir: string): Promise<string>; | ||
removeDir(dir: string): Promise<string>; | ||
uploadImageFromExternalUri(uri: string, path: string, ignoreHeaderContentType?: boolean): Promise<any>; | ||
imageStats(path: string): Promise<import("@file-storage/common").ImageStats>; | ||
} | ||
export declare const Storage: StorageClass; | ||
export {}; |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Storage = void 0; | ||
const common_1 = require("@file-storage/common"); | ||
const S3Driver = common_1.requireDefaultModule('@file-storage/s3'); | ||
const FtpDriver = common_1.requireDefaultModule('@file-storage/ftp'); | ||
const LocalDriver = common_1.requireDefaultModule('@file-storage/local'); | ||
const SftpDriver = common_1.requireDefaultModule('@file-storage/sftp'); | ||
let configableDefaultDriverName = 'local'; | ||
let configableDefaultDiskName = 'local'; | ||
const defaultDiskConfig = { | ||
@@ -17,3 +22,9 @@ driver: common_1.DriverName.LOCAL, | ||
let availableDisks = [defaultDiskConfig]; | ||
const drivers = [S3Driver, LocalDriver, FtpDriver, SftpDriver]; | ||
const drivers = [ | ||
common_1.requireDefaultModule('@file-storage/s3'), | ||
common_1.requireDefaultModule('@file-storage/ftp'), | ||
common_1.requireDefaultModule('@file-storage/local'), | ||
common_1.requireDefaultModule('@file-storage/sftp'), | ||
]; | ||
const plugins = [common_1.requireDefaultModule('@file-storage/image-manipulation')].filter((item) => !!item); | ||
function handleDiskConfigs(diskConfigs) { | ||
@@ -41,3 +52,3 @@ const seen = new Set(); | ||
if (diskConfig.isDefault) { | ||
configableDefaultDriverName = diskConfig.name; | ||
configableDefaultDiskName = diskConfig.name; | ||
break; | ||
@@ -47,8 +58,8 @@ } | ||
} | ||
function addCustomDriver(map = []) { | ||
if (map.length > 0) { | ||
drivers.push(...map); | ||
function addCustomDriver(customDrivers = []) { | ||
if (customDrivers.length > 0) { | ||
drivers.push(...customDrivers); | ||
} | ||
} | ||
function getDisk(diskName = configableDefaultDriverName) { | ||
function getDisk(diskName = configableDefaultDiskName) { | ||
const diskConfig = availableDisks.find((item) => item.name === diskName); | ||
@@ -63,2 +74,3 @@ if (!diskConfig) { | ||
catch (error) { | ||
// Throw error missing bult-in driver package. | ||
if (Object.values(common_1.DriverName).includes(diskConfig.driver)) { | ||
@@ -74,7 +86,4 @@ throw new Error(`Please install \`@file-storage/${diskConfig.driver}\` for ${diskConfig.driver} driver`); | ||
class StorageClass { | ||
constructor() { | ||
/** | ||
* Get default disk instance. | ||
*/ | ||
this.defaultDisk = getDisk(configableDefaultDriverName); | ||
constructor(diskName = configableDefaultDiskName) { | ||
this.initialize(diskName); | ||
} | ||
@@ -84,6 +93,14 @@ get name() { | ||
} | ||
// get driver() { | ||
// return this.defaultDisk.driver; | ||
// } | ||
/** | ||
* Initialize a storage. | ||
*/ | ||
initialize(diskName = configableDefaultDiskName) { | ||
this.defaultDisk = getDisk(diskName); | ||
this.pluginInstances = plugins.map((pluginClass) => { | ||
const plugin = new pluginClass(); | ||
plugin.init(this.defaultDisk); | ||
return plugin; | ||
}); | ||
} | ||
/** | ||
* Config for storage methods supported in the application. | ||
@@ -95,12 +112,6 @@ */ | ||
handleDiskConfigs(diskConfigs); | ||
this.defaultDisk = getDisk(configableDefaultDriverName); | ||
this.initialize(configableDefaultDiskName); | ||
} | ||
/** | ||
* Get disk instance by diskName. | ||
*/ | ||
disk(diskName) { | ||
if (!diskName) { | ||
return this.defaultDisk; | ||
} | ||
return getDisk(diskName); | ||
disk(diskName, asStorage = false) { | ||
return asStorage ? new StorageClass(diskName) : getDisk(diskName); | ||
} | ||
@@ -119,4 +130,15 @@ url(path) { | ||
} | ||
put(stream, path) { | ||
return this.defaultDisk.put(stream, path); | ||
put(data, path) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let result = {}; | ||
const putData = yield this.defaultDisk.put(data, path); | ||
result = Object.assign({}, result, putData); | ||
for (const plugin of this.pluginInstances) { | ||
if (plugin.afterPutKey && plugin.afterPut) { | ||
const afterPutData = yield plugin.afterPut(path); | ||
result[plugin.afterPutKey] = afterPutData; | ||
} | ||
} | ||
return result; | ||
}); | ||
} | ||
@@ -129,5 +151,2 @@ get(path) { | ||
} | ||
uploadImageFromExternalUri(uri, path, ignoreHeaderContentType = false) { | ||
return this.defaultDisk.uploadImageFromExternalUri(uri, path, ignoreHeaderContentType); | ||
} | ||
makeDir(dir) { | ||
@@ -139,3 +158,9 @@ return this.defaultDisk.makeDir(dir); | ||
} | ||
uploadImageFromExternalUri(uri, path, ignoreHeaderContentType = false) { | ||
return this.defaultDisk.uploadImageFromExternalUri(uri, path, ignoreHeaderContentType); | ||
} | ||
imageStats(path) { | ||
return this.defaultDisk.imageStats(path); | ||
} | ||
} | ||
exports.Storage = new StorageClass(); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
// export interface GetDiskOptions { | ||
// /** | ||
// * Return a storage instance. | ||
// */ | ||
// asStorage?: boolean; | ||
// } |
{ | ||
"name": "@file-storage/core", | ||
"version": "1.1.1", | ||
"version": "1.1.2", | ||
"description": "> TODO: description", | ||
@@ -29,10 +29,10 @@ "author": "Dang Nguyen <haidang009@gmail.com>", | ||
"dependencies": { | ||
"@file-storage/common": "^1.1.0", | ||
"@file-storage/local": "^1.1.0" | ||
"@file-storage/local": "^1.1.1" | ||
}, | ||
"devDependencies": { | ||
"@file-storage/common": "^1.1.1", | ||
"rimraf": "~3.0.2", | ||
"typescript": "~4.3.5" | ||
}, | ||
"gitHead": "bfd614160a13042eb996d98813187eb5dd0e68a4" | ||
"gitHead": "ee67f33b76b6536599251d52c783a55f77205f6a" | ||
} |
163
README.md
@@ -1,11 +0,164 @@ | ||
# `file-storage` | ||
``` | ||
____|_) | ___| | | ||
| | | _ \\___ \ __| _ \ __| _` | _` | _ \ | ||
__| | | __/ | | ( | | ( | ( | __/ | ||
_| _|_|\___|_____/ \__|\___/ _| \__,_|\__, |\___| | ||
A file system abstraction for Node.js |___/ | ||
``` | ||
> TODO: description | ||
[](https://github.com/googlicius/file-storage/actions/workflows/ci.yml) [](https://opensource.org/licenses/MIT) | ||
## Usage | ||
A simple abstraction to interact with file system inspired by [Laravel File System](https://laravel.com/docs/8.x/filesystem), provides one interface for many kind of drivers: `local`, `ftp`, `sftp`, `Amazon S3`, and `Google Cloud Storage`, even your custom driver. | ||
## Installation | ||
```bash | ||
$ yarn add @file-storage/core @file-storage/common | ||
# Or npm | ||
$ npm install @file-storage/core @file-storage/common | ||
``` | ||
const fileStorage = require('file-storage'); | ||
// TODO: DEMONSTRATE API | ||
And upload a file to local, it will be stored in `storage` folder in your root project directory by default: | ||
```javascript | ||
import Storage from '@file-storage/core'; | ||
// Upload from file path. | ||
Storage.put('/my-image.png', '/path/of/destination/my-image.png'); | ||
// Or from a read-stream/buffer: | ||
Storage.put(stream, '/path/of/destination/my-image.png'); | ||
``` | ||
## Configuration | ||
By default only local driver is supported, if you want to use another driver, you need to install corresponding package: | ||
- Amazon S3: `yarn add @file-storage/s3` | ||
- FTP: `yarn add @file-storage/ftp` | ||
- SFTP: `yarn add @file-storage/sftp` | ||
- Google Cloud Storage: `yarn add @file-storage/gcs` | ||
If there is no configuration, it will uploads to local disk. You can specific yours by using `config` method: | ||
```javascript | ||
import Storage from '@file-storage/core'; | ||
import { DriverName } from '@file-storage/common'; | ||
Storage.config({ | ||
diskConfigs: [ | ||
{ | ||
driver: DriverName.LOCAL, | ||
name: 'local', | ||
root: 'public', | ||
}, | ||
{ | ||
driver: DriverName.S3, | ||
name: 'mys3', | ||
bucketName: 'mybucket', | ||
isDefault: true, // Default disk that you can access directly via Storage facade. | ||
// Uncomment if you want specify credentials manually. | ||
// region: 'ap-southeast-1', | ||
// credentials: { | ||
// accessKeyId: '123abc', | ||
// secretAccessKey: '123abc', | ||
// }, | ||
}, | ||
], | ||
}); | ||
// Somewhere in your code... | ||
// Get file from s3: | ||
Storage.get('/path/to/s3-bucket/my-image.png'); | ||
``` | ||
## Obtain disk instance: | ||
If you want to interact with a specific disk instead of the default, use `disk` method to get that instance: | ||
```javascript | ||
Storage.disk('local').get('/path/to/local/my-image.png'); | ||
``` | ||
## Hash file name | ||
Enable hash file name to prevent a file get replaced when uploading same file (or same name): | ||
```javascript | ||
Storage.config({ | ||
... | ||
enableHash: true, | ||
}); | ||
// The path uploaded will be like this: /path/to/image/my-image_$ru6eu3.png | ||
``` | ||
## Create your custom driver | ||
If bult-in drivers doesn't match your need, just defines a custom driver by extends `Driver` abstract class: | ||
```typescript | ||
import Storage from '@file-storage/core'; | ||
import { Driver } from '@file-storage/common'; | ||
interface OneDriveConfig { | ||
name: string; // driver instance name is required. | ||
... | ||
} | ||
class OneDrive extends Driver { | ||
static readonly driverName = 'one_drive'; | ||
constructor(config: OneDriveConfig) { | ||
super(config); | ||
... | ||
} | ||
// Define all Driver's methods here. | ||
} | ||
``` | ||
And provide it to Storage.customDrivers: | ||
```typescript | ||
Storage.config<OneDriveConfig>({ | ||
diskConfigs: [ | ||
{ | ||
driver: 'one_drive', | ||
name: 'myCustomDisk', | ||
isDefault: true, | ||
... | ||
} | ||
], | ||
customDrivers: [OneDrive], | ||
}); | ||
``` | ||
## Image manipulation | ||
If you want to upload image and also creates many diferent sizes: large, medium, small, thumbnail for web resonsive, install this package, it is acting as a plugin, will generates those image sizes automatically: | ||
```bash | ||
$ yarn add @file-storage/image-manipulation | ||
``` | ||
**HINT**: `Image manipulation` only available on Starage facade, If you obtain a specific disk instance, set the second parameter to true to obtain a storage instance insteads: | ||
```javascript | ||
Storage.disk('your-disk', true); // Storage instance. | ||
``` | ||
## TODO | ||
- [ ] Create interface for all result (Need same result format for all drivers). | ||
- [x] Refactor `customDrivers` option: provides disk defination is enough. | ||
- [ ] Implement GCS disk. | ||
- [ ] Put file from a local path. | ||
- [ ] API section: detailed of each driver. | ||
- [ ] Remove `customDrivers` option, pass custom driver class directly to `diskConfigs.driver`. | ||
## License | ||
MIT |
15729
70.06%1
-50%242
22.84%165
1275%3
50%- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated