@flystorage/file-storage 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -29
- package/changelog.md +8 -1
- package/dist/cjs/file-storage.js +24 -2
- package/dist/cjs/path-prefixer.js +8 -2
- package/dist/esm/file-storage.js +24 -2
- package/dist/esm/path-prefixer.js +9 -3
- package/dist/types/file-storage.d.ts +18 -4
- package/dist/types/path-prefixer.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,35 +20,28 @@ to, simply because they cannot be abstracted over in a reasonable manner.
|
|
|
20
20
|
|
|
21
21
|
## Capabilities
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- [
|
|
43
|
-
- [
|
|
44
|
-
- [
|
|
45
|
-
- [x] [Test implementation (in-memory)](https://www.npmjs.com/package/@flystorage/in-memory)
|
|
46
|
-
- [x] [Google Cloud Storage](https://www.npmjs.com/package/@flystorage/google-cloud-storage)
|
|
47
|
-
- [x] [Chaos adapter decorator](https://www.npmjs.com/package/@flystorage/chaos)
|
|
48
|
-
|
|
49
|
-
### Planned
|
|
50
|
-
- [ ] FTP (using `basic-ftp`)
|
|
51
|
-
- [ ] SFTP (?)
|
|
23
|
+
- Write files using string | buffer | readable/stream
|
|
24
|
+
- Read files as stream, string, or Uint8Array
|
|
25
|
+
- List the contents of a directory/prefix, (shallow and deep).
|
|
26
|
+
- Metadata, such as; mime-type, last modified timestamp, and file size.
|
|
27
|
+
- Expose or calculate checksums for files.
|
|
28
|
+
- Delete files without failing when they don't exist.
|
|
29
|
+
- Set permissions using abstracted visibility
|
|
30
|
+
- Delete directories (and any files it contains)
|
|
31
|
+
- Generate public URLs.
|
|
32
|
+
- Generate temporary (signed) URLs.
|
|
33
|
+
- Secure direct uploads from the browser.
|
|
34
|
+
- Moving files
|
|
35
|
+
- Copying files
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## Adapters
|
|
39
|
+
- [Local Filesystem](https://www.npmjs.com/package/@flystorage/local-fs)
|
|
40
|
+
- [AWS S3 (using the V3 SDK)](https://www.npmjs.com/package/@flystorage/aws-s3)
|
|
41
|
+
- [Azure Blob Storage](https://www.npmjs.com/package/@flystorage/azure-storage-blob)
|
|
42
|
+
- [Test implementation (in-memory)](https://www.npmjs.com/package/@flystorage/in-memory)
|
|
43
|
+
- [Google Cloud Storage](https://www.npmjs.com/package/@flystorage/google-cloud-storage)
|
|
44
|
+
- [Chaos adapter decorator](https://www.npmjs.com/package/@flystorage/chaos)
|
|
52
45
|
|
|
53
46
|
## Usage
|
|
54
47
|
Install the main package and any adapters you might need:
|
package/changelog.md
CHANGED
package/dist/cjs/file-storage.js
CHANGED
|
@@ -197,6 +197,17 @@ class FileStorage {
|
|
|
197
197
|
}
|
|
198
198
|
async changeVisibility(path, visibility, options = {}) {
|
|
199
199
|
options = instrumentAbortSignal({ ...this.options.timeout, ...options });
|
|
200
|
+
if (options.useVisibility === false) {
|
|
201
|
+
const fallback = options.visibilityFallback;
|
|
202
|
+
if (fallback.strategy === 'ignore') {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
else if (fallback.strategy === 'error') {
|
|
206
|
+
throw errors_js_1.UnableToSetVisibility.because(fallback.errorMessage ?? 'Configured not to use visibility', {
|
|
207
|
+
context: { path, visibility },
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
200
211
|
try {
|
|
201
212
|
return await this.adapter.changeVisibility(this.pathNormalizer.normalizePath(path), visibility, options);
|
|
202
213
|
}
|
|
@@ -205,7 +216,18 @@ class FileStorage {
|
|
|
205
216
|
}
|
|
206
217
|
}
|
|
207
218
|
async visibility(path, options = {}) {
|
|
208
|
-
options = instrumentAbortSignal({ ...this.options.timeout, ...options });
|
|
219
|
+
options = instrumentAbortSignal({ ...this.options.timeout, ...this.options.visibility, ...options });
|
|
220
|
+
if (options.useVisibility === false) {
|
|
221
|
+
const fallback = options.visibilityFallback;
|
|
222
|
+
if (fallback.strategy === 'ignore') {
|
|
223
|
+
return fallback.stagedVisibilityResponse ?? 'unknown';
|
|
224
|
+
}
|
|
225
|
+
else if (fallback.strategy === 'error') {
|
|
226
|
+
throw errors_js_1.UnableToGetVisibility.because(fallback.errorMessage ?? 'Configured not to use visibility', {
|
|
227
|
+
context: { path },
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
209
231
|
try {
|
|
210
232
|
return await this.adapter.visibility(this.pathNormalizer.normalizePath(path), options);
|
|
211
233
|
}
|
|
@@ -223,7 +245,7 @@ class FileStorage {
|
|
|
223
245
|
}
|
|
224
246
|
}
|
|
225
247
|
list(path, options = {}) {
|
|
226
|
-
options = instrumentAbortSignal({ ...this.options.timeout, ...options });
|
|
248
|
+
options = instrumentAbortSignal({ ...this.options.timeout, ...this.options.list, ...options });
|
|
227
249
|
const adapterOptions = {
|
|
228
250
|
...options,
|
|
229
251
|
deep: options.deep ?? false,
|
|
@@ -6,7 +6,7 @@ class PathPrefixer {
|
|
|
6
6
|
separator;
|
|
7
7
|
joinFunc;
|
|
8
8
|
prefix = '';
|
|
9
|
-
constructor(prefix = '', separator = '/', joinFunc = node_path_1.join) {
|
|
9
|
+
constructor(prefix = '', separator = '/', joinFunc = node_path_1.posix.join) {
|
|
10
10
|
this.separator = separator;
|
|
11
11
|
this.joinFunc = joinFunc;
|
|
12
12
|
if (prefix.length > 0) {
|
|
@@ -17,7 +17,13 @@ class PathPrefixer {
|
|
|
17
17
|
return this.prefix.length > 0 ? this.joinFunc(this.prefix, path) : path;
|
|
18
18
|
}
|
|
19
19
|
prefixDirectoryPath(path) {
|
|
20
|
-
|
|
20
|
+
let fullPath = this.prefix.length > 0
|
|
21
|
+
? this.joinFunc(this.prefix, path)
|
|
22
|
+
: path;
|
|
23
|
+
if (fullPath.length > 0 && !fullPath.endsWith(this.separator)) {
|
|
24
|
+
fullPath = `${fullPath}${this.separator}`;
|
|
25
|
+
}
|
|
26
|
+
return fullPath;
|
|
21
27
|
}
|
|
22
28
|
stripFilePath(path) {
|
|
23
29
|
return path.substring(this.prefix.length);
|
package/dist/esm/file-storage.js
CHANGED
|
@@ -184,6 +184,17 @@ export class FileStorage {
|
|
|
184
184
|
}
|
|
185
185
|
async changeVisibility(path, visibility, options = {}) {
|
|
186
186
|
options = instrumentAbortSignal({ ...this.options.timeout, ...options });
|
|
187
|
+
if (options.useVisibility === false) {
|
|
188
|
+
const fallback = options.visibilityFallback;
|
|
189
|
+
if (fallback.strategy === 'ignore') {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
else if (fallback.strategy === 'error') {
|
|
193
|
+
throw UnableToSetVisibility.because(fallback.errorMessage ?? 'Configured not to use visibility', {
|
|
194
|
+
context: { path, visibility },
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
187
198
|
try {
|
|
188
199
|
return await this.adapter.changeVisibility(this.pathNormalizer.normalizePath(path), visibility, options);
|
|
189
200
|
}
|
|
@@ -192,7 +203,18 @@ export class FileStorage {
|
|
|
192
203
|
}
|
|
193
204
|
}
|
|
194
205
|
async visibility(path, options = {}) {
|
|
195
|
-
options = instrumentAbortSignal({ ...this.options.timeout, ...options });
|
|
206
|
+
options = instrumentAbortSignal({ ...this.options.timeout, ...this.options.visibility, ...options });
|
|
207
|
+
if (options.useVisibility === false) {
|
|
208
|
+
const fallback = options.visibilityFallback;
|
|
209
|
+
if (fallback.strategy === 'ignore') {
|
|
210
|
+
return fallback.stagedVisibilityResponse ?? 'unknown';
|
|
211
|
+
}
|
|
212
|
+
else if (fallback.strategy === 'error') {
|
|
213
|
+
throw UnableToGetVisibility.because(fallback.errorMessage ?? 'Configured not to use visibility', {
|
|
214
|
+
context: { path },
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
196
218
|
try {
|
|
197
219
|
return await this.adapter.visibility(this.pathNormalizer.normalizePath(path), options);
|
|
198
220
|
}
|
|
@@ -210,7 +232,7 @@ export class FileStorage {
|
|
|
210
232
|
}
|
|
211
233
|
}
|
|
212
234
|
list(path, options = {}) {
|
|
213
|
-
options = instrumentAbortSignal({ ...this.options.timeout, ...options });
|
|
235
|
+
options = instrumentAbortSignal({ ...this.options.timeout, ...this.options.list, ...options });
|
|
214
236
|
const adapterOptions = {
|
|
215
237
|
...options,
|
|
216
238
|
deep: options.deep ?? false,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { posix } from 'node:path';
|
|
2
2
|
export class PathPrefixer {
|
|
3
3
|
separator;
|
|
4
4
|
joinFunc;
|
|
5
5
|
prefix = '';
|
|
6
|
-
constructor(prefix = '', separator = '/', joinFunc = join) {
|
|
6
|
+
constructor(prefix = '', separator = '/', joinFunc = posix.join) {
|
|
7
7
|
this.separator = separator;
|
|
8
8
|
this.joinFunc = joinFunc;
|
|
9
9
|
if (prefix.length > 0) {
|
|
@@ -14,7 +14,13 @@ export class PathPrefixer {
|
|
|
14
14
|
return this.prefix.length > 0 ? this.joinFunc(this.prefix, path) : path;
|
|
15
15
|
}
|
|
16
16
|
prefixDirectoryPath(path) {
|
|
17
|
-
|
|
17
|
+
let fullPath = this.prefix.length > 0
|
|
18
|
+
? this.joinFunc(this.prefix, path)
|
|
19
|
+
: path;
|
|
20
|
+
if (fullPath.length > 0 && !fullPath.endsWith(this.separator)) {
|
|
21
|
+
fullPath = `${fullPath}${this.separator}`;
|
|
22
|
+
}
|
|
23
|
+
return fullPath;
|
|
18
24
|
}
|
|
19
25
|
stripFilePath(path) {
|
|
20
26
|
return path.substring(this.prefix.length);
|
|
@@ -67,10 +67,23 @@ export type MimeTypeOptions = MiscellaneousOptions & {
|
|
|
67
67
|
disallowFallback?: boolean;
|
|
68
68
|
fallbackMethod?: 'contents' | 'path';
|
|
69
69
|
};
|
|
70
|
-
export type
|
|
70
|
+
export type VisibilityFallback = {
|
|
71
|
+
strategy: 'ignore';
|
|
72
|
+
stagedVisibilityResponse?: string;
|
|
73
|
+
} | {
|
|
74
|
+
strategy: 'error';
|
|
75
|
+
errorMessage?: string;
|
|
76
|
+
};
|
|
77
|
+
export type VisibilityOptions = MiscellaneousOptions & {
|
|
71
78
|
visibility?: string;
|
|
72
79
|
directoryVisibility?: string;
|
|
73
|
-
|
|
80
|
+
retainVisibility?: boolean;
|
|
81
|
+
} & ({
|
|
82
|
+
useVisibility: true;
|
|
83
|
+
} | {
|
|
84
|
+
useVisibility: false;
|
|
85
|
+
visibilityFallback: VisibilityFallback;
|
|
86
|
+
} | {});
|
|
74
87
|
export type WriteOptions = VisibilityOptions & MiscellaneousOptions & {
|
|
75
88
|
mimeType?: string;
|
|
76
89
|
size?: number;
|
|
@@ -114,6 +127,7 @@ export type ConfigurationOptions = {
|
|
|
114
127
|
mimeTypes?: MimeTypeOptions;
|
|
115
128
|
preparedUploadStrategy?: PreparedUploadStrategy;
|
|
116
129
|
timeout?: TimeoutOptions;
|
|
130
|
+
list?: ListOptions;
|
|
117
131
|
};
|
|
118
132
|
export declare function toReadable(contents: FileContents): Readable;
|
|
119
133
|
export declare class FileStorage {
|
|
@@ -132,8 +146,8 @@ export declare class FileStorage {
|
|
|
132
146
|
stat(path: string, options?: MiscellaneousOptions): Promise<StatEntry>;
|
|
133
147
|
moveFile(from: string, to: string, options?: MoveFileOptions): Promise<void>;
|
|
134
148
|
copyFile(from: string, to: string, options?: CopyFileOptions): Promise<void>;
|
|
135
|
-
changeVisibility(path: string, visibility: string, options?:
|
|
136
|
-
visibility(path: string, options?:
|
|
149
|
+
changeVisibility(path: string, visibility: string, options?: VisibilityOptions): Promise<void>;
|
|
150
|
+
visibility(path: string, options?: VisibilityOptions): Promise<string>;
|
|
137
151
|
fileExists(path: string, options?: MiscellaneousOptions): Promise<boolean>;
|
|
138
152
|
list(path: string, options?: ListOptions): DirectoryListing;
|
|
139
153
|
statFile(path: string, options?: MiscellaneousOptions): Promise<FileInfo>;
|
package/package.json
CHANGED