Skip to content

Commit e3aa784

Browse files
feat: Support upload with preflight check (box/box-codegen#676) (#554)
1 parent 6779837 commit e3aa784

File tree

4 files changed

+401
-4
lines changed

4 files changed

+401
-4
lines changed

.codegen.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "engineHash": "3d68c3f", "specHash": "c303afc", "version": "1.13.2" }
1+
{ "engineHash": "0f745bf", "specHash": "c303afc", "version": "1.13.2" }

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/managers/uploads.generated.ts

Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,40 @@ export interface UploadFileOptionalsInput {
9898
readonly headers?: UploadFileHeaders;
9999
readonly cancellationToken?: undefined | CancellationToken;
100100
}
101+
export class UploadWithPreflightCheckOptionals {
102+
readonly queryParams: UploadWithPreflightCheckQueryParams =
103+
{} satisfies UploadWithPreflightCheckQueryParams;
104+
readonly headers: UploadWithPreflightCheckHeaders =
105+
new UploadWithPreflightCheckHeaders({});
106+
readonly cancellationToken?: CancellationToken = void 0;
107+
constructor(
108+
fields: Omit<
109+
UploadWithPreflightCheckOptionals,
110+
'queryParams' | 'headers' | 'cancellationToken'
111+
> &
112+
Partial<
113+
Pick<
114+
UploadWithPreflightCheckOptionals,
115+
'queryParams' | 'headers' | 'cancellationToken'
116+
>
117+
>,
118+
) {
119+
if (fields.queryParams !== undefined) {
120+
this.queryParams = fields.queryParams;
121+
}
122+
if (fields.headers !== undefined) {
123+
this.headers = fields.headers;
124+
}
125+
if (fields.cancellationToken !== undefined) {
126+
this.cancellationToken = fields.cancellationToken;
127+
}
128+
}
129+
}
130+
export interface UploadWithPreflightCheckOptionalsInput {
131+
readonly queryParams?: UploadWithPreflightCheckQueryParams;
132+
readonly headers?: UploadWithPreflightCheckHeaders;
133+
readonly cancellationToken?: undefined | CancellationToken;
134+
}
101135
export interface UploadFileVersionRequestBodyAttributesField {
102136
/**
103137
* An optional new name for the file. If specified, the file
@@ -353,6 +387,100 @@ export interface UploadFileHeadersInput {
353387
readonly [key: string]: undefined | string;
354388
};
355389
}
390+
export interface UploadWithPreflightCheckRequestBodyAttributesParentField {
391+
/**
392+
* The id of the parent folder. Use
393+
* `0` for the user's root folder. */
394+
readonly id: string;
395+
readonly rawData?: SerializedData;
396+
}
397+
export interface UploadWithPreflightCheckRequestBodyAttributesField {
398+
/**
399+
* The name of the file */
400+
readonly name: string;
401+
/**
402+
* The parent folder to upload the file to */
403+
readonly parent: UploadWithPreflightCheckRequestBodyAttributesParentField;
404+
/**
405+
* Defines the time the file was originally created at.
406+
*
407+
* If not set, the upload time will be used. */
408+
readonly contentCreatedAt?: DateTime;
409+
/**
410+
* Defines the time the file was last modified at.
411+
*
412+
* If not set, the upload time will be used. */
413+
readonly contentModifiedAt?: DateTime;
414+
/**
415+
* The size of the file in bytes */
416+
readonly size: number;
417+
readonly rawData?: SerializedData;
418+
}
419+
export interface UploadWithPreflightCheckRequestBody {
420+
readonly attributes: UploadWithPreflightCheckRequestBodyAttributesField;
421+
/**
422+
* The content of the file to upload to Box.
423+
*
424+
* <Message warning>
425+
*
426+
* The `attributes` part of the body must come **before** the
427+
* `file` part. Requests that do not follow this format when
428+
* uploading the file will receive a HTTP `400` error with a
429+
* `metadata_after_file_contents` error code.
430+
*
431+
* </Message> */
432+
readonly file: ByteStream;
433+
readonly fileFileName?: string;
434+
readonly fileContentType?: string;
435+
}
436+
export interface UploadWithPreflightCheckQueryParams {
437+
/**
438+
* A comma-separated list of attributes to include in the
439+
* response. This can be used to request fields that are
440+
* not normally returned in a standard response.
441+
*
442+
* Be aware that specifying this parameter will have the
443+
* effect that none of the standard fields are returned in
444+
* the response unless explicitly specified, instead only
445+
* fields for the mini representation are returned, additional
446+
* to the fields requested. */
447+
readonly fields?: readonly string[];
448+
}
449+
export class UploadWithPreflightCheckHeaders {
450+
/**
451+
* An optional header containing the SHA1 hash of the file to
452+
* ensure that the file was not corrupted in transit. */
453+
readonly contentMd5?: string;
454+
/**
455+
* Extra headers that will be included in the HTTP request. */
456+
readonly extraHeaders?: {
457+
readonly [key: string]: undefined | string;
458+
} = {};
459+
constructor(
460+
fields: Omit<UploadWithPreflightCheckHeaders, 'extraHeaders'> &
461+
Partial<Pick<UploadWithPreflightCheckHeaders, 'extraHeaders'>>,
462+
) {
463+
if (fields.contentMd5 !== undefined) {
464+
this.contentMd5 = fields.contentMd5;
465+
}
466+
if (fields.extraHeaders !== undefined) {
467+
this.extraHeaders = fields.extraHeaders;
468+
}
469+
}
470+
}
471+
export interface UploadWithPreflightCheckHeadersInput {
472+
/**
473+
* An optional header containing the SHA1 hash of the file to
474+
* ensure that the file was not corrupted in transit. */
475+
readonly contentMd5?: string;
476+
/**
477+
* Extra headers that will be included in the HTTP request. */
478+
readonly extraHeaders?:
479+
| undefined
480+
| {
481+
readonly [key: string]: undefined | string;
482+
};
483+
}
356484
export class UploadsManager {
357485
readonly auth?: Authentication;
358486
readonly networkSession: NetworkSession = new NetworkSession({});
@@ -363,6 +491,7 @@ export class UploadsManager {
363491
| 'uploadFileVersion'
364492
| 'preflightFileUploadCheck'
365493
| 'uploadFile'
494+
| 'uploadWithPreflightCheck'
366495
> &
367496
Partial<Pick<UploadsManager, 'networkSession'>>,
368497
) {
@@ -578,6 +707,90 @@ export class UploadsManager {
578707
rawData: response.data!,
579708
};
580709
}
710+
/**
711+
* Upload a file with a preflight check
712+
* @param {UploadWithPreflightCheckRequestBody} requestBody
713+
* @param {UploadWithPreflightCheckOptionalsInput} optionalsInput
714+
* @returns {Promise<Files>}
715+
*/
716+
async uploadWithPreflightCheck(
717+
requestBody: UploadWithPreflightCheckRequestBody,
718+
optionalsInput: UploadWithPreflightCheckOptionalsInput = {},
719+
): Promise<Files> {
720+
const optionals: UploadWithPreflightCheckOptionals =
721+
new UploadWithPreflightCheckOptionals({
722+
queryParams: optionalsInput.queryParams,
723+
headers: optionalsInput.headers,
724+
cancellationToken: optionalsInput.cancellationToken,
725+
});
726+
const queryParams: any = optionals.queryParams;
727+
const headers: any = optionals.headers;
728+
const cancellationToken: any = optionals.cancellationToken;
729+
const queryParamsMap: {
730+
readonly [key: string]: string;
731+
} = prepareParams({
732+
['fields']: queryParams.fields
733+
? queryParams.fields.map(toString).join(',')
734+
: undefined,
735+
});
736+
const headersMap: {
737+
readonly [key: string]: string;
738+
} = prepareParams({
739+
...{ ['content-md5']: toString(headers.contentMd5) as string },
740+
...headers.extraHeaders,
741+
});
742+
const preflightUploadUrl: UploadUrl = await this.preflightFileUploadCheck(
743+
{
744+
name: requestBody.attributes.name,
745+
size: requestBody.attributes.size,
746+
parent: {
747+
id: requestBody.attributes.parent.id,
748+
} satisfies PreflightFileUploadCheckRequestBodyParentField,
749+
} satisfies PreflightFileUploadCheckRequestBody,
750+
{
751+
extraHeaders: headers.extraHeaders,
752+
} satisfies PreflightFileUploadCheckHeadersInput,
753+
cancellationToken,
754+
);
755+
if (
756+
preflightUploadUrl.uploadUrl == void 0 ||
757+
!(preflightUploadUrl.uploadUrl!.includes('http') as boolean)
758+
) {
759+
throw new BoxSdkError({ message: 'Unable to get preflight upload URL' });
760+
}
761+
const response: FetchResponse =
762+
await this.networkSession.networkClient.fetch(
763+
new FetchOptions({
764+
url: preflightUploadUrl.uploadUrl!,
765+
method: 'POST',
766+
params: queryParamsMap,
767+
headers: headersMap,
768+
multipartData: [
769+
{
770+
partName: 'attributes',
771+
data: serializeUploadFileRequestBodyAttributesField(
772+
requestBody.attributes,
773+
),
774+
} satisfies MultipartItem,
775+
{
776+
partName: 'file',
777+
fileStream: requestBody.file,
778+
fileName: requestBody.fileFileName,
779+
contentType: requestBody.fileContentType,
780+
} satisfies MultipartItem,
781+
],
782+
contentType: 'multipart/form-data',
783+
responseFormat: 'json' as ResponseFormat,
784+
auth: this.auth,
785+
networkSession: this.networkSession,
786+
cancellationToken: cancellationToken,
787+
}),
788+
);
789+
return {
790+
...deserializeFiles(response.data!),
791+
rawData: response.data!,
792+
};
793+
}
581794
}
582795
export interface UploadsManagerInput {
583796
readonly auth?: Authentication;
@@ -808,3 +1021,133 @@ export function deserializeUploadFileRequestBodyAttributesField(
8081021
contentModifiedAt: contentModifiedAt,
8091022
} satisfies UploadFileRequestBodyAttributesField;
8101023
}
1024+
export function serializeUploadWithPreflightCheckRequestBodyAttributesParentField(
1025+
val: UploadWithPreflightCheckRequestBodyAttributesParentField,
1026+
): SerializedData {
1027+
return { ['id']: val.id };
1028+
}
1029+
export function deserializeUploadWithPreflightCheckRequestBodyAttributesParentField(
1030+
val: SerializedData,
1031+
): UploadWithPreflightCheckRequestBodyAttributesParentField {
1032+
if (!sdIsMap(val)) {
1033+
throw new BoxSdkError({
1034+
message:
1035+
'Expecting a map for "UploadWithPreflightCheckRequestBodyAttributesParentField"',
1036+
});
1037+
}
1038+
if (val.id == void 0) {
1039+
throw new BoxSdkError({
1040+
message:
1041+
'Expecting "id" of type "UploadWithPreflightCheckRequestBodyAttributesParentField" to be defined',
1042+
});
1043+
}
1044+
if (!sdIsString(val.id)) {
1045+
throw new BoxSdkError({
1046+
message:
1047+
'Expecting string for "id" of type "UploadWithPreflightCheckRequestBodyAttributesParentField"',
1048+
});
1049+
}
1050+
const id: string = val.id;
1051+
return {
1052+
id: id,
1053+
} satisfies UploadWithPreflightCheckRequestBodyAttributesParentField;
1054+
}
1055+
export function serializeUploadWithPreflightCheckRequestBodyAttributesField(
1056+
val: UploadWithPreflightCheckRequestBodyAttributesField,
1057+
): SerializedData {
1058+
return {
1059+
['name']: val.name,
1060+
['parent']:
1061+
serializeUploadWithPreflightCheckRequestBodyAttributesParentField(
1062+
val.parent,
1063+
),
1064+
['content_created_at']:
1065+
val.contentCreatedAt == void 0
1066+
? val.contentCreatedAt
1067+
: serializeDateTime(val.contentCreatedAt),
1068+
['content_modified_at']:
1069+
val.contentModifiedAt == void 0
1070+
? val.contentModifiedAt
1071+
: serializeDateTime(val.contentModifiedAt),
1072+
['size']: val.size,
1073+
};
1074+
}
1075+
export function deserializeUploadWithPreflightCheckRequestBodyAttributesField(
1076+
val: SerializedData,
1077+
): UploadWithPreflightCheckRequestBodyAttributesField {
1078+
if (!sdIsMap(val)) {
1079+
throw new BoxSdkError({
1080+
message:
1081+
'Expecting a map for "UploadWithPreflightCheckRequestBodyAttributesField"',
1082+
});
1083+
}
1084+
if (val.name == void 0) {
1085+
throw new BoxSdkError({
1086+
message:
1087+
'Expecting "name" of type "UploadWithPreflightCheckRequestBodyAttributesField" to be defined',
1088+
});
1089+
}
1090+
if (!sdIsString(val.name)) {
1091+
throw new BoxSdkError({
1092+
message:
1093+
'Expecting string for "name" of type "UploadWithPreflightCheckRequestBodyAttributesField"',
1094+
});
1095+
}
1096+
const name: string = val.name;
1097+
if (val.parent == void 0) {
1098+
throw new BoxSdkError({
1099+
message:
1100+
'Expecting "parent" of type "UploadWithPreflightCheckRequestBodyAttributesField" to be defined',
1101+
});
1102+
}
1103+
const parent: UploadWithPreflightCheckRequestBodyAttributesParentField =
1104+
deserializeUploadWithPreflightCheckRequestBodyAttributesParentField(
1105+
val.parent,
1106+
);
1107+
if (
1108+
!(val.content_created_at == void 0) &&
1109+
!sdIsString(val.content_created_at)
1110+
) {
1111+
throw new BoxSdkError({
1112+
message:
1113+
'Expecting string for "content_created_at" of type "UploadWithPreflightCheckRequestBodyAttributesField"',
1114+
});
1115+
}
1116+
const contentCreatedAt: undefined | DateTime =
1117+
val.content_created_at == void 0
1118+
? void 0
1119+
: deserializeDateTime(val.content_created_at);
1120+
if (
1121+
!(val.content_modified_at == void 0) &&
1122+
!sdIsString(val.content_modified_at)
1123+
) {
1124+
throw new BoxSdkError({
1125+
message:
1126+
'Expecting string for "content_modified_at" of type "UploadWithPreflightCheckRequestBodyAttributesField"',
1127+
});
1128+
}
1129+
const contentModifiedAt: undefined | DateTime =
1130+
val.content_modified_at == void 0
1131+
? void 0
1132+
: deserializeDateTime(val.content_modified_at);
1133+
if (val.size == void 0) {
1134+
throw new BoxSdkError({
1135+
message:
1136+
'Expecting "size" of type "UploadWithPreflightCheckRequestBodyAttributesField" to be defined',
1137+
});
1138+
}
1139+
if (!sdIsNumber(val.size)) {
1140+
throw new BoxSdkError({
1141+
message:
1142+
'Expecting number for "size" of type "UploadWithPreflightCheckRequestBodyAttributesField"',
1143+
});
1144+
}
1145+
const size: number = val.size;
1146+
return {
1147+
name: name,
1148+
parent: parent,
1149+
contentCreatedAt: contentCreatedAt,
1150+
contentModifiedAt: contentModifiedAt,
1151+
size: size,
1152+
} satisfies UploadWithPreflightCheckRequestBodyAttributesField;
1153+
}

0 commit comments

Comments
 (0)