@directus/storage-driver-gcs 12.0.8 → 12.0.9
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/dist/index.d.ts +35 -34
- package/dist/index.js +102 -108
- package/package.json +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { Readable } from "node:stream";
|
|
2
|
+
import { TusDriver } from "@directus/storage";
|
|
3
|
+
import { ChunkedUploadContext, ReadOptions } from "@directus/types";
|
|
4
4
|
|
|
5
|
+
//#region src/index.d.ts
|
|
5
6
|
type DriverGCSConfig = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
root?: string;
|
|
8
|
+
bucket: string;
|
|
9
|
+
apiEndpoint?: string;
|
|
10
|
+
tus?: {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
chunkSize?: number;
|
|
13
|
+
};
|
|
13
14
|
};
|
|
14
15
|
declare class DriverGCS implements TusDriver {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
16
|
+
private root;
|
|
17
|
+
private bucket;
|
|
18
|
+
private readonly preferredChunkSize;
|
|
19
|
+
constructor(config: DriverGCSConfig);
|
|
20
|
+
private fullPath;
|
|
21
|
+
private file;
|
|
22
|
+
read(filepath: string, options?: ReadOptions): Promise<Readable>;
|
|
23
|
+
write(filepath: string, content: Readable): Promise<void>;
|
|
24
|
+
delete(filepath: string): Promise<void>;
|
|
25
|
+
stat(filepath: string): Promise<{
|
|
26
|
+
size: number;
|
|
27
|
+
modified: Date;
|
|
28
|
+
}>;
|
|
29
|
+
exists(filepath: string): Promise<boolean>;
|
|
30
|
+
move(src: string, dest: string): Promise<void>;
|
|
31
|
+
copy(src: string, dest: string): Promise<void>;
|
|
32
|
+
list(prefix?: string): AsyncGenerator<string, void, unknown>;
|
|
33
|
+
get tusExtensions(): string[];
|
|
34
|
+
createChunkedUpload(filepath: string, context: ChunkedUploadContext): Promise<ChunkedUploadContext>;
|
|
35
|
+
writeChunk(filepath: string, content: Readable, offset: number, context: ChunkedUploadContext): Promise<number>;
|
|
36
|
+
finishChunkedUpload(_filepath: string, _context: ChunkedUploadContext): Promise<void>;
|
|
37
|
+
deleteChunkedUpload(filepath: string, _context: ChunkedUploadContext): Promise<void>;
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
-
export { DriverGCS,
|
|
39
|
+
//#endregion
|
|
40
|
+
export { DriverGCS, DriverGCS as default, DriverGCSConfig };
|
package/dist/index.js
CHANGED
|
@@ -1,113 +1,107 @@
|
|
|
1
|
-
// src/index.ts
|
|
2
1
|
import { DEFAULT_CHUNK_SIZE } from "@directus/constants";
|
|
3
2
|
import { normalizePath } from "@directus/utils";
|
|
4
3
|
import { Storage } from "@google-cloud/storage";
|
|
5
|
-
import { join } from "path";
|
|
6
|
-
import "stream";
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { pipeline } from "node:stream/promises";
|
|
6
|
+
|
|
7
|
+
//#region src/index.ts
|
|
8
|
+
const MINIMUM_CHUNK_SIZE = 262144;
|
|
9
9
|
var DriverGCS = class {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
async finishChunkedUpload(_filepath, _context) {
|
|
104
|
-
}
|
|
105
|
-
async deleteChunkedUpload(filepath, _context) {
|
|
106
|
-
await this.delete(filepath);
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
var index_default = DriverGCS;
|
|
110
|
-
export {
|
|
111
|
-
DriverGCS,
|
|
112
|
-
index_default as default
|
|
10
|
+
root;
|
|
11
|
+
bucket;
|
|
12
|
+
preferredChunkSize;
|
|
13
|
+
constructor(config) {
|
|
14
|
+
const { bucket, root, tus,...storageOptions } = config;
|
|
15
|
+
this.root = root ? normalizePath(root, { removeLeading: true }) : "";
|
|
16
|
+
this.bucket = new Storage(storageOptions).bucket(bucket);
|
|
17
|
+
this.preferredChunkSize = tus?.chunkSize || DEFAULT_CHUNK_SIZE;
|
|
18
|
+
if (tus?.enabled && (this.preferredChunkSize < MINIMUM_CHUNK_SIZE || Math.log2(this.preferredChunkSize) % 1 !== 0)) throw new Error("Invalid chunkSize provided");
|
|
19
|
+
}
|
|
20
|
+
fullPath(filepath) {
|
|
21
|
+
return normalizePath(join(this.root, filepath));
|
|
22
|
+
}
|
|
23
|
+
file(filepath) {
|
|
24
|
+
return this.bucket.file(filepath);
|
|
25
|
+
}
|
|
26
|
+
async read(filepath, options) {
|
|
27
|
+
const { range } = options || {};
|
|
28
|
+
const stream_options = {};
|
|
29
|
+
if (range?.start) stream_options.start = range.start;
|
|
30
|
+
if (range?.end) stream_options.end = range.end;
|
|
31
|
+
return this.file(this.fullPath(filepath)).createReadStream(stream_options);
|
|
32
|
+
}
|
|
33
|
+
async write(filepath, content) {
|
|
34
|
+
const stream = this.file(this.fullPath(filepath)).createWriteStream({ resumable: false });
|
|
35
|
+
await pipeline(content, stream);
|
|
36
|
+
}
|
|
37
|
+
async delete(filepath) {
|
|
38
|
+
await this.file(this.fullPath(filepath)).delete();
|
|
39
|
+
}
|
|
40
|
+
async stat(filepath) {
|
|
41
|
+
const [{ size, updated }] = await this.file(this.fullPath(filepath)).getMetadata();
|
|
42
|
+
return {
|
|
43
|
+
size,
|
|
44
|
+
modified: new Date(updated)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async exists(filepath) {
|
|
48
|
+
return (await this.file(this.fullPath(filepath)).exists())[0];
|
|
49
|
+
}
|
|
50
|
+
async move(src, dest) {
|
|
51
|
+
await this.file(this.fullPath(src)).move(this.file(this.fullPath(dest)));
|
|
52
|
+
}
|
|
53
|
+
async copy(src, dest) {
|
|
54
|
+
await this.file(this.fullPath(src)).copy(this.file(this.fullPath(dest)));
|
|
55
|
+
}
|
|
56
|
+
async *list(prefix = "") {
|
|
57
|
+
let query = {
|
|
58
|
+
prefix: this.fullPath(prefix),
|
|
59
|
+
autoPaginate: false,
|
|
60
|
+
maxResults: 500
|
|
61
|
+
};
|
|
62
|
+
while (query) {
|
|
63
|
+
const [files, nextQuery] = await this.bucket.getFiles(query);
|
|
64
|
+
for (const file of files) yield file.name.substring(this.root.length);
|
|
65
|
+
query = nextQuery;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
get tusExtensions() {
|
|
69
|
+
return [
|
|
70
|
+
"creation",
|
|
71
|
+
"termination",
|
|
72
|
+
"expiration"
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
async createChunkedUpload(filepath, context) {
|
|
76
|
+
const [uri] = await this.file(this.fullPath(filepath)).createResumableUpload();
|
|
77
|
+
context.metadata["uri"] = uri;
|
|
78
|
+
return context;
|
|
79
|
+
}
|
|
80
|
+
async writeChunk(filepath, content, offset, context) {
|
|
81
|
+
const stream = this.file(this.fullPath(filepath)).createWriteStream({
|
|
82
|
+
chunkSize: this.preferredChunkSize,
|
|
83
|
+
uri: context.metadata["uri"],
|
|
84
|
+
offset,
|
|
85
|
+
isPartialUpload: true,
|
|
86
|
+
resumeCRC32C: context.metadata["hash"],
|
|
87
|
+
metadata: { contentLength: context.size || 0 }
|
|
88
|
+
});
|
|
89
|
+
stream.on("crc32c", (hash) => {
|
|
90
|
+
context.metadata["hash"] = hash;
|
|
91
|
+
});
|
|
92
|
+
let bytesUploaded = offset || 0;
|
|
93
|
+
content.on("data", (chunk) => {
|
|
94
|
+
bytesUploaded += chunk.length;
|
|
95
|
+
});
|
|
96
|
+
await pipeline(content, stream);
|
|
97
|
+
return bytesUploaded;
|
|
98
|
+
}
|
|
99
|
+
async finishChunkedUpload(_filepath, _context) {}
|
|
100
|
+
async deleteChunkedUpload(filepath, _context) {
|
|
101
|
+
await this.delete(filepath);
|
|
102
|
+
}
|
|
113
103
|
};
|
|
104
|
+
var src_default = DriverGCS;
|
|
105
|
+
|
|
106
|
+
//#endregion
|
|
107
|
+
export { DriverGCS, src_default as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@directus/storage-driver-gcs",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.9",
|
|
4
4
|
"description": "GCS file storage abstraction for `@directus/storage`",
|
|
5
5
|
"homepage": "https://directus.io",
|
|
6
6
|
"repository": {
|
|
@@ -22,22 +22,22 @@
|
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@google-cloud/storage": "7.16.0",
|
|
25
|
-
"@directus/constants": "13.0.
|
|
26
|
-
"@directus/storage": "12.0.
|
|
27
|
-
"@directus/utils": "13.0.
|
|
25
|
+
"@directus/constants": "13.0.3",
|
|
26
|
+
"@directus/storage": "12.0.2",
|
|
27
|
+
"@directus/utils": "13.0.10"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@directus/tsconfig": "3.0.0",
|
|
31
31
|
"@ngneat/falso": "8.0.2",
|
|
32
32
|
"@vitest/coverage-v8": "3.2.4",
|
|
33
|
-
"
|
|
33
|
+
"tsdown": "0.14.2",
|
|
34
34
|
"typescript": "5.8.3",
|
|
35
35
|
"vitest": "3.2.4",
|
|
36
|
-
"@directus/types": "13.2.
|
|
36
|
+
"@directus/types": "13.2.3"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
|
-
"build": "
|
|
40
|
-
"dev": "
|
|
39
|
+
"build": "tsdown src/index.ts --dts",
|
|
40
|
+
"dev": "tsdown src/index.ts --dts --watch",
|
|
41
41
|
"test": "vitest run",
|
|
42
42
|
"test:coverage": "vitest run --coverage"
|
|
43
43
|
}
|