@travetto/web-upload 7.0.0-rc.1 → 7.0.0-rc.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/web-upload",
3
- "version": "7.0.0-rc.1",
3
+ "version": "7.0.0-rc.3",
4
4
  "description": "Provides integration between the travetto asset and web module.",
5
5
  "keywords": [
6
6
  "web",
@@ -26,13 +26,13 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@fastify/busboy": "^3.2.0",
29
- "@travetto/config": "^7.0.0-rc.0",
30
- "@travetto/web": "^7.0.0-rc.1",
29
+ "@travetto/config": "^7.0.0-rc.2",
30
+ "@travetto/web": "^7.0.0-rc.3",
31
31
  "file-type": "^21.1.1",
32
32
  "mime": "^4.1.0"
33
33
  },
34
34
  "peerDependencies": {
35
- "@travetto/test": "^7.0.0-rc.0"
35
+ "@travetto/test": "^7.0.0-rc.2"
36
36
  },
37
37
  "peerDependenciesMeta": {
38
38
  "@travetto/test": {
package/src/decorator.ts CHANGED
@@ -19,29 +19,30 @@ const FileMapContract = toConcrete<FileMap>();
19
19
  */
20
20
  export function Upload(
21
21
  param: Partial<EndpointParameterConfig> & UploadConfig = {},
22
- ): (instance: ClassInstance, property: string | symbol, idx: number) => void {
22
+ ): (instance: ClassInstance, property: string, idx: number) => void {
23
23
 
24
- const finalConf = { ...param };
24
+ const finalConfig = { ...param };
25
25
 
26
- return (instance: ClassInstance, property: string | symbol, idx: number): void => {
26
+ return (instance: ClassInstance, property: string, idx: number): void => {
27
27
  // Register field
28
- const cls = ControllerRegistryIndex.getForRegister(getClass(instance));
29
- const getName = (): string => SchemaRegistryIndex.getMethodConfig(instance.constructor, property).parameters[idx].name!.toString();
28
+ const cls = getClass(instance);
29
+ const adapter = ControllerRegistryIndex.getForRegister(cls);
30
+ const getName = (): string => SchemaRegistryIndex.get(cls).getMethod(property).parameters[idx].name!;
30
31
 
31
- cls.registerFinalizeHandler(() => {
32
- cls.registerEndpointInterceptorConfig(
32
+ adapter.registerFinalizeHandler(() => {
33
+ adapter.registerEndpointInterceptorConfig(
33
34
  property,
34
35
  WebUploadInterceptor,
35
36
  {
36
37
  applies: true,
37
- maxSize: finalConf.maxSize,
38
- types: finalConf.types,
39
- cleanupFiles: finalConf.cleanupFiles,
38
+ maxSize: finalConfig.maxSize,
39
+ types: finalConfig.types,
40
+ cleanupFiles: finalConfig.cleanupFiles,
40
41
  uploads: {
41
42
  [getName()]: {
42
- maxSize: finalConf.maxSize,
43
- types: finalConf.types,
44
- cleanupFiles: finalConf.cleanupFiles
43
+ maxSize: finalConfig.maxSize,
44
+ types: finalConfig.types,
45
+ cleanupFiles: finalConfig.cleanupFiles
45
46
  }
46
47
  }
47
48
  }
@@ -49,9 +50,9 @@ export function Upload(
49
50
  });
50
51
 
51
52
  return Param('body', {
52
- ...finalConf,
53
+ ...finalConfig,
53
54
  extract: (request) => {
54
- const input = SchemaRegistryIndex.getMethodConfig(instance.constructor, property).parameters[idx];
55
+ const input = SchemaRegistryIndex.get(cls).getMethod(property).parameters[idx];
55
56
 
56
57
  if (!input) {
57
58
  throw new AppError(`Unknown field type, ensure you are using ${Blob.name}, ${File.name} or ${FileMapContract.name}`);
@@ -24,8 +24,8 @@ export class WebUploadInterceptor implements WebInterceptor<WebUploadConfig> {
24
24
  finalizeConfig({ config: base }: WebInterceptorContext<WebUploadConfig>, inputs: Partial<WebUploadConfig>[]): WebUploadConfig {
25
25
  base.uploads ??= {};
26
26
  // Override the uploads object with all the data from the inputs
27
- for (const [k, cfg] of inputs.flatMap(el => Object.entries(el.uploads ?? {}))) {
28
- Object.assign(base.uploads[k] ??= {}, cfg);
27
+ for (const [key, config] of inputs.flatMap(inputConfig => Object.entries(inputConfig.uploads ?? {}))) {
28
+ Object.assign(base.uploads[key] ??= {}, config);
29
29
  }
30
30
  return base;
31
31
  }
package/src/util.ts CHANGED
@@ -64,9 +64,11 @@ export class WebUploadUtil {
64
64
  const contentType = WebHeaderUtil.parseHeaderSegment(request.headers.get('Content-Type'));
65
65
 
66
66
  if (MULTIPART.has(contentType.value)) {
67
- const fileMaxes = Object.values(config.uploads ?? {}).map(x => x.maxSize).filter(x => x !== undefined);
67
+ const fileMaxes = Object.values(config.uploads ?? {})
68
+ .map(uploadConfig => uploadConfig.maxSize)
69
+ .filter(uploadConfig => uploadConfig !== undefined);
68
70
  const largestMax = fileMaxes.length ? Math.max(...fileMaxes) : config.maxSize;
69
- const itr = new AsyncQueue<UploadItem>();
71
+ const queue = new AsyncQueue<UploadItem>();
70
72
 
71
73
  // Upload
72
74
  bodyStream.pipe(busboy({
@@ -80,12 +82,12 @@ export class WebUploadUtil {
80
82
  },
81
83
  limits: { fileSize: largestMax }
82
84
  })
83
- .on('file', (field, stream, filename) => itr.add({ stream, filename, field }))
84
- .on('limit', field => itr.throw(new AppError(`File size exceeded for ${field}`, { category: 'data' })))
85
- .on('finish', () => itr.close())
86
- .on('error', (err) => itr.throw(err instanceof Error ? err : new Error(`${err}`))));
85
+ .on('file', (field, stream, filename) => queue.add({ stream, filename, field }))
86
+ .on('limit', field => queue.throw(new AppError(`File size exceeded for ${field}`, { category: 'data' })))
87
+ .on('finish', () => queue.close())
88
+ .on('error', (error) => queue.throw(error instanceof Error ? error : new Error(`${error}`))));
87
89
 
88
- yield* itr;
90
+ yield* queue;
89
91
  } else {
90
92
  const filename = WebHeaderUtil.parseHeaderSegment(request.headers.get('Content-Disposition')).parameters.filename;
91
93
  yield { stream: bodyStream, filename, field: 'file' };
@@ -96,12 +98,12 @@ export class WebUploadUtil {
96
98
  * Convert an UploadItem to a File
97
99
  */
98
100
  static async toFile({ stream, filename, field }: UploadItem, config: Partial<WebUploadConfig>): Promise<File> {
99
- const uniqueDir = path.resolve(os.tmpdir(), `file_${Date.now()}_${Util.uuid(5)}`);
100
- await fs.mkdir(uniqueDir, { recursive: true });
101
+ const uniqueDirectory = path.resolve(os.tmpdir(), `file_${Date.now()}_${Util.uuid(5)}`);
102
+ await fs.mkdir(uniqueDirectory, { recursive: true });
101
103
 
102
104
  filename = filename ? path.basename(filename) : `unknown_${Date.now()}`;
103
105
 
104
- const location = path.resolve(uniqueDir, filename);
106
+ const location = path.resolve(uniqueDirectory, filename);
105
107
  const remove = (): Promise<void> => fs.rm(location).catch(() => { });
106
108
  const mimeCheck = config.matcher ??= WebCommonUtil.mimeTypeMatcher(config.types);
107
109
 
@@ -132,9 +134,9 @@ export class WebUploadUtil {
132
134
  Object.assign(file, { [RawFileSymbol]: location });
133
135
 
134
136
  return file;
135
- } catch (err) {
137
+ } catch (error) {
136
138
  await remove();
137
- throw err;
139
+ throw error;
138
140
  }
139
141
  }
140
142
 
@@ -146,14 +148,14 @@ export class WebUploadUtil {
146
148
  const { fromStream } = await import('strtok3');
147
149
 
148
150
  const parser = new FileTypeParser();
149
- let tok: ReturnType<typeof fromStream> | undefined;
151
+ let token: ReturnType<typeof fromStream> | undefined;
150
152
  let matched: FileType | undefined;
151
153
 
152
154
  try {
153
- tok = await fromStream(typeof input === 'string' ? createReadStream(input) : input);
154
- matched = await parser.fromTokenizer(tok);
155
+ token = await fromStream(typeof input === 'string' ? createReadStream(input) : input);
156
+ matched = await parser.fromTokenizer(token);
155
157
  } finally {
156
- await tok?.close();
158
+ await token?.close();
157
159
  }
158
160
 
159
161
  if (!matched && typeof input === 'string') {