Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic storage info to Upload model #624

Merged
merged 6 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/hungry-games-compete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@tus/file-store': minor
'@tus/gcs-store': minor
'@tus/s3-store': minor
'@tus/utils': minor
---

Add basic storage information to the Upload model. You can now access `upload.storage`
which has `type` (`file`, `s3`, `gcs`), `path`, and when applicable `bucket`.
Acconut marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 5 additions & 1 deletion packages/file-store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,14 @@ export class FileStore extends DataStore {
*/
async create(file: Upload): Promise<Upload> {
const dirs = file.id.split('/').slice(0, -1)
const filePath = path.join(this.directory, file.id)

await fsProm.mkdir(path.join(this.directory, ...dirs), {recursive: true})
await fsProm.writeFile(path.join(this.directory, file.id), '')
await fsProm.writeFile(filePath, '')
await this.configstore.set(file.id, file)

file.storage = {type: 'file', path: filePath}

return file
}

Expand Down Expand Up @@ -164,6 +167,7 @@ export class FileStore extends DataStore {
offset: stats.size,
metadata: file.metadata,
creation_date: file.creation_date,
storage: {type: 'file', path: file_path},
})
)
})
Expand Down
5 changes: 5 additions & 0 deletions packages/gcs-store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export class GCSStore extends DataStore {

const gcs_file = this.bucket.file(file.id)

file.storage = {type: 'gcs', path: file.id, bucket: this.bucket.name}

const options = {
metadata: {
metadata: {
Expand All @@ -41,6 +43,7 @@ export class GCSStore extends DataStore {
sizeIsDeferred: `${file.sizeIsDeferred}`,
offset: file.offset,
metadata: JSON.stringify(file.metadata),
storage: JSON.stringify(file.storage),
},
},
}
Expand Down Expand Up @@ -82,6 +85,7 @@ export class GCSStore extends DataStore {
sizeIsDeferred: `${upload.sizeIsDeferred}`,
offset,
metadata: JSON.stringify(upload.metadata),
storage: JSON.stringify(upload.storage),
},
},
}
Expand Down Expand Up @@ -150,6 +154,7 @@ export class GCSStore extends DataStore {
size: size ? Number.parseInt(size, 10) : size,
offset: Number.parseInt(metadata.size, 10), // `size` is set by GCS
metadata: meta ? JSON.parse(meta) : undefined,
storage: {type: 'gcs', path: id, bucket: this.bucket.name},
})
)
})
Expand Down
4 changes: 4 additions & 0 deletions packages/s3-store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ export class S3Store extends DataStore {
offset: Number.parseInt(file.offset, 10),
metadata: file.metadata,
creation_date: file.creation_date,
storage: file.storage,
}),
}
await this.cache.set(id, metadata)
Expand Down Expand Up @@ -530,6 +531,7 @@ export class S3Store extends DataStore {
upload.creation_date = new Date().toISOString()

const res = await this.client.createMultipartUpload(request)
upload.storage = {type: 's3', path: res.Key as string, bucket: this.bucket}
await this.saveMetadata(upload, res.UploadId as string)
log(`[${upload.id}] multipart upload created (${res.UploadId})`)

Expand Down Expand Up @@ -614,6 +616,7 @@ export class S3Store extends DataStore {
offset: metadata.file.size as number,
size: metadata.file.size,
metadata: metadata.file.metadata,
storage: metadata.file.storage,
})
}

Expand All @@ -627,6 +630,7 @@ export class S3Store extends DataStore {
...metadata.file,
offset: offset + (incompletePartSize ?? 0),
size: metadata.file.size,
storage: metadata.file.storage,
})
}

Expand Down
1 change: 1 addition & 0 deletions packages/server/test/DeleteHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ describe('DeleteHandler', () => {
creation_date: undefined,
offset: 1000,
size: 1000,
storage: {type: 'test', path: `${path}/abc`},
})
await assert.rejects(() => handler.send(req, res, context), {status_code: 400})
})
Expand Down
5 changes: 4 additions & 1 deletion packages/server/test/Server.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable no-throw-literal */
import 'should'

Expand Down Expand Up @@ -496,7 +497,9 @@ describe('Server', () => {
const server = new Server({
path: '/test/output',
datastore: new FileStore({directory}),
onUploadFinish() {
onUploadFinish(_, __, upload) {
assert.ok(upload.storage!.path, 'should have storage.path')
assert.ok(upload.storage!.type, 'should have storage.type')
throw {body: 'no', status_code: 500}
},
})
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/models/DataStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class DataStore extends EventEmitter {
* the upload.
*/
async getUpload(id: string): Promise<Upload> {
return new Upload({id, size: 0, offset: 0})
return new Upload({id, size: 0, offset: 0, storage: {type: 'datastore', path: ''}})
}

/**
Expand Down
9 changes: 8 additions & 1 deletion packages/utils/src/models/Upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@ type TUpload = {
size?: number
offset: number
metadata?: Record<string, string | null>
storage?: {
type: string
path: string
bucket?: string
}
creation_date?: string
}

export class Upload {
id: TUpload['id']
metadata: TUpload['metadata']
size?: TUpload['size']
size: TUpload['size']
offset: TUpload['offset']
creation_date: TUpload['creation_date']
storage: TUpload['storage']

constructor(upload: TUpload) {
if (!upload.id) {
Expand All @@ -22,6 +28,7 @@ export class Upload {
this.size = upload.size
this.offset = upload.offset
this.metadata = upload.metadata
this.storage = upload.storage

this.creation_date = upload.creation_date ?? new Date().toISOString()
}
Expand Down
2 changes: 2 additions & 0 deletions test/stores.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export const shouldCreateUploads = function () {

it('should resolve to file', async function () {
const newFile = await this.datastore.create(file)
assert.ok(newFile.storage.path)
assert.ok(newFile.storage.type)
assert.equal(newFile instanceof Upload, true)
})

Expand Down
Loading