@eik/sink-gcs 1.2.30 → 1.2.32
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/CHANGELOG.md +14 -0
- package/README.md +34 -31
- package/lib/main.js +233 -207
- package/package.json +22 -17
- package/types/main.d.ts +37 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [1.2.32](https://github.com/eik-lib/sink-gcs/compare/v1.2.31...v1.2.32) (2024-08-09)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* add type definitions ([a24ea1e](https://github.com/eik-lib/sink-gcs/commit/a24ea1e2ed8d66b0bb4b1c3ef44640adaa56bac0))
|
|
7
|
+
|
|
8
|
+
## [1.2.31](https://github.com/eik-lib/sink-gcs/compare/v1.2.30...v1.2.31) (2024-07-03)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* increase the default timeout to 60000 ([#263](https://github.com/eik-lib/sink-gcs/issues/263)) ([9fe63d7](https://github.com/eik-lib/sink-gcs/commit/9fe63d76a9efdd5ce762fa9417a7d4a634a2dcbd))
|
|
14
|
+
|
|
1
15
|
## [1.2.30](https://github.com/eik-lib/sink-gcs/compare/v1.2.29...v1.2.30) (2023-07-17)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -22,22 +22,25 @@ $ npm install @eik/sink-gcs
|
|
|
22
22
|
Read a file from [Google Cloud Storage][gcs] and serve it on HTTP:
|
|
23
23
|
|
|
24
24
|
```js
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
import { pipeline } from 'node:stream';
|
|
26
|
+
import express from 'express';
|
|
27
|
+
import Sink from '@eik/sink-gcs';
|
|
28
28
|
|
|
29
29
|
const app = express();
|
|
30
|
-
const sink = new Sink(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
const sink = new Sink(
|
|
31
|
+
{
|
|
32
|
+
credentials: {
|
|
33
|
+
client_email: 'a@email.address',
|
|
34
|
+
private_key: '[ ...snip... ]',
|
|
35
|
+
projectId: 'myProject',
|
|
36
|
+
},
|
|
35
37
|
},
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
38
|
+
{
|
|
39
|
+
writeTimeout: 20000,
|
|
40
|
+
},
|
|
41
|
+
);
|
|
39
42
|
|
|
40
|
-
app.get(
|
|
43
|
+
app.get('/file.js', async (req, res, next) => {
|
|
41
44
|
try {
|
|
42
45
|
const file = await sink.read('/path/to/file/file.js');
|
|
43
46
|
pipeline(file.stream, res, (error) => {
|
|
@@ -56,7 +59,7 @@ app.listen(8000);
|
|
|
56
59
|
Create a new Sink instance.
|
|
57
60
|
|
|
58
61
|
```js
|
|
59
|
-
|
|
62
|
+
import Sink from '@eik/sink-gcs';
|
|
60
63
|
|
|
61
64
|
const sink = new Sink({
|
|
62
65
|
credentials: {
|
|
@@ -71,12 +74,12 @@ const sink = new Sink({
|
|
|
71
74
|
|
|
72
75
|
This constructor takes the following arguments:
|
|
73
76
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
- `storageOptions` - Object - A Google Cloud Storage [storage options object][gcs-storage-options] - Required.
|
|
78
|
+
- `options` - Object - Other options related to storage and behavior - Optional.
|
|
79
|
+
- `writeTimeout` - Number - Timeout, in milliseconds, for write operations to the sink - Default: `60000` - Optional.
|
|
80
|
+
- `writeGzip` - Boolean - If files should be written with gzip compression - Default: `false` - Optional.
|
|
81
|
+
- `rootPath` - String - Root directory for where to store files in the GCS bucket - Default: `eik` - Optional.
|
|
82
|
+
- `bucket` - String - Name of the bucket to store files in - Default: `eik_files` - Optional.
|
|
80
83
|
|
|
81
84
|
## API
|
|
82
85
|
|
|
@@ -88,8 +91,8 @@ Async method for writing a file to storage.
|
|
|
88
91
|
|
|
89
92
|
This method takes the following arguments:
|
|
90
93
|
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
- `filePath` - String - Path to the file to be stored - Required.
|
|
95
|
+
- `contentType` - String - The content type of the file - Required.
|
|
93
96
|
|
|
94
97
|
Resolves with a writable stream.
|
|
95
98
|
|
|
@@ -115,14 +118,14 @@ Async method for reading a file from storage.
|
|
|
115
118
|
|
|
116
119
|
This method takes the following arguments:
|
|
117
120
|
|
|
118
|
-
|
|
121
|
+
- `filePath` - String - Path to the file to be read - Required.
|
|
119
122
|
|
|
120
123
|
Resolves with a [ReadFile][read-file] object which holds metadata about
|
|
121
124
|
the file and a readable stream with the byte stream of the file on the
|
|
122
125
|
`.stream` property.
|
|
123
126
|
|
|
124
127
|
```js
|
|
125
|
-
|
|
128
|
+
import { pipeline } from 'node:stream';
|
|
126
129
|
|
|
127
130
|
const toStream = new SomeWritableStream();
|
|
128
131
|
const sink = new Sink({ ... });
|
|
@@ -143,7 +146,7 @@ Async method for deleting a file in storage.
|
|
|
143
146
|
|
|
144
147
|
This method takes the following arguments:
|
|
145
148
|
|
|
146
|
-
|
|
149
|
+
- `filePath` - String - Path to the file to be deleted - Required.
|
|
147
150
|
|
|
148
151
|
Resolves if file is deleted and rejects if file could not be deleted.
|
|
149
152
|
|
|
@@ -163,7 +166,7 @@ Async method for checking if a file exist in the storage.
|
|
|
163
166
|
|
|
164
167
|
This method takes the following arguments:
|
|
165
168
|
|
|
166
|
-
|
|
169
|
+
- `filePath` - String - Path to the file to be checked for existence - Required.
|
|
167
170
|
|
|
168
171
|
Resolves if file exists and rejects if file does not exist.
|
|
169
172
|
|
|
@@ -216,13 +219,13 @@ The stream will emit an event of the following character for each metric:
|
|
|
216
219
|
|
|
217
220
|
The metric will have the following labels:
|
|
218
221
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
+
- `operation` - `String` - The operation which triggered the metric. Can be `write`, `read`, `delete` or `exist`.
|
|
223
|
+
- `success` - `Boolean` - If the operation was successfull in terms of being a valid operation and running the operation against the Google Cloud Storage without erroring.
|
|
224
|
+
- `access` - `Boolean` - If the operation triggered access to the Google Cloud Storage.
|
|
222
225
|
|
|
223
|
-
Do note that the `access` label is `true` when the Sink runs an operation against the
|
|
226
|
+
Do note that the `access` label is `true` when the Sink runs an operation against the
|
|
224
227
|
Google Cloud Storage which can generate a cost. In other words; this can be used to
|
|
225
|
-
monitor excessive access to prevent cost.
|
|
228
|
+
monitor excessive access to prevent cost.
|
|
226
229
|
|
|
227
230
|
## License
|
|
228
231
|
|
|
@@ -250,4 +253,4 @@ SOFTWARE.
|
|
|
250
253
|
[gcs-auth]: https://googlecloudplatform.github.io/google-cloud-node/#/docs/google-cloud/0.50.0/google-cloud
|
|
251
254
|
[gcs-storage-options]: https://googleapis.dev/nodejs/storage/latest/global.html#StorageOptions
|
|
252
255
|
[gcs]: https://cloud.google.com/storage/
|
|
253
|
-
[read-file]: https://github.com/eik-lib/common/blob/
|
|
256
|
+
[read-file]: https://github.com/eik-lib/common/blob/main/lib/classes/read-file.js
|
package/lib/main.js
CHANGED
|
@@ -1,216 +1,242 @@
|
|
|
1
|
-
import { Storage } from
|
|
2
|
-
import { ReadFile } from
|
|
3
|
-
import Metrics from
|
|
4
|
-
import Sink from
|
|
5
|
-
import path from
|
|
1
|
+
import { Storage } from "@google-cloud/storage";
|
|
2
|
+
import { ReadFile } from "@eik/common";
|
|
3
|
+
import Metrics from "@metrics/client";
|
|
4
|
+
import Sink from "@eik/sink";
|
|
5
|
+
import path from "node:path";
|
|
6
6
|
|
|
7
|
-
const DEFAULT_ROOT_PATH =
|
|
8
|
-
const DEFAULT_BUCKET =
|
|
7
|
+
const DEFAULT_ROOT_PATH = "eik";
|
|
8
|
+
const DEFAULT_BUCKET = "eik_files";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {object} SinkGCSOptions
|
|
12
|
+
* @property {number} [writeTimeout=60_000]
|
|
13
|
+
* @property {boolean} [writeGzip=false]
|
|
14
|
+
* @property {string} [rootPath="eik"]
|
|
15
|
+
* @property {string} [bucket="eik_files"]
|
|
16
|
+
*/
|
|
9
17
|
|
|
10
18
|
/**
|
|
11
19
|
* A sink for uploading files to Google Cloud Storage
|
|
12
20
|
* https://googleapis.dev/nodejs/storage/latest/
|
|
13
|
-
*
|
|
14
|
-
* @class SinkGCS
|
|
15
21
|
*/
|
|
16
|
-
|
|
17
22
|
const SinkGCS = class SinkGCS extends Sink {
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param {import('@google-cloud/storage').StorageOptions} storageOptions
|
|
26
|
+
* @param {SinkGCSOptions} sinkOptions
|
|
27
|
+
*/
|
|
28
|
+
constructor(
|
|
29
|
+
storageOptions,
|
|
30
|
+
{
|
|
31
|
+
writeTimeout = 60000,
|
|
32
|
+
writeGzip = false,
|
|
33
|
+
rootPath = DEFAULT_ROOT_PATH,
|
|
34
|
+
bucket = DEFAULT_BUCKET,
|
|
35
|
+
} = {},
|
|
36
|
+
) {
|
|
37
|
+
super();
|
|
38
|
+
if (typeof storageOptions !== "object" || storageOptions === null)
|
|
39
|
+
throw new Error('"storageOptions" argument must be provided');
|
|
40
|
+
this._writeTimeout = writeTimeout;
|
|
41
|
+
this._writeGzip = writeGzip;
|
|
42
|
+
this._rootPath = rootPath;
|
|
43
|
+
this._storage = new Storage(storageOptions);
|
|
44
|
+
this._bucket = this._storage.bucket(bucket);
|
|
45
|
+
this._metrics = new Metrics();
|
|
46
|
+
this._counter = this._metrics.counter({
|
|
47
|
+
name: "eik_core_sink_gcs",
|
|
48
|
+
description: "Counter measuring access to the Google Cloud Storage sink",
|
|
49
|
+
labels: {
|
|
50
|
+
operation: "n/a",
|
|
51
|
+
success: false,
|
|
52
|
+
access: false,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get metrics() {
|
|
58
|
+
return this._metrics;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
write(filePath, contentType) {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
const operation = "write";
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
super.constructor.validateFilePath(filePath);
|
|
67
|
+
super.constructor.validateContentType(contentType);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
this._counter.inc({ labels: { operation } });
|
|
70
|
+
reject(error);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const pathname = path.join(this._rootPath, filePath);
|
|
75
|
+
|
|
76
|
+
if (pathname.indexOf(this._rootPath) !== 0) {
|
|
77
|
+
this._counter.inc({ labels: { operation } });
|
|
78
|
+
reject(new Error(`Directory traversal - ${filePath}`));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const src = this._bucket.file(pathname);
|
|
83
|
+
const gcsStream = src.createWriteStream({
|
|
84
|
+
resumable: false,
|
|
85
|
+
metadata: {
|
|
86
|
+
cacheControl: "public, max-age=31536000",
|
|
87
|
+
contentType,
|
|
88
|
+
},
|
|
89
|
+
timeout: this._writeTimeout,
|
|
90
|
+
gzip: this._writeGzip,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
gcsStream.on("error", () => {
|
|
94
|
+
this._counter.inc({ labels: { access: true, operation } });
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
gcsStream.on("finish", () => {
|
|
98
|
+
this._counter.inc({
|
|
99
|
+
labels: { success: true, access: true, operation },
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
resolve(gcsStream);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
read(filePath) {
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
const operation = "read";
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
super.constructor.validateFilePath(filePath);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
this._counter.inc({ labels: { operation } });
|
|
115
|
+
reject(error);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const pathname = path.join(this._rootPath, filePath);
|
|
120
|
+
|
|
121
|
+
if (pathname.indexOf(this._rootPath) !== 0) {
|
|
122
|
+
this._counter.inc({ labels: { operation } });
|
|
123
|
+
reject(new Error(`Directory traversal - ${filePath}`));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let streamClosed = true;
|
|
128
|
+
|
|
129
|
+
const src = this._bucket.file(pathname);
|
|
130
|
+
const gcsStream = src.createReadStream();
|
|
131
|
+
|
|
132
|
+
gcsStream.on("readable", () => {
|
|
133
|
+
gcsStream.read();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
gcsStream.on("error", (error) => {
|
|
137
|
+
if (streamClosed) {
|
|
138
|
+
this._counter.inc({ labels: { access: true, operation } });
|
|
139
|
+
reject(error);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
gcsStream.on("response", (response) => {
|
|
144
|
+
this._counter.inc({
|
|
145
|
+
labels: { success: true, access: true, operation },
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
if (response.statusCode === 200) {
|
|
149
|
+
streamClosed = false;
|
|
150
|
+
const obj = new ReadFile({
|
|
151
|
+
mimeType: response.headers["content-type"],
|
|
152
|
+
etag: response.headers.etag,
|
|
153
|
+
});
|
|
154
|
+
obj.stream = gcsStream;
|
|
155
|
+
resolve(obj);
|
|
156
|
+
} else {
|
|
157
|
+
reject(
|
|
158
|
+
new Error(
|
|
159
|
+
`Could not read file. Got http status code ${response.statusCode} from GCS`,
|
|
160
|
+
),
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
delete(filePath) {
|
|
168
|
+
return new Promise((resolve, reject) => {
|
|
169
|
+
const operation = "delete";
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
super.constructor.validateFilePath(filePath);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
this._counter.inc({ labels: { operation } });
|
|
175
|
+
reject(error);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const pathname = path.join(this._rootPath, filePath);
|
|
180
|
+
|
|
181
|
+
if (pathname.indexOf(this._rootPath) !== 0) {
|
|
182
|
+
this._counter.inc({ labels: { operation } });
|
|
183
|
+
reject(new Error(`Directory traversal - ${filePath}`));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
this._counter.inc({
|
|
188
|
+
labels: { success: true, access: true, operation },
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
this._bucket.deleteFiles(
|
|
192
|
+
{
|
|
193
|
+
prefix: pathname,
|
|
194
|
+
force: true,
|
|
195
|
+
},
|
|
196
|
+
(error) => {
|
|
197
|
+
if (error) return reject(error);
|
|
198
|
+
return resolve();
|
|
199
|
+
},
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
exist(filePath) {
|
|
205
|
+
return new Promise((resolve, reject) => {
|
|
206
|
+
const operation = "exist";
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
super.constructor.validateFilePath(filePath);
|
|
210
|
+
} catch (error) {
|
|
211
|
+
this._counter.inc({ labels: { operation } });
|
|
212
|
+
reject(error);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const pathname = path.join(this._rootPath, filePath);
|
|
217
|
+
|
|
218
|
+
if (pathname.indexOf(this._rootPath) !== 0) {
|
|
219
|
+
this._counter.inc({ labels: { operation } });
|
|
220
|
+
reject(new Error(`Directory traversal - ${filePath}`));
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
this._counter.inc({
|
|
225
|
+
labels: { success: true, access: true, operation },
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const src = this._bucket.file(pathname);
|
|
229
|
+
|
|
230
|
+
src.exists((error, exists) => {
|
|
231
|
+
if (error) return reject(error);
|
|
232
|
+
if (exists) return resolve();
|
|
233
|
+
return reject();
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
get [Symbol.toStringTag]() {
|
|
239
|
+
return "SinkGCS";
|
|
240
|
+
}
|
|
215
241
|
};
|
|
216
242
|
export default SinkGCS;
|
package/package.json
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eik/sink-gcs",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.32",
|
|
4
4
|
"description": "Sink for Google Cloud Storage",
|
|
5
5
|
"main": "lib/main.js",
|
|
6
|
+
"types": "./types/main.d.ts",
|
|
6
7
|
"type": "module",
|
|
7
8
|
"files": [
|
|
8
9
|
"CHANGELOG.md",
|
|
9
10
|
"package.json",
|
|
10
11
|
"README.md",
|
|
11
|
-
"lib"
|
|
12
|
+
"lib",
|
|
13
|
+
"types"
|
|
12
14
|
],
|
|
13
15
|
"scripts": {
|
|
14
|
-
"test": "tap --
|
|
15
|
-
"test:snapshots
|
|
16
|
+
"test": "tap --disable-coverage --allow-empty-coverage",
|
|
17
|
+
"test:snapshots": "tap test/**/*.js --snapshot",
|
|
16
18
|
"lint:fix": "eslint --fix .",
|
|
17
|
-
"lint": "eslint ."
|
|
19
|
+
"lint": "eslint .",
|
|
20
|
+
"types": "run-s types:module types:test",
|
|
21
|
+
"types:module": "tsc",
|
|
22
|
+
"types:test": "tsc --project tsconfig.test.json"
|
|
18
23
|
},
|
|
19
24
|
"repository": {
|
|
20
25
|
"type": "git",
|
|
@@ -33,17 +38,17 @@
|
|
|
33
38
|
"@metrics/client": "^2.5.0"
|
|
34
39
|
},
|
|
35
40
|
"devDependencies": {
|
|
36
|
-
"@
|
|
37
|
-
"@
|
|
38
|
-
"@semantic-release
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"eslint
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"unique-slug": "
|
|
41
|
+
"@eik/eslint-config": "1.0.2",
|
|
42
|
+
"@eik/prettier-config": "1.0.1",
|
|
43
|
+
"@eik/semantic-release-config": "1.0.0",
|
|
44
|
+
"@eik/typescript-config": "1.0.0",
|
|
45
|
+
"@types/readable-stream": "4.0.15",
|
|
46
|
+
"eslint": "9.8.0",
|
|
47
|
+
"npm-run-all": "4.1.5",
|
|
48
|
+
"prettier": "3.3.3",
|
|
49
|
+
"semantic-release": "24.0.0",
|
|
50
|
+
"tap": "18.8.0",
|
|
51
|
+
"typescript": "5.5.4",
|
|
52
|
+
"unique-slug": "4.0.0"
|
|
48
53
|
}
|
|
49
54
|
}
|
package/types/main.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export default SinkGCS;
|
|
2
|
+
export type SinkGCSOptions = {
|
|
3
|
+
writeTimeout?: number;
|
|
4
|
+
writeGzip?: boolean;
|
|
5
|
+
rootPath?: string;
|
|
6
|
+
bucket?: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {object} SinkGCSOptions
|
|
10
|
+
* @property {number} [writeTimeout=60_000]
|
|
11
|
+
* @property {boolean} [writeGzip=false]
|
|
12
|
+
* @property {string} [rootPath="eik"]
|
|
13
|
+
* @property {string} [bucket="eik_files"]
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* A sink for uploading files to Google Cloud Storage
|
|
17
|
+
* https://googleapis.dev/nodejs/storage/latest/
|
|
18
|
+
*/
|
|
19
|
+
declare const SinkGCS: {
|
|
20
|
+
new (storageOptions: import("@google-cloud/storage").StorageOptions, { writeTimeout, writeGzip, rootPath, bucket, }?: SinkGCSOptions): {
|
|
21
|
+
_writeTimeout: number;
|
|
22
|
+
_writeGzip: boolean;
|
|
23
|
+
_rootPath: string;
|
|
24
|
+
_storage: Storage;
|
|
25
|
+
_bucket: import("@google-cloud/storage").Bucket;
|
|
26
|
+
_metrics: Metrics;
|
|
27
|
+
_counter: Metrics.MetricsCounter;
|
|
28
|
+
readonly metrics: Metrics;
|
|
29
|
+
write(filePath: any, contentType: any): Promise<any>;
|
|
30
|
+
read(filePath: any): Promise<any>;
|
|
31
|
+
delete(filePath: any): Promise<any>;
|
|
32
|
+
exist(filePath: any): Promise<any>;
|
|
33
|
+
readonly [Symbol.toStringTag]: string;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
import { Storage } from "@google-cloud/storage";
|
|
37
|
+
import Metrics from "@metrics/client";
|