Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
df0a439def | |||
7245b49c31 | |||
4b70edb947 | |||
9629a04da6 | |||
963463d40d | |||
ce58b99fc7 | |||
591c99736d | |||
559e3da47b | |||
a7ac870e05 | |||
d48c5e229a | |||
b9c384dd08 | |||
91c04b2364 | |||
b5dcc131e2 | |||
cb0ab2c9db | |||
2a17ee542e | |||
95e9d2f0ff | |||
1a71c76da3 | |||
e924511147 | |||
645ebbdd4d | |||
168148b2c9 | |||
1293fc4ca6 | |||
b040120813 | |||
5c2d92c041 | |||
eaf2e7e6bb |
@ -8,25 +8,28 @@
|
|||||||
"githost": "code.foss.global",
|
"githost": "code.foss.global",
|
||||||
"gitscope": "push.rocks",
|
"gitscope": "push.rocks",
|
||||||
"gitrepo": "smartbucket",
|
"gitrepo": "smartbucket",
|
||||||
"description": "A TypeScript library that offers simple, cloud-independent object storage with features like bucket creation, file management, and directory management.",
|
"description": "A TypeScript library offering simple and cloud-agnostic object storage with advanced features like bucket creation, file and directory management, and data streaming.",
|
||||||
"npmPackagename": "@push.rocks/smartbucket",
|
"npmPackagename": "@push.rocks/smartbucket",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
"TypeScript",
|
||||||
"cloud storage",
|
"cloud storage",
|
||||||
"object storage",
|
"object storage",
|
||||||
"TypeScript",
|
"bucket creation",
|
||||||
"S3",
|
|
||||||
"minio",
|
|
||||||
"file management",
|
"file management",
|
||||||
"directory management",
|
"directory management",
|
||||||
"bucket creation",
|
|
||||||
"data streaming",
|
"data streaming",
|
||||||
"multi-cloud",
|
"multi-cloud",
|
||||||
"API",
|
"API",
|
||||||
"unified storage",
|
"unified storage",
|
||||||
|
"S3",
|
||||||
|
"minio",
|
||||||
|
"file locking",
|
||||||
|
"metadata",
|
||||||
"buffer handling",
|
"buffer handling",
|
||||||
"access key",
|
"access key",
|
||||||
"secret key"
|
"secret key",
|
||||||
|
"cloud agnostic"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@push.rocks/smartbucket",
|
"name": "@push.rocks/smartbucket",
|
||||||
"version": "3.0.3",
|
"version": "3.0.14",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@push.rocks/smartbucket",
|
"name": "@push.rocks/smartbucket",
|
||||||
"version": "3.0.3",
|
"version": "3.0.14",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@push.rocks/smartpath": "^5.0.18",
|
"@push.rocks/smartpath": "^5.0.18",
|
||||||
|
31
package.json
31
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@push.rocks/smartbucket",
|
"name": "@push.rocks/smartbucket",
|
||||||
"version": "3.0.3",
|
"version": "3.0.14",
|
||||||
"description": "A TypeScript library that offers simple, cloud-independent object storage with features like bucket creation, file management, and directory management.",
|
"description": "A TypeScript library offering simple and cloud-agnostic object storage with advanced features like bucket creation, file and directory management, and data streaming.",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@ -19,11 +19,14 @@
|
|||||||
"@push.rocks/tapbundle": "^5.0.23"
|
"@push.rocks/tapbundle": "^5.0.23"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@push.rocks/smartmime": "^2.0.2",
|
||||||
"@push.rocks/smartpath": "^5.0.18",
|
"@push.rocks/smartpath": "^5.0.18",
|
||||||
"@push.rocks/smartpromise": "^4.0.3",
|
"@push.rocks/smartpromise": "^4.0.3",
|
||||||
"@push.rocks/smartrx": "^3.0.7",
|
"@push.rocks/smartrx": "^3.0.7",
|
||||||
"@push.rocks/smartstream": "^3.0.38",
|
"@push.rocks/smartstream": "^3.0.44",
|
||||||
"@tsclass/tsclass": "^4.0.54",
|
"@push.rocks/smartstring": "^4.0.15",
|
||||||
|
"@push.rocks/smartunique": "^3.0.9",
|
||||||
|
"@tsclass/tsclass": "^4.0.55",
|
||||||
"minio": "^8.0.0"
|
"minio": "^8.0.0"
|
||||||
},
|
},
|
||||||
"private": false,
|
"private": false,
|
||||||
@ -43,20 +46,28 @@
|
|||||||
"last 1 chrome versions"
|
"last 1 chrome versions"
|
||||||
],
|
],
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
"TypeScript",
|
||||||
"cloud storage",
|
"cloud storage",
|
||||||
"object storage",
|
"object storage",
|
||||||
"TypeScript",
|
"bucket creation",
|
||||||
"S3",
|
|
||||||
"minio",
|
|
||||||
"file management",
|
"file management",
|
||||||
"directory management",
|
"directory management",
|
||||||
"bucket creation",
|
|
||||||
"data streaming",
|
"data streaming",
|
||||||
"multi-cloud",
|
"multi-cloud",
|
||||||
"API",
|
"API",
|
||||||
"unified storage",
|
"unified storage",
|
||||||
|
"S3",
|
||||||
|
"minio",
|
||||||
|
"file locking",
|
||||||
|
"metadata",
|
||||||
"buffer handling",
|
"buffer handling",
|
||||||
"access key",
|
"access key",
|
||||||
"secret key"
|
"secret key",
|
||||||
]
|
"cloud agnostic"
|
||||||
|
],
|
||||||
|
"homepage": "https://code.foss.global/push.rocks/smartbucket",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://code.foss.global/push.rocks/smartbucket.git"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
137
pnpm-lock.yaml
generated
137
pnpm-lock.yaml
generated
@ -8,6 +8,9 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@push.rocks/smartmime':
|
||||||
|
specifier: ^2.0.2
|
||||||
|
version: 2.0.2
|
||||||
'@push.rocks/smartpath':
|
'@push.rocks/smartpath':
|
||||||
specifier: ^5.0.18
|
specifier: ^5.0.18
|
||||||
version: 5.0.18
|
version: 5.0.18
|
||||||
@ -18,11 +21,17 @@ importers:
|
|||||||
specifier: ^3.0.7
|
specifier: ^3.0.7
|
||||||
version: 3.0.7
|
version: 3.0.7
|
||||||
'@push.rocks/smartstream':
|
'@push.rocks/smartstream':
|
||||||
specifier: ^3.0.38
|
specifier: ^3.0.44
|
||||||
version: 3.0.38
|
version: 3.0.44
|
||||||
|
'@push.rocks/smartstring':
|
||||||
|
specifier: ^4.0.15
|
||||||
|
version: 4.0.15
|
||||||
|
'@push.rocks/smartunique':
|
||||||
|
specifier: ^3.0.9
|
||||||
|
version: 3.0.9
|
||||||
'@tsclass/tsclass':
|
'@tsclass/tsclass':
|
||||||
specifier: ^4.0.54
|
specifier: ^4.0.55
|
||||||
version: 4.0.54
|
version: 4.0.55
|
||||||
minio:
|
minio:
|
||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.0.0
|
version: 8.0.0
|
||||||
@ -32,10 +41,10 @@ importers:
|
|||||||
version: 2.1.80
|
version: 2.1.80
|
||||||
'@git.zone/tsrun':
|
'@git.zone/tsrun':
|
||||||
specifier: ^1.2.46
|
specifier: ^1.2.46
|
||||||
version: 1.2.46(@types/node@20.12.12)
|
version: 1.2.46(@types/node@20.14.2)
|
||||||
'@git.zone/tstest':
|
'@git.zone/tstest':
|
||||||
specifier: ^1.0.90
|
specifier: ^1.0.90
|
||||||
version: 1.0.90(@types/node@20.12.12)
|
version: 1.0.90(@types/node@20.14.2)
|
||||||
'@push.rocks/qenv':
|
'@push.rocks/qenv':
|
||||||
specifier: ^6.0.5
|
specifier: ^6.0.5
|
||||||
version: 6.0.5
|
version: 6.0.5
|
||||||
@ -409,6 +418,9 @@ packages:
|
|||||||
'@push.rocks/smartmime@1.0.6':
|
'@push.rocks/smartmime@1.0.6':
|
||||||
resolution: {integrity: sha512-PHd+I4UcsnOATNg8wjDsSAmmJ4CwQFrQCNzd0HSJMs4ZpiK3Ya91almd6GLpDPU370U4HFh4FaPF4eEAI6vkJQ==}
|
resolution: {integrity: sha512-PHd+I4UcsnOATNg8wjDsSAmmJ4CwQFrQCNzd0HSJMs4ZpiK3Ya91almd6GLpDPU370U4HFh4FaPF4eEAI6vkJQ==}
|
||||||
|
|
||||||
|
'@push.rocks/smartmime@2.0.2':
|
||||||
|
resolution: {integrity: sha512-aXH1sFD73q9cEwPdeSeN7Zxd2aoVt9wE97ILFCW5gORylvm85Hgfq7SYkqykjQzEL8IDJKJF3G78+xcL2rALTg==}
|
||||||
|
|
||||||
'@push.rocks/smartnetwork@3.0.2':
|
'@push.rocks/smartnetwork@3.0.2':
|
||||||
resolution: {integrity: sha512-s6CNGzQ1n/d/6cOKXbxeW6/tO//dr1woLqI01g7XhqTriw0nsm2G2kWaZh2J0VOguGNWBgQVCIpR0LjdRNWb3g==}
|
resolution: {integrity: sha512-s6CNGzQ1n/d/6cOKXbxeW6/tO//dr1woLqI01g7XhqTriw0nsm2G2kWaZh2J0VOguGNWBgQVCIpR0LjdRNWb3g==}
|
||||||
|
|
||||||
@ -461,8 +473,8 @@ packages:
|
|||||||
'@push.rocks/smartstream@2.0.8':
|
'@push.rocks/smartstream@2.0.8':
|
||||||
resolution: {integrity: sha512-GlF/9cCkvBHwKa3DK4DO5wjfSgqkj6gAS4TrY9uD5NMHu9RQv4WiNrElTYj7iCEpnZgUnLO3tzw1JA3NRIMnnA==}
|
resolution: {integrity: sha512-GlF/9cCkvBHwKa3DK4DO5wjfSgqkj6gAS4TrY9uD5NMHu9RQv4WiNrElTYj7iCEpnZgUnLO3tzw1JA3NRIMnnA==}
|
||||||
|
|
||||||
'@push.rocks/smartstream@3.0.38':
|
'@push.rocks/smartstream@3.0.44':
|
||||||
resolution: {integrity: sha512-Sk9esPURWXldS0ZvgClCtrEyvELjvFnbQgUAelwoXWMfM8pXuB9BX1tE+Z1iBkB9Xyw2p1d9jYelO6waSXg0BQ==}
|
resolution: {integrity: sha512-BZwSUmhVD/CEzRdG/e2UachlyNjshiknqBnwHzIFPIjVKC66UgWX5lYCs2LOwJtuUEpfL1vTMOAYUFNcmPjW9A==}
|
||||||
|
|
||||||
'@push.rocks/smartstring@4.0.15':
|
'@push.rocks/smartstring@4.0.15':
|
||||||
resolution: {integrity: sha512-NTNeOjWyg+aHtBTiQEyXamr7oTvYZ3wS1fudHo9ua7CLrykpK+i+RxFyJaLg1zB5x9xQF3NLEQecB14HPFX8Cg==}
|
resolution: {integrity: sha512-NTNeOjWyg+aHtBTiQEyXamr7oTvYZ3wS1fudHo9ua7CLrykpK+i+RxFyJaLg1zB5x9xQF3NLEQecB14HPFX8Cg==}
|
||||||
@ -609,11 +621,14 @@ packages:
|
|||||||
'@tempfix/watcher@2.3.0':
|
'@tempfix/watcher@2.3.0':
|
||||||
resolution: {integrity: sha512-a2qVQffcrnetehvwsN+LdipxQ6jejwZLgAvS9/91+C0gP4CKyikY01c0tSs0I4tSL7qHdCw1Fx0quLw+A9uyLA==}
|
resolution: {integrity: sha512-a2qVQffcrnetehvwsN+LdipxQ6jejwZLgAvS9/91+C0gP4CKyikY01c0tSs0I4tSL7qHdCw1Fx0quLw+A9uyLA==}
|
||||||
|
|
||||||
|
'@tokenizer/token@0.3.0':
|
||||||
|
resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
|
||||||
|
|
||||||
'@tsclass/tsclass@3.0.48':
|
'@tsclass/tsclass@3.0.48':
|
||||||
resolution: {integrity: sha512-hC65UvDlp9qvsl6OcIZXz0JNiWZ0gyzsTzbXpg215sGxopgbkOLCr6E0s4qCTnweYm95gt2AdY95uP7M7kExaQ==}
|
resolution: {integrity: sha512-hC65UvDlp9qvsl6OcIZXz0JNiWZ0gyzsTzbXpg215sGxopgbkOLCr6E0s4qCTnweYm95gt2AdY95uP7M7kExaQ==}
|
||||||
|
|
||||||
'@tsclass/tsclass@4.0.54':
|
'@tsclass/tsclass@4.0.55':
|
||||||
resolution: {integrity: sha512-v+Xc7M0BKNT79/kx7S5Jsc17zj+acUuMDxJtKbQgdU4H8ke3aHAHJr2KicXJeXDTcn41ZEbwJPQ1cc+bjy8bZw==}
|
resolution: {integrity: sha512-zg774JF90/3/rJ7xk4LyGgxcUzxdKIQcwtBVxez4LhvegESxvHiFmX42WL105iBpE53ISJ8sctLWlwG1JQZdlA==}
|
||||||
|
|
||||||
'@tsconfig/node10@1.0.11':
|
'@tsconfig/node10@1.0.11':
|
||||||
resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
|
resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
|
||||||
@ -756,6 +771,9 @@ packages:
|
|||||||
'@types/node@20.12.12':
|
'@types/node@20.12.12':
|
||||||
resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==}
|
resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==}
|
||||||
|
|
||||||
|
'@types/node@20.14.2':
|
||||||
|
resolution: {integrity: sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==}
|
||||||
|
|
||||||
'@types/parse5@6.0.3':
|
'@types/parse5@6.0.3':
|
||||||
resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==}
|
resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==}
|
||||||
|
|
||||||
@ -1445,6 +1463,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
|
resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
|
||||||
engines: {node: '>=18'}
|
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:
|
fill-range@7.0.1:
|
||||||
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@ -2142,6 +2164,11 @@ packages:
|
|||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
mime@4.0.3:
|
||||||
|
resolution: {integrity: sha512-KgUb15Oorc0NEKPbvfa0wRU+PItIEZmiv+pyAO2i0oTIVTJhlzMclU7w4RXWQrSOVH5ax/p/CkIO7KI4OyFJTQ==}
|
||||||
|
engines: {node: '>=16'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
mimic-fn@2.1.0:
|
mimic-fn@2.1.0:
|
||||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@ -2358,6 +2385,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-AHXsYi9EcYlSm3uUANz7h5WSktHiyTnUeHqdWmyRdjdMhgq9LgZ8pggl9FOUGuCLVfe+NKxp2k9sEMCH3tHIEg==}
|
resolution: {integrity: sha512-AHXsYi9EcYlSm3uUANz7h5WSktHiyTnUeHqdWmyRdjdMhgq9LgZ8pggl9FOUGuCLVfe+NKxp2k9sEMCH3tHIEg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
|
peek-readable@5.0.0:
|
||||||
|
resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==}
|
||||||
|
engines: {node: '>=14.16'}
|
||||||
|
|
||||||
pend@1.2.0:
|
pend@1.2.0:
|
||||||
resolution: {integrity: sha1-elfrVQpng/kRUzH89GY9XI4AelA=}
|
resolution: {integrity: sha1-elfrVQpng/kRUzH89GY9XI4AelA=}
|
||||||
|
|
||||||
@ -2464,6 +2495,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
|
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
|
||||||
engines: {node: '>= 6'}
|
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:
|
readdirp@3.6.0:
|
||||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||||
engines: {node: '>=8.10.0'}
|
engines: {node: '>=8.10.0'}
|
||||||
@ -2682,6 +2717,10 @@ packages:
|
|||||||
strnum@1.0.5:
|
strnum@1.0.5:
|
||||||
resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==}
|
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:
|
stubborn-fs@1.2.5:
|
||||||
resolution: {integrity: sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==}
|
resolution: {integrity: sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==}
|
||||||
|
|
||||||
@ -2732,6 +2771,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
|
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
|
||||||
engines: {node: '>=0.6'}
|
engines: {node: '>=0.6'}
|
||||||
|
|
||||||
|
token-types@5.0.1:
|
||||||
|
resolution: {integrity: sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==}
|
||||||
|
engines: {node: '>=14.16'}
|
||||||
|
|
||||||
tr46@0.0.3:
|
tr46@0.0.3:
|
||||||
resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=}
|
resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=}
|
||||||
|
|
||||||
@ -2787,8 +2830,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
|
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
|
||||||
engines: {node: '>=12.20'}
|
engines: {node: '>=12.20'}
|
||||||
|
|
||||||
type-fest@4.18.2:
|
type-fest@4.20.0:
|
||||||
resolution: {integrity: sha512-+suCYpfJLAe4OXS6+PPXjW3urOS4IoP9waSiLuXfLgqZODKw/aWwASvzqE886wA0kQgGy0mIWyhd87VpqIy6Xg==}
|
resolution: {integrity: sha512-MBh+PHUHHisjXf4tlx0CFWoMdjx8zCMLJHOjnV1prABYZFHqtFOyauCIK2/7w4oIfwkF8iNhLtnJEfVY2vn3iw==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
type-is@1.6.18:
|
type-is@1.6.18:
|
||||||
@ -3093,12 +3136,12 @@ snapshots:
|
|||||||
'@push.rocks/smartrequest': 2.0.22
|
'@push.rocks/smartrequest': 2.0.22
|
||||||
'@push.rocks/smartrx': 3.0.7
|
'@push.rocks/smartrx': 3.0.7
|
||||||
'@push.rocks/smartsitemap': 2.0.3
|
'@push.rocks/smartsitemap': 2.0.3
|
||||||
'@push.rocks/smartstream': 3.0.38
|
'@push.rocks/smartstream': 3.0.44
|
||||||
'@push.rocks/smarttime': 4.0.6
|
'@push.rocks/smarttime': 4.0.6
|
||||||
'@push.rocks/taskbuffer': 3.1.7
|
'@push.rocks/taskbuffer': 3.1.7
|
||||||
'@push.rocks/webrequest': 3.0.37
|
'@push.rocks/webrequest': 3.0.37
|
||||||
'@push.rocks/webstore': 2.0.17
|
'@push.rocks/webstore': 2.0.17
|
||||||
'@tsclass/tsclass': 4.0.54
|
'@tsclass/tsclass': 4.0.55
|
||||||
'@types/express': 4.17.21
|
'@types/express': 4.17.21
|
||||||
body-parser: 1.20.2
|
body-parser: 1.20.2
|
||||||
cors: 2.8.5
|
cors: 2.8.5
|
||||||
@ -3299,22 +3342,22 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@git.zone/tsrun@1.2.46(@types/node@20.12.12)':
|
'@git.zone/tsrun@1.2.46(@types/node@20.14.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/smartfile': 10.0.41
|
'@push.rocks/smartfile': 10.0.41
|
||||||
'@push.rocks/smartshell': 3.0.5
|
'@push.rocks/smartshell': 3.0.5
|
||||||
ts-node: 10.9.2(@types/node@20.12.12)(typescript@5.1.6)
|
ts-node: 10.9.2(@types/node@20.14.2)(typescript@5.1.6)
|
||||||
typescript: 5.1.6
|
typescript: 5.1.6
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@swc/core'
|
- '@swc/core'
|
||||||
- '@swc/wasm'
|
- '@swc/wasm'
|
||||||
- '@types/node'
|
- '@types/node'
|
||||||
|
|
||||||
'@git.zone/tstest@1.0.90(@types/node@20.12.12)':
|
'@git.zone/tstest@1.0.90(@types/node@20.14.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@api.global/typedserver': 3.0.37
|
'@api.global/typedserver': 3.0.37
|
||||||
'@git.zone/tsbundle': 2.0.15
|
'@git.zone/tsbundle': 2.0.15
|
||||||
'@git.zone/tsrun': 1.2.46(@types/node@20.12.12)
|
'@git.zone/tsrun': 1.2.46(@types/node@20.14.2)
|
||||||
'@push.rocks/consolecolor': 2.0.2
|
'@push.rocks/consolecolor': 2.0.2
|
||||||
'@push.rocks/smartbrowser': 2.0.6
|
'@push.rocks/smartbrowser': 2.0.6
|
||||||
'@push.rocks/smartdelay': 3.0.5
|
'@push.rocks/smartdelay': 3.0.5
|
||||||
@ -3563,7 +3606,7 @@ snapshots:
|
|||||||
'@push.rocks/smartpath': 5.0.18
|
'@push.rocks/smartpath': 5.0.18
|
||||||
'@push.rocks/smartpromise': 4.0.3
|
'@push.rocks/smartpromise': 4.0.3
|
||||||
'@push.rocks/smartrequest': 2.0.22
|
'@push.rocks/smartrequest': 2.0.22
|
||||||
'@push.rocks/smartstream': 3.0.38
|
'@push.rocks/smartstream': 3.0.44
|
||||||
'@types/fs-extra': 11.0.4
|
'@types/fs-extra': 11.0.4
|
||||||
'@types/glob': 8.1.0
|
'@types/glob': 8.1.0
|
||||||
'@types/js-yaml': 4.0.9
|
'@types/js-yaml': 4.0.9
|
||||||
@ -3630,6 +3673,12 @@ snapshots:
|
|||||||
'@types/mime-types': 2.1.4
|
'@types/mime-types': 2.1.4
|
||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
|
|
||||||
|
'@push.rocks/smartmime@2.0.2':
|
||||||
|
dependencies:
|
||||||
|
'@types/mime-types': 2.1.4
|
||||||
|
file-type: 19.0.0
|
||||||
|
mime: 4.0.3
|
||||||
|
|
||||||
'@push.rocks/smartnetwork@3.0.2':
|
'@push.rocks/smartnetwork@3.0.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@pushrocks/smartping': 1.0.8
|
'@pushrocks/smartping': 1.0.8
|
||||||
@ -3671,7 +3720,7 @@ snapshots:
|
|||||||
'@push.rocks/smartpromise': 4.0.3
|
'@push.rocks/smartpromise': 4.0.3
|
||||||
'@push.rocks/smartpuppeteer': 2.0.2
|
'@push.rocks/smartpuppeteer': 2.0.2
|
||||||
'@push.rocks/smartunique': 3.0.9
|
'@push.rocks/smartunique': 3.0.9
|
||||||
'@tsclass/tsclass': 4.0.54
|
'@tsclass/tsclass': 4.0.55
|
||||||
'@types/express': 4.17.21
|
'@types/express': 4.17.21
|
||||||
express: 4.19.2
|
express: 4.19.2
|
||||||
pdf-lib: 1.17.1
|
pdf-lib: 1.17.1
|
||||||
@ -3729,7 +3778,7 @@ snapshots:
|
|||||||
'@push.rocks/smartxml': 1.0.8
|
'@push.rocks/smartxml': 1.0.8
|
||||||
'@push.rocks/smartyaml': 2.0.5
|
'@push.rocks/smartyaml': 2.0.5
|
||||||
'@push.rocks/webrequest': 3.0.37
|
'@push.rocks/webrequest': 3.0.37
|
||||||
'@tsclass/tsclass': 4.0.54
|
'@tsclass/tsclass': 4.0.55
|
||||||
|
|
||||||
'@push.rocks/smartsocket@2.0.27':
|
'@push.rocks/smartsocket@2.0.27':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -3781,12 +3830,12 @@ snapshots:
|
|||||||
from2: 2.3.0
|
from2: 2.3.0
|
||||||
through2: 4.0.2
|
through2: 4.0.2
|
||||||
|
|
||||||
'@push.rocks/smartstream@3.0.38':
|
'@push.rocks/smartstream@3.0.44':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@push.rocks/lik': 6.0.15
|
'@push.rocks/lik': 6.0.15
|
||||||
|
'@push.rocks/smartenv': 5.0.12
|
||||||
'@push.rocks/smartpromise': 4.0.3
|
'@push.rocks/smartpromise': 4.0.3
|
||||||
'@push.rocks/smartrx': 3.0.7
|
'@push.rocks/smartrx': 3.0.7
|
||||||
'@push.rocks/webstream': 1.0.8
|
|
||||||
|
|
||||||
'@push.rocks/smartstring@4.0.15':
|
'@push.rocks/smartstring@4.0.15':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -3863,7 +3912,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@pushrocks/smartdelay': 3.0.1
|
'@pushrocks/smartdelay': 3.0.1
|
||||||
'@pushrocks/smartpromise': 4.0.2
|
'@pushrocks/smartpromise': 4.0.2
|
||||||
'@tsclass/tsclass': 4.0.54
|
'@tsclass/tsclass': 4.0.55
|
||||||
|
|
||||||
'@push.rocks/webstore@2.0.17':
|
'@push.rocks/webstore@2.0.17':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -4037,13 +4086,15 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
stubborn-fs: 1.2.5
|
stubborn-fs: 1.2.5
|
||||||
|
|
||||||
|
'@tokenizer/token@0.3.0': {}
|
||||||
|
|
||||||
'@tsclass/tsclass@3.0.48':
|
'@tsclass/tsclass@3.0.48':
|
||||||
dependencies:
|
dependencies:
|
||||||
type-fest: 2.19.0
|
type-fest: 2.19.0
|
||||||
|
|
||||||
'@tsclass/tsclass@4.0.54':
|
'@tsclass/tsclass@4.0.55':
|
||||||
dependencies:
|
dependencies:
|
||||||
type-fest: 4.18.2
|
type-fest: 4.20.0
|
||||||
|
|
||||||
'@tsconfig/node10@1.0.11': {}
|
'@tsconfig/node10@1.0.11': {}
|
||||||
|
|
||||||
@ -4208,6 +4259,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 5.26.5
|
undici-types: 5.26.5
|
||||||
|
|
||||||
|
'@types/node@20.14.2':
|
||||||
|
dependencies:
|
||||||
|
undici-types: 5.26.5
|
||||||
|
|
||||||
'@types/parse5@6.0.3': {}
|
'@types/parse5@6.0.3': {}
|
||||||
|
|
||||||
'@types/ping@0.4.4': {}
|
'@types/ping@0.4.4': {}
|
||||||
@ -4969,6 +5024,12 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-unicode-supported: 2.0.0
|
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:
|
fill-range@7.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
to-regex-range: 5.0.1
|
to-regex-range: 5.0.1
|
||||||
@ -5956,6 +6017,8 @@ snapshots:
|
|||||||
|
|
||||||
mime@1.6.0: {}
|
mime@1.6.0: {}
|
||||||
|
|
||||||
|
mime@4.0.3: {}
|
||||||
|
|
||||||
mimic-fn@2.1.0: {}
|
mimic-fn@2.1.0: {}
|
||||||
|
|
||||||
mimic-response@3.1.0: {}
|
mimic-response@3.1.0: {}
|
||||||
@ -6125,6 +6188,8 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
peek-readable@5.0.0: {}
|
||||||
|
|
||||||
pend@1.2.0: {}
|
pend@1.2.0: {}
|
||||||
|
|
||||||
picocolors@1.0.1: {}
|
picocolors@1.0.1: {}
|
||||||
@ -6248,6 +6313,10 @@ snapshots:
|
|||||||
string_decoder: 1.3.0
|
string_decoder: 1.3.0
|
||||||
util-deprecate: 1.0.2
|
util-deprecate: 1.0.2
|
||||||
|
|
||||||
|
readable-web-to-node-stream@3.0.2:
|
||||||
|
dependencies:
|
||||||
|
readable-stream: 3.6.2
|
||||||
|
|
||||||
readdirp@3.6.0:
|
readdirp@3.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
@ -6530,6 +6599,11 @@ snapshots:
|
|||||||
|
|
||||||
strnum@1.0.5: {}
|
strnum@1.0.5: {}
|
||||||
|
|
||||||
|
strtok3@7.0.0:
|
||||||
|
dependencies:
|
||||||
|
'@tokenizer/token': 0.3.0
|
||||||
|
peek-readable: 5.0.0
|
||||||
|
|
||||||
stubborn-fs@1.2.5: {}
|
stubborn-fs@1.2.5: {}
|
||||||
|
|
||||||
supports-color@5.5.0:
|
supports-color@5.5.0:
|
||||||
@ -6588,6 +6662,11 @@ snapshots:
|
|||||||
|
|
||||||
toidentifier@1.0.1: {}
|
toidentifier@1.0.1: {}
|
||||||
|
|
||||||
|
token-types@5.0.1:
|
||||||
|
dependencies:
|
||||||
|
'@tokenizer/token': 0.3.0
|
||||||
|
ieee754: 1.2.1
|
||||||
|
|
||||||
tr46@0.0.3: {}
|
tr46@0.0.3: {}
|
||||||
|
|
||||||
tr46@2.1.0:
|
tr46@2.1.0:
|
||||||
@ -6600,14 +6679,14 @@ snapshots:
|
|||||||
|
|
||||||
trough@2.2.0: {}
|
trough@2.2.0: {}
|
||||||
|
|
||||||
ts-node@10.9.2(@types/node@20.12.12)(typescript@5.1.6):
|
ts-node@10.9.2(@types/node@20.14.2)(typescript@5.1.6):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@cspotcode/source-map-support': 0.8.1
|
'@cspotcode/source-map-support': 0.8.1
|
||||||
'@tsconfig/node10': 1.0.11
|
'@tsconfig/node10': 1.0.11
|
||||||
'@tsconfig/node12': 1.0.11
|
'@tsconfig/node12': 1.0.11
|
||||||
'@tsconfig/node14': 1.0.3
|
'@tsconfig/node14': 1.0.3
|
||||||
'@tsconfig/node16': 1.0.4
|
'@tsconfig/node16': 1.0.4
|
||||||
'@types/node': 20.12.12
|
'@types/node': 20.14.2
|
||||||
acorn: 8.11.3
|
acorn: 8.11.3
|
||||||
acorn-walk: 8.3.2
|
acorn-walk: 8.3.2
|
||||||
arg: 4.1.3
|
arg: 4.1.3
|
||||||
@ -6634,7 +6713,7 @@ snapshots:
|
|||||||
|
|
||||||
type-fest@2.19.0: {}
|
type-fest@2.19.0: {}
|
||||||
|
|
||||||
type-fest@4.18.2: {}
|
type-fest@4.20.0: {}
|
||||||
|
|
||||||
type-is@1.6.18:
|
type-is@1.6.18:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
20
readme.md
20
readme.md
@ -1,9 +1,10 @@
|
|||||||
# @push.rocks/smartbucket
|
# @push.rocks/smartbucket
|
||||||
A TypeScript library for simple cloud independent object storage with support for buckets, directories, and files.
|
|
||||||
|
A TypeScript library for cloud-independent object storage, providing features like bucket creation, file and directory management, and data streaming.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
To install `@push.rocks/smartbucket`, you need to have Node.js and npm (Node Package Manager) installed on your system. If you have them installed, you can add `@push.rocks/smartbucket` to your project by running the following command in your project's root directory:
|
To install `@push.rocks/smartbucket`, you need to have Node.js and npm (Node Package Manager) installed. If they are installed, you can add `@push.rocks/smartbucket` to your project by running the following command in your project's root directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install @push.rocks/smartbucket --save
|
npm install @push.rocks/smartbucket --save
|
||||||
@ -13,7 +14,7 @@ This command will download and install `@push.rocks/smartbucket` along with its
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
`@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.
|
`@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.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ const mySmartBucket = new SmartBucket({
|
|||||||
accessKey: "yourAccessKey",
|
accessKey: "yourAccessKey",
|
||||||
accessSecret: "yourSecretKey",
|
accessSecret: "yourSecretKey",
|
||||||
endpoint: "yourEndpointURL",
|
endpoint: "yourEndpointURL",
|
||||||
port: 443, // Default is 443, could be customized for specific endpoint
|
port: 443, // Default is 443, can be customized for specific endpoint
|
||||||
useSsl: true // Defaults to true
|
useSsl: true // Defaults to true
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@ -189,7 +190,7 @@ async function writeFileStream(bucketName: string, filePath: string, readableStr
|
|||||||
// Create a readable stream from a string
|
// Create a readable stream from a string
|
||||||
const readable = new Readable();
|
const readable = new Readable();
|
||||||
readable.push('Hello world streamed as a file!');
|
readable.push('Hello world streamed as a file!');
|
||||||
readable.push(null); // Indicates end of the stream
|
readable.push(null); // End of stream
|
||||||
|
|
||||||
// Use the function
|
// Use the function
|
||||||
writeFileStream("exampleBucket", "path/to/streamedObject.txt", readable);
|
writeFileStream("exampleBucket", "path/to/streamedObject.txt", readable);
|
||||||
@ -197,7 +198,9 @@ writeFileStream("exampleBucket", "path/to/streamedObject.txt", readable);
|
|||||||
|
|
||||||
### Working with Directories
|
### 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.
|
`@push.rocks/smartbucket` offers abstractions for directories within buckets for easier object management. You can create, list, and delete directories using the `Directory` class.
|
||||||
|
|
||||||
|
To list the contents of a directory:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
async function listDirectoryContents(bucketName: string, directoryPath: string) {
|
async function listDirectoryContents(bucketName: string, directoryPath: string) {
|
||||||
@ -205,6 +208,7 @@ async function listDirectoryContents(bucketName: string, directoryPath: string)
|
|||||||
if (myBucket) {
|
if (myBucket) {
|
||||||
const baseDirectory: Directory = await myBucket.getBaseDirectory();
|
const baseDirectory: Directory = await myBucket.getBaseDirectory();
|
||||||
const targetDirectory: Directory = await baseDirectory.getSubDirectoryByName(directoryPath);
|
const targetDirectory: Directory = await baseDirectory.getSubDirectoryByName(directoryPath);
|
||||||
|
|
||||||
console.log('Listing directories:');
|
console.log('Listing directories:');
|
||||||
const directories = await targetDirectory.listDirectories();
|
const directories = await targetDirectory.listDirectories();
|
||||||
directories.forEach(dir => {
|
directories.forEach(dir => {
|
||||||
@ -250,11 +254,11 @@ createFileInDirectory("exampleBucket", "some/directory", "newfile.txt", "Hello,
|
|||||||
|
|
||||||
#### Bucket Policies
|
#### 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).
|
Manage bucket policies to control access permissions. This feature depends on the policies provided by the storage service (e.g., AWS S3, MinIO).
|
||||||
|
|
||||||
#### Object Metadata
|
#### Object Metadata
|
||||||
|
|
||||||
You can retrieve and modify object metadata. Metadata can be useful for storing additional information about an object.
|
Retrieve and modify object metadata. Metadata can be useful for storing additional information about an object.
|
||||||
|
|
||||||
To retrieve metadata:
|
To retrieve metadata:
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ tap.test('should get data in bucket', async () => {
|
|||||||
});
|
});
|
||||||
const fileStringStream = await myBucket.fastGetStream({
|
const fileStringStream = await myBucket.fastGetStream({
|
||||||
path: 'hithere/socool.txt',
|
path: 'hithere/socool.txt',
|
||||||
});
|
}, 'nodestream');
|
||||||
console.log(fileString);
|
console.log(fileString);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ tap.test('prepare for directory style tests', async () => {
|
|||||||
contents: 'dir3/dir4/file1.txt content',
|
contents: 'dir3/dir4/file1.txt content',
|
||||||
});
|
});
|
||||||
await myBucket.fastPut({
|
await myBucket.fastPut({
|
||||||
path: 'file1.txt',
|
path: '/file1.txt',
|
||||||
contents: 'file1 content',
|
contents: 'file1 content',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartbucket',
|
name: '@push.rocks/smartbucket',
|
||||||
version: '3.0.3',
|
version: '3.0.14',
|
||||||
description: 'A TypeScript library that offers simple, cloud-independent object storage with features like bucket creation, file management, and directory management.'
|
description: 'A TypeScript library offering simple and cloud-agnostic object storage with advanced features like bucket creation, file and directory management, and data streaming.'
|
||||||
}
|
}
|
||||||
|
460
ts/classes.bucket.ts
Normal file
460
ts/classes.bucket.ts
Normal file
@ -0,0 +1,460 @@
|
|||||||
|
import * as plugins from './plugins.js';
|
||||||
|
import * as helpers from './helpers.js';
|
||||||
|
import * as interfaces from './interfaces.js';
|
||||||
|
import { SmartBucket } from './classes.smartbucket.js';
|
||||||
|
import { Directory } from './classes.directory.js';
|
||||||
|
import { File } from './classes.file.js';
|
||||||
|
import { Trash } from './classes.trash.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bucket class exposes the basc functionality of a bucket.
|
||||||
|
* The functions of the bucket alone are enough to
|
||||||
|
* operate in s3 basic fashion on blobs of data.
|
||||||
|
*/
|
||||||
|
export class Bucket {
|
||||||
|
public static async getBucketByName(smartbucketRef: SmartBucket, bucketNameArg: string) {
|
||||||
|
const buckets = await smartbucketRef.minioClient.listBuckets();
|
||||||
|
const foundBucket = buckets.find((bucket) => {
|
||||||
|
return bucket.name === bucketNameArg;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (foundBucket) {
|
||||||
|
console.log(`bucket with name ${bucketNameArg} exists.`);
|
||||||
|
console.log(`Taking this as base for new Bucket instance`);
|
||||||
|
return new this(smartbucketRef, bucketNameArg);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async createBucketByName(smartbucketRef: SmartBucket, bucketName: string) {
|
||||||
|
await smartbucketRef.minioClient.makeBucket(bucketName, 'ams3').catch((e) => console.log(e));
|
||||||
|
return new Bucket(smartbucketRef, bucketName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async removeBucketByName(smartbucketRef: SmartBucket, bucketName: string) {
|
||||||
|
await smartbucketRef.minioClient.removeBucket(bucketName).catch((e) => console.log(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
public smartbucketRef: SmartBucket;
|
||||||
|
public name: string;
|
||||||
|
|
||||||
|
constructor(smartbucketRef: SmartBucket, bucketName: string) {
|
||||||
|
this.smartbucketRef = smartbucketRef;
|
||||||
|
this.name = bucketName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the base directory of the bucket
|
||||||
|
*/
|
||||||
|
public async getBaseDirectory(): Promise<Directory> {
|
||||||
|
return new Directory(this, null, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the trash directory
|
||||||
|
*/
|
||||||
|
public async getTrash(): Promise<Trash> {
|
||||||
|
const trash = new Trash(this);
|
||||||
|
return trash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getDirectoryFromPath(
|
||||||
|
pathDescriptorArg: interfaces.IPathDecriptor
|
||||||
|
): Promise<Directory> {
|
||||||
|
if (!pathDescriptorArg.path && !pathDescriptorArg.directory) {
|
||||||
|
return this.getBaseDirectory();
|
||||||
|
}
|
||||||
|
let checkPath = await helpers.reducePathDescriptorToPath(pathDescriptorArg);
|
||||||
|
const baseDirectory = await this.getBaseDirectory();
|
||||||
|
return await baseDirectory.getSubDirectoryByName(checkPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===============
|
||||||
|
// Fast Operations
|
||||||
|
// ===============
|
||||||
|
|
||||||
|
/**
|
||||||
|
* store file
|
||||||
|
*/
|
||||||
|
public async fastPut(optionsArg: interfaces.IPathDecriptor & {
|
||||||
|
contents: string | Buffer;
|
||||||
|
overwrite?: boolean;
|
||||||
|
}): Promise<File> {
|
||||||
|
try {
|
||||||
|
const reducedPath = await helpers.reducePathDescriptorToPath(optionsArg);
|
||||||
|
// Check if the object already exists
|
||||||
|
const exists = await this.fastExists({ path: reducedPath });
|
||||||
|
|
||||||
|
if (exists && !optionsArg.overwrite) {
|
||||||
|
console.error(`Object already exists at path '${reducedPath}' in bucket '${this.name}'.`);
|
||||||
|
return;
|
||||||
|
} else if (exists && optionsArg.overwrite) {
|
||||||
|
console.log(
|
||||||
|
`Overwriting existing object at path '${reducedPath}' in bucket '${this.name}'.`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.log(`Creating new object at path '${reducedPath}' in bucket '${this.name}'.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proceed with putting the object
|
||||||
|
const streamIntake = new plugins.smartstream.StreamIntake();
|
||||||
|
const putPromise = this.smartbucketRef.minioClient.putObject(
|
||||||
|
this.name,
|
||||||
|
reducedPath,
|
||||||
|
streamIntake
|
||||||
|
);
|
||||||
|
streamIntake.pushData(optionsArg.contents);
|
||||||
|
streamIntake.signalEnd();
|
||||||
|
await putPromise;
|
||||||
|
|
||||||
|
console.log(`Object '${reducedPath}' has been successfully stored in bucket '${this.name}'.`);
|
||||||
|
const parsedPath = plugins.path.parse(reducedPath);
|
||||||
|
return new File({
|
||||||
|
directoryRefArg: await this.getDirectoryFromPath({
|
||||||
|
path: parsedPath.dir,
|
||||||
|
}),
|
||||||
|
fileName: parsedPath.base,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
`Error storing object at path '${optionsArg.path}' in bucket '${this.name}':`,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get file
|
||||||
|
*/
|
||||||
|
public async fastGet(optionsArg: { path: string }): Promise<Buffer> {
|
||||||
|
const done = plugins.smartpromise.defer();
|
||||||
|
let completeFile: Buffer;
|
||||||
|
const replaySubject = await this.fastGetReplaySubject(optionsArg);
|
||||||
|
const subscription = replaySubject.subscribe({
|
||||||
|
next: (chunk) => {
|
||||||
|
if (completeFile) {
|
||||||
|
completeFile = Buffer.concat([completeFile, chunk]);
|
||||||
|
} else {
|
||||||
|
completeFile = chunk;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
complete: () => {
|
||||||
|
done.resolve();
|
||||||
|
subscription.unsubscribe();
|
||||||
|
},
|
||||||
|
error: (err) => {
|
||||||
|
console.log(err);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await done.promise;
|
||||||
|
return completeFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* good when time to first byte is important
|
||||||
|
* and multiple subscribers are expected
|
||||||
|
* @param optionsArg
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public async fastGetReplaySubject(optionsArg: {
|
||||||
|
path: string;
|
||||||
|
}): Promise<plugins.smartrx.rxjs.ReplaySubject<Buffer>> {
|
||||||
|
const fileStream = await this.smartbucketRef.minioClient
|
||||||
|
.getObject(this.name, optionsArg.path)
|
||||||
|
.catch((e) => console.log(e));
|
||||||
|
const replaySubject = new plugins.smartrx.rxjs.ReplaySubject<Buffer>();
|
||||||
|
const duplexStream = new plugins.smartstream.SmartDuplex<Buffer, void>({
|
||||||
|
writeFunction: async (chunk) => {
|
||||||
|
replaySubject.next(chunk);
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
finalFunction: async (cb) => {
|
||||||
|
replaySubject.complete();
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!fileStream) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const smartstream = new plugins.smartstream.StreamWrapper([fileStream, duplexStream]);
|
||||||
|
smartstream.run();
|
||||||
|
return replaySubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public fastGetStream(
|
||||||
|
optionsArg: {
|
||||||
|
path: string;
|
||||||
|
},
|
||||||
|
typeArg: 'webstream'
|
||||||
|
): Promise<ReadableStream>;
|
||||||
|
public async fastGetStream(
|
||||||
|
optionsArg: {
|
||||||
|
path: string;
|
||||||
|
},
|
||||||
|
typeArg: 'nodestream'
|
||||||
|
): Promise<plugins.stream.Readable>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fastGetStream
|
||||||
|
* @param optionsArg
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public async fastGetStream(
|
||||||
|
optionsArg: { path: string },
|
||||||
|
typeArg: 'webstream' | 'nodestream' = 'nodestream'
|
||||||
|
): Promise<ReadableStream | plugins.stream.Readable> {
|
||||||
|
const fileStream = await this.smartbucketRef.minioClient
|
||||||
|
.getObject(this.name, optionsArg.path)
|
||||||
|
.catch((e) => console.log(e));
|
||||||
|
const duplexStream = new plugins.smartstream.SmartDuplex<Buffer, Buffer>({
|
||||||
|
writeFunction: async (chunk) => {
|
||||||
|
return chunk;
|
||||||
|
},
|
||||||
|
finalFunction: async (cb) => {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!fileStream) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const smartstream = new plugins.smartstream.StreamWrapper([fileStream, duplexStream]);
|
||||||
|
smartstream.run();
|
||||||
|
if (typeArg === 'nodestream') {
|
||||||
|
return duplexStream;
|
||||||
|
}
|
||||||
|
if (typeArg === 'webstream') {
|
||||||
|
return (await duplexStream.getWebStreams()).readable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* store file as stream
|
||||||
|
*/
|
||||||
|
public async fastPutStream(optionsArg: {
|
||||||
|
path: string;
|
||||||
|
readableStream: plugins.stream.Readable | ReadableStream;
|
||||||
|
nativeMetadata?: { [key: string]: string };
|
||||||
|
overwrite?: boolean;
|
||||||
|
}): Promise<void> {
|
||||||
|
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}'.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const streamIntake = await plugins.smartstream.StreamIntake.fromStream<Uint8Array>(
|
||||||
|
optionsArg.readableStream
|
||||||
|
);
|
||||||
|
|
||||||
|
// Proceed with putting the object
|
||||||
|
await this.smartbucketRef.minioClient.putObject(
|
||||||
|
this.name,
|
||||||
|
optionsArg.path,
|
||||||
|
streamIntake,
|
||||||
|
null,
|
||||||
|
null // TODO: Add support for custom metadata once proper support is in minio.
|
||||||
|
);
|
||||||
|
|
||||||
|
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 fastCopy(optionsArg: {
|
||||||
|
sourcePath: string;
|
||||||
|
destinationPath?: string;
|
||||||
|
targetBucket?: Bucket;
|
||||||
|
nativeMetadata?: { [key: string]: string };
|
||||||
|
deleteExistingNativeMetadata?: boolean;
|
||||||
|
}): Promise<void> {
|
||||||
|
try {
|
||||||
|
const targetBucketName = optionsArg.targetBucket ? optionsArg.targetBucket.name : this.name;
|
||||||
|
|
||||||
|
// Retrieve current object information to use in copy conditions
|
||||||
|
const currentObjInfo = await this.smartbucketRef.minioClient.statObject(
|
||||||
|
targetBucketName,
|
||||||
|
optionsArg.sourcePath
|
||||||
|
);
|
||||||
|
|
||||||
|
// Setting up copy conditions
|
||||||
|
const copyConditions = new plugins.minio.CopyConditions();
|
||||||
|
|
||||||
|
// Prepare new metadata
|
||||||
|
const newNativeMetadata = {
|
||||||
|
...(optionsArg.deleteExistingNativeMetadata ? {} : currentObjInfo.metaData),
|
||||||
|
...optionsArg.nativeMetadata,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define the copy operation as a Promise
|
||||||
|
// TODO: check on issue here: https://github.com/minio/minio-js/issues/1286
|
||||||
|
await this.smartbucketRef.minioClient.copyObject(
|
||||||
|
this.name,
|
||||||
|
optionsArg.sourcePath,
|
||||||
|
`/${targetBucketName}/${optionsArg.destinationPath || optionsArg.sourcePath}`,
|
||||||
|
copyConditions
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error updating metadata:', err);
|
||||||
|
throw err; // rethrow to allow caller to handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move object from one path to another within the same bucket or to another bucket
|
||||||
|
*/
|
||||||
|
public async fastMove(optionsArg: {
|
||||||
|
sourcePath: string;
|
||||||
|
destinationPath: string;
|
||||||
|
targetBucket?: Bucket;
|
||||||
|
overwrite?: boolean;
|
||||||
|
}): Promise<void> {
|
||||||
|
try {
|
||||||
|
// Check if the destination object already exists
|
||||||
|
const destinationBucket = optionsArg.targetBucket || this;
|
||||||
|
const exists = await destinationBucket.fastExists({ path: optionsArg.destinationPath });
|
||||||
|
|
||||||
|
if (exists && !optionsArg.overwrite) {
|
||||||
|
console.error(
|
||||||
|
`Object already exists at destination path '${optionsArg.destinationPath}' in bucket '${destinationBucket.name}'.`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
} else if (exists && optionsArg.overwrite) {
|
||||||
|
console.log(
|
||||||
|
`Overwriting existing object at destination path '${optionsArg.destinationPath}' in bucket '${destinationBucket.name}'.`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
`Moving object to path '${optionsArg.destinationPath}' in bucket '${destinationBucket.name}'.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proceed with copying the object to the new path
|
||||||
|
await this.fastCopy(optionsArg);
|
||||||
|
|
||||||
|
// Remove the original object after successful copy
|
||||||
|
await this.fastRemove({ path: optionsArg.sourcePath });
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Object '${optionsArg.sourcePath}' has been successfully moved to '${optionsArg.destinationPath}' in bucket '${destinationBucket.name}'.`
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(
|
||||||
|
`Error moving object from '${optionsArg.sourcePath}' to '${optionsArg.destinationPath}':`,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removeObject
|
||||||
|
*/
|
||||||
|
public async fastRemove(optionsArg: { path: string }) {
|
||||||
|
await this.smartbucketRef.minioClient.removeObject(this.name, optionsArg.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check wether file exists
|
||||||
|
* @param optionsArg
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public async fastExists(optionsArg: { path: string }): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await this.smartbucketRef.minioClient.statObject(this.name, optionsArg.path);
|
||||||
|
console.log(`Object '${optionsArg.path}' exists in bucket '${this.name}'.`);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code === 'NotFound') {
|
||||||
|
console.log(`Object '${optionsArg.path}' does not exist in bucket '${this.name}'.`);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
console.error('Error checking object existence:', error);
|
||||||
|
throw error; // Rethrow if it's not a NotFound error to handle unexpected issues
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* deletes this bucket
|
||||||
|
*/
|
||||||
|
public async delete() {
|
||||||
|
await this.smartbucketRef.minioClient.removeBucket(this.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async fastStat(pathDescriptor: interfaces.IPathDecriptor) {
|
||||||
|
let checkPath = await helpers.reducePathDescriptorToPath(pathDescriptor);
|
||||||
|
return this.smartbucketRef.minioClient.statObject(this.name, checkPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async isDirectory(pathDescriptor: interfaces.IPathDecriptor): Promise<boolean> {
|
||||||
|
let checkPath = await helpers.reducePathDescriptorToPath(pathDescriptor);
|
||||||
|
|
||||||
|
// lets check if the checkPath is a directory
|
||||||
|
const stream = this.smartbucketRef.minioClient.listObjectsV2(this.name, checkPath, true);
|
||||||
|
const done = plugins.smartpromise.defer<boolean>();
|
||||||
|
stream.on('data', (dataArg) => {
|
||||||
|
stream.destroy(); // Stop the stream early if we find at least one object
|
||||||
|
if (dataArg.prefix.startsWith(checkPath + '/')) {
|
||||||
|
done.resolve(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('end', () => {
|
||||||
|
done.resolve(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('error', (err) => {
|
||||||
|
done.reject(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
return done.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async isFile(pathDescriptor: interfaces.IPathDecriptor): Promise<boolean> {
|
||||||
|
let checkPath = await helpers.reducePathDescriptorToPath(pathDescriptor);
|
||||||
|
|
||||||
|
// lets check if the checkPath is a directory
|
||||||
|
const stream = this.smartbucketRef.minioClient.listObjectsV2(this.name, checkPath, true);
|
||||||
|
const done = plugins.smartpromise.defer<boolean>();
|
||||||
|
stream.on('data', (dataArg) => {
|
||||||
|
stream.destroy(); // Stop the stream early if we find at least one object
|
||||||
|
if (dataArg.prefix === checkPath) {
|
||||||
|
done.resolve(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('end', () => {
|
||||||
|
done.resolve(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('error', (err) => {
|
||||||
|
done.reject(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
return done.promise;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
import * as plugins from './smartbucket.plugins.js';
|
import * as plugins from './plugins.js';
|
||||||
import { Bucket } from './smartbucket.classes.bucket.js';
|
import { Bucket } from './classes.bucket.js';
|
||||||
import { File } from './smartbucket.classes.file.js';
|
import { File } from './classes.file.js';
|
||||||
|
|
||||||
|
import * as helpers from './helpers.js';
|
||||||
|
|
||||||
export class Directory {
|
export class Directory {
|
||||||
public bucketRef: Bucket;
|
public bucketRef: Bucket;
|
||||||
@ -59,6 +61,45 @@ export class Directory {
|
|||||||
return basePath;
|
return basePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets a file by name
|
||||||
|
*/
|
||||||
|
public async getFile(optionsArg: {
|
||||||
|
name: string;
|
||||||
|
createWithContents?: string | Buffer;
|
||||||
|
getFromTrash?: boolean;
|
||||||
|
}): Promise<File> {
|
||||||
|
const pathDescriptor = {
|
||||||
|
directory: this,
|
||||||
|
path: optionsArg.name,
|
||||||
|
};
|
||||||
|
// check wether the file exists
|
||||||
|
const exists = await this.bucketRef.fastExists({
|
||||||
|
path: await helpers.reducePathDescriptorToPath(pathDescriptor),
|
||||||
|
});
|
||||||
|
if (!exists && optionsArg.getFromTrash) {
|
||||||
|
const trash = await this.bucketRef.getTrash();
|
||||||
|
const trashedFile = await trash.getTrashedFileByOriginalName(
|
||||||
|
pathDescriptor
|
||||||
|
)
|
||||||
|
return trashedFile;
|
||||||
|
}
|
||||||
|
if (!exists && !optionsArg.createWithContents) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!exists && optionsArg.createWithContents) {
|
||||||
|
await File.create({
|
||||||
|
directory: this,
|
||||||
|
name: optionsArg.name,
|
||||||
|
contents: optionsArg.createWithContents,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new File({
|
||||||
|
directoryRefArg: this,
|
||||||
|
fileName: optionsArg.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lists all files
|
* lists all files
|
||||||
*/
|
*/
|
||||||
@ -94,7 +135,7 @@ export class Directory {
|
|||||||
},
|
},
|
||||||
finalFunction: async (tools) => {
|
finalFunction: async (tools) => {
|
||||||
done.resolve();
|
done.resolve();
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
fileNameStream.pipe(duplexStream);
|
fileNameStream.pipe(duplexStream);
|
||||||
await done.promise;
|
await done.promise;
|
||||||
@ -133,7 +174,7 @@ export class Directory {
|
|||||||
},
|
},
|
||||||
finalFunction: async (tools) => {
|
finalFunction: async (tools) => {
|
||||||
done.resolve();
|
done.resolve();
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
completeDirStream.pipe(duplexStream);
|
completeDirStream.pipe(duplexStream);
|
||||||
await done.promise;
|
await done.promise;
|
||||||
@ -208,14 +249,56 @@ export class Directory {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async fastGetStream(pathArg: string): Promise<plugins.smartrx.rxjs.ReplaySubject<Buffer>> {
|
public fastGetStream(
|
||||||
const path = plugins.path.join(this.getBasePath(), pathArg);
|
optionsArg: {
|
||||||
const result = await this.bucketRef.fastGetStream({
|
path: string;
|
||||||
path,
|
},
|
||||||
});
|
typeArg: 'webstream'
|
||||||
|
): Promise<ReadableStream>;
|
||||||
|
public async fastGetStream(
|
||||||
|
optionsArg: {
|
||||||
|
path: string;
|
||||||
|
},
|
||||||
|
typeArg: 'nodestream'
|
||||||
|
): Promise<plugins.stream.Readable>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fastGetStream
|
||||||
|
* @param optionsArg
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public async fastGetStream(
|
||||||
|
optionsArg: { path: string },
|
||||||
|
typeArg: 'webstream' | 'nodestream'
|
||||||
|
): Promise<ReadableStream | plugins.stream.Readable> {
|
||||||
|
const path = plugins.path.join(this.getBasePath(), optionsArg.path);
|
||||||
|
const result = await this.bucketRef.fastGetStream(
|
||||||
|
{
|
||||||
|
path,
|
||||||
|
},
|
||||||
|
typeArg as any
|
||||||
|
);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fast put stream
|
||||||
|
*/
|
||||||
|
public async fastPutStream(optionsArg: {
|
||||||
|
path: string;
|
||||||
|
stream: plugins.stream.Readable;
|
||||||
|
}): Promise<void> {
|
||||||
|
const path = plugins.path.join(this.getBasePath(), optionsArg.path);
|
||||||
|
await this.bucketRef.fastPutStream({
|
||||||
|
path,
|
||||||
|
readableStream: optionsArg.stream,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removes a file within the directory
|
||||||
|
* @param optionsArg
|
||||||
|
*/
|
||||||
public async fastRemove(optionsArg: { path: string }) {
|
public async fastRemove(optionsArg: { path: string }) {
|
||||||
const path = plugins.path.join(this.getBasePath(), optionsArg.path);
|
const path = plugins.path.join(this.getBasePath(), optionsArg.path);
|
||||||
await this.bucketRef.fastRemove({
|
await this.bucketRef.fastRemove({
|
233
ts/classes.file.ts
Normal file
233
ts/classes.file.ts
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
import * as plugins from './plugins.js';
|
||||||
|
import * as helpers from './helpers.js';
|
||||||
|
import * as interfaces from './interfaces.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) {
|
||||||
|
await optionsArg.directory.fastPutStream({
|
||||||
|
path: optionsArg.name,
|
||||||
|
stream: contents,
|
||||||
|
});
|
||||||
|
} 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(typeArg: 'webstream'): Promise<ReadableStream>;
|
||||||
|
public async getReadStream(typeArg: 'nodestream'): Promise<plugins.stream.Readable>;
|
||||||
|
public async getReadStream(
|
||||||
|
typeArg: 'nodestream' | 'webstream'
|
||||||
|
): Promise<ReadableStream | plugins.stream.Readable> {
|
||||||
|
const readStream = this.parentDirectoryRef.bucketRef.fastGetStream(
|
||||||
|
{
|
||||||
|
path: this.getBasePath(),
|
||||||
|
},
|
||||||
|
typeArg as any
|
||||||
|
);
|
||||||
|
return readStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* deletes this file
|
||||||
|
*/
|
||||||
|
public async delete(optionsArg?: {
|
||||||
|
mode: 'trash' | 'permanent';
|
||||||
|
}) {
|
||||||
|
|
||||||
|
optionsArg = {
|
||||||
|
... {
|
||||||
|
mode: 'permanent',
|
||||||
|
},
|
||||||
|
...optionsArg,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optionsArg.mode === 'permanent') {
|
||||||
|
await this.parentDirectoryRef.bucketRef.fastRemove({
|
||||||
|
path: this.getBasePath(),
|
||||||
|
});
|
||||||
|
if (!this.name.endsWith('.metadata')) {
|
||||||
|
const metadata = await this.getMetaData();
|
||||||
|
await metadata.metadataFile.delete(optionsArg);
|
||||||
|
}
|
||||||
|
} else if (optionsArg.mode === 'trash') {
|
||||||
|
const metadata = await this.getMetaData();
|
||||||
|
await metadata.storeCustomMetaData({
|
||||||
|
key: 'recycle',
|
||||||
|
value: {
|
||||||
|
deletedAt: Date.now(),
|
||||||
|
originalPath: this.getBasePath(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const trash = await this.parentDirectoryRef.bucketRef.getTrash();
|
||||||
|
await this.move({
|
||||||
|
directory: await trash.getTrashDir(),
|
||||||
|
path: await trash.getTrashKeyByOriginalBasePath(this.getBasePath()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.parentDirectoryRef.listFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 | ReadableStream;
|
||||||
|
encoding?: 'utf8' | 'binary';
|
||||||
|
}) {
|
||||||
|
if (
|
||||||
|
optionsArg.contents instanceof plugins.stream.Readable ||
|
||||||
|
optionsArg.contents instanceof ReadableStream
|
||||||
|
) {
|
||||||
|
await this.parentDirectoryRef.bucketRef.fastPutStream({
|
||||||
|
path: this.getBasePath(),
|
||||||
|
readableStream: 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),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* moves the file to another directory
|
||||||
|
*/
|
||||||
|
public async move(pathDescriptorArg: interfaces.IPathDecriptor) {
|
||||||
|
let moveToPath = '';
|
||||||
|
const isDirectory = await this.parentDirectoryRef.bucketRef.isDirectory(pathDescriptorArg);
|
||||||
|
if (isDirectory) {
|
||||||
|
moveToPath = await helpers.reducePathDescriptorToPath({
|
||||||
|
...pathDescriptorArg,
|
||||||
|
path: plugins.path.join(pathDescriptorArg.path, this.name),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// lets move the file
|
||||||
|
await this.parentDirectoryRef.bucketRef.fastMove({
|
||||||
|
sourcePath: this.getBasePath(),
|
||||||
|
destinationPath: moveToPath,
|
||||||
|
});
|
||||||
|
|
||||||
|
// lets move the metadatafile
|
||||||
|
const metadata = await this.getMetaData();
|
||||||
|
await metadata.metadataFile.move(pathDescriptorArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 * as plugins from './plugins.js';
|
||||||
import { Bucket } from './smartbucket.classes.bucket.js';
|
import { Bucket } from './classes.bucket.js';
|
||||||
|
|
||||||
export class SmartBucket {
|
export class SmartBucket {
|
||||||
public config: plugins.tsclass.storage.IS3Descriptor;
|
public config: plugins.tsclass.storage.IS3Descriptor;
|
30
ts/classes.trash.ts
Normal file
30
ts/classes.trash.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import * as plugins from './plugins.js';
|
||||||
|
import * as interfaces from './interfaces.js';
|
||||||
|
import * as helpers from './helpers.js';
|
||||||
|
import type { Bucket } from './classes.bucket.js';
|
||||||
|
import type { Directory } from './classes.directory.js';
|
||||||
|
import type { File } from './classes.file.js';
|
||||||
|
|
||||||
|
|
||||||
|
export class Trash {
|
||||||
|
public bucketRef: Bucket;
|
||||||
|
|
||||||
|
constructor(bucketRefArg: Bucket) {
|
||||||
|
this.bucketRef = bucketRefArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getTrashDir() {
|
||||||
|
return this.bucketRef.getDirectoryFromPath({ path: '.trash' });
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getTrashedFileByOriginalName(pathDescriptor: interfaces.IPathDecriptor): Promise<File> {
|
||||||
|
const trashDir = await this.getTrashDir();
|
||||||
|
const originalPath = await helpers.reducePathDescriptorToPath(pathDescriptor);
|
||||||
|
const trashKey = await this.getTrashKeyByOriginalBasePath(originalPath);
|
||||||
|
return trashDir.getFile({ name: trashKey });
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getTrashKeyByOriginalBasePath (originalPath: string): Promise<string> {
|
||||||
|
return plugins.smartstring.base64.encode(originalPath);
|
||||||
|
}
|
||||||
|
}
|
22
ts/helpers.ts
Normal file
22
ts/helpers.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import * as plugins from './plugins.js';
|
||||||
|
import * as interfaces from './interfaces.js';
|
||||||
|
|
||||||
|
export const reducePathDescriptorToPath = async (pathDescriptorArg: interfaces.IPathDecriptor): Promise<string> => {
|
||||||
|
let returnPath = ``
|
||||||
|
if (pathDescriptorArg.directory) {
|
||||||
|
if (pathDescriptorArg.path && plugins.path.isAbsolute(pathDescriptorArg.path)) {
|
||||||
|
console.warn('Directory is being ignored when path is absolute.');
|
||||||
|
returnPath = pathDescriptorArg.path;
|
||||||
|
} else if (pathDescriptorArg.path) {
|
||||||
|
returnPath = plugins.path.join(pathDescriptorArg.directory.getBasePath(), pathDescriptorArg.path);
|
||||||
|
}
|
||||||
|
} else if (pathDescriptorArg.path) {
|
||||||
|
returnPath = pathDescriptorArg.path;
|
||||||
|
} else {
|
||||||
|
throw new Error('You must specify either a path or a directory.');
|
||||||
|
}
|
||||||
|
if (returnPath.startsWith('/')) {
|
||||||
|
returnPath = returnPath.substring(1);
|
||||||
|
}
|
||||||
|
return returnPath;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
export * from './smartbucket.classes.smartbucket.js';
|
export * from './classes.smartbucket.js';
|
||||||
export * from './smartbucket.classes.bucket.js';
|
export * from './classes.bucket.js';
|
||||||
export * from './smartbucket.classes.directory.js';
|
export * from './classes.directory.js';
|
||||||
export * from './smartbucket.classes.file.js';
|
export * from './classes.file.js';
|
||||||
|
6
ts/interfaces.ts
Normal file
6
ts/interfaces.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import type { Directory } from "./classes.directory.js";
|
||||||
|
|
||||||
|
export interface IPathDecriptor {
|
||||||
|
path?: string;
|
||||||
|
directory?: Directory;
|
||||||
|
}
|
@ -5,12 +5,15 @@ import * as stream from 'stream';
|
|||||||
export { path, stream };
|
export { path, stream };
|
||||||
|
|
||||||
// @push.rocks scope
|
// @push.rocks scope
|
||||||
|
import * as smartmime from '@push.rocks/smartmime';
|
||||||
import * as smartpath from '@push.rocks/smartpath';
|
import * as smartpath from '@push.rocks/smartpath';
|
||||||
import * as smartpromise from '@push.rocks/smartpromise';
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
import * as smartrx from '@push.rocks/smartrx';
|
import * as smartrx from '@push.rocks/smartrx';
|
||||||
import * as smartstream from '@push.rocks/smartstream';
|
import * as smartstream from '@push.rocks/smartstream';
|
||||||
|
import * as smartstring from '@push.rocks/smartstring';
|
||||||
|
import * as smartunique from '@push.rocks/smartunique';
|
||||||
|
|
||||||
export { smartpath, smartpromise, smartrx, smartstream };
|
export { smartmime, smartpath, smartpromise, smartrx, smartstream, smartstring, smartunique };
|
||||||
|
|
||||||
// @tsclass
|
// @tsclass
|
||||||
import * as tsclass from '@tsclass/tsclass';
|
import * as tsclass from '@tsclass/tsclass';
|
@ -1,218 +0,0 @@
|
|||||||
import * as plugins from './smartbucket.plugins.js';
|
|
||||||
import { SmartBucket } from './smartbucket.classes.smartbucket.js';
|
|
||||||
import { Directory } from './smartbucket.classes.directory.js';
|
|
||||||
|
|
||||||
export class Bucket {
|
|
||||||
public static async getBucketByName(smartbucketRef: SmartBucket, bucketNameArg: string) {
|
|
||||||
const buckets = await smartbucketRef.minioClient.listBuckets();
|
|
||||||
const foundBucket = buckets.find((bucket) => {
|
|
||||||
return bucket.name === bucketNameArg;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (foundBucket) {
|
|
||||||
console.log(`bucket with name ${bucketNameArg} exists.`);
|
|
||||||
console.log(`Taking this as base for new Bucket instance`);
|
|
||||||
return new this(smartbucketRef, bucketNameArg);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async createBucketByName(smartbucketRef: SmartBucket, bucketName: string) {
|
|
||||||
await smartbucketRef.minioClient.makeBucket(bucketName, 'ams3').catch((e) => console.log(e));
|
|
||||||
return new Bucket(smartbucketRef, bucketName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async removeBucketByName(smartbucketRef: SmartBucket, bucketName: string) {
|
|
||||||
await smartbucketRef.minioClient.removeBucket(bucketName).catch((e) => console.log(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
public smartbucketRef: SmartBucket;
|
|
||||||
public name: string;
|
|
||||||
|
|
||||||
constructor(smartbucketRef: SmartBucket, bucketName: string) {
|
|
||||||
this.smartbucketRef = smartbucketRef;
|
|
||||||
this.name = bucketName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets the base directory of the bucket
|
|
||||||
*/
|
|
||||||
public async getBaseDirectory() {
|
|
||||||
return new Directory(this, null, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===============
|
|
||||||
// Fast Operations
|
|
||||||
// ===============
|
|
||||||
|
|
||||||
/**
|
|
||||||
* store file
|
|
||||||
*/
|
|
||||||
public async fastPut(optionsArg: {
|
|
||||||
path: string;
|
|
||||||
contents: string | Buffer;
|
|
||||||
}): 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get file
|
|
||||||
*/
|
|
||||||
public async fastGet(optionsArg: Parameters<typeof this.fastGetStream>[0]): Promise<Buffer> {
|
|
||||||
const done = plugins.smartpromise.defer();
|
|
||||||
let completeFile: Buffer;
|
|
||||||
const replaySubject = await this.fastGetStream(optionsArg);
|
|
||||||
const subscription = replaySubject.subscribe({
|
|
||||||
next: (chunk) => {
|
|
||||||
if (completeFile) {
|
|
||||||
completeFile = Buffer.concat([completeFile, chunk]);
|
|
||||||
} else {
|
|
||||||
completeFile = chunk;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
complete: () => {
|
|
||||||
done.resolve();
|
|
||||||
subscription.unsubscribe();
|
|
||||||
},
|
|
||||||
error: (err) => {
|
|
||||||
console.log(err);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await done.promise;
|
|
||||||
return completeFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async fastGetStream(optionsArg: {
|
|
||||||
path: string;
|
|
||||||
}): Promise<plugins.smartrx.rxjs.ReplaySubject<Buffer>> {
|
|
||||||
const fileStream = await this.smartbucketRef.minioClient
|
|
||||||
.getObject(this.name, optionsArg.path)
|
|
||||||
.catch((e) => console.log(e));
|
|
||||||
const replaySubject = new plugins.smartrx.rxjs.ReplaySubject<Buffer>();
|
|
||||||
const duplexStream = new plugins.smartstream.SmartDuplex<Buffer, void>({
|
|
||||||
writeFunction: async (chunk) => {
|
|
||||||
replaySubject.next(chunk);
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
finalFunction: async (cb) => {
|
|
||||||
replaySubject.complete();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!fileStream) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const smartstream = new plugins.smartstream.StreamWrapper([
|
|
||||||
fileStream,
|
|
||||||
duplexStream,
|
|
||||||
]);
|
|
||||||
smartstream.run();
|
|
||||||
return replaySubject;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* store file as stream
|
|
||||||
*/
|
|
||||||
public async fastPutStream(optionsArg: {
|
|
||||||
path: string;
|
|
||||||
dataStream: plugins.stream.Readable;
|
|
||||||
nativeMetadata?: { [key: string]: string };
|
|
||||||
}): Promise<void> {
|
|
||||||
await this.smartbucketRef.minioClient.putObject(
|
|
||||||
this.name,
|
|
||||||
optionsArg.path,
|
|
||||||
optionsArg.dataStream,
|
|
||||||
null,
|
|
||||||
...(optionsArg.nativeMetadata
|
|
||||||
? (() => {
|
|
||||||
const returnObject: any = {};
|
|
||||||
return returnObject;
|
|
||||||
})()
|
|
||||||
: {})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async copyObject(optionsArg: {
|
|
||||||
/**
|
|
||||||
* the
|
|
||||||
*/
|
|
||||||
objectKey: string;
|
|
||||||
/**
|
|
||||||
* in case you want to copy to another bucket specify it here
|
|
||||||
*/
|
|
||||||
targetBucket?: Bucket;
|
|
||||||
targetBucketKey?: string;
|
|
||||||
/**
|
|
||||||
* metadata will be merged with existing metadata
|
|
||||||
*/
|
|
||||||
nativeMetadata?: { [key: string]: string };
|
|
||||||
deleteExistingNativeMetadata?: boolean;
|
|
||||||
}): Promise<void> {
|
|
||||||
try {
|
|
||||||
const targetBucketName = optionsArg.targetBucket ? optionsArg.targetBucket.name : this.name;
|
|
||||||
|
|
||||||
// Retrieve current object information to use in copy conditions
|
|
||||||
const currentObjInfo = await this.smartbucketRef.minioClient.statObject(
|
|
||||||
targetBucketName,
|
|
||||||
optionsArg.objectKey
|
|
||||||
);
|
|
||||||
|
|
||||||
// Setting up copy conditions
|
|
||||||
const copyConditions = new plugins.minio.CopyConditions();
|
|
||||||
|
|
||||||
// Prepare new metadata
|
|
||||||
const newNativeMetadata = {
|
|
||||||
...(optionsArg.deleteExistingNativeMetadata ? {} : currentObjInfo.metaData),
|
|
||||||
...optionsArg.nativeMetadata,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Define the copy operation as a Promise
|
|
||||||
// TODO: check on issue here: https://github.com/minio/minio-js/issues/1286
|
|
||||||
await this.smartbucketRef.minioClient.copyObject(
|
|
||||||
this.name,
|
|
||||||
optionsArg.objectKey,
|
|
||||||
`/${targetBucketName}/${optionsArg.objectKey}`,
|
|
||||||
copyConditions
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error updating metadata:', err);
|
|
||||||
throw err; // rethrow to allow caller to handle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* removeObject
|
|
||||||
*/
|
|
||||||
public async fastRemove(optionsArg: {
|
|
||||||
path: string;
|
|
||||||
}) {
|
|
||||||
await this.smartbucketRef.minioClient.removeObject(this.name, optionsArg.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async doesObjectExist(optionsArg: {
|
|
||||||
path: string;
|
|
||||||
}): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
await this.smartbucketRef.minioClient.statObject(this.name, optionsArg.path);
|
|
||||||
console.log(`Object '${optionsArg.path}' exists in bucket '${this.name}'.`);
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
if (error.code === 'NotFound') {
|
|
||||||
console.log(`Object '${optionsArg.path}' does not exist in bucket '${this.name}'.`);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
console.error('Error checking object existence:', error);
|
|
||||||
throw error; // Rethrow if it's not a NotFound error to handle unexpected issues
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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