@travetto/web-upload 8.0.0-alpha.3 → 8.0.0-alpha.30

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/README.md CHANGED
@@ -15,18 +15,17 @@ yarn add @travetto/web-upload
15
15
 
16
16
  This module provides a clean and direct mechanism for processing uploads, built upon [@fastify/busboy](https://github.com/fastify/busboy). The module also provides some best practices with respect to temporary file management.
17
17
 
18
- Once the files are uploaded, they are exposed via [Endpoint](https://github.com/travetto/travetto/tree/main/module/web/src/decorator/endpoint.ts#L14) parameters using the [@Upload](https://github.com/travetto/travetto/tree/main/module/web-upload/src/decorator.ts#L20) decorator. This decorator requires the related field type to be a standard [Buffer](https://nodejs.org/api/buffer.html#class-file) object, or a [FileMap](https://github.com/travetto/travetto/tree/main/module/web-upload/src/types.ts#L7).
18
+ Once the files are uploaded, they are exposed via [Endpoint](https://github.com/travetto/travetto/tree/main/module/web/src/decorator/endpoint.ts#L14) parameters using the [@Upload](https://github.com/travetto/travetto/tree/main/module/web-upload/src/decorator.ts#L20) decorator. This decorator requires the related field type to be a standard [Buffer](https://nodejs.org/api/buffer.html#class-file) object, or a [FileMap](https://github.com/travetto/travetto/tree/main/module/web-upload/src/types.ts#L7).
19
19
 
20
20
  A simple example:
21
21
 
22
22
  **Code: Web controller with upload support**
23
23
  ```typescript
24
- import { Controller, Post, Get } from '@travetto/web';
24
+ import { Controller, Get, Post } from '@travetto/web';
25
25
  import { type FileMap, Upload } from '@travetto/web-upload';
26
26
 
27
27
  @Controller('/simple')
28
28
  export class Simple {
29
-
30
29
  @Get('/age')
31
30
  getAge() {
32
31
  return { age: 50 };
package/__index__.ts CHANGED
@@ -1,5 +1,6 @@
1
- import type { } from './src/trv.d.ts';
2
- export * from './src/decorator.ts';
1
+ import type {} from './src/trv.d.ts';
2
+
3
3
  export * from './src/config.ts';
4
+ export * from './src/decorator.ts';
5
+ export * from './src/types.ts';
4
6
  export * from './src/util.ts';
5
- export * from './src/types.ts';
package/package.json CHANGED
@@ -1,39 +1,43 @@
1
1
  {
2
2
  "name": "@travetto/web-upload",
3
- "version": "8.0.0-alpha.3",
4
- "type": "module",
3
+ "version": "8.0.0-alpha.30",
4
+ "private": false,
5
5
  "description": "Provides integration between the travetto asset and web module.",
6
6
  "keywords": [
7
- "web",
8
7
  "travetto",
9
8
  "typescript",
10
- "upload"
9
+ "upload",
10
+ "web"
11
11
  ],
12
12
  "homepage": "https://travetto.io",
13
13
  "license": "MIT",
14
14
  "author": {
15
- "email": "travetto.framework@gmail.com",
16
- "name": "Travetto Framework"
15
+ "name": "Travetto Framework",
16
+ "email": "travetto.framework@gmail.com"
17
+ },
18
+ "repository": {
19
+ "url": "git+https://github.com/travetto/travetto.git",
20
+ "directory": "module/web-upload"
17
21
  },
18
22
  "files": [
19
23
  "__index__.ts",
20
24
  "src",
21
25
  "support"
22
26
  ],
27
+ "type": "module",
23
28
  "main": "__index__.ts",
24
- "repository": {
25
- "url": "git+https://github.com/travetto/travetto.git",
26
- "directory": "module/web-upload"
29
+ "publishConfig": {
30
+ "access": "public"
27
31
  },
28
32
  "dependencies": {
29
- "@fastify/busboy": "^3.2.0",
30
- "@travetto/config": "^8.0.0-alpha.3",
31
- "@travetto/web": "^8.0.0-alpha.3",
32
- "file-type": "^21.3.1",
33
+ "@fastify/busboy": "^3.2.2",
34
+ "@travetto/config": "^8.0.0-alpha.27",
35
+ "@travetto/web": "^8.0.0-alpha.30",
36
+ "file-type": "^22.0.2",
33
37
  "mime": "^4.1.0"
34
38
  },
35
39
  "peerDependencies": {
36
- "@travetto/test": "^8.0.0-alpha.3"
40
+ "@travetto/test": "^8.0.0-alpha.26"
37
41
  },
38
42
  "peerDependenciesMeta": {
39
43
  "@travetto/test": {
@@ -42,9 +46,5 @@
42
46
  },
43
47
  "travetto": {
44
48
  "displayName": "Web Upload Support"
45
- },
46
- "private": false,
47
- "publishConfig": {
48
- "access": "public"
49
49
  }
50
50
  }
package/src/config.ts CHANGED
@@ -26,4 +26,4 @@ export class WebUploadConfig {
26
26
 
27
27
  @Ignore()
28
28
  matcher: (contentType: string) => boolean;
29
- }
29
+ }
package/src/decorator.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { RuntimeError, toConcrete, type ClassInstance, getClass } from '@travetto/runtime';
2
- import { ControllerRegistryIndex, type EndpointParameterConfig, Param } from '@travetto/web';
1
+ import { type ClassInstance, getClass, RuntimeError, toConcrete } from '@travetto/runtime';
3
2
  import { SchemaRegistryIndex } from '@travetto/schema';
3
+ import { ControllerRegistryIndex, type EndpointParameterConfig, Param } from '@travetto/web';
4
4
 
5
- import { WebUploadInterceptor } from './interceptor.ts';
6
5
  import type { WebUploadConfig } from './config.ts';
6
+ import { WebUploadInterceptor } from './interceptor.ts';
7
7
  import type { FileMap } from './types.ts';
8
8
  import { WebUploadUtil } from './util.ts';
9
9
 
@@ -18,9 +18,8 @@ const FileMapContract = toConcrete<FileMap>();
18
18
  * @kind decorator
19
19
  */
20
20
  export function Upload(
21
- param: Partial<EndpointParameterConfig> & UploadConfig = {},
21
+ param: Partial<EndpointParameterConfig> & UploadConfig = {}
22
22
  ): (instance: ClassInstance, property: string, idx: number) => void {
23
-
24
23
  const finalConfig = { ...param };
25
24
 
26
25
  return (instance: ClassInstance, property: string, idx: number): void => {
@@ -30,28 +29,24 @@ export function Upload(
30
29
  const getName = (): string => SchemaRegistryIndex.get(cls).getMethod(property).parameters[idx].name!;
31
30
 
32
31
  adapter.registerFinalizeHandler(() => {
33
- adapter.registerEndpointInterceptorConfig(
34
- property,
35
- WebUploadInterceptor,
36
- {
37
- applies: true,
38
- maxSize: finalConfig.maxSize,
39
- types: finalConfig.types,
40
- cleanupFiles: finalConfig.cleanupFiles,
41
- uploads: {
42
- [getName()]: {
43
- maxSize: finalConfig.maxSize,
44
- types: finalConfig.types,
45
- cleanupFiles: finalConfig.cleanupFiles
46
- }
32
+ adapter.registerEndpointInterceptorConfig(property, WebUploadInterceptor, {
33
+ applies: true,
34
+ maxSize: finalConfig.maxSize,
35
+ types: finalConfig.types,
36
+ cleanupFiles: finalConfig.cleanupFiles,
37
+ uploads: {
38
+ [getName()]: {
39
+ maxSize: finalConfig.maxSize,
40
+ types: finalConfig.types,
41
+ cleanupFiles: finalConfig.cleanupFiles
47
42
  }
48
43
  }
49
- );
44
+ });
50
45
  });
51
46
 
52
- return Param('body', {
47
+ Param('body', {
53
48
  ...finalConfig,
54
- extract: (request) => {
49
+ extract: request => {
55
50
  const input = SchemaRegistryIndex.get(cls).getMethod(property).parameters[idx];
56
51
 
57
52
  if (!input) {
@@ -59,7 +54,9 @@ export function Upload(
59
54
  }
60
55
 
61
56
  if (!(input.type === Blob || input.type === File || input.type === FileMapContract)) {
62
- throw new RuntimeError(`Cannot use upload decorator with ${input.type.name}, but only an ${Blob.name}, ${File.name} or ${FileMapContract.name}`);
57
+ throw new RuntimeError(
58
+ `Cannot use upload decorator with ${input.type.name}, but only an ${Blob.name}, ${File.name} or ${FileMapContract.name}`
59
+ );
63
60
  }
64
61
 
65
62
  const isMap = input.type === FileMapContract;
@@ -68,4 +65,4 @@ export function Upload(
68
65
  }
69
66
  })(instance, property, idx);
70
67
  };
71
- }
68
+ }
@@ -1,7 +1,12 @@
1
1
  import { Inject, Injectable } from '@travetto/di';
2
2
  import {
3
- BodyInterceptor, type WebInterceptor, type WebInterceptorCategory, type WebChainedContext,
4
- type WebResponse, DecompressInterceptor, type WebInterceptorContext
3
+ BodyInterceptor,
4
+ DecompressInterceptor,
5
+ type WebChainedContext,
6
+ type WebInterceptor,
7
+ type WebInterceptorCategory,
8
+ type WebInterceptorContext,
9
+ type WebResponse
5
10
  } from '@travetto/web';
6
11
 
7
12
  import type { WebUploadConfig } from './config.ts';
@@ -9,7 +14,6 @@ import { WebUploadUtil } from './util.ts';
9
14
 
10
15
  @Injectable()
11
16
  export class WebUploadInterceptor implements WebInterceptor<WebUploadConfig> {
12
-
13
17
  category: WebInterceptorCategory = 'request';
14
18
  runsBefore = [BodyInterceptor];
15
19
  dependsOn = [DecompressInterceptor];
@@ -24,7 +28,7 @@ export class WebUploadInterceptor implements WebInterceptor<WebUploadConfig> {
24
28
  base.uploads ??= {};
25
29
  // Override the uploads object with all the data from the inputs
26
30
  for (const [key, config] of inputs.flatMap(inputConfig => Object.entries(inputConfig.uploads ?? {}))) {
27
- Object.assign(base.uploads[key] ??= {}, config);
31
+ Object.assign((base.uploads[key] ??= {}), config);
28
32
  }
29
33
  return base;
30
34
  }
@@ -50,4 +54,4 @@ export class WebUploadInterceptor implements WebInterceptor<WebUploadConfig> {
50
54
  }
51
55
  }
52
56
  }
53
- }
57
+ }
package/src/trv.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { FileMap } from './types.ts';
1
+ import type { FileMap } from './types.ts';
2
2
 
3
3
  declare module '@travetto/web' {
4
4
  interface WebRequestInternal {
5
- uploads?: FileMap
5
+ uploads?: FileMap;
6
6
  }
7
- }
7
+ }
package/src/types.ts CHANGED
@@ -4,7 +4,9 @@ import { SchemaTypeUtil } from '@travetto/schema';
4
4
  /**
5
5
  * @concrete
6
6
  */
7
- export interface FileMap extends Record<string, File> { }
7
+ export interface FileMap extends Record<string, File> {}
8
8
 
9
- SchemaTypeUtil.register(toConcrete<FileMap>(),
10
- input => typeof input === 'object' && !!input && Object.values(input).every(v => v instanceof Blob));
9
+ SchemaTypeUtil.register(
10
+ toConcrete<FileMap>(),
11
+ input => typeof input === 'object' && !!input && Object.values(input).every(v => v instanceof Blob)
12
+ );
package/src/util.ts CHANGED
@@ -1,29 +1,37 @@
1
1
  import { createReadStream, createWriteStream } from 'node:fs';
2
- import path from 'node:path';
3
- import os from 'node:os';
4
2
  import fs from 'node:fs/promises';
5
- import { pipeline } from 'node:stream/promises';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
6
5
  import { Transform } from 'node:stream';
6
+ import { pipeline } from 'node:stream/promises';
7
7
 
8
8
  import busboy from '@fastify/busboy';
9
9
 
10
- import { type WebRequest, WebCommonUtil, WebBodyUtil, WebHeaderUtil } from '@travetto/web';
11
- import { AsyncQueue, RuntimeError, CodecUtil, Util, BinaryUtil, type BinaryType, type BinaryStream, BinaryMetadataUtil } from '@travetto/runtime';
10
+ import {
11
+ AsyncQueue,
12
+ BinaryMetadataUtil,
13
+ type BinaryStream,
14
+ type BinaryType,
15
+ BinaryUtil,
16
+ CodecUtil,
17
+ RuntimeError,
18
+ Util
19
+ } from '@travetto/runtime';
20
+ import { WebBodyUtil, WebCommonUtil, WebHeaderUtil, type WebRequest } from '@travetto/web';
12
21
 
13
22
  import type { WebUploadConfig } from './config.ts';
14
23
  import type { FileMap } from './types.ts';
15
24
 
16
25
  const MULTIPART = new Set(['application/x-www-form-urlencoded', 'multipart/form-data']);
17
26
 
18
- type UploadItem = { stream: BinaryStream, filename?: string, field: string, contentType?: string };
19
- type FileType = { ext: string, mime: string };
27
+ type UploadItem = { stream: BinaryStream; filename?: string; field: string; contentType?: string };
28
+ type FileType = { ext: string; mime: string };
20
29
  const WebUploadSymbol = Symbol();
21
30
 
22
31
  /**
23
32
  * Web upload utilities
24
33
  */
25
34
  export class WebUploadUtil {
26
-
27
35
  /**
28
36
  * Write limiter
29
37
  * @returns
@@ -39,14 +47,14 @@ export class WebUploadUtil {
39
47
  } else {
40
48
  callback(null, chunk);
41
49
  }
42
- },
50
+ }
43
51
  });
44
52
  }
45
53
 
46
54
  /**
47
55
  * Get all the uploads, separating multipart from direct
48
56
  */
49
- static async * getUploads(request: WebRequest, config: Partial<WebUploadConfig>): AsyncIterable<UploadItem> {
57
+ static async *getUploads(request: WebRequest, config: Partial<WebUploadConfig>): AsyncIterable<UploadItem> {
50
58
  if (!WebBodyUtil.isRawBinary(request.body)) {
51
59
  throw new RuntimeError('No input stream provided for upload', { category: 'data' });
52
60
  }
@@ -70,14 +78,14 @@ export class WebUploadUtil {
70
78
  'content-length': request.headers.get('Content-Length')!,
71
79
  'content-range': request.headers.get('Content-Range')!,
72
80
  'content-encoding': request.headers.get('Content-Encoding')!,
73
- 'content-transfer-encoding': request.headers.get('Content-Transfer-Encoding')!,
81
+ 'content-transfer-encoding': request.headers.get('Content-Transfer-Encoding')!
74
82
  },
75
83
  limits: { fileSize: largestMax }
76
84
  })
77
85
  .on('file', (field, stream, filename, _encoding, mimetype) => queue.add({ stream, filename, field, contentType: mimetype }))
78
86
  .on('limit', field => queue.throw(new RuntimeError(`File size exceeded for ${field}`, { category: 'data' })))
79
87
  .on('finish', () => queue.close())
80
- .on('error', (error) => queue.throw(error instanceof Error ? error : new Error(`${error}`)));
88
+ .on('error', error => queue.throw(error instanceof Error ? error : new Error(`${error}`)));
81
89
 
82
90
  // Upload
83
91
  void BinaryUtil.pipeline(requestBody, uploadHandler).catch(err => queue.throw(err));
@@ -93,7 +101,7 @@ export class WebUploadUtil {
93
101
  * Detect mime from request input, usually http headers
94
102
  */
95
103
  static async detectMimeTypeFromRequestInput(location?: string, contentType?: string): Promise<FileType | undefined> {
96
- const { Mime } = (await import('mime'));
104
+ const { Mime } = await import('mime');
97
105
  const otherTypes = (await import('mime/types/other.js')).default;
98
106
  const standardTypes = (await import('mime/types/standard.js')).default;
99
107
  const checker = new Mime(standardTypes, otherTypes);
@@ -117,7 +125,7 @@ export class WebUploadUtil {
117
125
  const { fromWebStream } = await import('strtok3');
118
126
  const parser = new FileTypeParser();
119
127
  const token = fromWebStream(BinaryUtil.toReadableStream(input));
120
- cleanup = (): Promise<void> => token.close();
128
+ cleanup = (): Promise<void> => token.close().catch(() => {});
121
129
  return await parser.fromTokenizer(token);
122
130
  } finally {
123
131
  await cleanup?.();
@@ -128,9 +136,10 @@ export class WebUploadUtil {
128
136
  * Get file type
129
137
  */
130
138
  static async getFileType(input: BinaryType, filename?: string, contentType?: string): Promise<FileType> {
131
- return (await this.detectMimeTypeFromBinary(input)) ??
132
- (await this.detectMimeTypeFromRequestInput(filename, contentType)) ??
133
- { ext: 'bin', mime: 'application/octet-stream' };
139
+ return (
140
+ (await this.detectMimeTypeFromBinary(input)) ??
141
+ (await this.detectMimeTypeFromRequestInput(filename, contentType)) ?? { ext: 'bin', mime: 'application/octet-stream' }
142
+ );
134
143
  }
135
144
 
136
145
  /**
@@ -143,16 +152,14 @@ export class WebUploadUtil {
143
152
  filename = filename ? path.basename(filename) : `unknown_${Date.now()}`;
144
153
 
145
154
  const location = path.resolve(uniqueDirectory, filename);
146
- const remove = (): Promise<void> => fs.rm(location).catch(() => { });
147
- const mimeCheck = config.matcher ??= WebCommonUtil.mimeTypeMatcher(config.types);
155
+ const remove = (): Promise<void> => fs.rm(location).catch(() => {});
156
+ const mimeCheck = (config.matcher ??= WebCommonUtil.mimeTypeMatcher(config.types));
148
157
  const response = (): BinaryStream => createReadStream(location);
149
158
 
150
159
  try {
151
160
  const target = createWriteStream(location);
152
161
 
153
- await (config.maxSize ?
154
- pipeline(stream, this.limitWrite(config.maxSize, field), target) :
155
- pipeline(stream, target));
162
+ await (config.maxSize ? pipeline(stream, this.limitWrite(config.maxSize, field), target) : pipeline(stream, target));
156
163
 
157
164
  const detected = await this.getFileType(response(), filename, contentType);
158
165
 
@@ -164,10 +171,10 @@ export class WebUploadUtil {
164
171
  filename = `${filename}.${detected.ext}`;
165
172
  }
166
173
 
167
- const metadata = await BinaryMetadataUtil.compute(response, { contentType: detected.mime, filename, });
174
+ const metadata = await BinaryMetadataUtil.compute(response, { contentType: detected.mime, filename });
168
175
  const file = BinaryMetadataUtil.defineBlob(new File([], ''), response, metadata);
169
176
  Object.defineProperty(file, 'cleanup', {
170
- value: () => config.cleanupFiles !== false && fs.rm(location).catch(() => { })
177
+ value: () => config.cleanupFiles !== false && fs.rm(location).catch(() => {})
171
178
  });
172
179
  return file;
173
180
  } catch (error) {
@@ -189,4 +196,4 @@ export class WebUploadUtil {
189
196
  static setRequestUploads(request: WebRequest & { [WebUploadSymbol]?: FileMap }, uploads: FileMap): void {
190
197
  request[WebUploadSymbol] ??= uploads;
191
198
  }
192
- }
199
+ }
@@ -1,9 +1,9 @@
1
1
  import assert from 'node:assert';
2
2
 
3
+ import { Registry } from '@travetto/registry';
3
4
  import { BinaryMetadataUtil, castTo } from '@travetto/runtime';
4
- import { Controller, Post } from '@travetto/web';
5
5
  import { BeforeAll, Suite, Test, TestFixtures } from '@travetto/test';
6
- import { Registry } from '@travetto/registry';
6
+ import { Controller, Post } from '@travetto/web';
7
7
 
8
8
  import { BaseWebSuite } from '@travetto/web/support/test/suite/base.ts';
9
9
 
@@ -14,7 +14,6 @@ const getHash = (blob: Blob) => BinaryMetadataUtil.read(blob)?.hash;
14
14
 
15
15
  @Controller('/test/upload')
16
16
  class TestUploadController {
17
-
18
17
  @Post('/all')
19
18
  async uploadAll(@Upload() uploads: FileMap): Promise<{ hash?: string } | undefined> {
20
19
  for (const [, blob] of Object.entries(uploads)) {
@@ -45,18 +44,19 @@ class TestUploadController {
45
44
 
46
45
  @Suite()
47
46
  export abstract class WebUploadServerSuite extends BaseWebSuite {
48
-
49
47
  fixture: TestFixtures;
50
48
 
51
- async getUploads(...files: { name: string, resource: string, type?: string }[]): Promise<FormData> {
49
+ async getUploads(...files: { name: string; resource: string; type?: string }[]): Promise<FormData> {
52
50
  const data = new FormData();
53
- await Promise.all(files.map(async ({ name, type, resource }) => {
54
- const file = await this.fixture.readFile(resource);
55
- if (type) {
56
- Object.defineProperty(file, 'type', { get: () => type });
57
- }
58
- data.append(name, file);
59
- }));
51
+ await Promise.all(
52
+ files.map(async ({ name, type, resource }) => {
53
+ const file = await this.fixture.readFile(resource);
54
+ if (type) {
55
+ Object.defineProperty(file, 'type', { get: () => type });
56
+ }
57
+ data.append(name, file);
58
+ })
59
+ );
60
60
  return data;
61
61
  }
62
62
 
@@ -72,7 +72,7 @@ export abstract class WebUploadServerSuite extends BaseWebSuite {
72
72
  const response = await this.request<{ hash: string }>({ body: uploads, context: { httpMethod: 'POST', path: '/test/upload/all' } });
73
73
 
74
74
  const file = await this.fixture.readBinaryStream('/logo.png');
75
- assert(response.body?.hash === await BinaryMetadataUtil.hash(file, { hashAlgorithm: 'sha256' }));
75
+ assert(response.body?.hash === (await BinaryMetadataUtil.hash(file, { hashAlgorithm: 'sha256' })));
76
76
  }
77
77
 
78
78
  @Test()
@@ -82,7 +82,7 @@ export abstract class WebUploadServerSuite extends BaseWebSuite {
82
82
  const response = await this.request<{ hash: string }>({ context: { httpMethod: 'POST', path: '/test/upload' }, body: sent });
83
83
 
84
84
  const file = await this.fixture.readBinaryStream('/logo.png');
85
- assert(response.body?.hash === await BinaryMetadataUtil.hash(file, { hashAlgorithm: 'sha256' }));
85
+ assert(response.body?.hash === (await BinaryMetadataUtil.hash(file, { hashAlgorithm: 'sha256' })));
86
86
  }
87
87
 
88
88
  @Test()
@@ -91,7 +91,7 @@ export abstract class WebUploadServerSuite extends BaseWebSuite {
91
91
  const response = await this.request<{ hash: string }>({ body: uploads, context: { httpMethod: 'POST', path: '/test/upload' } });
92
92
 
93
93
  const file = await this.fixture.readBinaryStream('/logo.png');
94
- assert(response.body?.hash === await BinaryMetadataUtil.hash(file, { hashAlgorithm: 'sha256' }));
94
+ assert(response.body?.hash === (await BinaryMetadataUtil.hash(file, { hashAlgorithm: 'sha256' })));
95
95
  }
96
96
 
97
97
  @Test()
@@ -100,10 +100,11 @@ export abstract class WebUploadServerSuite extends BaseWebSuite {
100
100
  { name: 'file1', resource: 'logo.png', type: 'image/png' },
101
101
  { name: 'file2', resource: 'logo.png', type: 'image/png' }
102
102
  );
103
- const response = await this.request<{ hash1: string, hash2: string }>({
103
+ const response = await this.request<{ hash1: string; hash2: string }>({
104
104
  body: uploads,
105
105
  context: {
106
- httpMethod: 'POST', path: '/test/upload/all-named'
106
+ httpMethod: 'POST',
107
+ path: '/test/upload/all-named'
107
108
  }
108
109
  });
109
110
  const file = await this.fixture.readBinaryStream('/logo.png');
@@ -120,20 +121,26 @@ export abstract class WebUploadServerSuite extends BaseWebSuite {
120
121
  { name: 'file2', resource: 'logo.png', type: 'image/png' }
121
122
  );
122
123
 
123
- const badResponse = await this.request<{ hash1: string, hash2: string }>({
124
- body: uploadBad,
125
- context: { httpMethod: 'POST', path: '/test/upload/all-named-custom' },
126
- }, false);
124
+ const badResponse = await this.request<{ hash1: string; hash2: string }>(
125
+ {
126
+ body: uploadBad,
127
+ context: { httpMethod: 'POST', path: '/test/upload/all-named-custom' }
128
+ },
129
+ false
130
+ );
127
131
  assert(badResponse.context.httpStatusCode === 400);
128
132
 
129
133
  const uploads = await this.getUploads(
130
134
  { name: 'file1', resource: 'logo.gif', type: 'image/gif' },
131
135
  { name: 'file2', resource: 'logo.png', type: 'image/png' }
132
136
  );
133
- const response = await this.request<{ hash1: string, hash2: string }>({
134
- body: uploads,
135
- context: { httpMethod: 'POST', path: '/test/upload/all-named-custom' },
136
- }, false);
137
+ const response = await this.request<{ hash1: string; hash2: string }>(
138
+ {
139
+ body: uploads,
140
+ context: { httpMethod: 'POST', path: '/test/upload/all-named-custom' }
141
+ },
142
+ false
143
+ );
137
144
  assert(response.context.httpStatusCode === 200);
138
145
 
139
146
  const file1 = await this.fixture.readBinaryStream('/logo.gif');
@@ -153,20 +160,26 @@ export abstract class WebUploadServerSuite extends BaseWebSuite {
153
160
  { name: 'file2', resource: 'logo.png', type: 'image/png' }
154
161
  );
155
162
 
156
- const badResponse = await this.request<{ hash1: string, hash2: string }>({
157
- body: uploadBad,
158
- context: { httpMethod: 'POST', path: '/test/upload/all-named-size' },
159
- }, false);
163
+ const badResponse = await this.request<{ hash1: string; hash2: string }>(
164
+ {
165
+ body: uploadBad,
166
+ context: { httpMethod: 'POST', path: '/test/upload/all-named-size' }
167
+ },
168
+ false
169
+ );
160
170
  assert(badResponse.context.httpStatusCode === 400);
161
171
 
162
172
  const uploads = await this.getUploads(
163
173
  { name: 'file1', resource: 'asset.yml', type: 'text/plain' },
164
174
  { name: 'file2', resource: 'logo.png', type: 'image/png' }
165
175
  );
166
- const response = await this.request<{ hash1: string, hash2: string }>({
167
- body: uploads,
168
- context: { httpMethod: 'POST', path: '/test/upload/all-named-size' },
169
- }, false);
176
+ const response = await this.request<{ hash1: string; hash2: string }>(
177
+ {
178
+ body: uploads,
179
+ context: { httpMethod: 'POST', path: '/test/upload/all-named-size' }
180
+ },
181
+ false
182
+ );
170
183
  assert(response.context.httpStatusCode === 200);
171
184
 
172
185
  const file1 = await this.fixture.readBinaryStream('/asset.yml');
@@ -178,4 +191,4 @@ export abstract class WebUploadServerSuite extends BaseWebSuite {
178
191
  assert(response.body?.hash1 === hash1);
179
192
  assert(response.body?.hash2 === hash2);
180
193
  }
181
- }
194
+ }