@kiyasov/platform-hono 1.6.1 → 2.0.1

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.
Files changed (237) hide show
  1. package/.claude/settings.local.json +7 -1
  2. package/dist/cjs/src/adapters/hono-adapter.d.ts +1 -0
  3. package/dist/cjs/src/adapters/hono-adapter.js +14 -3
  4. package/dist/cjs/src/adapters/hono-adapter.js.map +1 -1
  5. package/dist/cjs/src/drivers/graphQLUpload/GraphQLUpload.d.ts +1 -1
  6. package/dist/cjs/src/drivers/graphQLUpload/Upload.d.ts +11 -8
  7. package/dist/cjs/src/drivers/graphQLUpload/Upload.js.map +1 -1
  8. package/dist/cjs/src/drivers/graphQLUpload/fs-capacitor.d.ts +20 -8
  9. package/dist/cjs/src/drivers/graphQLUpload/fs-capacitor.js +111 -58
  10. package/dist/cjs/src/drivers/graphQLUpload/fs-capacitor.js.map +1 -1
  11. package/dist/cjs/src/drivers/graphQLUpload/index.d.ts +9 -3
  12. package/dist/cjs/src/drivers/graphQLUpload/index.js +21 -3
  13. package/dist/cjs/src/drivers/graphQLUpload/index.js.map +1 -1
  14. package/dist/cjs/src/drivers/graphQLUpload/processRequest.d.ts +8 -1
  15. package/dist/cjs/src/drivers/graphQLUpload/processRequest.js +43 -37
  16. package/dist/cjs/src/drivers/graphQLUpload/processRequest.js.map +1 -1
  17. package/dist/cjs/src/drivers/graphQLUpload/storage/capacitor-storage.d.ts +15 -0
  18. package/dist/cjs/src/drivers/graphQLUpload/storage/capacitor-storage.js +47 -0
  19. package/dist/cjs/src/drivers/graphQLUpload/storage/capacitor-storage.js.map +1 -0
  20. package/dist/cjs/src/drivers/graphQLUpload/storage/index.d.ts +3 -0
  21. package/dist/cjs/src/drivers/graphQLUpload/storage/index.js +20 -0
  22. package/dist/cjs/src/drivers/graphQLUpload/storage/index.js.map +1 -0
  23. package/dist/cjs/src/drivers/graphQLUpload/storage/memory-storage.d.ts +13 -0
  24. package/dist/cjs/src/drivers/graphQLUpload/storage/memory-storage.js +31 -0
  25. package/dist/cjs/src/drivers/graphQLUpload/storage/memory-storage.js.map +1 -0
  26. package/dist/cjs/src/drivers/graphQLUpload/storage/storage.d.ts +17 -0
  27. package/dist/cjs/src/drivers/graphQLUpload/storage/storage.js +3 -0
  28. package/dist/cjs/src/drivers/graphQLUpload/storage/storage.js.map +1 -0
  29. package/dist/cjs/src/drivers/graphQLUpload/utils/file.d.ts +6 -0
  30. package/dist/cjs/src/drivers/graphQLUpload/utils/file.js +62 -0
  31. package/dist/cjs/src/drivers/graphQLUpload/utils/file.js.map +1 -0
  32. package/dist/cjs/src/drivers/graphQLUpload/utils/index.d.ts +2 -0
  33. package/dist/cjs/src/drivers/graphQLUpload/utils/index.js +19 -0
  34. package/dist/cjs/src/drivers/graphQLUpload/utils/index.js.map +1 -0
  35. package/dist/cjs/src/drivers/graphQLUpload/utils/validators.d.ts +18 -0
  36. package/dist/cjs/src/drivers/graphQLUpload/utils/validators.js +171 -0
  37. package/dist/cjs/src/drivers/graphQLUpload/utils/validators.js.map +1 -0
  38. package/dist/cjs/src/multer/index.d.ts +1 -0
  39. package/dist/cjs/src/multer/index.js +1 -0
  40. package/dist/cjs/src/multer/index.js.map +1 -1
  41. package/dist/cjs/src/multer/interceptors/any-files-interceptor.d.ts +2 -2
  42. package/dist/cjs/src/multer/interceptors/any-files-interceptor.js +6 -23
  43. package/dist/cjs/src/multer/interceptors/any-files-interceptor.js.map +1 -1
  44. package/dist/cjs/src/multer/interceptors/base-interceptor.d.ts +6 -0
  45. package/dist/cjs/src/multer/interceptors/base-interceptor.js +26 -0
  46. package/dist/cjs/src/multer/interceptors/base-interceptor.js.map +1 -0
  47. package/dist/cjs/src/multer/interceptors/file-fields-interceptor.d.ts +2 -2
  48. package/dist/cjs/src/multer/interceptors/file-fields-interceptor.js +7 -24
  49. package/dist/cjs/src/multer/interceptors/file-fields-interceptor.js.map +1 -1
  50. package/dist/cjs/src/multer/interceptors/file-interceptor.d.ts +2 -2
  51. package/dist/cjs/src/multer/interceptors/file-interceptor.js +6 -23
  52. package/dist/cjs/src/multer/interceptors/file-interceptor.js.map +1 -1
  53. package/dist/cjs/src/multer/interceptors/files-interceptor.d.ts +2 -2
  54. package/dist/cjs/src/multer/interceptors/files-interceptor.js +6 -23
  55. package/dist/cjs/src/multer/interceptors/files-interceptor.js.map +1 -1
  56. package/dist/cjs/src/multer/interceptors/index.d.ts +1 -0
  57. package/dist/cjs/src/multer/interceptors/index.js +1 -0
  58. package/dist/cjs/src/multer/interceptors/index.js.map +1 -1
  59. package/dist/cjs/src/multer/multipart/handlers/any-files.d.ts +2 -8
  60. package/dist/cjs/src/multer/multipart/handlers/any-files.js +12 -25
  61. package/dist/cjs/src/multer/multipart/handlers/any-files.js.map +1 -1
  62. package/dist/cjs/src/multer/multipart/handlers/base-handler.d.ts +42 -0
  63. package/dist/cjs/src/multer/multipart/handlers/base-handler.js +106 -0
  64. package/dist/cjs/src/multer/multipart/handlers/base-handler.js.map +1 -0
  65. package/dist/cjs/src/multer/multipart/handlers/file-fields.d.ts +3 -10
  66. package/dist/cjs/src/multer/multipart/handlers/file-fields.js +19 -33
  67. package/dist/cjs/src/multer/multipart/handlers/file-fields.js.map +1 -1
  68. package/dist/cjs/src/multer/multipart/handlers/index.d.ts +6 -1
  69. package/dist/cjs/src/multer/multipart/handlers/index.js +13 -0
  70. package/dist/cjs/src/multer/multipart/handlers/index.js.map +1 -1
  71. package/dist/cjs/src/multer/multipart/handlers/multiple-files.d.ts +2 -8
  72. package/dist/cjs/src/multer/multipart/handlers/multiple-files.js +18 -36
  73. package/dist/cjs/src/multer/multipart/handlers/multiple-files.js.map +1 -1
  74. package/dist/cjs/src/multer/multipart/handlers/single-file.d.ts +2 -8
  75. package/dist/cjs/src/multer/multipart/handlers/single-file.js +11 -33
  76. package/dist/cjs/src/multer/multipart/handlers/single-file.js.map +1 -1
  77. package/dist/cjs/src/multer/multipart/index.d.ts +1 -1
  78. package/dist/cjs/src/multer/multipart/options.d.ts +10 -16
  79. package/dist/cjs/src/multer/multipart/options.js.map +1 -1
  80. package/dist/cjs/src/multer/multipart/request.js +14 -3
  81. package/dist/cjs/src/multer/multipart/request.js.map +1 -1
  82. package/dist/cjs/src/multer/storage/disk-storage.d.ts +2 -1
  83. package/dist/cjs/src/multer/storage/disk-storage.js +2 -1
  84. package/dist/cjs/src/multer/storage/disk-storage.js.map +1 -1
  85. package/dist/cjs/src/multer/storage/memory-storage.d.ts +2 -11
  86. package/dist/cjs/src/multer/storage/memory-storage.js +6 -4
  87. package/dist/cjs/src/multer/storage/memory-storage.js.map +1 -1
  88. package/dist/cjs/src/multer/storage/storage.d.ts +6 -5
  89. package/dist/cjs/src/multer/utils/file.d.ts +6 -0
  90. package/dist/cjs/src/multer/utils/file.js +62 -0
  91. package/dist/cjs/src/multer/utils/file.js.map +1 -0
  92. package/dist/cjs/src/multer/utils/index.d.ts +2 -0
  93. package/dist/cjs/src/multer/utils/index.js +19 -0
  94. package/dist/cjs/src/multer/utils/index.js.map +1 -0
  95. package/dist/cjs/src/multer/utils/validators.d.ts +18 -0
  96. package/dist/cjs/src/multer/utils/validators.js +171 -0
  97. package/dist/cjs/src/multer/utils/validators.js.map +1 -0
  98. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  99. package/dist/esm/src/adapters/hono-adapter.d.ts +1 -0
  100. package/dist/esm/src/adapters/hono-adapter.js +14 -3
  101. package/dist/esm/src/adapters/hono-adapter.js.map +1 -1
  102. package/dist/esm/src/drivers/graphQLUpload/GraphQLUpload.d.ts +1 -1
  103. package/dist/esm/src/drivers/graphQLUpload/Upload.d.ts +11 -8
  104. package/dist/esm/src/drivers/graphQLUpload/Upload.js.map +1 -1
  105. package/dist/esm/src/drivers/graphQLUpload/fs-capacitor.d.ts +20 -8
  106. package/dist/esm/src/drivers/graphQLUpload/fs-capacitor.js +112 -59
  107. package/dist/esm/src/drivers/graphQLUpload/fs-capacitor.js.map +1 -1
  108. package/dist/esm/src/drivers/graphQLUpload/index.d.ts +9 -3
  109. package/dist/esm/src/drivers/graphQLUpload/index.js +7 -3
  110. package/dist/esm/src/drivers/graphQLUpload/index.js.map +1 -1
  111. package/dist/esm/src/drivers/graphQLUpload/processRequest.d.ts +8 -1
  112. package/dist/esm/src/drivers/graphQLUpload/processRequest.js +42 -36
  113. package/dist/esm/src/drivers/graphQLUpload/processRequest.js.map +1 -1
  114. package/dist/esm/src/drivers/graphQLUpload/storage/capacitor-storage.d.ts +15 -0
  115. package/dist/esm/src/drivers/graphQLUpload/storage/capacitor-storage.js +43 -0
  116. package/dist/esm/src/drivers/graphQLUpload/storage/capacitor-storage.js.map +1 -0
  117. package/dist/esm/src/drivers/graphQLUpload/storage/index.d.ts +3 -0
  118. package/dist/esm/src/drivers/graphQLUpload/storage/index.js +4 -0
  119. package/dist/esm/src/drivers/graphQLUpload/storage/index.js.map +1 -0
  120. package/dist/esm/src/drivers/graphQLUpload/storage/memory-storage.d.ts +13 -0
  121. package/dist/esm/src/drivers/graphQLUpload/storage/memory-storage.js +27 -0
  122. package/dist/esm/src/drivers/graphQLUpload/storage/memory-storage.js.map +1 -0
  123. package/dist/esm/src/drivers/graphQLUpload/storage/storage.d.ts +17 -0
  124. package/dist/esm/src/drivers/graphQLUpload/storage/storage.js +2 -0
  125. package/dist/esm/src/drivers/graphQLUpload/storage/storage.js.map +1 -0
  126. package/dist/esm/src/drivers/graphQLUpload/utils/file.d.ts +6 -0
  127. package/dist/esm/src/drivers/graphQLUpload/utils/file.js +54 -0
  128. package/dist/esm/src/drivers/graphQLUpload/utils/file.js.map +1 -0
  129. package/dist/esm/src/drivers/graphQLUpload/utils/index.d.ts +2 -0
  130. package/dist/esm/src/drivers/graphQLUpload/utils/index.js +3 -0
  131. package/dist/esm/src/drivers/graphQLUpload/utils/index.js.map +1 -0
  132. package/dist/esm/src/drivers/graphQLUpload/utils/validators.d.ts +18 -0
  133. package/dist/esm/src/drivers/graphQLUpload/utils/validators.js +167 -0
  134. package/dist/esm/src/drivers/graphQLUpload/utils/validators.js.map +1 -0
  135. package/dist/esm/src/multer/index.d.ts +1 -0
  136. package/dist/esm/src/multer/index.js +1 -0
  137. package/dist/esm/src/multer/index.js.map +1 -1
  138. package/dist/esm/src/multer/interceptors/any-files-interceptor.d.ts +2 -2
  139. package/dist/esm/src/multer/interceptors/any-files-interceptor.js +6 -23
  140. package/dist/esm/src/multer/interceptors/any-files-interceptor.js.map +1 -1
  141. package/dist/esm/src/multer/interceptors/base-interceptor.d.ts +6 -0
  142. package/dist/esm/src/multer/interceptors/base-interceptor.js +23 -0
  143. package/dist/esm/src/multer/interceptors/base-interceptor.js.map +1 -0
  144. package/dist/esm/src/multer/interceptors/file-fields-interceptor.d.ts +2 -2
  145. package/dist/esm/src/multer/interceptors/file-fields-interceptor.js +7 -24
  146. package/dist/esm/src/multer/interceptors/file-fields-interceptor.js.map +1 -1
  147. package/dist/esm/src/multer/interceptors/file-interceptor.d.ts +2 -2
  148. package/dist/esm/src/multer/interceptors/file-interceptor.js +6 -23
  149. package/dist/esm/src/multer/interceptors/file-interceptor.js.map +1 -1
  150. package/dist/esm/src/multer/interceptors/files-interceptor.d.ts +2 -2
  151. package/dist/esm/src/multer/interceptors/files-interceptor.js +6 -23
  152. package/dist/esm/src/multer/interceptors/files-interceptor.js.map +1 -1
  153. package/dist/esm/src/multer/interceptors/index.d.ts +1 -0
  154. package/dist/esm/src/multer/interceptors/index.js +1 -0
  155. package/dist/esm/src/multer/interceptors/index.js.map +1 -1
  156. package/dist/esm/src/multer/multipart/handlers/any-files.d.ts +2 -8
  157. package/dist/esm/src/multer/multipart/handlers/any-files.js +12 -25
  158. package/dist/esm/src/multer/multipart/handlers/any-files.js.map +1 -1
  159. package/dist/esm/src/multer/multipart/handlers/base-handler.d.ts +42 -0
  160. package/dist/esm/src/multer/multipart/handlers/base-handler.js +102 -0
  161. package/dist/esm/src/multer/multipart/handlers/base-handler.js.map +1 -0
  162. package/dist/esm/src/multer/multipart/handlers/file-fields.d.ts +3 -10
  163. package/dist/esm/src/multer/multipart/handlers/file-fields.js +19 -33
  164. package/dist/esm/src/multer/multipart/handlers/file-fields.js.map +1 -1
  165. package/dist/esm/src/multer/multipart/handlers/index.d.ts +6 -1
  166. package/dist/esm/src/multer/multipart/handlers/index.js +6 -1
  167. package/dist/esm/src/multer/multipart/handlers/index.js.map +1 -1
  168. package/dist/esm/src/multer/multipart/handlers/multiple-files.d.ts +2 -8
  169. package/dist/esm/src/multer/multipart/handlers/multiple-files.js +18 -36
  170. package/dist/esm/src/multer/multipart/handlers/multiple-files.js.map +1 -1
  171. package/dist/esm/src/multer/multipart/handlers/single-file.d.ts +2 -8
  172. package/dist/esm/src/multer/multipart/handlers/single-file.js +11 -33
  173. package/dist/esm/src/multer/multipart/handlers/single-file.js.map +1 -1
  174. package/dist/esm/src/multer/multipart/index.d.ts +1 -1
  175. package/dist/esm/src/multer/multipart/options.d.ts +10 -16
  176. package/dist/esm/src/multer/multipart/options.js.map +1 -1
  177. package/dist/esm/src/multer/multipart/request.js +14 -3
  178. package/dist/esm/src/multer/multipart/request.js.map +1 -1
  179. package/dist/esm/src/multer/storage/disk-storage.d.ts +2 -1
  180. package/dist/esm/src/multer/storage/disk-storage.js +2 -1
  181. package/dist/esm/src/multer/storage/disk-storage.js.map +1 -1
  182. package/dist/esm/src/multer/storage/memory-storage.d.ts +2 -11
  183. package/dist/esm/src/multer/storage/memory-storage.js +6 -4
  184. package/dist/esm/src/multer/storage/memory-storage.js.map +1 -1
  185. package/dist/esm/src/multer/storage/storage.d.ts +6 -5
  186. package/dist/esm/src/multer/utils/file.d.ts +6 -0
  187. package/dist/esm/src/multer/utils/file.js +54 -0
  188. package/dist/esm/src/multer/utils/file.js.map +1 -0
  189. package/dist/esm/src/multer/utils/index.d.ts +2 -0
  190. package/dist/esm/src/multer/utils/index.js +3 -0
  191. package/dist/esm/src/multer/utils/index.js.map +1 -0
  192. package/dist/esm/src/multer/utils/validators.d.ts +18 -0
  193. package/dist/esm/src/multer/utils/validators.js +167 -0
  194. package/dist/esm/src/multer/utils/validators.js.map +1 -0
  195. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  196. package/package.json +6 -4
  197. package/src/adapters/hono-adapter.ts +18 -3
  198. package/src/drivers/graphQLUpload/Upload.ts +34 -14
  199. package/src/drivers/graphQLUpload/fs-capacitor.ts +240 -116
  200. package/src/drivers/graphQLUpload/index.ts +37 -3
  201. package/src/drivers/graphQLUpload/processRequest.ts +92 -38
  202. package/src/drivers/graphQLUpload/storage/capacitor-storage.ts +82 -0
  203. package/src/drivers/graphQLUpload/storage/index.ts +3 -0
  204. package/src/drivers/graphQLUpload/storage/memory-storage.ts +58 -0
  205. package/src/drivers/graphQLUpload/storage/storage.ts +52 -0
  206. package/src/drivers/graphQLUpload/utils/file.ts +109 -0
  207. package/src/drivers/graphQLUpload/utils/index.ts +2 -0
  208. package/src/drivers/graphQLUpload/utils/validators.ts +219 -0
  209. package/src/multer/index.ts +1 -0
  210. package/src/multer/interceptors/any-files-interceptor.ts +12 -43
  211. package/src/multer/interceptors/base-interceptor.ts +54 -0
  212. package/src/multer/interceptors/file-fields-interceptor.ts +14 -48
  213. package/src/multer/interceptors/file-interceptor.ts +12 -44
  214. package/src/multer/interceptors/files-interceptor.ts +13 -45
  215. package/src/multer/interceptors/index.ts +1 -0
  216. package/src/multer/multipart/handlers/any-files.ts +14 -32
  217. package/src/multer/multipart/handlers/base-handler.ts +204 -0
  218. package/src/multer/multipart/handlers/file-fields.ts +29 -57
  219. package/src/multer/multipart/handlers/index.ts +11 -1
  220. package/src/multer/multipart/handlers/multiple-files.ts +23 -54
  221. package/src/multer/multipart/handlers/single-file.ts +14 -47
  222. package/src/multer/multipart/index.ts +1 -1
  223. package/src/multer/multipart/options.ts +26 -8
  224. package/src/multer/multipart/request.ts +19 -3
  225. package/src/multer/storage/disk-storage.ts +2 -1
  226. package/src/multer/storage/memory-storage.ts +13 -6
  227. package/src/multer/storage/storage.ts +12 -5
  228. package/src/multer/utils/file.ts +109 -0
  229. package/src/multer/utils/index.ts +2 -0
  230. package/src/multer/utils/validators.ts +219 -0
  231. package/test/README.md +247 -0
  232. package/test/graphql-upload.test.ts +509 -0
  233. package/test/helpers.ts +70 -0
  234. package/test/integration.test.ts +197 -0
  235. package/test/interceptors-e2e.test.ts +362 -0
  236. package/test/multipart-upload.test.ts +354 -0
  237. package/test/smoke.test.ts +227 -0
@@ -0,0 +1,219 @@
1
+ import { isAllowedFileType } from './file';
2
+
3
+ /**
4
+ * Common file type groups for validation
5
+ */
6
+ export const FileTypes = {
7
+ // Images
8
+ IMAGES: [
9
+ 'image/jpeg',
10
+ 'image/png',
11
+ 'image/gif',
12
+ 'image/webp',
13
+ 'image/svg+xml',
14
+ 'image/avif',
15
+ 'image/heic',
16
+ 'image/heif',
17
+ 'image/tiff',
18
+ 'image/bmp',
19
+ 'image/x-icon',
20
+ '.jpg',
21
+ '.jpeg',
22
+ '.png',
23
+ '.gif',
24
+ '.webp',
25
+ '.svg',
26
+ '.avif',
27
+ '.heic',
28
+ '.heif',
29
+ '.tiff',
30
+ '.bmp',
31
+ '.ico',
32
+ ] as const,
33
+
34
+ // Documents
35
+ DOCUMENTS: [
36
+ // PDF
37
+ 'application/pdf',
38
+ '.pdf',
39
+ // Microsoft Word
40
+ 'application/msword',
41
+ '.doc',
42
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
43
+ '.docx',
44
+ // Microsoft Excel
45
+ 'application/vnd.ms-excel',
46
+ '.xls',
47
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
48
+ '.xlsx',
49
+ // Microsoft PowerPoint
50
+ 'application/vnd.ms-powerpoint',
51
+ '.ppt',
52
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
53
+ '.pptx',
54
+ // OpenDocument formats
55
+ 'application/vnd.oasis.opendocument.text',
56
+ '.odt',
57
+ 'application/vnd.oasis.opendocument.spreadsheet',
58
+ '.ods',
59
+ 'application/vnd.oasis.opendocument.presentation',
60
+ '.odp',
61
+ // Apple iWork
62
+ 'application/vnd.apple.pages',
63
+ '.pages',
64
+ 'application/vnd.apple.numbers',
65
+ '.numbers',
66
+ 'application/vnd.apple.keynote',
67
+ '.key',
68
+ // Rich text
69
+ 'application/rtf',
70
+ '.rtf',
71
+ 'text/plain',
72
+ '.txt',
73
+ // CSV
74
+ 'text/csv',
75
+ '.csv',
76
+ ] as const,
77
+
78
+ // Videos
79
+ VIDEOS: [
80
+ 'video/mp4',
81
+ 'video/mpeg',
82
+ 'video/quicktime',
83
+ 'video/webm',
84
+ 'video/x-msvideo',
85
+ 'video/x-matroska',
86
+ 'video/quicktime',
87
+ 'video/x-flv',
88
+ '.mp4',
89
+ '.mpeg',
90
+ '.mov',
91
+ '.webm',
92
+ '.avi',
93
+ '.mkv',
94
+ '.flv',
95
+ ] as const,
96
+
97
+ // Audio
98
+ AUDIO: [
99
+ 'audio/mpeg',
100
+ 'audio/mp4',
101
+ 'audio/wav',
102
+ 'audio/ogg',
103
+ 'audio/webm',
104
+ 'audio/flac',
105
+ 'audio/aac',
106
+ 'audio/x-m4a',
107
+ 'audio/x-wav',
108
+ '.mp3',
109
+ '.m4a',
110
+ '.wav',
111
+ '.ogg',
112
+ '.flac',
113
+ '.aac',
114
+ ] as const,
115
+
116
+ // Archives
117
+ ARCHIVES: [
118
+ 'application/zip',
119
+ 'application/x-zip-compressed',
120
+ '.zip',
121
+ 'application/x-rar-compressed',
122
+ '.rar',
123
+ 'application/x-7z-compressed',
124
+ '.7z',
125
+ 'application/x-tar',
126
+ '.tar',
127
+ 'application/gzip',
128
+ '.gz',
129
+ 'application/x-gzip',
130
+ 'application/x-bzip2',
131
+ '.bz2',
132
+ 'application/x-compress',
133
+ '.Z',
134
+ 'application/x-apple-diskimage',
135
+ '.dmg',
136
+ 'application/x-iso9660-image',
137
+ '.iso',
138
+ ] as const,
139
+
140
+ // 3D Models
141
+ MODELS_3D: [
142
+ 'model/stl',
143
+ '.stl',
144
+ 'model/obj',
145
+ '.obj',
146
+ 'model/gltf-binary',
147
+ '.glb',
148
+ 'model/gltf+json',
149
+ '.gltf',
150
+ 'model/fbx',
151
+ '.fbx',
152
+ 'model/dae',
153
+ '.dae',
154
+ 'model/vnd.collada+xml',
155
+ ] as const,
156
+
157
+ // Fonts
158
+ FONTS: [
159
+ 'font/ttf',
160
+ '.ttf',
161
+ 'font/otf',
162
+ '.otf',
163
+ 'font/woff',
164
+ '.woff',
165
+ 'font/woff2',
166
+ '.woff2',
167
+ 'application/x-font-ttf',
168
+ 'application/x-font-opentype',
169
+ ] as const,
170
+ } as const;
171
+
172
+ /**
173
+ * Validator configuration for file uploads
174
+ */
175
+ export interface FileValidatorOptions {
176
+ /** Maximum file size in bytes */
177
+ maxSize?: number;
178
+ /** Allowed MIME types or extensions */
179
+ allowedTypes?: string[];
180
+ /** Denied MIME types or extensions */
181
+ deniedTypes?: string[];
182
+ }
183
+
184
+ /**
185
+ * Validates a file against the given options
186
+ * @param file - File to validate
187
+ * @param options - Validation options
188
+ * @returns Object with isValid flag and error message
189
+ */
190
+ export function validateFile(
191
+ file: File,
192
+ options: FileValidatorOptions,
193
+ ): { isValid: boolean; error?: string } {
194
+ // Check file size
195
+ if (options.maxSize && file.size > options.maxSize) {
196
+ return {
197
+ isValid: false,
198
+ error: `File "${file.name}" exceeds maximum size of ${options.maxSize} bytes`,
199
+ };
200
+ }
201
+
202
+ // Check denied types
203
+ if (options.deniedTypes && isAllowedFileType(file, options.deniedTypes)) {
204
+ return {
205
+ isValid: false,
206
+ error: `File type "${file.type}" is not allowed`,
207
+ };
208
+ }
209
+
210
+ // Check allowed types
211
+ if (options.allowedTypes && !isAllowedFileType(file, options.allowedTypes)) {
212
+ return {
213
+ isValid: false,
214
+ error: `File type "${file.type}" is not allowed. Allowed types: ${options.allowedTypes.join(', ')}`,
215
+ };
216
+ }
217
+
218
+ return { isValid: true };
219
+ }
@@ -2,3 +2,4 @@ export * from './interceptors';
2
2
  export * from './decorators';
3
3
  export * from './storage';
4
4
  export * from './multipart';
5
+ export * from './utils';
@@ -1,47 +1,16 @@
1
- import {
2
- CallHandler,
3
- ExecutionContext,
4
- mixin,
5
- NestInterceptor,
6
- Type,
7
- } from '@nestjs/common';
8
- import { finalize } from 'rxjs';
9
-
10
1
  import { handleMultipartAnyFiles } from '../multipart/handlers/any-files';
11
- import { transformUploadOptions, UploadOptions } from '../multipart/options';
12
- import { getMultipartRequest } from '../multipart/request';
2
+ import { UploadOptions } from '../multipart/options';
3
+ import { createInterceptor } from './base-interceptor';
13
4
 
14
5
  export function AnyFilesInterceptor(
15
- options?: UploadOptions,
16
- ): Type<NestInterceptor> {
17
- class MixinInterceptor implements NestInterceptor {
18
- private readonly options: UploadOptions;
19
-
20
- constructor() {
21
- this.options = transformUploadOptions(options);
22
- }
23
-
24
- async intercept(context: ExecutionContext, next: CallHandler) {
25
- const ctx = context.switchToHttp();
26
- const req = getMultipartRequest(ctx);
27
-
28
- if (!req.header('content-type')?.startsWith('multipart/form-data')) {
29
- return next.handle();
30
- }
31
-
32
- const { body, files, remove } = await handleMultipartAnyFiles(
33
- req,
34
- this.options,
35
- );
36
-
37
- req.body = body;
38
- req.storageFiles = files;
39
-
40
- return next.handle().pipe(finalize(remove));
41
- }
42
- }
43
-
44
- const Interceptor = mixin(MixinInterceptor);
45
-
46
- return Interceptor;
6
+ localOptions?: UploadOptions,
7
+ ): ReturnType<typeof createInterceptor> {
8
+ return createInterceptor(
9
+ localOptions ?? {},
10
+ (req, options) => handleMultipartAnyFiles(req, options),
11
+ (req, result) => {
12
+ req.body = result.body;
13
+ req.storageFiles = result.files;
14
+ },
15
+ );
47
16
  }
@@ -0,0 +1,54 @@
1
+ import {
2
+ CallHandler,
3
+ ExecutionContext,
4
+ mixin,
5
+ NestInterceptor,
6
+ Type,
7
+ } from '@nestjs/common';
8
+ import { finalize } from 'rxjs';
9
+ import { Observable } from 'rxjs/internal/Observable';
10
+
11
+ import { FileProcessResult } from '../multipart/handlers/base-handler';
12
+ import { transformUploadOptions, UploadOptions } from '../multipart/options';
13
+ import { getMultipartRequest } from '../multipart/request';
14
+
15
+ export type HandlerFunction<T extends FileProcessResult> = (
16
+ req: ReturnType<typeof getMultipartRequest>,
17
+ options: UploadOptions,
18
+ ) => Promise<T>;
19
+
20
+ export function createInterceptor<T extends FileProcessResult>(
21
+ rawOptions: UploadOptions,
22
+ handlerFn: HandlerFunction<T>,
23
+ resultProcessor: (
24
+ req: ReturnType<typeof getMultipartRequest>,
25
+ result: T,
26
+ ) => void,
27
+ ): Type<NestInterceptor> {
28
+ class MixinInterceptor implements NestInterceptor {
29
+ private readonly options: UploadOptions;
30
+
31
+ constructor() {
32
+ this.options = transformUploadOptions(rawOptions);
33
+ }
34
+
35
+ async intercept(
36
+ context: ExecutionContext,
37
+ next: CallHandler,
38
+ ): Promise<Observable<unknown>> {
39
+ const ctx = context.switchToHttp();
40
+ const req = getMultipartRequest(ctx);
41
+
42
+ if (!req.header('content-type')?.startsWith('multipart/form-data')) {
43
+ return next.handle();
44
+ }
45
+
46
+ const result = await handlerFn(req, this.options);
47
+ resultProcessor(req, result);
48
+
49
+ return next.handle().pipe(finalize(result.remove));
50
+ }
51
+ }
52
+
53
+ return mixin(MixinInterceptor);
54
+ }
@@ -1,57 +1,23 @@
1
- import {
2
- CallHandler,
3
- ExecutionContext,
4
- mixin,
5
- NestInterceptor,
6
- Type,
7
- } from '@nestjs/common';
8
- import { finalize } from 'rxjs';
9
-
10
1
  import {
11
2
  handleMultipartFileFields,
12
3
  UploadField,
13
- UploadFieldMapEntry,
14
4
  uploadFieldsToMap,
15
5
  } from '../multipart/handlers/file-fields';
16
- import { transformUploadOptions, UploadOptions } from '../multipart/options';
17
- import { getMultipartRequest } from '../multipart/request';
6
+ import { UploadOptions } from '../multipart/options';
7
+ import { createInterceptor } from './base-interceptor';
18
8
 
19
9
  export function FileFieldsInterceptor(
20
10
  uploadFields: UploadField[],
21
- options?: UploadOptions,
22
- ): Type<NestInterceptor> {
23
- class MixinInterceptor implements NestInterceptor {
24
- private readonly options: UploadOptions;
25
-
26
- private readonly fieldsMap: Map<string, UploadFieldMapEntry>;
27
-
28
- constructor() {
29
- this.options = transformUploadOptions(options);
30
- this.fieldsMap = uploadFieldsToMap(uploadFields);
31
- }
32
-
33
- async intercept(context: ExecutionContext, next: CallHandler) {
34
- const ctx = context.switchToHttp();
35
- const req = getMultipartRequest(ctx);
36
-
37
- if (!req.header('content-type')?.startsWith('multipart/form-data')) {
38
- return next.handle();
39
- }
40
-
41
- const { body, files, remove } = await handleMultipartFileFields(
42
- req,
43
- this.fieldsMap,
44
- this.options,
45
- );
46
-
47
- req.body = body;
48
- req.storageFiles = files;
49
-
50
- return next.handle().pipe(finalize(remove));
51
- }
52
- }
53
-
54
- const Interceptor = mixin(MixinInterceptor);
55
-
56
- return Interceptor;
11
+ localOptions?: UploadOptions,
12
+ ): ReturnType<typeof createInterceptor> {
13
+ const fieldsMap = uploadFieldsToMap(uploadFields);
14
+
15
+ return createInterceptor(
16
+ localOptions ?? {},
17
+ (req, options) => handleMultipartFileFields(req, fieldsMap, options),
18
+ (req, result) => {
19
+ req.body = result.body;
20
+ req.storageFiles = result.files;
21
+ },
22
+ );
57
23
  }
@@ -1,49 +1,17 @@
1
- import {
2
- CallHandler,
3
- ExecutionContext,
4
- mixin,
5
- NestInterceptor,
6
- Type,
7
- } from '@nestjs/common';
8
- import { finalize } from 'rxjs';
9
-
10
1
  import { handleMultipartSingleFile } from '../multipart/handlers/single-file';
11
- import { transformUploadOptions, UploadOptions } from '../multipart/options';
12
- import { getMultipartRequest } from '../multipart/request';
2
+ import { UploadOptions } from '../multipart/options';
3
+ import { createInterceptor } from './base-interceptor';
13
4
 
14
5
  export function FileInterceptor(
15
6
  fieldname: string,
16
- options?: UploadOptions,
17
- ): Type<NestInterceptor> {
18
- class MixinInterceptor implements NestInterceptor {
19
- private readonly options: UploadOptions;
20
-
21
- constructor() {
22
- this.options = transformUploadOptions(options);
23
- }
24
-
25
- async intercept(context: ExecutionContext, next: CallHandler) {
26
- const ctx = context.switchToHttp();
27
- const req = getMultipartRequest(ctx);
28
-
29
- if (!req.header('content-type')?.startsWith('multipart/form-data')) {
30
- return next.handle();
31
- }
32
-
33
- const { file, body, remove } = await handleMultipartSingleFile(
34
- req,
35
- fieldname,
36
- this.options,
37
- );
38
-
39
- req.body = body;
40
- req.storageFile = file;
41
-
42
- return next.handle().pipe(finalize(remove));
43
- }
44
- }
45
-
46
- const Interceptor = mixin(MixinInterceptor);
47
-
48
- return Interceptor;
7
+ localOptions?: UploadOptions,
8
+ ): ReturnType<typeof createInterceptor> {
9
+ return createInterceptor(
10
+ localOptions ?? {},
11
+ (req, options) => handleMultipartSingleFile(req, fieldname, options),
12
+ (req, result) => {
13
+ req.body = result.body;
14
+ req.storageFile = result.file;
15
+ },
16
+ );
49
17
  }
@@ -1,51 +1,19 @@
1
- import {
2
- CallHandler,
3
- ExecutionContext,
4
- mixin,
5
- NestInterceptor,
6
- Type,
7
- } from '@nestjs/common';
8
- import { finalize } from 'rxjs';
9
-
10
1
  import { handleMultipartMultipleFiles } from '../multipart/handlers/multiple-files';
11
- import { transformUploadOptions, UploadOptions } from '../multipart/options';
12
- import { getMultipartRequest } from '../multipart/request';
2
+ import { UploadOptions } from '../multipart/options';
3
+ import { createInterceptor } from './base-interceptor';
13
4
 
14
5
  export function FilesInterceptor(
15
6
  fieldname: string,
16
7
  maxCount = 1,
17
- options?: UploadOptions,
18
- ): Type<NestInterceptor> {
19
- class MixinInterceptor implements NestInterceptor {
20
- private readonly options: UploadOptions;
21
-
22
- constructor() {
23
- this.options = transformUploadOptions(options);
24
- }
25
-
26
- async intercept(context: ExecutionContext, next: CallHandler) {
27
- const ctx = context.switchToHttp();
28
- const req = getMultipartRequest(ctx);
29
-
30
- if (!req.header('content-type')?.startsWith('multipart/form-data')) {
31
- return next.handle();
32
- }
33
-
34
- const { body, files, remove } = await handleMultipartMultipleFiles(
35
- req,
36
- fieldname,
37
- maxCount,
38
- this.options,
39
- );
40
-
41
- req.body = body;
42
- req.storageFiles = files;
43
-
44
- return next.handle().pipe(finalize(remove));
45
- }
46
- }
47
-
48
- const Interceptor = mixin(MixinInterceptor);
49
-
50
- return Interceptor;
8
+ localOptions?: UploadOptions,
9
+ ): ReturnType<typeof createInterceptor> {
10
+ return createInterceptor(
11
+ localOptions ?? {},
12
+ (req, options) =>
13
+ handleMultipartMultipleFiles(req, fieldname, maxCount, options),
14
+ (req, result) => {
15
+ req.body = result.body;
16
+ req.storageFiles = result.files;
17
+ },
18
+ );
51
19
  }
@@ -2,3 +2,4 @@ export * from './file-fields-interceptor';
2
2
  export * from './file-interceptor';
3
3
  export * from './any-files-interceptor';
4
4
  export * from './files-interceptor';
5
+ export * from './base-interceptor';
@@ -1,41 +1,23 @@
1
- import { BodyData } from 'hono/utils/body';
2
-
3
- import { StorageFile } from '../../storage';
4
- import { removeStorageFiles } from '../file';
5
- import { filterUpload } from '../filter';
6
1
  import { UploadOptions } from '../options';
7
- import { THonoRequest, getParts } from '../request';
2
+ import { THonoRequest } from '../request';
3
+ import { FileHandler, MultipleFilesResult } from './base-handler';
8
4
 
9
5
  export const handleMultipartAnyFiles = async (
10
6
  req: THonoRequest,
11
7
  options: UploadOptions,
12
- ) => {
13
- const parts = getParts(req, options);
14
-
15
- const body: BodyData = {};
8
+ ): Promise<MultipleFilesResult> => {
9
+ const handler = new FileHandler(req, options);
16
10
 
17
- const files: StorageFile[] = [];
18
-
19
- const removeFiles = async (error?: boolean) => {
20
- return await removeStorageFiles(options.storage!, files, error);
21
- };
22
-
23
- try {
24
- for await (const [partFieldName, part] of Object.entries(parts)) {
25
- if (!(part instanceof File)) {
26
- body[partFieldName] = part;
27
- continue;
28
- }
29
- const file = await options.storage!.handleFile(part, req, partFieldName);
30
-
31
- if (await filterUpload(options, req, file)) {
32
- files.push(file);
33
- }
11
+ await handler.process(async (fieldName, part) => {
12
+ const storageFile = await handler.handleSingleFile(fieldName, part);
13
+ if (storageFile) {
14
+ handler.addFile(fieldName, storageFile);
34
15
  }
35
- } catch (error) {
36
- await removeFiles(true);
37
- throw error;
38
- }
16
+ });
39
17
 
40
- return { body, files, remove: () => removeFiles() };
18
+ return {
19
+ body: handler.getBody(),
20
+ files: handler.getFiles(),
21
+ remove: handler.createRemoveFunction(),
22
+ };
41
23
  };