Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
1293fc4ca6 | |||
b040120813 | |||
5c2d92c041 | |||
eaf2e7e6bb | |||
1e1f65119c | |||
c70ee820d7 |
@ -8,22 +8,25 @@
|
||||
"githost": "code.foss.global",
|
||||
"gitscope": "push.rocks",
|
||||
"gitrepo": "smartbucket",
|
||||
"description": "A TypeScript library for simple cloud independent object storage with support for buckets, directories, and files.",
|
||||
"description": "A TypeScript library that offers simple, cloud-independent object storage with features like bucket creation, file management, and directory management.",
|
||||
"npmPackagename": "@push.rocks/smartbucket",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"cloud storage",
|
||||
"object storage",
|
||||
"minio",
|
||||
"S3",
|
||||
"TypeScript",
|
||||
"smartstream",
|
||||
"smartpromise",
|
||||
"smartpath",
|
||||
"smartrx",
|
||||
"buckets",
|
||||
"files management",
|
||||
"directories management"
|
||||
"S3",
|
||||
"minio",
|
||||
"file management",
|
||||
"directory management",
|
||||
"bucket creation",
|
||||
"data streaming",
|
||||
"multi-cloud",
|
||||
"API",
|
||||
"unified storage",
|
||||
"buffer handling",
|
||||
"access key",
|
||||
"secret key"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@push.rocks/smartbucket",
|
||||
"version": "3.0.2",
|
||||
"version": "3.0.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@push.rocks/smartbucket",
|
||||
"version": "3.0.2",
|
||||
"version": "3.0.5",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"@push.rocks/smartpath": "^5.0.18",
|
||||
|
26
package.json
26
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@push.rocks/smartbucket",
|
||||
"version": "3.0.2",
|
||||
"description": "A TypeScript library for simple cloud independent object storage with support for buckets, directories, and files.",
|
||||
"version": "3.0.5",
|
||||
"description": "A TypeScript library that offers simple, cloud-independent object storage with features like bucket creation, file management, and directory management.",
|
||||
"main": "dist_ts/index.js",
|
||||
"typings": "dist_ts/index.d.ts",
|
||||
"type": "module",
|
||||
@ -19,6 +19,7 @@
|
||||
"@push.rocks/tapbundle": "^5.0.23"
|
||||
},
|
||||
"dependencies": {
|
||||
"@push.rocks/smartmime": "^2.0.0",
|
||||
"@push.rocks/smartpath": "^5.0.18",
|
||||
"@push.rocks/smartpromise": "^4.0.3",
|
||||
"@push.rocks/smartrx": "^3.0.7",
|
||||
@ -45,15 +46,18 @@
|
||||
"keywords": [
|
||||
"cloud storage",
|
||||
"object storage",
|
||||
"minio",
|
||||
"S3",
|
||||
"TypeScript",
|
||||
"smartstream",
|
||||
"smartpromise",
|
||||
"smartpath",
|
||||
"smartrx",
|
||||
"buckets",
|
||||
"files management",
|
||||
"directories management"
|
||||
"S3",
|
||||
"minio",
|
||||
"file management",
|
||||
"directory management",
|
||||
"bucket creation",
|
||||
"data streaming",
|
||||
"multi-cloud",
|
||||
"API",
|
||||
"unified storage",
|
||||
"buffer handling",
|
||||
"access key",
|
||||
"secret key"
|
||||
]
|
||||
}
|
||||
|
66
pnpm-lock.yaml
generated
66
pnpm-lock.yaml
generated
@ -8,6 +8,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@push.rocks/smartmime':
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
'@push.rocks/smartpath':
|
||||
specifier: ^5.0.18
|
||||
version: 5.0.18
|
||||
@ -409,6 +412,9 @@ packages:
|
||||
'@push.rocks/smartmime@1.0.6':
|
||||
resolution: {integrity: sha512-PHd+I4UcsnOATNg8wjDsSAmmJ4CwQFrQCNzd0HSJMs4ZpiK3Ya91almd6GLpDPU370U4HFh4FaPF4eEAI6vkJQ==}
|
||||
|
||||
'@push.rocks/smartmime@2.0.0':
|
||||
resolution: {integrity: sha512-yNEYrQzWjxwinCT8djw9eFumpCIvIQQS9KXWLH0LT9COlFoaP/ruk7pogrGYKCo20tFITJyO6NmMCa24402rvA==}
|
||||
|
||||
'@push.rocks/smartnetwork@3.0.2':
|
||||
resolution: {integrity: sha512-s6CNGzQ1n/d/6cOKXbxeW6/tO//dr1woLqI01g7XhqTriw0nsm2G2kWaZh2J0VOguGNWBgQVCIpR0LjdRNWb3g==}
|
||||
|
||||
@ -609,6 +615,9 @@ packages:
|
||||
'@tempfix/watcher@2.3.0':
|
||||
resolution: {integrity: sha512-a2qVQffcrnetehvwsN+LdipxQ6jejwZLgAvS9/91+C0gP4CKyikY01c0tSs0I4tSL7qHdCw1Fx0quLw+A9uyLA==}
|
||||
|
||||
'@tokenizer/token@0.3.0':
|
||||
resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
|
||||
|
||||
'@tsclass/tsclass@3.0.48':
|
||||
resolution: {integrity: sha512-hC65UvDlp9qvsl6OcIZXz0JNiWZ0gyzsTzbXpg215sGxopgbkOLCr6E0s4qCTnweYm95gt2AdY95uP7M7kExaQ==}
|
||||
|
||||
@ -1445,6 +1454,10 @@ packages:
|
||||
resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
file-type@19.0.0:
|
||||
resolution: {integrity: sha512-s7cxa7/leUWLiXO78DVVfBVse+milos9FitauDLG1pI7lNaJ2+5lzPnr2N24ym+84HVwJL6hVuGfgVE+ALvU8Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
fill-range@7.0.1:
|
||||
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
||||
engines: {node: '>=8'}
|
||||
@ -2142,6 +2155,11 @@ packages:
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
|
||||
mime@4.0.3:
|
||||
resolution: {integrity: sha512-KgUb15Oorc0NEKPbvfa0wRU+PItIEZmiv+pyAO2i0oTIVTJhlzMclU7w4RXWQrSOVH5ax/p/CkIO7KI4OyFJTQ==}
|
||||
engines: {node: '>=16'}
|
||||
hasBin: true
|
||||
|
||||
mimic-fn@2.1.0:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
engines: {node: '>=6'}
|
||||
@ -2358,6 +2376,10 @@ packages:
|
||||
resolution: {integrity: sha512-AHXsYi9EcYlSm3uUANz7h5WSktHiyTnUeHqdWmyRdjdMhgq9LgZ8pggl9FOUGuCLVfe+NKxp2k9sEMCH3tHIEg==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
peek-readable@5.0.0:
|
||||
resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
pend@1.2.0:
|
||||
resolution: {integrity: sha1-elfrVQpng/kRUzH89GY9XI4AelA=}
|
||||
|
||||
@ -2464,6 +2486,10 @@ packages:
|
||||
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
readable-web-to-node-stream@3.0.2:
|
||||
resolution: {integrity: sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
readdirp@3.6.0:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
@ -2682,6 +2708,10 @@ packages:
|
||||
strnum@1.0.5:
|
||||
resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==}
|
||||
|
||||
strtok3@7.0.0:
|
||||
resolution: {integrity: sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
stubborn-fs@1.2.5:
|
||||
resolution: {integrity: sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==}
|
||||
|
||||
@ -2732,6 +2762,10 @@ packages:
|
||||
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
|
||||
engines: {node: '>=0.6'}
|
||||
|
||||
token-types@5.0.1:
|
||||
resolution: {integrity: sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
tr46@0.0.3:
|
||||
resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=}
|
||||
|
||||
@ -3630,6 +3664,12 @@ snapshots:
|
||||
'@types/mime-types': 2.1.4
|
||||
mime-types: 2.1.35
|
||||
|
||||
'@push.rocks/smartmime@2.0.0':
|
||||
dependencies:
|
||||
'@types/mime-types': 2.1.4
|
||||
file-type: 19.0.0
|
||||
mime: 4.0.3
|
||||
|
||||
'@push.rocks/smartnetwork@3.0.2':
|
||||
dependencies:
|
||||
'@pushrocks/smartping': 1.0.8
|
||||
@ -4037,6 +4077,8 @@ snapshots:
|
||||
dependencies:
|
||||
stubborn-fs: 1.2.5
|
||||
|
||||
'@tokenizer/token@0.3.0': {}
|
||||
|
||||
'@tsclass/tsclass@3.0.48':
|
||||
dependencies:
|
||||
type-fest: 2.19.0
|
||||
@ -4969,6 +5011,12 @@ snapshots:
|
||||
dependencies:
|
||||
is-unicode-supported: 2.0.0
|
||||
|
||||
file-type@19.0.0:
|
||||
dependencies:
|
||||
readable-web-to-node-stream: 3.0.2
|
||||
strtok3: 7.0.0
|
||||
token-types: 5.0.1
|
||||
|
||||
fill-range@7.0.1:
|
||||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
@ -5956,6 +6004,8 @@ snapshots:
|
||||
|
||||
mime@1.6.0: {}
|
||||
|
||||
mime@4.0.3: {}
|
||||
|
||||
mimic-fn@2.1.0: {}
|
||||
|
||||
mimic-response@3.1.0: {}
|
||||
@ -6125,6 +6175,8 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
peek-readable@5.0.0: {}
|
||||
|
||||
pend@1.2.0: {}
|
||||
|
||||
picocolors@1.0.1: {}
|
||||
@ -6248,6 +6300,10 @@ snapshots:
|
||||
string_decoder: 1.3.0
|
||||
util-deprecate: 1.0.2
|
||||
|
||||
readable-web-to-node-stream@3.0.2:
|
||||
dependencies:
|
||||
readable-stream: 3.6.2
|
||||
|
||||
readdirp@3.6.0:
|
||||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
@ -6530,6 +6586,11 @@ snapshots:
|
||||
|
||||
strnum@1.0.5: {}
|
||||
|
||||
strtok3@7.0.0:
|
||||
dependencies:
|
||||
'@tokenizer/token': 0.3.0
|
||||
peek-readable: 5.0.0
|
||||
|
||||
stubborn-fs@1.2.5: {}
|
||||
|
||||
supports-color@5.5.0:
|
||||
@ -6588,6 +6649,11 @@ snapshots:
|
||||
|
||||
toidentifier@1.0.1: {}
|
||||
|
||||
token-types@5.0.1:
|
||||
dependencies:
|
||||
'@tokenizer/token': 0.3.0
|
||||
ieee754: 1.2.1
|
||||
|
||||
tr46@0.0.3: {}
|
||||
|
||||
tr46@2.1.0:
|
||||
|
219
readme.md
219
readme.md
@ -1,5 +1,5 @@
|
||||
# @push.rocks/smartbucket
|
||||
simple cloud independent object storage
|
||||
A TypeScript library for simple cloud independent object storage with support for buckets, directories, and files.
|
||||
|
||||
## Install
|
||||
|
||||
@ -13,15 +13,28 @@ This command will download and install `@push.rocks/smartbucket` along with its
|
||||
|
||||
## Usage
|
||||
|
||||
`@push.rocks/smartbucket` is a module designed to provide simple cloud-independent object storage functionality. It wraps various cloud storage providers such as AWS S3, Google Cloud Storage, and others, offering a unified API to manage storage buckets and objects within those buckets.
|
||||
`@push.rocks/smartbucket` is a TypeScript module designed to provide simple cloud-independent object storage functionality. It wraps various cloud storage providers such as AWS S3, Google Cloud Storage, and others, offering a unified API to manage storage buckets and objects within those buckets.
|
||||
|
||||
To use `@push.rocks/smartbucket` in your project, you'll need to follow these general steps:
|
||||
In this guide, we will delve into the usage of SmartBucket, covering its full range of features from setting up the library to advanced usage scenarios.
|
||||
|
||||
### Table of Contents
|
||||
1. [Setting Up](#setting-up)
|
||||
2. [Creating a New Bucket](#creating-a-new-bucket)
|
||||
3. [Listing Buckets](#listing-buckets)
|
||||
4. [Working with Files](#working-with-files)
|
||||
- [Uploading Files](#uploading-files)
|
||||
- [Downloading Files](#downloading-files)
|
||||
- [Deleting Files](#deleting-files)
|
||||
- [Streaming Files](#streaming-files)
|
||||
5. [Working with Directories](#working-with-directories)
|
||||
6. [Advanced Features](#advanced-features)
|
||||
- [Bucket Policies](#bucket-policies)
|
||||
- [Object Metadata](#object-metadata)
|
||||
- [Cloud Agnostic](#cloud-agnostic)
|
||||
|
||||
### Setting Up
|
||||
|
||||
First, ensure you are using ECMAScript modules (ESM) and TypeScript in your project for best compatibility.
|
||||
|
||||
Here's how to import and initialize smartbucket in a TypeScript file:
|
||||
First, ensure you are using ECMAScript modules (ESM) and TypeScript in your project for best compatibility. Here's how to import and initialize SmartBucket in a TypeScript file:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
@ -35,10 +48,12 @@ const mySmartBucket = new SmartBucket({
|
||||
accessKey: "yourAccessKey",
|
||||
accessSecret: "yourSecretKey",
|
||||
endpoint: "yourEndpointURL",
|
||||
port: 443, // Default is 443, could be customized for specific endpoint
|
||||
useSsl: true // Defaults to true
|
||||
});
|
||||
```
|
||||
|
||||
Make sure to replace `"yourAccessKey"`, `"yourSecretKey"`, and `"yourEndpointURL"` with your actual credentials and endpoint URL.
|
||||
Make sure to replace `"yourAccessKey"`, `"yourSecretKey"`, and `"yourEndpointURL"` with your actual credentials and endpoint URL. The `port` and `useSsl` options are optional and can be omitted if the defaults are acceptable.
|
||||
|
||||
### Creating a New Bucket
|
||||
|
||||
@ -58,19 +73,15 @@ async function createBucket(bucketName: string) {
|
||||
createBucket("exampleBucket");
|
||||
```
|
||||
|
||||
**Important:** Bucket names must be unique across the storage service.
|
||||
Bucket names must be unique across the storage service.
|
||||
|
||||
### Listing Buckets
|
||||
|
||||
To list all buckets:
|
||||
Currently, SmartBucket does not include a direct method to list all buckets, but you can access the underlying client provided by the cloud storage SDK to perform such operations, depending on the SDK's capabilities.
|
||||
|
||||
```typescript
|
||||
// Currently, SmartBucket does not include a direct method to list all buckets,
|
||||
// but you can access the underlying client provided by the cloud storage SDK
|
||||
// to perform such operations, depending on the SDK's capabilities.
|
||||
```
|
||||
### Working with Files
|
||||
|
||||
### Uploading Objects to a Bucket
|
||||
#### Uploading Files
|
||||
|
||||
To upload an object to a bucket:
|
||||
|
||||
@ -78,8 +89,10 @@ To upload an object to a bucket:
|
||||
async function uploadFile(bucketName: string, filePath: string, fileContent: Buffer | string) {
|
||||
const myBucket: Bucket = await mySmartBucket.getBucketByName(bucketName);
|
||||
if (myBucket) {
|
||||
await myBucket.fastStore(filePath, fileContent);
|
||||
await myBucket.fastPut({ path: filePath, contents: fileContent });
|
||||
console.log(`File uploaded to ${bucketName} at ${filePath}`);
|
||||
} else {
|
||||
console.error(`Bucket ${bucketName} does not exist.`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,7 +100,7 @@ async function uploadFile(bucketName: string, filePath: string, fileContent: Buf
|
||||
uploadFile("exampleBucket", "path/to/object.txt", "Hello, world!");
|
||||
```
|
||||
|
||||
### Downloading Objects from a Bucket
|
||||
#### Downloading Files
|
||||
|
||||
To download an object:
|
||||
|
||||
@ -95,8 +108,10 @@ To download an object:
|
||||
async function downloadFile(bucketName: string, filePath: string) {
|
||||
const myBucket: Bucket = await mySmartBucket.getBucketByName(bucketName);
|
||||
if (myBucket) {
|
||||
const fileContent: Buffer = await myBucket.fastGet(filePath);
|
||||
const fileContent: Buffer = await myBucket.fastGet({ path: filePath });
|
||||
console.log("Downloaded file content:", fileContent.toString());
|
||||
} else {
|
||||
console.error(`Bucket ${bucketName} does not exist.`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +119,7 @@ async function downloadFile(bucketName: string, filePath: string) {
|
||||
downloadFile("exampleBucket", "path/to/object.txt");
|
||||
```
|
||||
|
||||
### Deleting Objects
|
||||
#### Deleting Files
|
||||
|
||||
To delete an object from a bucket:
|
||||
|
||||
@ -112,8 +127,10 @@ To delete an object from a bucket:
|
||||
async function deleteFile(bucketName: string, filePath: string) {
|
||||
const myBucket: Bucket = await mySmartBucket.getBucketByName(bucketName);
|
||||
if (myBucket) {
|
||||
await myBucket.fastRemove(filePath);
|
||||
await myBucket.fastRemove({ path: filePath });
|
||||
console.log(`File at ${filePath} deleted from ${bucketName}.`);
|
||||
} else {
|
||||
console.error(`Bucket ${bucketName} does not exist.`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,19 +138,171 @@ async function deleteFile(bucketName: string, filePath: string) {
|
||||
deleteFile("exampleBucket", "path/to/object.txt");
|
||||
```
|
||||
|
||||
#### Streaming Files
|
||||
|
||||
SmartBucket allows you to work with file streams, which can be useful for handling large files.
|
||||
|
||||
To read a file as a stream:
|
||||
|
||||
```typescript
|
||||
import { ReplaySubject } from '@push.rocks/smartrx';
|
||||
|
||||
async function readFileStream(bucketName: string, filePath: string) {
|
||||
const myBucket: Bucket = await mySmartBucket.getBucketByName(bucketName);
|
||||
if (myBucket) {
|
||||
const fileStream: ReplaySubject<Buffer> = await myBucket.fastGetStream({ path: filePath });
|
||||
fileStream.subscribe({
|
||||
next(chunk: Buffer) {
|
||||
console.log("Chunk received:", chunk.toString());
|
||||
},
|
||||
complete() {
|
||||
console.log("File read completed.");
|
||||
},
|
||||
error(err) {
|
||||
console.error("Error reading file stream:", err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.error(`Bucket ${bucketName} does not exist.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the function
|
||||
readFileStream("exampleBucket", "path/to/object.txt");
|
||||
```
|
||||
|
||||
To write a file as a stream:
|
||||
|
||||
```typescript
|
||||
import { Readable } from 'stream';
|
||||
|
||||
async function writeFileStream(bucketName: string, filePath: string, readableStream: Readable) {
|
||||
const myBucket: Bucket = await mySmartBucket.getBucketByName(bucketName);
|
||||
if (myBucket) {
|
||||
await myBucket.fastPutStream({ path: filePath, dataStream: readableStream });
|
||||
console.log(`File streamed to ${bucketName} at ${filePath}`);
|
||||
} else {
|
||||
console.error(`Bucket ${bucketName} does not exist.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a readable stream from a string
|
||||
const readable = new Readable();
|
||||
readable.push('Hello world streamed as a file!');
|
||||
readable.push(null); // Indicates end of the stream
|
||||
|
||||
// Use the function
|
||||
writeFileStream("exampleBucket", "path/to/streamedObject.txt", readable);
|
||||
```
|
||||
|
||||
### Working with Directories
|
||||
|
||||
`@push.rocks/smartbucket` abstracts directories within buckets for easier object management. You can create, list, and delete directories using the `Directory` class.
|
||||
|
||||
### Additional Features
|
||||
```typescript
|
||||
async function listDirectoryContents(bucketName: string, directoryPath: string) {
|
||||
const myBucket: Bucket = await mySmartBucket.getBucketByName(bucketName);
|
||||
if (myBucket) {
|
||||
const baseDirectory: Directory = await myBucket.getBaseDirectory();
|
||||
const targetDirectory: Directory = await baseDirectory.getSubDirectoryByName(directoryPath);
|
||||
console.log('Listing directories:');
|
||||
const directories = await targetDirectory.listDirectories();
|
||||
directories.forEach(dir => {
|
||||
console.log(`- ${dir.name}`);
|
||||
});
|
||||
|
||||
- **Bucket Policies:** Manage bucket policies to control access permissions.
|
||||
- **Object Metadata:** Retrieve and modify object metadata.
|
||||
- **Cloud-Agnostic:** Designed to work with multiple cloud providers, allowing for easier migration or multi-cloud strategies.
|
||||
console.log('Listing files:');
|
||||
const files = await targetDirectory.listFiles();
|
||||
files.forEach(file => {
|
||||
console.log(`- ${file.name}`);
|
||||
});
|
||||
} else {
|
||||
console.error(`Bucket ${bucketName} does not exist.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the function
|
||||
listDirectoryContents("exampleBucket", "some/directory/path");
|
||||
```
|
||||
|
||||
To create a file within a directory:
|
||||
|
||||
```typescript
|
||||
async function createFileInDirectory(bucketName: string, directoryPath: string, fileName: string, fileContent: string) {
|
||||
const myBucket: Bucket = await mySmartBucket.getBucketByName(bucketName);
|
||||
if (myBucket) {
|
||||
const baseDirectory: Directory = await myBucket.getBaseDirectory();
|
||||
const targetDirectory: Directory = await baseDirectory.getSubDirectoryByName(directoryPath);
|
||||
await targetDirectory.createEmptyFile(fileName); // Create an empty file
|
||||
const file = new File({ directoryRefArg: targetDirectory, fileName });
|
||||
await file.updateWithContents({ contents: fileContent });
|
||||
console.log(`File created: ${fileName}`);
|
||||
} else {
|
||||
console.error(`Bucket ${bucketName} does not exist.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the function
|
||||
createFileInDirectory("exampleBucket", "some/directory", "newfile.txt", "Hello, world!");
|
||||
```
|
||||
|
||||
### Advanced Features
|
||||
|
||||
#### Bucket Policies
|
||||
|
||||
Manage bucket policies to control access permissions. This feature is dependent on the policies provided by the storage service (e.g., AWS S3, MinIO).
|
||||
|
||||
#### Object Metadata
|
||||
|
||||
You can retrieve and modify object metadata. Metadata can be useful for storing additional information about an object.
|
||||
|
||||
To retrieve metadata:
|
||||
|
||||
```typescript
|
||||
async function getObjectMetadata(bucketName: string, filePath: string) {
|
||||
const myBucket: Bucket = await mySmartBucket.getBucketByName(bucketName);
|
||||
if (myBucket) {
|
||||
const metadata = await mySmartBucket.minioClient.statObject(bucketName, filePath);
|
||||
console.log("Object metadata:", metadata);
|
||||
} else {
|
||||
console.error(`Bucket ${bucketName} does not exist.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the function
|
||||
getObjectMetadata("exampleBucket", "path/to/object.txt");
|
||||
```
|
||||
|
||||
To update metadata:
|
||||
|
||||
```typescript
|
||||
async function updateObjectMetadata(bucketName: string, filePath: string, newMetadata: { [key: string]: string }) {
|
||||
const myBucket: Bucket = await mySmartBucket.getBucketByName(bucketName);
|
||||
if (myBucket) {
|
||||
await myBucket.copyObject({
|
||||
objectKey: filePath,
|
||||
nativeMetadata: newMetadata,
|
||||
deleteExistingNativeMetadata: false,
|
||||
});
|
||||
console.log(`Metadata updated for ${filePath}`);
|
||||
} else {
|
||||
console.error(`Bucket ${bucketName} does not exist.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the function
|
||||
updateObjectMetadata("exampleBucket", "path/to/object.txt", {
|
||||
customKey: "customValue"
|
||||
});
|
||||
```
|
||||
|
||||
#### Cloud Agnostic
|
||||
|
||||
`@push.rocks/smartbucket` is designed to work with multiple cloud providers, allowing for easier migration or multi-cloud strategies. This means you can switch from one provider to another with minimal changes to your codebase.
|
||||
|
||||
Remember, each cloud provider has specific features and limitations. `@push.rocks/smartbucket` aims to abstract common functionalities, but always refer to the specific cloud provider's documentation for advanced features or limitations.
|
||||
|
||||
> **Note:** This document focuses on basic operations to get you started with `@push.rocks/smartbucket`. For advanced usage, including streaming data, managing bucket policies, and handling large file uploads, refer to the detailed API documentation and examples.
|
||||
This guide covers the basic to advanced scenarios of using `@push.rocks/smartbucket`. For further details, refer to the API documentation and examples.
|
||||
|
||||
## License and Legal Information
|
||||
|
||||
|
@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@push.rocks/smartbucket',
|
||||
version: '3.0.2',
|
||||
description: 'A TypeScript library for simple cloud independent object storage with support for buckets, directories, and files.'
|
||||
version: '3.0.5',
|
||||
description: 'A TypeScript library that offers simple, cloud-independent object storage with features like bucket creation, file management, and directory management.'
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as plugins from './smartbucket.plugins.js';
|
||||
import { SmartBucket } from './smartbucket.classes.smartbucket.js';
|
||||
import { Directory } from './smartbucket.classes.directory.js';
|
||||
import * as plugins from './plugins.js';
|
||||
import { SmartBucket } from './classes.smartbucket.js';
|
||||
import { Directory } from './classes.directory.js';
|
||||
|
||||
export class Bucket {
|
||||
public static async getBucketByName(smartbucketRef: SmartBucket, bucketNameArg: string) {
|
||||
@ -52,15 +52,35 @@ export class Bucket {
|
||||
public async fastPut(optionsArg: {
|
||||
path: string;
|
||||
contents: string | Buffer;
|
||||
overwrite?: boolean;
|
||||
}): Promise<void> {
|
||||
const streamIntake = new plugins.smartstream.StreamIntake();
|
||||
const putPromise = this.smartbucketRef.minioClient
|
||||
.putObject(this.name, optionsArg.path, streamIntake)
|
||||
.catch((e) => console.log(e));
|
||||
streamIntake.pushData(optionsArg.contents);
|
||||
streamIntake.signalEnd();
|
||||
const response = await putPromise;
|
||||
try {
|
||||
// Check if the object already exists
|
||||
const exists = await this.fastExists({ path: optionsArg.path });
|
||||
|
||||
if (exists && !optionsArg.overwrite) {
|
||||
console.error(`Object already exists at path '${optionsArg.path}' in bucket '${this.name}'.`);
|
||||
return;
|
||||
} else if (exists && optionsArg.overwrite) {
|
||||
console.log(`Overwriting existing object at path '${optionsArg.path}' in bucket '${this.name}'.`);
|
||||
} else {
|
||||
console.log(`Creating new object at path '${optionsArg.path}' in bucket '${this.name}'.`);
|
||||
}
|
||||
|
||||
// Proceed with putting the object
|
||||
const streamIntake = new plugins.smartstream.StreamIntake();
|
||||
const putPromise = this.smartbucketRef.minioClient.putObject(this.name, optionsArg.path, streamIntake);
|
||||
streamIntake.pushData(optionsArg.contents);
|
||||
streamIntake.signalEnd();
|
||||
await putPromise;
|
||||
|
||||
console.log(`Object '${optionsArg.path}' has been successfully stored in bucket '${this.name}'.`);
|
||||
} catch (error) {
|
||||
console.error(`Error storing object at path '${optionsArg.path}' in bucket '${this.name}':`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get file
|
||||
@ -126,20 +146,42 @@ export class Bucket {
|
||||
path: string;
|
||||
dataStream: plugins.stream.Readable;
|
||||
nativeMetadata?: { [key: string]: string };
|
||||
overwrite?: boolean;
|
||||
}): Promise<void> {
|
||||
await this.smartbucketRef.minioClient.putObject(
|
||||
this.name,
|
||||
optionsArg.path,
|
||||
optionsArg.dataStream,
|
||||
null,
|
||||
...(optionsArg.nativeMetadata
|
||||
? (() => {
|
||||
const returnObject: any = {};
|
||||
return returnObject;
|
||||
})()
|
||||
: {})
|
||||
);
|
||||
try {
|
||||
// Check if the object already exists
|
||||
const exists = await this.fastExists({ path: optionsArg.path });
|
||||
|
||||
if (exists && !optionsArg.overwrite) {
|
||||
console.error(`Object already exists at path '${optionsArg.path}' in bucket '${this.name}'.`);
|
||||
return;
|
||||
} else if (exists && optionsArg.overwrite) {
|
||||
console.log(`Overwriting existing object at path '${optionsArg.path}' in bucket '${this.name}'.`);
|
||||
} else {
|
||||
console.log(`Creating new object at path '${optionsArg.path}' in bucket '${this.name}'.`);
|
||||
}
|
||||
|
||||
// Proceed with putting the object
|
||||
await this.smartbucketRef.minioClient.putObject(
|
||||
this.name,
|
||||
optionsArg.path,
|
||||
optionsArg.dataStream,
|
||||
null,
|
||||
...(optionsArg.nativeMetadata
|
||||
? (() => {
|
||||
const returnObject: any = {};
|
||||
return returnObject;
|
||||
})()
|
||||
: {})
|
||||
);
|
||||
|
||||
console.log(`Object '${optionsArg.path}' has been successfully stored in bucket '${this.name}'.`);
|
||||
} catch (error) {
|
||||
console.error(`Error storing object at path '${optionsArg.path}' in bucket '${this.name}':`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async copyObject(optionsArg: {
|
||||
/**
|
||||
@ -198,7 +240,12 @@ export class Bucket {
|
||||
await this.smartbucketRef.minioClient.removeObject(this.name, optionsArg.path);
|
||||
}
|
||||
|
||||
public async doesObjectExist(optionsArg: {
|
||||
/**
|
||||
* check wether file exists
|
||||
* @param optionsArg
|
||||
* @returns
|
||||
*/
|
||||
public async fastExists(optionsArg: {
|
||||
path: string;
|
||||
}): Promise<boolean> {
|
||||
try {
|
||||
@ -215,4 +262,10 @@ export class Bucket {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async fastStat(optionsArg: {
|
||||
path: string;
|
||||
}) {
|
||||
return this.smartbucketRef.minioClient.statObject(this.name, optionsArg.path);
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import * as plugins from './smartbucket.plugins.js';
|
||||
import { Bucket } from './smartbucket.classes.bucket.js';
|
||||
import { File } from './smartbucket.classes.file.js';
|
||||
import * as plugins from './plugins.js';
|
||||
import { Bucket } from './classes.bucket.js';
|
||||
import { File } from './classes.file.js';
|
||||
|
||||
export class Directory {
|
||||
public bucketRef: Bucket;
|
||||
@ -59,6 +59,32 @@ export class Directory {
|
||||
return basePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a file by name
|
||||
*/
|
||||
public async getFile(optionsArg: {
|
||||
name: string;
|
||||
createWithContents?: string | Buffer;
|
||||
}): Promise<File> {
|
||||
// check wether the file exists
|
||||
const exists = await this.bucketRef.fastExists({
|
||||
path: this.getBasePath() + optionsArg.name,
|
||||
});
|
||||
if (!exists && !optionsArg.createWithContents) {
|
||||
return null;
|
||||
}
|
||||
if (!exists && optionsArg.createWithContents) {
|
||||
await this.fastPut({
|
||||
path: optionsArg.name,
|
||||
contents: optionsArg.createWithContents,
|
||||
});
|
||||
}
|
||||
return new File({
|
||||
directoryRefArg: this,
|
||||
fileName: optionsArg.name,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* lists all files
|
||||
*/
|
175
ts/classes.file.ts
Normal file
175
ts/classes.file.ts
Normal file
@ -0,0 +1,175 @@
|
||||
import * as plugins from './plugins.js';
|
||||
import { Directory } from './classes.directory.js';
|
||||
import { MetaData } from './classes.metadata.js';
|
||||
|
||||
|
||||
/**
|
||||
* represents a file in a directory
|
||||
*/
|
||||
export class File {
|
||||
// STATIC
|
||||
|
||||
/**
|
||||
* creates a file in draft mode
|
||||
* you need to call .save() to store it in s3
|
||||
* @param optionsArg
|
||||
*/
|
||||
public static async create(optionsArg: {
|
||||
directory: Directory;
|
||||
name: string;
|
||||
contents: Buffer | string | plugins.stream.Readable;
|
||||
/**
|
||||
* if contents are of type string, you can specify the encoding here
|
||||
*/
|
||||
encoding?: 'utf8' | 'binary';
|
||||
}): Promise<File> {
|
||||
const contents =
|
||||
typeof optionsArg.contents === 'string'
|
||||
? Buffer.from(optionsArg.contents, optionsArg.encoding)
|
||||
: optionsArg.contents;
|
||||
const file = new File({
|
||||
directoryRefArg: optionsArg.directory,
|
||||
fileName: optionsArg.name,
|
||||
});
|
||||
if (contents instanceof plugins.stream.Readable) {} else {
|
||||
await optionsArg.directory.fastPut({
|
||||
path: optionsArg.name,
|
||||
contents: contents,
|
||||
});
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
// INSTANCE
|
||||
public parentDirectoryRef: Directory;
|
||||
public name: string;
|
||||
|
||||
public getBasePath(): string {
|
||||
return plugins.path.join(this.parentDirectoryRef.getBasePath(), this.name);
|
||||
};
|
||||
|
||||
constructor(optionsArg: { directoryRefArg: Directory; fileName: string }) {
|
||||
this.parentDirectoryRef = optionsArg.directoryRefArg;
|
||||
this.name = optionsArg.fileName;
|
||||
}
|
||||
|
||||
public async getContentsAsString(): Promise<string> {
|
||||
const fileBuffer = await this.getContents();
|
||||
return fileBuffer.toString();
|
||||
}
|
||||
|
||||
public async getContents(): Promise<Buffer> {
|
||||
const resultBuffer = await this.parentDirectoryRef.bucketRef.fastGet({
|
||||
path: this.getBasePath(),
|
||||
});
|
||||
return resultBuffer;
|
||||
}
|
||||
|
||||
public async getReadStream() {
|
||||
const readStream = this.parentDirectoryRef.bucketRef.fastGetStream({
|
||||
path: this.getBasePath(),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* removes this file
|
||||
* for using recycling mechanics use .delete()
|
||||
*/
|
||||
public async remove() {
|
||||
await this.parentDirectoryRef.bucketRef.fastRemove({
|
||||
path: this.getBasePath(),
|
||||
});
|
||||
if (!this.name.endsWith('.metadata')) {
|
||||
await this.parentDirectoryRef.bucketRef.fastRemove({
|
||||
path: this.getBasePath() + '.metadata',
|
||||
});
|
||||
}
|
||||
await this.parentDirectoryRef.listFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes the file with recycling mechanics
|
||||
*/
|
||||
public async delete() {
|
||||
await this.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* allows locking the file
|
||||
* @param optionsArg
|
||||
*/
|
||||
public async lock(optionsArg?: { timeoutMillis?: number }) {
|
||||
const metadata = await this.getMetaData();
|
||||
await metadata.setLock({
|
||||
lock: 'locked',
|
||||
expires: Date.now() + (optionsArg?.timeoutMillis || 1000),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* actively unlocks a file
|
||||
*
|
||||
*/
|
||||
public async unlock(optionsArg?: {
|
||||
/**
|
||||
* unlock the file even if not locked from this instance
|
||||
*/
|
||||
force?: boolean;
|
||||
}) {
|
||||
const metadata = await this.getMetaData();
|
||||
await metadata.removeLock({
|
||||
force: optionsArg?.force,
|
||||
});
|
||||
}
|
||||
|
||||
public async updateWithContents(optionsArg: {
|
||||
contents: Buffer | string | plugins.stream.Readable;
|
||||
encoding?: 'utf8' | 'binary';
|
||||
}) {
|
||||
if (optionsArg.contents instanceof plugins.stream.Readable) {
|
||||
await this.parentDirectoryRef.bucketRef.fastPutStream({
|
||||
path: this.getBasePath(),
|
||||
dataStream: optionsArg.contents,
|
||||
});
|
||||
} else if (Buffer.isBuffer(optionsArg.contents)) {
|
||||
await this.parentDirectoryRef.bucketRef.fastPut({
|
||||
path: this.getBasePath(),
|
||||
contents: optionsArg.contents,
|
||||
});
|
||||
} else if (typeof optionsArg.contents === 'string') {
|
||||
await this.parentDirectoryRef.bucketRef.fastPut({
|
||||
path: this.getBasePath(),
|
||||
contents: Buffer.from(optionsArg.contents, optionsArg.encoding),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* allows updating the metadata of a file
|
||||
* @param updatedMetadata
|
||||
*/
|
||||
public async getMetaData() {
|
||||
if (this.name.endsWith('.metadata')) {
|
||||
throw new Error('metadata files cannot have metadata');
|
||||
}
|
||||
const metadata = await MetaData.createForFile({
|
||||
file: this,
|
||||
});
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the contents as json
|
||||
*/
|
||||
public async getJsonData() {
|
||||
const json = await this.getContentsAsString();
|
||||
const parsed = await JSON.parse(json);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
public async writeJsonData(dataArg: any) {
|
||||
await this.updateWithContents({
|
||||
contents: JSON.stringify(dataArg),
|
||||
});
|
||||
}
|
||||
}
|
100
ts/classes.metadata.ts
Normal file
100
ts/classes.metadata.ts
Normal file
@ -0,0 +1,100 @@
|
||||
import * as plugins from './plugins.js';
|
||||
|
||||
import { File } from './classes.file.js';
|
||||
|
||||
export class MetaData {
|
||||
// static
|
||||
public static async createForFile(optionsArg: { file: File }) {
|
||||
const metaData = new MetaData();
|
||||
metaData.fileRef = optionsArg.file;
|
||||
|
||||
// lets find the existing metadata file
|
||||
metaData.metadataFile = await metaData.fileRef.parentDirectoryRef.getFile({
|
||||
name: metaData.fileRef.name + '.metadata',
|
||||
createWithContents: '{}',
|
||||
});
|
||||
|
||||
return metaData;
|
||||
}
|
||||
|
||||
// instance
|
||||
/**
|
||||
* the file that contains the metadata
|
||||
*/
|
||||
metadataFile: File;
|
||||
|
||||
/**
|
||||
* the file that the metadata is for
|
||||
*/
|
||||
fileRef: File;
|
||||
|
||||
public async getFileType(optionsArg?: {
|
||||
useFileExtension?: boolean;
|
||||
useMagicBytes?: boolean;
|
||||
}): Promise<string> {
|
||||
if ((optionsArg && optionsArg.useFileExtension) || optionsArg.useFileExtension === undefined) {
|
||||
return plugins.path.extname(this.fileRef.name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the size of the fileRef
|
||||
*/
|
||||
public async getSizeInBytes(): Promise<number> {
|
||||
const stat = await this.fileRef.parentDirectoryRef.bucketRef.fastStat({
|
||||
path: this.fileRef.getBasePath(),
|
||||
});
|
||||
return stat.size;
|
||||
}
|
||||
|
||||
private prefixCustomMetaData = 'custom_';
|
||||
|
||||
public async storeCustomMetaData<T = any>(optionsArg: { key: string; value: T }) {
|
||||
const data = await this.metadataFile.getContentsAsString();
|
||||
data[this.prefixCustomMetaData + optionsArg.key] = optionsArg.value;
|
||||
await this.metadataFile.writeJsonData(data);
|
||||
}
|
||||
|
||||
public async getCustomMetaData<T = any>(optionsArg: { key: string }): Promise<T> {
|
||||
const data = await this.metadataFile.getJsonData();
|
||||
return data[this.prefixCustomMetaData + optionsArg.key];
|
||||
}
|
||||
|
||||
public async deleteCustomMetaData(optionsArg: { key: string }) {
|
||||
const data = await this.metadataFile.getJsonData();
|
||||
delete data[this.prefixCustomMetaData + optionsArg.key];
|
||||
await this.metadataFile.writeJsonData(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* set a lock on the ref file
|
||||
* @param optionsArg
|
||||
*/
|
||||
public async setLock(optionsArg: { lock: string; expires: number }) {
|
||||
const data = await this.metadataFile.getJsonData();
|
||||
data.lock = optionsArg.lock;
|
||||
data.lockExpires = optionsArg.expires;
|
||||
await this.metadataFile.writeJsonData(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove the lock on the ref file
|
||||
* @param optionsArg
|
||||
*/
|
||||
public async removeLock(optionsArg: { force: boolean }) {
|
||||
const data = await this.metadataFile.getJsonData();
|
||||
delete data.lock;
|
||||
delete data.lockExpires;
|
||||
await this.metadataFile.writeJsonData(data);
|
||||
}
|
||||
|
||||
public async checkLocked(): Promise<boolean> {
|
||||
const data = await this.metadataFile.getJsonData();
|
||||
return data.lock && data.lockExpires > Date.now();
|
||||
}
|
||||
|
||||
public async getLockInfo(): Promise<{ lock: string; expires: number }> {
|
||||
const data = await this.metadataFile.getJsonData();
|
||||
return { lock: data.lock, expires: data.lockExpires };
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import * as plugins from './smartbucket.plugins.js';
|
||||
import { Bucket } from './smartbucket.classes.bucket.js';
|
||||
import * as plugins from './plugins.js';
|
||||
import { Bucket } from './classes.bucket.js';
|
||||
|
||||
export class SmartBucket {
|
||||
public config: plugins.tsclass.storage.IS3Descriptor;
|
@ -1,4 +1,4 @@
|
||||
export * from './smartbucket.classes.smartbucket.js';
|
||||
export * from './smartbucket.classes.bucket.js';
|
||||
export * from './smartbucket.classes.directory.js';
|
||||
export * from './smartbucket.classes.file.js';
|
||||
export * from './classes.smartbucket.js';
|
||||
export * from './classes.bucket.js';
|
||||
export * from './classes.directory.js';
|
||||
export * from './classes.file.js';
|
||||
|
@ -5,12 +5,13 @@ import * as stream from 'stream';
|
||||
export { path, stream };
|
||||
|
||||
// @push.rocks scope
|
||||
import * as smartmime from '@push.rocks/smartmime';
|
||||
import * as smartpath from '@push.rocks/smartpath';
|
||||
import * as smartpromise from '@push.rocks/smartpromise';
|
||||
import * as smartrx from '@push.rocks/smartrx';
|
||||
import * as smartstream from '@push.rocks/smartstream';
|
||||
|
||||
export { smartpath, smartpromise, smartrx, smartstream };
|
||||
export { smartmime, smartpath, smartpromise, smartrx, smartstream };
|
||||
|
||||
// @tsclass
|
||||
import * as tsclass from '@tsclass/tsclass';
|
@ -1,140 +0,0 @@
|
||||
import * as plugins from './smartbucket.plugins.js';
|
||||
import { Directory } from './smartbucket.classes.directory.js';
|
||||
|
||||
export interface IFileMetaData {
|
||||
name: string;
|
||||
fileType: string;
|
||||
size: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* represents a file in a directory
|
||||
*/
|
||||
export class File {
|
||||
// STATIC
|
||||
|
||||
/**
|
||||
* creates a file in draft mode
|
||||
* you need to call .save() to store it in s3
|
||||
* @param optionsArg
|
||||
*/
|
||||
public static async create(optionsArg: {
|
||||
directory: Directory;
|
||||
name: string;
|
||||
contents: Buffer | string | plugins.stream.Readable;
|
||||
/**
|
||||
* if contents are of type string, you can specify the encoding here
|
||||
*/
|
||||
encoding?: 'utf8' | 'binary';
|
||||
}): Promise<File> {
|
||||
const contents =
|
||||
typeof optionsArg.contents === 'string'
|
||||
? Buffer.from(optionsArg.contents, optionsArg.encoding)
|
||||
: optionsArg.contents;
|
||||
const file = new File({
|
||||
directoryRefArg: optionsArg.directory,
|
||||
fileName: optionsArg.name,
|
||||
});
|
||||
if (contents instanceof plugins.stream.Readable) {} else {
|
||||
await optionsArg.directory.fastPut({
|
||||
path: optionsArg.name,
|
||||
contents: contents,
|
||||
});
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
// INSTANCE
|
||||
public parentDirectoryRef: Directory;
|
||||
public name: string;
|
||||
|
||||
public path: string;
|
||||
public metaData: IFileMetaData;
|
||||
|
||||
constructor(optionsArg: { directoryRefArg: Directory; fileName: string }) {
|
||||
this.parentDirectoryRef = optionsArg.directoryRefArg;
|
||||
this.name = optionsArg.fileName;
|
||||
}
|
||||
|
||||
public async getContentAsString() {
|
||||
const fileBuffer = await this.getContentAsBuffer();
|
||||
return fileBuffer.toString();
|
||||
}
|
||||
|
||||
public async getContentAsBuffer() {
|
||||
const done = plugins.smartpromise.defer();
|
||||
const fileStream = await this.parentDirectoryRef.bucketRef.smartbucketRef.minioClient
|
||||
.getObject(this.parentDirectoryRef.bucketRef.name, this.path)
|
||||
.catch((e) => console.log(e));
|
||||
let completeFile = Buffer.from('');
|
||||
const duplexStream = new plugins.smartstream.SmartDuplex<Buffer, Buffer>(
|
||||
{
|
||||
writeFunction: async (chunk) => {
|
||||
completeFile = Buffer.concat([chunk]);
|
||||
return chunk;
|
||||
},
|
||||
finalFunction: async (cb) => {
|
||||
done.resolve();
|
||||
return Buffer.from('');
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (!fileStream) {
|
||||
return null;
|
||||
}
|
||||
|
||||
fileStream.pipe(duplexStream);
|
||||
await done.promise;
|
||||
return completeFile;
|
||||
}
|
||||
|
||||
public async readStreaming() {
|
||||
// TODO
|
||||
throw new Error('not yet implemented');
|
||||
}
|
||||
|
||||
/**
|
||||
* removes this file
|
||||
*/
|
||||
public async remove() {
|
||||
await this.parentDirectoryRef.bucketRef.smartbucketRef.minioClient.removeObject(
|
||||
this.parentDirectoryRef.bucketRef.name,
|
||||
this.path
|
||||
);
|
||||
await this.parentDirectoryRef.listFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes the file
|
||||
*/
|
||||
public async delete() {}
|
||||
|
||||
/**
|
||||
* allows locking the file
|
||||
* @param optionsArg
|
||||
*/
|
||||
public async lock(optionsArg?: { timeoutMillis?: number }) {}
|
||||
|
||||
/**
|
||||
* actively unlocks a file
|
||||
*
|
||||
*/
|
||||
public async unlock(optionsArg?: {
|
||||
/**
|
||||
* unlock the file even if not locked from this instance
|
||||
*/
|
||||
force?: boolean;
|
||||
}) {}
|
||||
|
||||
public async updateWithContents(optionsArg: {
|
||||
contents: Buffer | string | plugins.stream.Readable;
|
||||
encoding?: 'utf8' | 'binary';
|
||||
}) {}
|
||||
|
||||
/**
|
||||
* allows updating the metadata of a file
|
||||
* @param updatedMetadata
|
||||
*/
|
||||
public async updateMetaData(updatedMetadata: any) {}
|
||||
}
|
Reference in New Issue
Block a user