fix(core): update
This commit is contained in:
		| @@ -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", | ||||
|   | ||||
							
								
								
									
										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: | ||||
|   | ||||
| @@ -3,6 +3,6 @@ | ||||
|  */ | ||||
| export const commitinfo = { | ||||
|   name: '@push.rocks/smartbucket', | ||||
|   version: '3.0.3', | ||||
|   version: '3.0.4', | ||||
|   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 | ||||
|    */ | ||||
							
								
								
									
										154
									
								
								ts/classes.file.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								ts/classes.file.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,154 @@ | ||||
| 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: new Date(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; | ||||
|   }) { | ||||
|  | ||||
|   } | ||||
|  | ||||
|   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() { | ||||
|     const metadata = await MetaData.createForFile({ | ||||
|       file: this, | ||||
|     }); | ||||
|     return metadata; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										105
									
								
								ts/classes.metadata.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								ts/classes.metadata.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| 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 json = await this.metadataFile.getContentsAsString(); | ||||
|     const parsed = await JSON.parse(json); | ||||
|     parsed[this.prefixCustomMetaData + optionsArg.key] = optionsArg.value; | ||||
|     await this.metadataFile.updateWithContents({ | ||||
|       contents: JSON.stringify(parsed), | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   public async getCustomMetaData<T = any>(optionsArg: { | ||||
|     key: string; | ||||
|   }): Promise<T> { | ||||
|     const json = await this.metadataFile.getContentsAsString(); | ||||
|     const parsed = await JSON.parse(json); | ||||
|     return parsed[this.prefixCustomMetaData + optionsArg.key]; | ||||
|   } | ||||
|  | ||||
|   public async deleteCustomMetaData(optionsArg: { | ||||
|     key: string; | ||||
|   }) { | ||||
|     const json = await this.metadataFile.getContentsAsString(); | ||||
|     const parsed = await JSON.parse(json); | ||||
|     delete parsed[this.prefixCustomMetaData + optionsArg.key]; | ||||
|     await this.metadataFile.updateWithContents({ | ||||
|       contents: JSON.stringify(parsed), | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * set a lock on the ref file | ||||
|    * @param optionsArg | ||||
|    */ | ||||
|   public async setLock(optionsArg: { | ||||
|     lock: string; | ||||
|     expires: Date; | ||||
|   }) { | ||||
|      | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * remove the lock on the ref file | ||||
|    * @param optionsArg  | ||||
|    */ | ||||
|   public async removeLock(optionsArg: { | ||||
|     force: boolean; | ||||
|   }) { | ||||
|  | ||||
|   } | ||||
| } | ||||
| @@ -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