Skip to content

Commit 5a36abd

Browse files
committed
Merge branch 'main' into async-configstores
* main: Bump typescript from 4.9.3 to 5.0.4 (tus#425) Bump sinon from 15.0.0 to 15.0.4 (tus#426) @tus/gcs-store: allow user to pass bucket instance to GCSStore (tus#388) Fix e2e test typecheking (tus#429) Update incorrect comment (tus#430) @tus/s3-store: add missing error code in termination extension (tus#413) @tus/[email protected] @tus/s3-store: fix uncaught exception when cancelling an upload (tus#412) @tus/[email protected] @tus/s3-store: fix uncaught exception when removing files (tus#410) @tus/s3-store: add termination extension (tus#401) @tus/[email protected] Bump @google-cloud/storage from 6.8.0 to 6.9.3 (tus#404) Bump http-cache-semantics from 4.1.0 to 4.1.1 (tus#393) Bump eslint-config-prettier from 8.5.0 to 8.6.0 (tus#392) Bump cookiejar from 2.1.3 to 2.1.4 (tus#383) Bump aws-sdk from 2.1269.0 to 2.1325.0 (tus#403) @tus/server: refactor and improve request validator (tus#402) Fix demo (tus#386)
2 parents 1f0a3dc + 8b8be66 commit 5a36abd

27 files changed

+821
-820
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,28 +110,28 @@ The tus protocol supports optional [extensions][]. Below is a table of the suppo
110110
| [Creation With Upload][] ||||
111111
| [Expiration][] ||||
112112
| [Checksum][] ||||
113-
| [Termination][] || ||
113+
| [Termination][] || ||
114114
| [Concatenation][] ||||
115115

116116
## Demos
117117

118118
Start the demo server using Local File Storage
119119

120120
```bash
121-
yarn workspace demo start
121+
yarn build && yarn demo
122122
```
123123

124124
Start up the demo server using AWS S3. The environment variables `AWS_BUCKET`,
125125
`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_REGION` need to be present.
126126

127127
```bash
128-
yarn workspace demo start:s3
128+
yarn build && yarn demo:s3
129129
```
130130

131131
Start up the demo server using Google Cloud Storage. A `keyfile.json` needs to be present in the root of the repository.
132132

133133
```bash
134-
yarn workspace demo start:gcs
134+
yarn build && yarn demo:gcs
135135
```
136136

137137
Then navigate to the demo ([localhost:1080](http://localhost:1080)) which uses [`tus-js-client`](https://github.com/tus/tus-js-client).

demo/server.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const writeFile = (req, res) => {
5959
if (!filename.startsWith('/dist/')) {
6060
filename = '/demos/browser' + filename
6161
}
62-
filename = path.join(process.cwd(), '/node_modules/tus-js-client', filename)
62+
filename = path.join(process.cwd(), '../node_modules/tus-js-client', filename)
6363
fs.readFile(filename, 'binary', (err, file) => {
6464
if (err) {
6565
res.writeHead(500, {'Content-Type': 'text/plain'})

packages/eslint-config-custom/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"@typescript-eslint/eslint-plugin": "^5.45.1",
1313
"@typescript-eslint/parser": "^5.47.1",
1414
"eslint": "^8.29.0",
15-
"eslint-config-prettier": "^8.5.0",
15+
"eslint-config-prettier": "^8.6.0",
1616
"eslint-config-turbo": "latest",
1717
"eslint-plugin-prettier": "^4.2.1",
1818
"prettier": "^2.8.1"

packages/gcs-store/README.md

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ npm install @tus/gcs-store
2929
const {Server} = require('@tus/server')
3030
const {GCSStore} = require('@tus/gcs-store')
3131

32+
const {Storage} = require('@google-cloud/storage');
33+
34+
const storage = new Storage({keyFilename: 'key.json'})
35+
3236
const server = new Server({
3337
path: '/files',
3438
datastore: new GCSStore({
35-
projectId: 'id',
36-
keyFilename: path.resolve('./some-path', 'keyfile.json'),
37-
bucket: 'tus-node-server-ci',
39+
bucket: storage.bucket('tus-node-server-ci'),
3840
}),
3941
})
4042
// ...
@@ -46,19 +48,11 @@ This package exports `GCSStore`. There is no default export.
4648

4749
### `new GCSStore(options)`
4850

49-
Creates a new Google Cloud Storage store with options.
50-
51-
#### `options.projectId`
52-
53-
The GCS project ID (`string`).
54-
55-
#### `options.keyFilename`
56-
57-
Path to the keyfile with credentials (`string`).
51+
Creates a new Google Cloud Storage store by passing a GCS bucket instance.
5852

5953
#### `options.bucket`
6054

61-
The bucket name.
55+
The bucket instance
6256

6357
## Extensions
6458

packages/gcs-store/index.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
1-
import {Storage, Bucket} from '@google-cloud/storage'
1+
import {Bucket} from '@google-cloud/storage'
22
import stream from 'node:stream'
33
import http from 'node:http'
44
import debug from 'debug'
55

66
import {ERRORS, TUS_RESUMABLE} from '@tus/server'
77
import {Upload, DataStore} from '@tus/server'
88

9-
type Options = {
10-
bucket: string
11-
projectId: string
12-
keyFilename: string
13-
}
14-
159
const log = debug('tus-node-server:stores:gcsstore')
1610

11+
type Options = {bucket: Bucket}
12+
1713
export class GCSStore extends DataStore {
1814
bucket: Bucket
19-
bucket_name: string
20-
gcs: Storage
2115

2216
constructor(options: Options) {
2317
super()
@@ -26,13 +20,9 @@ export class GCSStore extends DataStore {
2620
throw new Error('GCSDataStore must have a bucket')
2721
}
2822

23+
this.bucket = options.bucket
24+
2925
this.extensions = ['creation', 'creation-with-upload', 'creation-defer-length']
30-
this.bucket_name = options.bucket
31-
this.gcs = new Storage({
32-
projectId: options.projectId,
33-
keyFilename: options.keyFilename,
34-
})
35-
this.bucket = this.gcs.bucket(this.bucket_name)
3626
}
3727

3828
create(file: Upload): Promise<Upload> {

packages/gcs-store/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
"test": "mocha test.ts --timeout 30000 --exit --extension ts --require ts-node/register"
2222
},
2323
"dependencies": {
24-
"@google-cloud/storage": "^6.2.2",
2524
"debug": "^4.3.3"
2625
},
2726
"devDependencies": {
27+
"@google-cloud/storage": "^6.9.3",
2828
"@tus/server": "workspace:^",
2929
"@types/debug": "^4.1.7",
3030
"@types/mocha": "^10.0.1",
@@ -35,7 +35,8 @@
3535
"should": "^13.2.3",
3636
"typescript": "latest"
3737
},
38-
"peerdependencies": {
38+
"peerDependencies": {
39+
"@google-cloud/storage": "*",
3940
"@tus/server": "workspace:^"
4041
},
4142
"engines": {

packages/gcs-store/test.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import {GCSStore} from './'
44

55
import * as shared from '../../test/stores.test'
66

7+
import {Storage} from '@google-cloud/storage'
8+
79
const fixturesPath = path.resolve('../', '../', 'test', 'fixtures')
810
const storePath = path.resolve('../', '../', 'test', 'output')
911

@@ -16,10 +18,13 @@ describe('GCSStore', () => {
1618
})
1719

1820
beforeEach(function () {
19-
this.datastore = new GCSStore({
21+
const storage = new Storage({
2022
projectId: 'tus-node-server',
2123
keyFilename: path.resolve('../', '../', 'keyfile.json'),
22-
bucket: 'tus-node-server-ci',
24+
})
25+
26+
this.datastore = new GCSStore({
27+
bucket: storage.bucket('tus-node-server-ci'),
2328
})
2429
})
2530

packages/s3-store/README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
> 👉 **Note**: since 1.0.0 packages are split and published under the `@tus` scope.
44
> The old package, `tus-node-server`, is considered unstable and will only receive security fixes.
5-
> Make sure to use the new packages, currently in beta at `1.0.0-beta.1`.
5+
> Make sure to use the new package, currently in beta at `1.0.0-beta.5`.
66
77
## Contents
88

@@ -67,7 +67,7 @@ but may increase it to not exceed the S3 10K parts limit.
6767

6868
Options to pass to the AWS S3 SDK.
6969
Checkout the [`S3ClientConfig`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/interfaces/s3clientconfig.html)
70-
docs for the supported options. You need to at least set the `region`, `bucket` name, and your preferred method of authentication.
70+
docs for the supported options. You need to at least set the `region`, `bucket` name, and your preferred method of authentication.
7171

7272
## Extensions
7373

@@ -79,9 +79,13 @@ The tus protocol supports optional [extensions][]. Below is a table of the suppo
7979
| [Creation With Upload][] ||
8080
| [Expiration][] ||
8181
| [Checksum][] ||
82-
| [Termination][] | |
82+
| [Termination][] | |
8383
| [Concatenation][] ||
8484

85+
### Termination
86+
87+
After a multipart upload is aborted, no additional parts can be uploaded using that upload ID. The storage consumed by any previously uploaded parts will be freed. However, if any part uploads are currently in progress, those part uploads might or might not succeed. As a result, it might be necessary to set an [S3 Lifecycle configuration](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpu-abort-incomplete-mpu-lifecycle-config.html) to abort incomplete multipart uploads.
88+
8589
## Examples
8690

8791
### Example: using `credentials` to fetch credentials inside a AWS container

packages/s3-store/index.ts

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ export class S3Store extends DataStore {
7272
super()
7373
const {partSize, s3ClientConfig} = options
7474
const {bucket, ...restS3ClientConfig} = s3ClientConfig
75-
this.extensions = ['creation', 'creation-with-upload', 'creation-defer-length']
75+
this.extensions = [
76+
'creation',
77+
'creation-with-upload',
78+
'creation-defer-length',
79+
'termination',
80+
]
7681
this.bucket = bucket
7782
this.preferredPartSize = partSize || 8 * 1024 * 1024
7883
this.client = new aws.S3(restS3ClientConfig)
@@ -257,19 +262,23 @@ export class S3Store extends DataStore {
257262
])
258263
}
259264

265+
const readable = fs.createReadStream(path)
266+
readable.on('error', reject)
260267
if (partSize > this.minPartSize || isFinalChunk) {
261-
await this.uploadPart(metadata, fs.createReadStream(path), partNumber)
268+
await this.uploadPart(metadata, readable, partNumber)
262269
offset += partSize
263270
} else {
264-
await this.uploadIncompletePart(incompletePartId, fs.createReadStream(path))
271+
await this.uploadIncompletePart(incompletePartId, readable)
265272
}
266273

267274
bytesUploaded += partSize
268275
resolve()
269276
} catch (error) {
270277
reject(error)
271278
} finally {
272-
fsProm.rm(path).catch(/* ignore */)
279+
fsProm.rm(path).catch(() => {
280+
/* ignore */
281+
})
273282
}
274283
})
275284

@@ -517,4 +526,36 @@ export class S3Store extends DataStore {
517526

518527
this.saveMetadata(file, upload_id)
519528
}
529+
530+
public async remove(id: string): Promise<void> {
531+
try {
532+
const {upload_id} = await this.getMetadata(id)
533+
if (upload_id) {
534+
await this.client
535+
.abortMultipartUpload({
536+
Bucket: this.bucket,
537+
Key: id,
538+
UploadId: upload_id,
539+
})
540+
.promise()
541+
}
542+
} catch (error) {
543+
if (error?.code && ['NotFound', 'NoSuchKey', 'NoSuchUpload'].includes(error.code)) {
544+
log('remove: No file found.', error)
545+
throw ERRORS.FILE_NOT_FOUND
546+
}
547+
throw error
548+
}
549+
550+
await this.client
551+
.deleteObjects({
552+
Bucket: this.bucket,
553+
Delete: {
554+
Objects: [{Key: id}, {Key: `${id}.info`}],
555+
},
556+
})
557+
.promise()
558+
559+
this.clearCache(id)
560+
}
520561
}

packages/s3-store/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://json.schemastore.org/package.json",
33
"name": "@tus/s3-store",
4-
"version": "1.0.0-beta.3",
4+
"version": "1.0.0-beta.5",
55
"description": "AWS S3 store for @tus/server",
66
"main": "dist/index.js",
77
"types": "dist/index.d.ts",
@@ -21,7 +21,7 @@
2121
"test": "mocha test.ts --timeout 40000 --exit --extension ts --require ts-node/register"
2222
},
2323
"dependencies": {
24-
"aws-sdk": "^2.1064.0",
24+
"aws-sdk": "^2.1325.0",
2525
"debug": "^4.3.3"
2626
},
2727
"devDependencies": {

0 commit comments

Comments
 (0)