@balena/pinejs 17.0.0-build-wip-large-file-uploads-8d9c57891b422476172efba74cacc2a0fea09248-1 → 17.0.0-build-v17-13acf75c74cc64a383aca6e91ba9582f40f60ea1-2
Sign up to get free protection for your applications and to get access to all the features.
- package/.pinejs-cache.json +1 -1
- package/.versionbot/CHANGELOG.yml +5 -4
- package/CHANGELOG.md +2 -2
- package/out/migrator/utils.js +2 -2
- package/out/migrator/utils.js.map +1 -1
- package/out/server-glue/module.js +0 -2
- package/out/server-glue/module.js.map +1 -1
- package/out/webresource-handler/handlers/NoopHandler.d.ts +0 -3
- package/out/webresource-handler/handlers/NoopHandler.js +0 -6
- package/out/webresource-handler/handlers/NoopHandler.js.map +1 -1
- package/out/webresource-handler/handlers/S3Handler.d.ts +0 -7
- package/out/webresource-handler/handlers/S3Handler.js +2 -68
- package/out/webresource-handler/handlers/S3Handler.js.map +1 -1
- package/out/webresource-handler/index.d.ts +1 -10
- package/out/webresource-handler/index.js +10 -25
- package/out/webresource-handler/index.js.map +1 -1
- package/package.json +3 -3
- package/src/migrator/utils.ts +1 -1
- package/src/server-glue/module.ts +0 -2
- package/src/webresource-handler/handlers/NoopHandler.ts +0 -21
- package/src/webresource-handler/handlers/S3Handler.ts +4 -130
- package/src/webresource-handler/index.ts +11 -46
- package/out/webresource-handler/multipartUpload.d.ts +0 -39
- package/out/webresource-handler/multipartUpload.js +0 -187
- package/out/webresource-handler/multipartUpload.js.map +0 -1
- package/out/webresource-handler/webresource.sbvr +0 -63
- package/src/webresource-handler/multipartUpload.ts +0 -286
- package/src/webresource-handler/webresource.sbvr +0 -63
@@ -6,27 +6,17 @@ import {
|
|
6
6
|
WebResourceError,
|
7
7
|
type WebResourceHandler,
|
8
8
|
} from '..';
|
9
|
-
import type {
|
10
|
-
BeginUploadHandlerResponse,
|
11
|
-
BeginUploadPayload,
|
12
|
-
CommitUploadHandlerPayload,
|
13
|
-
UploadUrl,
|
14
|
-
} from '../multipartUpload';
|
15
9
|
import {
|
16
10
|
S3Client,
|
17
11
|
type S3ClientConfig,
|
18
12
|
DeleteObjectCommand,
|
19
13
|
type PutObjectCommandInput,
|
20
14
|
GetObjectCommand,
|
21
|
-
CreateMultipartUploadCommand,
|
22
|
-
UploadPartCommand,
|
23
|
-
CompleteMultipartUploadCommand,
|
24
|
-
HeadObjectCommand,
|
25
15
|
} from '@aws-sdk/client-s3';
|
26
16
|
import { Upload } from '@aws-sdk/lib-storage';
|
27
17
|
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
28
18
|
|
29
|
-
import { randomUUID } from '
|
19
|
+
import { randomUUID } from 'crypto';
|
30
20
|
import type { WebResourceType as WebResource } from '@balena/sbvr-types';
|
31
21
|
import memoize from 'memoizee';
|
32
22
|
|
@@ -81,7 +71,9 @@ export class S3Handler implements WebResourceHandler {
|
|
81
71
|
|
82
72
|
public async handleFile(resource: IncomingFile): Promise<UploadResponse> {
|
83
73
|
let size = 0;
|
84
|
-
const key =
|
74
|
+
const key = `${resource.fieldname}_${randomUUID()}_${
|
75
|
+
resource.originalname
|
76
|
+
}`;
|
85
77
|
const params: PutObjectCommandInput = {
|
86
78
|
Bucket: this.bucket,
|
87
79
|
Key: key,
|
@@ -130,62 +122,6 @@ export class S3Handler implements WebResourceHandler {
|
|
130
122
|
return webResource;
|
131
123
|
}
|
132
124
|
|
133
|
-
public async beginUpload(
|
134
|
-
fieldName: string,
|
135
|
-
payload: BeginUploadPayload,
|
136
|
-
): Promise<BeginUploadHandlerResponse> {
|
137
|
-
const fileKey = this.getFileKey(fieldName, payload.filename);
|
138
|
-
|
139
|
-
const createMultiPartResponse = await this.client.send(
|
140
|
-
new CreateMultipartUploadCommand({
|
141
|
-
Bucket: this.bucket,
|
142
|
-
Key: fileKey,
|
143
|
-
ContentType: payload.content_type,
|
144
|
-
}),
|
145
|
-
);
|
146
|
-
|
147
|
-
if (createMultiPartResponse.UploadId == null) {
|
148
|
-
throw new WebResourceError('Failed to create multipart upload.');
|
149
|
-
}
|
150
|
-
|
151
|
-
const uploadUrls = await this.getPartUploadUrls(
|
152
|
-
fileKey,
|
153
|
-
createMultiPartResponse.UploadId,
|
154
|
-
payload,
|
155
|
-
);
|
156
|
-
return { fileKey, uploadId: createMultiPartResponse.UploadId, uploadUrls };
|
157
|
-
}
|
158
|
-
|
159
|
-
public async commitUpload({
|
160
|
-
fileKey,
|
161
|
-
uploadId,
|
162
|
-
filename,
|
163
|
-
multipartUploadChecksums,
|
164
|
-
}: CommitUploadHandlerPayload): Promise<WebResource> {
|
165
|
-
await this.client.send(
|
166
|
-
new CompleteMultipartUploadCommand({
|
167
|
-
Bucket: this.bucket,
|
168
|
-
Key: fileKey,
|
169
|
-
UploadId: uploadId,
|
170
|
-
MultipartUpload: multipartUploadChecksums,
|
171
|
-
}),
|
172
|
-
);
|
173
|
-
|
174
|
-
const headResult = await this.client.send(
|
175
|
-
new HeadObjectCommand({
|
176
|
-
Bucket: this.bucket,
|
177
|
-
Key: fileKey,
|
178
|
-
}),
|
179
|
-
);
|
180
|
-
|
181
|
-
return {
|
182
|
-
href: this.getS3URL(fileKey),
|
183
|
-
filename: filename,
|
184
|
-
size: headResult.ContentLength,
|
185
|
-
content_type: headResult.ContentType,
|
186
|
-
};
|
187
|
-
}
|
188
|
-
|
189
125
|
private s3SignUrl(fileKey: string): Promise<string> {
|
190
126
|
const command = new GetObjectCommand({
|
191
127
|
Bucket: this.bucket,
|
@@ -200,70 +136,8 @@ export class S3Handler implements WebResourceHandler {
|
|
200
136
|
return `${this.config.endpoint}/${this.bucket}/${key}`;
|
201
137
|
}
|
202
138
|
|
203
|
-
private getFileKey(fieldName: string, fileName: string) {
|
204
|
-
return `${fieldName}_${randomUUID()}_${fileName}`;
|
205
|
-
}
|
206
|
-
|
207
139
|
private getKeyFromHref(href: string): string {
|
208
140
|
const hrefWithoutParams = normalizeHref(href);
|
209
141
|
return hrefWithoutParams.substring(hrefWithoutParams.lastIndexOf('/') + 1);
|
210
142
|
}
|
211
|
-
|
212
|
-
private async getPartUploadUrls(
|
213
|
-
fileKey: string,
|
214
|
-
uploadId: string,
|
215
|
-
payload: BeginUploadPayload,
|
216
|
-
): Promise<UploadUrl[]> {
|
217
|
-
const chunkSizesWithParts = await this.getChunkSizesWithParts(
|
218
|
-
payload.size,
|
219
|
-
payload.chunk_size,
|
220
|
-
);
|
221
|
-
return Promise.all(
|
222
|
-
chunkSizesWithParts.map(async ({ chunkSize, partNumber }) => ({
|
223
|
-
chunkSize,
|
224
|
-
partNumber,
|
225
|
-
url: await this.getPartUploadUrl(
|
226
|
-
fileKey,
|
227
|
-
uploadId,
|
228
|
-
partNumber,
|
229
|
-
chunkSize,
|
230
|
-
),
|
231
|
-
})),
|
232
|
-
);
|
233
|
-
}
|
234
|
-
|
235
|
-
private async getPartUploadUrl(
|
236
|
-
fileKey: string,
|
237
|
-
uploadId: string,
|
238
|
-
partNumber: number,
|
239
|
-
partSize: number,
|
240
|
-
): Promise<string> {
|
241
|
-
const command = new UploadPartCommand({
|
242
|
-
Bucket: this.bucket,
|
243
|
-
Key: fileKey,
|
244
|
-
UploadId: uploadId,
|
245
|
-
PartNumber: partNumber,
|
246
|
-
ContentLength: partSize,
|
247
|
-
});
|
248
|
-
|
249
|
-
return getSignedUrl(this.client, command, {
|
250
|
-
expiresIn: this.signedUrlExpireTimeSeconds,
|
251
|
-
});
|
252
|
-
}
|
253
|
-
|
254
|
-
private async getChunkSizesWithParts(
|
255
|
-
size: number,
|
256
|
-
chunkSize: number,
|
257
|
-
): Promise<Array<Pick<UploadUrl, 'chunkSize' | 'partNumber'>>> {
|
258
|
-
const chunkSizesWithParts = [];
|
259
|
-
let partNumber = 1;
|
260
|
-
let remainingSize = size;
|
261
|
-
while (remainingSize > 0) {
|
262
|
-
const currentChunkSize = Math.min(remainingSize, chunkSize);
|
263
|
-
chunkSizesWithParts.push({ chunkSize: currentChunkSize, partNumber });
|
264
|
-
remainingSize -= currentChunkSize;
|
265
|
-
partNumber += 1;
|
266
|
-
}
|
267
|
-
return chunkSizesWithParts;
|
268
|
-
}
|
269
143
|
}
|
@@ -1,25 +1,19 @@
|
|
1
|
+
import type * as Express from 'express';
|
2
|
+
import busboy from 'busboy';
|
3
|
+
import type * as stream from 'node:stream';
|
4
|
+
import * as uriParser from '../sbvr-api/uri-parser';
|
5
|
+
import * as sbvrUtils from '../sbvr-api/sbvr-utils';
|
6
|
+
import type { HookArgs } from '../sbvr-api/hooks';
|
7
|
+
import { getApiRoot, getModel } from '../sbvr-api/sbvr-utils';
|
8
|
+
import { checkPermissions } from '../sbvr-api/permissions';
|
9
|
+
import { NoopHandler } from './handlers/NoopHandler';
|
1
10
|
import {
|
2
11
|
odataNameToSqlName,
|
3
12
|
sqlNameToODataName,
|
4
13
|
} from '@balena/odata-to-abstract-sql';
|
14
|
+
import { errors, permissions } from '../server-glue/module';
|
5
15
|
import type { WebResourceType as WebResource } from '@balena/sbvr-types';
|
6
|
-
import busboy from 'busboy';
|
7
|
-
import type * as Express from 'express';
|
8
|
-
import type * as stream from 'node:stream';
|
9
16
|
import { TypedError } from 'typed-error';
|
10
|
-
import type { HookArgs } from '../sbvr-api/hooks';
|
11
|
-
import { checkPermissions } from '../sbvr-api/permissions';
|
12
|
-
import * as sbvrUtils from '../sbvr-api/sbvr-utils';
|
13
|
-
import { getApiRoot, getModel } from '../sbvr-api/sbvr-utils';
|
14
|
-
import * as uriParser from '../sbvr-api/uri-parser';
|
15
|
-
import { errors, permissions } from '../server-glue/module';
|
16
|
-
import { NoopHandler } from './handlers/NoopHandler';
|
17
|
-
import type {
|
18
|
-
BeginUploadHandlerResponse,
|
19
|
-
BeginUploadPayload,
|
20
|
-
CommitUploadHandlerPayload,
|
21
|
-
} from './multipartUpload';
|
22
|
-
import { multipartUploadHooks } from './multipartUpload';
|
23
17
|
|
24
18
|
export * from './handlers';
|
25
19
|
|
@@ -40,14 +34,6 @@ export interface WebResourceHandler {
|
|
40
34
|
handleFile: (resource: IncomingFile) => Promise<UploadResponse>;
|
41
35
|
removeFile: (fileReference: string) => Promise<void>;
|
42
36
|
onPreRespond: (webResource: WebResource) => Promise<WebResource>;
|
43
|
-
|
44
|
-
beginUpload: (
|
45
|
-
fieldName: string,
|
46
|
-
payload: BeginUploadPayload,
|
47
|
-
) => Promise<BeginUploadHandlerResponse>;
|
48
|
-
commitUpload: (
|
49
|
-
commitInfo: CommitUploadHandlerPayload,
|
50
|
-
) => Promise<WebResource>;
|
51
37
|
}
|
52
38
|
|
53
39
|
export class WebResourceError extends TypedError {}
|
@@ -230,7 +216,7 @@ export const getUploaderMiddlware = (
|
|
230
216
|
};
|
231
217
|
};
|
232
218
|
|
233
|
-
|
219
|
+
const getWebResourceFields = (
|
234
220
|
request: uriParser.ODataRequest,
|
235
221
|
useTranslations = true,
|
236
222
|
): string[] => {
|
@@ -263,8 +249,6 @@ const throwIfWebresourceNotInMultipart = (
|
|
263
249
|
{ req, request }: HookArgs,
|
264
250
|
) => {
|
265
251
|
if (
|
266
|
-
request.custom.isAction !== 'beginUpload' &&
|
267
|
-
request.custom.isAction !== 'commitUpload' &&
|
268
252
|
!req.is?.('multipart') &&
|
269
253
|
webResourceFields.some((field) => request.values[field] != null)
|
270
254
|
) {
|
@@ -463,23 +447,4 @@ export const setupUploadHooks = (
|
|
463
447
|
resourceName,
|
464
448
|
getCreateWebResourceHooks(handler),
|
465
449
|
);
|
466
|
-
|
467
|
-
sbvrUtils.addPureHook(
|
468
|
-
'POST',
|
469
|
-
apiRoot,
|
470
|
-
resourceName,
|
471
|
-
multipartUploadHooks(handler),
|
472
|
-
);
|
473
|
-
};
|
474
|
-
|
475
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
476
|
-
const webresourceModel: string = require('./webresource.sbvr');
|
477
|
-
export const config = {
|
478
|
-
models: [
|
479
|
-
{
|
480
|
-
apiRoot: 'webresource',
|
481
|
-
modelText: webresourceModel,
|
482
|
-
modelName: 'webresource',
|
483
|
-
},
|
484
|
-
] as sbvrUtils.ExecutableModel[],
|
485
450
|
};
|
@@ -1,39 +0,0 @@
|
|
1
|
-
import type { AnyObject } from 'pinejs-client-core';
|
2
|
-
import type { WebResourceHandler } from '.';
|
3
|
-
import type { ODataRequest } from '../sbvr-api/uri-parser';
|
4
|
-
import { sbvrUtils } from '../server-glue/module';
|
5
|
-
export interface BeginUploadPayload {
|
6
|
-
filename: string;
|
7
|
-
content_type: string;
|
8
|
-
size: number;
|
9
|
-
chunk_size: number;
|
10
|
-
}
|
11
|
-
export interface UploadUrl {
|
12
|
-
url: string;
|
13
|
-
chunkSize: number;
|
14
|
-
partNumber: number;
|
15
|
-
}
|
16
|
-
export interface BeginUploadHandlerResponse {
|
17
|
-
uploadUrls: UploadUrl[];
|
18
|
-
fileKey: string;
|
19
|
-
uploadId: string;
|
20
|
-
}
|
21
|
-
export interface PendingUpload extends BeginUploadPayload {
|
22
|
-
fieldName: string;
|
23
|
-
fileKey: string;
|
24
|
-
uploadId: string;
|
25
|
-
}
|
26
|
-
export interface BeginUploadResponse {
|
27
|
-
[fieldName: string]: {
|
28
|
-
key: string;
|
29
|
-
uploadUrls: UploadUrl[];
|
30
|
-
};
|
31
|
-
}
|
32
|
-
export interface CommitUploadHandlerPayload {
|
33
|
-
fileKey: string;
|
34
|
-
uploadId: string;
|
35
|
-
filename: string;
|
36
|
-
multipartUploadChecksums?: AnyObject;
|
37
|
-
}
|
38
|
-
export declare const multipartUploadHooks: (webResourceHandler: WebResourceHandler) => sbvrUtils.Hooks;
|
39
|
-
export declare const beginUpload: (webResourceHandler: WebResourceHandler, odataRequest: ODataRequest, actorId?: number) => Promise<BeginUploadResponse>;
|
@@ -1,187 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.beginUpload = exports.multipartUploadHooks = void 0;
|
4
|
-
const node_crypto_1 = require("node:crypto");
|
5
|
-
const _1 = require(".");
|
6
|
-
const sbvr_utils_1 = require("../sbvr-api/sbvr-utils");
|
7
|
-
const module_1 = require("../server-glue/module");
|
8
|
-
const MB = 1024 * 1024;
|
9
|
-
const multipartUploadHooks = (webResourceHandler) => {
|
10
|
-
return {
|
11
|
-
POSTPARSE: async ({ req, request, tx, api: vocabularyApi }) => {
|
12
|
-
if (request.odataQuery.property?.resource === 'beginUpload') {
|
13
|
-
const uploadParams = parseBeginUpload(request);
|
14
|
-
await vocabularyApi.post({
|
15
|
-
url: request.url.substring(1).replace('beginUpload', 'canAccess'),
|
16
|
-
body: { method: 'PATCH' },
|
17
|
-
});
|
18
|
-
tx = await module_1.sbvrUtils.db.transaction();
|
19
|
-
req.tx = tx;
|
20
|
-
request.tx = tx;
|
21
|
-
request.method = 'PATCH';
|
22
|
-
request.values = uploadParams;
|
23
|
-
request.odataQuery.resource = request.resourceName;
|
24
|
-
delete request.odataQuery.property;
|
25
|
-
request.custom.isAction = 'beginUpload';
|
26
|
-
}
|
27
|
-
else if (request.odataQuery.property?.resource === 'commitUpload') {
|
28
|
-
const commitPayload = await parseCommitUpload(request);
|
29
|
-
await vocabularyApi.post({
|
30
|
-
url: request.url.substring(1).replace('commitUpload', 'canAccess'),
|
31
|
-
body: { method: 'PATCH' },
|
32
|
-
});
|
33
|
-
const webresource = await webResourceHandler.commitUpload({
|
34
|
-
fileKey: commitPayload.metadata.fileKey,
|
35
|
-
uploadId: commitPayload.metadata.uploadId,
|
36
|
-
filename: commitPayload.metadata.filename,
|
37
|
-
multipartUploadChecksums: commitPayload.additionalCommitInfo,
|
38
|
-
});
|
39
|
-
await sbvr_utils_1.api.webresource.patch({
|
40
|
-
resource: 'multipart_upload',
|
41
|
-
body: {
|
42
|
-
status: 'completed',
|
43
|
-
},
|
44
|
-
options: {
|
45
|
-
$filter: {
|
46
|
-
uuid: commitPayload.key,
|
47
|
-
},
|
48
|
-
},
|
49
|
-
passthrough: {
|
50
|
-
req: module_1.permissions.root,
|
51
|
-
tx: tx,
|
52
|
-
},
|
53
|
-
});
|
54
|
-
request.method = 'PATCH';
|
55
|
-
request.values = {
|
56
|
-
[commitPayload.metadata.fieldName]: webresource,
|
57
|
-
};
|
58
|
-
request.odataQuery.resource = request.resourceName;
|
59
|
-
delete request.odataQuery.property;
|
60
|
-
request.custom.isAction = 'commitUpload';
|
61
|
-
request.custom.commitUploadPayload = webresource;
|
62
|
-
}
|
63
|
-
},
|
64
|
-
PRERESPOND: async ({ req, request, response, tx }) => {
|
65
|
-
if (request.custom.isAction === 'beginUpload') {
|
66
|
-
await tx.rollback();
|
67
|
-
response.statusCode = 200;
|
68
|
-
response.body = await (0, exports.beginUpload)(webResourceHandler, request, req.user?.actor);
|
69
|
-
}
|
70
|
-
else if (request.custom.isAction === 'commitUpload') {
|
71
|
-
response.body = await webResourceHandler.onPreRespond(request.custom.commitUploadPayload);
|
72
|
-
}
|
73
|
-
},
|
74
|
-
};
|
75
|
-
};
|
76
|
-
exports.multipartUploadHooks = multipartUploadHooks;
|
77
|
-
const beginUpload = async (webResourceHandler, odataRequest, actorId) => {
|
78
|
-
const payload = odataRequest.values;
|
79
|
-
const fieldName = Object.keys(payload)[0];
|
80
|
-
const metadata = payload[fieldName];
|
81
|
-
const { fileKey, uploadId, uploadUrls } = await webResourceHandler.beginUpload(fieldName, metadata);
|
82
|
-
const uuid = (0, node_crypto_1.randomUUID)();
|
83
|
-
try {
|
84
|
-
await sbvr_utils_1.api.webresource.post({
|
85
|
-
resource: 'multipart_upload',
|
86
|
-
body: {
|
87
|
-
uuid,
|
88
|
-
resource_name: odataRequest.resourceName,
|
89
|
-
field_name: fieldName,
|
90
|
-
resource_id: odataRequest.affectedIds?.[0],
|
91
|
-
upload_id: uploadId,
|
92
|
-
file_key: fileKey,
|
93
|
-
status: 'pending',
|
94
|
-
filename: metadata.filename,
|
95
|
-
content_type: metadata.content_type,
|
96
|
-
size: metadata.size,
|
97
|
-
chunk_size: metadata.chunk_size,
|
98
|
-
expiry_date: Date.now() + 7 * 24 * 60 * 60 * 1000,
|
99
|
-
is_created_by__actor: actorId,
|
100
|
-
},
|
101
|
-
passthrough: {
|
102
|
-
req: module_1.permissions.root,
|
103
|
-
},
|
104
|
-
});
|
105
|
-
}
|
106
|
-
catch (err) {
|
107
|
-
console.error('failed to start multipart upload', err);
|
108
|
-
throw new module_1.errors.BadRequestError('Failed to start multipart upload');
|
109
|
-
}
|
110
|
-
return { [fieldName]: { key: uuid, uploadUrls } };
|
111
|
-
};
|
112
|
-
exports.beginUpload = beginUpload;
|
113
|
-
const parseBeginUpload = (request) => {
|
114
|
-
if (request.odataQuery.key == null) {
|
115
|
-
throw new module_1.errors.BadRequestError();
|
116
|
-
}
|
117
|
-
const fieldNames = Object.keys(request.values);
|
118
|
-
if (fieldNames.length !== 1) {
|
119
|
-
throw new module_1.errors.BadRequestError('You can only get upload url for one field at a time');
|
120
|
-
}
|
121
|
-
const [fieldName] = fieldNames;
|
122
|
-
const webResourceFields = (0, _1.getWebResourceFields)(request, false);
|
123
|
-
if (!webResourceFields.includes(fieldName)) {
|
124
|
-
throw new module_1.errors.BadRequestError(`You must provide a valid webresource field from: ${JSON.stringify(webResourceFields)}`);
|
125
|
-
}
|
126
|
-
const beginUploadPayload = parseBeginUploadPayload(request.values[fieldName]);
|
127
|
-
if (beginUploadPayload == null) {
|
128
|
-
throw new module_1.errors.BadRequestError('Invalid file metadata');
|
129
|
-
}
|
130
|
-
const uploadMetadataCheck = {
|
131
|
-
...beginUploadPayload,
|
132
|
-
href: 'metadata_check',
|
133
|
-
};
|
134
|
-
return { [fieldName]: uploadMetadataCheck };
|
135
|
-
};
|
136
|
-
const parseBeginUploadPayload = (payload) => {
|
137
|
-
if (typeof payload !== 'object') {
|
138
|
-
return null;
|
139
|
-
}
|
140
|
-
let { filename, content_type, size, chunk_size } = payload;
|
141
|
-
if (typeof filename !== 'string' ||
|
142
|
-
typeof content_type !== 'string' ||
|
143
|
-
typeof size !== 'number' ||
|
144
|
-
(chunk_size != null && typeof chunk_size !== 'number') ||
|
145
|
-
(chunk_size != null && chunk_size < 5 * MB)) {
|
146
|
-
return null;
|
147
|
-
}
|
148
|
-
if (chunk_size == null) {
|
149
|
-
chunk_size = 5 * MB;
|
150
|
-
}
|
151
|
-
return { filename, content_type, size, chunk_size };
|
152
|
-
};
|
153
|
-
const parseCommitUpload = async (request) => {
|
154
|
-
if (request.odataQuery.key == null) {
|
155
|
-
throw new module_1.errors.BadRequestError();
|
156
|
-
}
|
157
|
-
const { key, additionalCommitInfo } = request.values;
|
158
|
-
if (typeof key !== 'string') {
|
159
|
-
throw new module_1.errors.BadRequestError('Invalid key type');
|
160
|
-
}
|
161
|
-
const [multipartUpload] = (await sbvr_utils_1.api.webresource.get({
|
162
|
-
resource: 'multipart_upload',
|
163
|
-
options: {
|
164
|
-
$select: ['id', 'file_key', 'upload_id', 'field_name', 'filename'],
|
165
|
-
$filter: {
|
166
|
-
uuid: key,
|
167
|
-
status: 'pending',
|
168
|
-
expiry_date: { $gt: { $now: {} } },
|
169
|
-
},
|
170
|
-
},
|
171
|
-
passthrough: {
|
172
|
-
req: module_1.permissions.root,
|
173
|
-
tx: request.tx,
|
174
|
-
},
|
175
|
-
}));
|
176
|
-
if (multipartUpload == null) {
|
177
|
-
throw new module_1.errors.BadRequestError(`Invalid upload for key ${key}`);
|
178
|
-
}
|
179
|
-
const metadata = {
|
180
|
-
fileKey: multipartUpload.file_key,
|
181
|
-
uploadId: multipartUpload.upload_id,
|
182
|
-
filename: multipartUpload.filename,
|
183
|
-
fieldName: multipartUpload.field_name,
|
184
|
-
};
|
185
|
-
return { key, additionalCommitInfo, metadata };
|
186
|
-
};
|
187
|
-
//# sourceMappingURL=multipartUpload.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"multipartUpload.js","sourceRoot":"","sources":["../../src/webresource-handler/multipartUpload.ts"],"names":[],"mappings":"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"}
|
@@ -1,63 +0,0 @@
|
|
1
|
-
Vocabulary: Auth
|
2
|
-
|
3
|
-
Term: actor
|
4
|
-
Term: expiry date
|
5
|
-
Concept Type: Date Time (Type)
|
6
|
-
|
7
|
-
Vocabulary: webresource
|
8
|
-
|
9
|
-
Term: uuid
|
10
|
-
Concept Type: Short Text (Type)
|
11
|
-
Term: resource name
|
12
|
-
Concept Type: Short Text (Type)
|
13
|
-
Term: field name
|
14
|
-
Concept Type: Short Text (Type)
|
15
|
-
Term: resource id
|
16
|
-
Concept Type: Integer (Type)
|
17
|
-
Term: upload id
|
18
|
-
Concept Type: Short Text (Type)
|
19
|
-
Term: file key
|
20
|
-
Concept Type: Short Text (Type)
|
21
|
-
Term: status
|
22
|
-
Concept Type: Short Text (Type)
|
23
|
-
Term: filename
|
24
|
-
Concept Type: Short Text (Type)
|
25
|
-
Term: content type
|
26
|
-
Concept Type: Short Text (Type)
|
27
|
-
Term: size
|
28
|
-
Concept Type: Integer (Type)
|
29
|
-
Term: chunk size
|
30
|
-
Concept Type: Integer (Type)
|
31
|
-
Term: valid until date
|
32
|
-
Concept Type: Date Time (Type)
|
33
|
-
|
34
|
-
Term: multipart upload
|
35
|
-
Fact type: multipart upload has uuid
|
36
|
-
Necessity: each multipart upload has exactly one uuid
|
37
|
-
Necessity: each uuid is of exactly one multipart upload
|
38
|
-
Fact type: multipart upload has resource name
|
39
|
-
Necessity: each multipart upload has exactly one resource name
|
40
|
-
Fact type: multipart upload has field name
|
41
|
-
Necessity: each multipart upload has exactly one field name
|
42
|
-
Fact type: multipart upload has resource id
|
43
|
-
Necessity: each multipart upload has exactly one resource id
|
44
|
-
Fact type: multipart upload has upload id
|
45
|
-
Necessity: each multipart upload has exactly one upload id
|
46
|
-
Fact type: multipart upload has file key
|
47
|
-
Necessity: each multipart upload has exactly one file key
|
48
|
-
Fact type: multipart upload has status
|
49
|
-
Necessity: each multipart upload has exactly one status
|
50
|
-
Definition: "pending" or "completed" or "cancelled"
|
51
|
-
Fact type: multipart upload has filename
|
52
|
-
Necessity: each multipart upload has exactly one filename
|
53
|
-
Fact type: multipart upload has content type
|
54
|
-
Necessity: each multipart upload has exactly one content type
|
55
|
-
Fact type: multipart upload has size
|
56
|
-
Necessity: each multipart upload has exactly one size
|
57
|
-
Fact type: multipart upload has chunk size
|
58
|
-
Necessity: each multipart upload has exactly one chunk size
|
59
|
-
Fact type: multipart upload has expiry date (Auth)
|
60
|
-
Necessity: each multipart upload has exactly one expiry date (Auth)
|
61
|
-
Fact type: multipart upload is created by actor (Auth)
|
62
|
-
Necessity: each multipart upload is created by at most one actor (Auth)
|
63
|
-
Reference Type: informative
|