@kiyasov/platform-hono 1.0.7 → 1.0.9

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 (284) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/Readme.md +0 -7
  3. package/dist/cjs/index.d.ts +1 -0
  4. package/dist/cjs/index.js +1 -0
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/cjs/src/adapters/hono-adapter.d.ts +11 -11
  7. package/dist/cjs/src/adapters/hono-adapter.js +24 -24
  8. package/dist/cjs/src/adapters/hono-adapter.js.map +1 -1
  9. package/dist/cjs/src/drivers/constants/apollo.constants.d.ts +1 -0
  10. package/dist/cjs/src/drivers/constants/apollo.constants.js +5 -0
  11. package/dist/cjs/src/drivers/constants/apollo.constants.js.map +1 -0
  12. package/dist/cjs/src/drivers/constants/index.d.ts +1 -0
  13. package/dist/cjs/src/drivers/constants/index.js +18 -0
  14. package/dist/cjs/src/drivers/constants/index.js.map +1 -0
  15. package/dist/cjs/src/drivers/graphQLUpload/GraphQLUpload.d.ts +3 -0
  16. package/dist/cjs/src/drivers/graphQLUpload/GraphQLUpload.js +21 -0
  17. package/dist/cjs/src/drivers/graphQLUpload/GraphQLUpload.js.map +1 -0
  18. package/dist/cjs/src/drivers/graphQLUpload/Upload.d.ts +16 -0
  19. package/dist/cjs/src/drivers/graphQLUpload/Upload.js +17 -0
  20. package/dist/cjs/src/drivers/graphQLUpload/Upload.js.map +1 -0
  21. package/dist/cjs/src/drivers/graphQLUpload/fs-capacitor.d.ts +44 -0
  22. package/dist/cjs/src/drivers/graphQLUpload/fs-capacitor.js +190 -0
  23. package/dist/cjs/src/drivers/graphQLUpload/fs-capacitor.js.map +1 -0
  24. package/dist/cjs/src/drivers/graphQLUpload/index.d.ts +4 -0
  25. package/dist/cjs/src/drivers/graphQLUpload/index.js +21 -0
  26. package/dist/cjs/src/drivers/graphQLUpload/index.js.map +1 -0
  27. package/dist/cjs/src/drivers/graphQLUpload/processRequest.d.ts +2 -0
  28. package/dist/cjs/src/drivers/graphQLUpload/processRequest.js +45 -0
  29. package/dist/cjs/src/drivers/graphQLUpload/processRequest.js.map +1 -0
  30. package/dist/cjs/src/drivers/graphql.driver.d.ts +7 -0
  31. package/dist/cjs/src/drivers/graphql.driver.js +32 -5
  32. package/dist/cjs/src/drivers/graphql.driver.js.map +1 -1
  33. package/dist/cjs/src/drivers/index.d.ts +1 -0
  34. package/dist/cjs/src/drivers/index.js +1 -0
  35. package/dist/cjs/src/drivers/index.js.map +1 -1
  36. package/dist/cjs/src/drivers/services/plugins-explorer.service.d.ts +9 -0
  37. package/dist/cjs/src/drivers/services/plugins-explorer.service.js +25 -0
  38. package/dist/cjs/src/drivers/services/plugins-explorer.service.js.map +1 -0
  39. package/dist/cjs/src/drivers/services/processRequest.d.ts +2 -0
  40. package/dist/cjs/src/drivers/services/processRequest.js +45 -0
  41. package/dist/cjs/src/drivers/services/processRequest.js.map +1 -0
  42. package/dist/cjs/src/multer/crypto/index.d.ts +2 -0
  43. package/dist/cjs/src/multer/crypto/index.js +7 -0
  44. package/dist/cjs/src/multer/crypto/index.js.map +1 -0
  45. package/dist/cjs/src/multer/decorators/index.d.ts +2 -0
  46. package/dist/cjs/src/multer/decorators/index.js +19 -0
  47. package/dist/cjs/src/multer/decorators/index.js.map +1 -0
  48. package/dist/cjs/src/multer/decorators/uploaded-file-decorator.d.ts +1 -0
  49. package/dist/cjs/src/multer/decorators/uploaded-file-decorator.js +10 -0
  50. package/dist/cjs/src/multer/decorators/uploaded-file-decorator.js.map +1 -0
  51. package/dist/cjs/src/multer/decorators/uploaded-files-decorator.d.ts +1 -0
  52. package/dist/cjs/src/multer/decorators/uploaded-files-decorator.js +10 -0
  53. package/dist/cjs/src/multer/decorators/uploaded-files-decorator.js.map +1 -0
  54. package/dist/cjs/src/multer/fs/index.d.ts +2 -0
  55. package/dist/cjs/src/multer/fs/index.js +23 -0
  56. package/dist/cjs/src/multer/fs/index.js.map +1 -0
  57. package/dist/cjs/src/multer/index.d.ts +4 -0
  58. package/dist/cjs/src/multer/index.js +21 -0
  59. package/dist/cjs/src/multer/index.js.map +1 -0
  60. package/dist/cjs/src/multer/interceptors/any-files-interceptor.d.ts +3 -0
  61. package/dist/cjs/src/multer/interceptors/any-files-interceptor.js +27 -0
  62. package/dist/cjs/src/multer/interceptors/any-files-interceptor.js.map +1 -0
  63. package/dist/cjs/src/multer/interceptors/file-fields-interceptor.d.ts +4 -0
  64. package/dist/cjs/src/multer/interceptors/file-fields-interceptor.js +28 -0
  65. package/dist/cjs/src/multer/interceptors/file-fields-interceptor.js.map +1 -0
  66. package/dist/cjs/src/multer/interceptors/file-interceptor.d.ts +3 -0
  67. package/dist/cjs/src/multer/interceptors/file-interceptor.js +27 -0
  68. package/dist/cjs/src/multer/interceptors/file-interceptor.js.map +1 -0
  69. package/dist/cjs/src/multer/interceptors/files-interceptor.d.ts +3 -0
  70. package/dist/cjs/src/multer/interceptors/files-interceptor.js +27 -0
  71. package/dist/cjs/src/multer/interceptors/files-interceptor.js.map +1 -0
  72. package/dist/cjs/src/multer/interceptors/index.d.ts +4 -0
  73. package/dist/cjs/src/multer/interceptors/index.js +21 -0
  74. package/dist/cjs/src/multer/interceptors/index.js.map +1 -0
  75. package/dist/cjs/src/multer/multipart/exceptions.d.ts +1 -0
  76. package/dist/cjs/src/multer/multipart/exceptions.js +22 -0
  77. package/dist/cjs/src/multer/multipart/exceptions.js.map +1 -0
  78. package/dist/cjs/src/multer/multipart/file.d.ts +10 -0
  79. package/dist/cjs/src/multer/multipart/file.js +10 -0
  80. package/dist/cjs/src/multer/multipart/file.js.map +1 -0
  81. package/dist/cjs/src/multer/multipart/filter.d.ts +6 -0
  82. package/dist/cjs/src/multer/multipart/filter.js +22 -0
  83. package/dist/cjs/src/multer/multipart/filter.js.map +1 -0
  84. package/dist/cjs/src/multer/multipart/handlers/any-files.d.ts +8 -0
  85. package/dist/cjs/src/multer/multipart/handlers/any-files.js +33 -0
  86. package/dist/cjs/src/multer/multipart/handlers/any-files.js.map +1 -0
  87. package/dist/cjs/src/multer/multipart/handlers/file-fields.d.ts +14 -0
  88. package/dist/cjs/src/multer/multipart/handlers/file-fields.js +57 -0
  89. package/dist/cjs/src/multer/multipart/handlers/file-fields.js.map +1 -0
  90. package/dist/cjs/src/multer/multipart/handlers/index.d.ts +1 -0
  91. package/dist/cjs/src/multer/multipart/handlers/index.js +3 -0
  92. package/dist/cjs/src/multer/multipart/handlers/index.js.map +1 -0
  93. package/dist/cjs/src/multer/multipart/handlers/multiple-files.d.ts +8 -0
  94. package/dist/cjs/src/multer/multipart/handlers/multiple-files.js +40 -0
  95. package/dist/cjs/src/multer/multipart/handlers/multiple-files.js.map +1 -0
  96. package/dist/cjs/src/multer/multipart/handlers/single-file.d.ts +8 -0
  97. package/dist/cjs/src/multer/multipart/handlers/single-file.js +45 -0
  98. package/dist/cjs/src/multer/multipart/handlers/single-file.js.map +1 -0
  99. package/dist/cjs/src/multer/multipart/index.d.ts +3 -0
  100. package/dist/cjs/src/multer/multipart/index.js +19 -0
  101. package/dist/cjs/src/multer/multipart/index.js.map +1 -0
  102. package/dist/cjs/src/multer/multipart/options.d.ts +22 -0
  103. package/dist/cjs/src/multer/multipart/options.js +23 -0
  104. package/dist/cjs/src/multer/multipart/options.js.map +1 -0
  105. package/dist/cjs/src/multer/multipart/request.d.ts +16 -0
  106. package/dist/cjs/src/multer/multipart/request.js +25 -0
  107. package/dist/cjs/src/multer/multipart/request.js.map +1 -0
  108. package/dist/cjs/src/multer/storage/disk-storage.d.ts +31 -0
  109. package/dist/cjs/src/multer/storage/disk-storage.js +62 -0
  110. package/dist/cjs/src/multer/storage/disk-storage.js.map +1 -0
  111. package/dist/cjs/src/multer/storage/index.d.ts +3 -0
  112. package/dist/cjs/src/multer/storage/index.js +20 -0
  113. package/dist/cjs/src/multer/storage/index.js.map +1 -0
  114. package/dist/cjs/src/multer/storage/memory-storage.d.ts +17 -0
  115. package/dist/cjs/src/multer/storage/memory-storage.js +21 -0
  116. package/dist/cjs/src/multer/storage/memory-storage.js.map +1 -0
  117. package/dist/cjs/src/multer/storage/storage.d.ts +13 -0
  118. package/dist/cjs/src/multer/storage/storage.js +3 -0
  119. package/dist/cjs/src/multer/storage/storage.js.map +1 -0
  120. package/dist/cjs/src/multer/stream/index.d.ts +3 -0
  121. package/dist/cjs/src/multer/stream/index.js +7 -0
  122. package/dist/cjs/src/multer/stream/index.js.map +1 -0
  123. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  124. package/dist/esm/index.d.ts +1 -0
  125. package/dist/esm/index.js +1 -0
  126. package/dist/esm/index.js.map +1 -1
  127. package/dist/esm/src/adapters/hono-adapter.d.ts +11 -11
  128. package/dist/esm/src/adapters/hono-adapter.js +35 -35
  129. package/dist/esm/src/adapters/hono-adapter.js.map +1 -1
  130. package/dist/esm/src/drivers/constants/apollo.constants.d.ts +1 -0
  131. package/dist/esm/src/drivers/constants/apollo.constants.js +2 -0
  132. package/dist/esm/src/drivers/constants/apollo.constants.js.map +1 -0
  133. package/dist/esm/src/drivers/constants/index.d.ts +1 -0
  134. package/dist/esm/src/drivers/constants/index.js +2 -0
  135. package/dist/esm/src/drivers/constants/index.js.map +1 -0
  136. package/dist/esm/src/drivers/graphQLUpload/GraphQLUpload.d.ts +3 -0
  137. package/dist/esm/src/drivers/graphQLUpload/GraphQLUpload.js +18 -0
  138. package/dist/esm/src/drivers/graphQLUpload/GraphQLUpload.js.map +1 -0
  139. package/dist/esm/src/drivers/graphQLUpload/Upload.d.ts +16 -0
  140. package/dist/esm/src/drivers/graphQLUpload/Upload.js +13 -0
  141. package/dist/esm/src/drivers/graphQLUpload/Upload.js.map +1 -0
  142. package/dist/esm/src/drivers/graphQLUpload/fs-capacitor.d.ts +44 -0
  143. package/dist/esm/src/drivers/graphQLUpload/fs-capacitor.js +183 -0
  144. package/dist/esm/src/drivers/graphQLUpload/fs-capacitor.js.map +1 -0
  145. package/dist/esm/src/drivers/graphQLUpload/index.d.ts +4 -0
  146. package/dist/esm/src/drivers/graphQLUpload/index.js +5 -0
  147. package/dist/esm/src/drivers/graphQLUpload/index.js.map +1 -0
  148. package/dist/esm/src/drivers/graphQLUpload/processRequest.d.ts +2 -0
  149. package/dist/esm/src/drivers/graphQLUpload/processRequest.js +41 -0
  150. package/dist/esm/src/drivers/graphQLUpload/processRequest.js.map +1 -0
  151. package/dist/esm/src/drivers/graphql.driver.d.ts +7 -0
  152. package/dist/esm/src/drivers/graphql.driver.js +33 -6
  153. package/dist/esm/src/drivers/graphql.driver.js.map +1 -1
  154. package/dist/esm/src/drivers/index.d.ts +1 -0
  155. package/dist/esm/src/drivers/index.js +1 -0
  156. package/dist/esm/src/drivers/index.js.map +1 -1
  157. package/dist/esm/src/drivers/services/plugins-explorer.service.d.ts +9 -0
  158. package/dist/esm/src/drivers/services/plugins-explorer.service.js +21 -0
  159. package/dist/esm/src/drivers/services/plugins-explorer.service.js.map +1 -0
  160. package/dist/esm/src/drivers/services/processRequest.d.ts +2 -0
  161. package/dist/esm/src/drivers/services/processRequest.js +41 -0
  162. package/dist/esm/src/drivers/services/processRequest.js.map +1 -0
  163. package/dist/esm/src/multer/crypto/index.d.ts +2 -0
  164. package/dist/esm/src/multer/crypto/index.js +4 -0
  165. package/dist/esm/src/multer/crypto/index.js.map +1 -0
  166. package/dist/esm/src/multer/decorators/index.d.ts +2 -0
  167. package/dist/esm/src/multer/decorators/index.js +3 -0
  168. package/dist/esm/src/multer/decorators/index.js.map +1 -0
  169. package/dist/esm/src/multer/decorators/uploaded-file-decorator.d.ts +1 -0
  170. package/dist/esm/src/multer/decorators/uploaded-file-decorator.js +7 -0
  171. package/dist/esm/src/multer/decorators/uploaded-file-decorator.js.map +1 -0
  172. package/dist/esm/src/multer/decorators/uploaded-files-decorator.d.ts +1 -0
  173. package/dist/esm/src/multer/decorators/uploaded-files-decorator.js +7 -0
  174. package/dist/esm/src/multer/decorators/uploaded-files-decorator.js.map +1 -0
  175. package/dist/esm/src/multer/fs/index.d.ts +2 -0
  176. package/dist/esm/src/multer/fs/index.js +18 -0
  177. package/dist/esm/src/multer/fs/index.js.map +1 -0
  178. package/dist/esm/src/multer/index.d.ts +4 -0
  179. package/dist/esm/src/multer/index.js +5 -0
  180. package/dist/esm/src/multer/index.js.map +1 -0
  181. package/dist/esm/src/multer/interceptors/any-files-interceptor.d.ts +3 -0
  182. package/dist/esm/src/multer/interceptors/any-files-interceptor.js +23 -0
  183. package/dist/esm/src/multer/interceptors/any-files-interceptor.js.map +1 -0
  184. package/dist/esm/src/multer/interceptors/file-fields-interceptor.d.ts +4 -0
  185. package/dist/esm/src/multer/interceptors/file-fields-interceptor.js +24 -0
  186. package/dist/esm/src/multer/interceptors/file-fields-interceptor.js.map +1 -0
  187. package/dist/esm/src/multer/interceptors/file-interceptor.d.ts +3 -0
  188. package/dist/esm/src/multer/interceptors/file-interceptor.js +23 -0
  189. package/dist/esm/src/multer/interceptors/file-interceptor.js.map +1 -0
  190. package/dist/esm/src/multer/interceptors/files-interceptor.d.ts +3 -0
  191. package/dist/esm/src/multer/interceptors/files-interceptor.js +23 -0
  192. package/dist/esm/src/multer/interceptors/files-interceptor.js.map +1 -0
  193. package/dist/esm/src/multer/interceptors/index.d.ts +4 -0
  194. package/dist/esm/src/multer/interceptors/index.js +5 -0
  195. package/dist/esm/src/multer/interceptors/index.js.map +1 -0
  196. package/dist/esm/src/multer/multipart/exceptions.d.ts +1 -0
  197. package/dist/esm/src/multer/multipart/exceptions.js +18 -0
  198. package/dist/esm/src/multer/multipart/exceptions.js.map +1 -0
  199. package/dist/esm/src/multer/multipart/file.d.ts +10 -0
  200. package/dist/esm/src/multer/multipart/file.js +6 -0
  201. package/dist/esm/src/multer/multipart/file.js.map +1 -0
  202. package/dist/esm/src/multer/multipart/filter.d.ts +6 -0
  203. package/dist/esm/src/multer/multipart/filter.js +18 -0
  204. package/dist/esm/src/multer/multipart/filter.js.map +1 -0
  205. package/dist/esm/src/multer/multipart/handlers/any-files.d.ts +8 -0
  206. package/dist/esm/src/multer/multipart/handlers/any-files.js +29 -0
  207. package/dist/esm/src/multer/multipart/handlers/any-files.js.map +1 -0
  208. package/dist/esm/src/multer/multipart/handlers/file-fields.d.ts +14 -0
  209. package/dist/esm/src/multer/multipart/handlers/file-fields.js +52 -0
  210. package/dist/esm/src/multer/multipart/handlers/file-fields.js.map +1 -0
  211. package/dist/esm/src/multer/multipart/handlers/index.d.ts +1 -0
  212. package/dist/esm/src/multer/multipart/handlers/index.js +2 -0
  213. package/dist/esm/src/multer/multipart/handlers/index.js.map +1 -0
  214. package/dist/esm/src/multer/multipart/handlers/multiple-files.d.ts +8 -0
  215. package/dist/esm/src/multer/multipart/handlers/multiple-files.js +36 -0
  216. package/dist/esm/src/multer/multipart/handlers/multiple-files.js.map +1 -0
  217. package/dist/esm/src/multer/multipart/handlers/single-file.d.ts +8 -0
  218. package/dist/esm/src/multer/multipart/handlers/single-file.js +41 -0
  219. package/dist/esm/src/multer/multipart/handlers/single-file.js.map +1 -0
  220. package/dist/esm/src/multer/multipart/index.d.ts +3 -0
  221. package/dist/esm/src/multer/multipart/index.js +3 -0
  222. package/dist/esm/src/multer/multipart/index.js.map +1 -0
  223. package/dist/esm/src/multer/multipart/options.d.ts +22 -0
  224. package/dist/esm/src/multer/multipart/options.js +19 -0
  225. package/dist/esm/src/multer/multipart/options.js.map +1 -0
  226. package/dist/esm/src/multer/multipart/request.d.ts +16 -0
  227. package/dist/esm/src/multer/multipart/request.js +20 -0
  228. package/dist/esm/src/multer/multipart/request.js.map +1 -0
  229. package/dist/esm/src/multer/storage/disk-storage.d.ts +31 -0
  230. package/dist/esm/src/multer/storage/disk-storage.js +58 -0
  231. package/dist/esm/src/multer/storage/disk-storage.js.map +1 -0
  232. package/dist/esm/src/multer/storage/index.d.ts +3 -0
  233. package/dist/esm/src/multer/storage/index.js +4 -0
  234. package/dist/esm/src/multer/storage/index.js.map +1 -0
  235. package/dist/esm/src/multer/storage/memory-storage.d.ts +17 -0
  236. package/dist/esm/src/multer/storage/memory-storage.js +17 -0
  237. package/dist/esm/src/multer/storage/memory-storage.js.map +1 -0
  238. package/dist/esm/src/multer/storage/storage.d.ts +13 -0
  239. package/dist/esm/src/multer/storage/storage.js +2 -0
  240. package/dist/esm/src/multer/storage/storage.js.map +1 -0
  241. package/dist/esm/src/multer/stream/index.d.ts +3 -0
  242. package/dist/esm/src/multer/stream/index.js +4 -0
  243. package/dist/esm/src/multer/stream/index.js.map +1 -0
  244. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  245. package/index.ts +1 -0
  246. package/package.json +3 -1
  247. package/src/adapters/hono-adapter.ts +51 -50
  248. package/src/drivers/constants/apollo.constants.ts +1 -0
  249. package/src/drivers/constants/index.ts +1 -0
  250. package/src/drivers/graphQLUpload/GraphQLUpload.ts +86 -0
  251. package/src/drivers/graphQLUpload/Upload.ts +35 -0
  252. package/src/drivers/graphQLUpload/fs-capacitor.ts +285 -0
  253. package/src/drivers/graphQLUpload/index.ts +4 -0
  254. package/src/drivers/graphQLUpload/processRequest.ts +50 -0
  255. package/src/drivers/graphql.driver.ts +50 -6
  256. package/src/drivers/index.ts +1 -0
  257. package/src/drivers/services/plugins-explorer.service.ts +27 -0
  258. package/src/multer/crypto/index.ts +4 -0
  259. package/src/multer/decorators/index.ts +2 -0
  260. package/src/multer/decorators/uploaded-file-decorator.ts +12 -0
  261. package/src/multer/decorators/uploaded-files-decorator.ts +15 -0
  262. package/src/multer/fs/index.ts +22 -0
  263. package/src/multer/index.ts +4 -0
  264. package/src/multer/interceptors/any-files-interceptor.ts +46 -0
  265. package/src/multer/interceptors/file-fields-interceptor.ts +56 -0
  266. package/src/multer/interceptors/file-interceptor.ts +48 -0
  267. package/src/multer/interceptors/files-interceptor.ts +50 -0
  268. package/src/multer/interceptors/index.ts +4 -0
  269. package/src/multer/multipart/exceptions.ts +25 -0
  270. package/src/multer/multipart/file.ts +18 -0
  271. package/src/multer/multipart/filter.ts +38 -0
  272. package/src/multer/multipart/handlers/any-files.ts +39 -0
  273. package/src/multer/multipart/handlers/file-fields.ts +89 -0
  274. package/src/multer/multipart/handlers/index.ts +1 -0
  275. package/src/multer/multipart/handlers/multiple-files.ts +55 -0
  276. package/src/multer/multipart/handlers/single-file.ts +56 -0
  277. package/src/multer/multipart/index.ts +3 -0
  278. package/src/multer/multipart/options.ts +29 -0
  279. package/src/multer/multipart/request.ts +44 -0
  280. package/src/multer/storage/disk-storage.ts +107 -0
  281. package/src/multer/storage/index.ts +3 -0
  282. package/src/multer/storage/memory-storage.ts +25 -0
  283. package/src/multer/storage/storage.ts +15 -0
  284. package/src/multer/stream/index.ts +4 -0
@@ -0,0 +1,50 @@
1
+ import { Context } from "hono";
2
+ import { WriteStream, Upload } from ".";
3
+ import { Readable } from "stream";
4
+
5
+ export async function processRequest(
6
+ ctx: Context
7
+ ): Promise<Record<string, any>> {
8
+ const body = await ctx.req.parseBody();
9
+ const operations = JSON.parse(body.operations as string);
10
+ const map = new Map(Object.entries(JSON.parse(body.map as string)));
11
+
12
+ for (const [fieldName, file] of Object.entries(body)) {
13
+ if (
14
+ fieldName === "operations" ||
15
+ fieldName === "map" ||
16
+ !(file instanceof File)
17
+ )
18
+ continue;
19
+
20
+ const fileKeys = map.get(fieldName);
21
+ if (!Array.isArray(fileKeys) || !fileKeys.length) continue;
22
+
23
+ const buffer = Buffer.from(await file.arrayBuffer());
24
+ const capacitor = new WriteStream();
25
+ Readable.from(buffer).pipe(capacitor);
26
+
27
+ const upload = new Upload();
28
+ upload.file = {
29
+ filename: file.name,
30
+ mimetype: file.type,
31
+ fieldName,
32
+ encoding: "7bit",
33
+ createReadStream: (options) => capacitor.createReadStream(options),
34
+ capacitor,
35
+ };
36
+ upload.resolve(upload.file);
37
+
38
+ for (const fileKey of fileKeys) {
39
+ const pathSegments = fileKey.split(".");
40
+ let current = operations;
41
+ for (let i = 0; i < pathSegments.length - 1; i++) {
42
+ if (!current[pathSegments[i]]) current[pathSegments[i]] = {};
43
+ current = current[pathSegments[i]];
44
+ }
45
+ current[pathSegments[pathSegments.length - 1]] = upload;
46
+ }
47
+ }
48
+
49
+ return operations;
50
+ }
@@ -1,15 +1,31 @@
1
1
  import { ApolloServer, BaseContext, HeaderMap } from "@apollo/server";
2
- import { AbstractGraphQLDriver } from "@nestjs/graphql";
2
+ import { ModulesContainer } from "@nestjs/core";
3
+ import {
4
+ AbstractGraphQLDriver,
5
+ GqlSubscriptionService,
6
+ SubscriptionConfig,
7
+ } from "@nestjs/graphql";
3
8
  import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";
4
9
  import { ApolloDriverConfig } from "@nestjs/apollo";
5
10
  import { Context, HonoRequest } from "hono";
6
11
  import { StatusCode } from "hono/utils/http-status";
7
12
  import { Logger } from "@nestjs/common";
13
+ import http from "http";
14
+
15
+ import { PluginsExplorerService } from "./services/plugins-explorer.service";
16
+ import { processRequest } from "./graphQLUpload";
8
17
 
9
18
  export class HonoGraphQLDriver<
10
19
  T extends Record<string, any> = ApolloDriverConfig
11
20
  > extends AbstractGraphQLDriver {
12
21
  protected apolloServer: ApolloServer<BaseContext>;
22
+ private _subscriptionService?: GqlSubscriptionService;
23
+ private readonly pluginsExplorerService: PluginsExplorerService;
24
+
25
+ constructor(modulesContainer: ModulesContainer) {
26
+ super();
27
+ this.pluginsExplorerService = new PluginsExplorerService(modulesContainer);
28
+ }
13
29
 
14
30
  get instance(): ApolloServer<BaseContext> {
15
31
  return this.apolloServer;
@@ -23,7 +39,21 @@ export class HonoGraphQLDriver<
23
39
  throw new Error("This driver is only compatible with the Hono platform");
24
40
  }
25
41
 
26
- return this.registerHono(options);
42
+ await this.registerHono(options);
43
+
44
+ if (options.installSubscriptionHandlers || options.subscriptions) {
45
+ const subscriptionsOptions: SubscriptionConfig =
46
+ options.subscriptions || { "subscriptions-transport-ws": {} };
47
+ this._subscriptionService = new GqlSubscriptionService(
48
+ {
49
+ schema: options.schema,
50
+ path: options.path,
51
+ context: options.context,
52
+ ...subscriptionsOptions,
53
+ },
54
+ this.httpAdapterHost.httpAdapter?.getHttpServer()
55
+ );
56
+ }
27
57
  }
28
58
 
29
59
  protected async registerHono(
@@ -50,7 +80,7 @@ export class HonoGraphQLDriver<
50
80
  await server.start();
51
81
 
52
82
  app.use(path, async (ctx: Context) => {
53
- const bodyData = await this.parseBody(ctx.req);
83
+ const bodyData = await this.parseBody(ctx);
54
84
 
55
85
  const defaultContext = () => Promise.resolve({} as BaseContext);
56
86
 
@@ -101,8 +131,9 @@ export class HonoGraphQLDriver<
101
131
  this.apolloServer = server;
102
132
  }
103
133
 
104
- public stop() {
105
- return this.apolloServer?.stop();
134
+ public async stop() {
135
+ await this._subscriptionService?.stop();
136
+ await this.apolloServer?.stop();
106
137
  }
107
138
 
108
139
  private httpHeadersToMap(headers: Headers) {
@@ -111,17 +142,30 @@ export class HonoGraphQLDriver<
111
142
  return map;
112
143
  }
113
144
 
114
- private async parseBody(req: HonoRequest): Promise<Record<string, unknown>> {
145
+ private async parseBody(ctx: Context): Promise<Record<string, unknown>> {
146
+ const req = ctx.req;
115
147
  const contentType = req.header("content-type");
148
+
116
149
  if (contentType === "application/graphql")
117
150
  return { query: await req.text() };
118
151
  if (contentType === "application/json")
119
152
  return req.json().catch(this.logError);
120
153
  if (contentType === "application/x-www-form-urlencoded")
121
154
  return this.parseFormURL(req);
155
+ if (contentType?.startsWith("multipart/form-data")) {
156
+ return processRequest(ctx);
157
+ }
122
158
  return {};
123
159
  }
124
160
 
161
+ headersToRecord(headers: Headers): http.IncomingHttpHeaders {
162
+ const obj: http.IncomingHttpHeaders = {};
163
+ headers.forEach((value, key) => {
164
+ obj[key] = value;
165
+ });
166
+ return obj;
167
+ }
168
+
125
169
  private logError(e: unknown): void {
126
170
  if (e instanceof Error) {
127
171
  Logger.error(e.stack || e.message);
@@ -1 +1,2 @@
1
1
  export * from "./graphql.driver";
2
+ export * from "./graphQLUpload";
@@ -0,0 +1,27 @@
1
+ import { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
2
+ import { ModulesContainer } from '@nestjs/core/injector/modules-container';
3
+ import { BaseExplorerService, GqlModuleOptions } from '@nestjs/graphql';
4
+ import { PLUGIN_METADATA } from '../constants';
5
+
6
+ export class PluginsExplorerService extends BaseExplorerService {
7
+ constructor(private readonly modulesContainer: ModulesContainer) {
8
+ super();
9
+ }
10
+
11
+ explore(options: GqlModuleOptions) {
12
+ const modules = this.getModules(
13
+ this.modulesContainer,
14
+ options.include || [],
15
+ );
16
+ return this.flatMap(modules, (instance) => this.filterPlugins(instance));
17
+ }
18
+
19
+ filterPlugins<T = any>(wrapper: InstanceWrapper<T>) {
20
+ const { instance } = wrapper;
21
+ if (!instance) {
22
+ return undefined;
23
+ }
24
+ const metadata = Reflect.getMetadata(PLUGIN_METADATA, instance.constructor);
25
+ return metadata ? instance : undefined;
26
+ }
27
+ }
@@ -0,0 +1,4 @@
1
+ import { promisify } from 'node:util';
2
+ import { randomBytes as cryptoRandomBytes } from 'node:crypto';
3
+
4
+ export const randomBytes = promisify(cryptoRandomBytes);
@@ -0,0 +1,2 @@
1
+ export * from "./uploaded-files-decorator";
2
+ export * from "./uploaded-file-decorator";
@@ -0,0 +1,12 @@
1
+ import { createParamDecorator, ExecutionContext } from '@nestjs/common';
2
+
3
+ import { getMultipartRequest } from '../multipart/request';
4
+ import { StorageFile } from '../storage/storage';
5
+
6
+ export const UploadedFile = createParamDecorator(
7
+ async (_data, ctx: ExecutionContext): Promise<StorageFile | undefined> => {
8
+ const req = getMultipartRequest(ctx.switchToHttp());
9
+
10
+ return req?.storageFile;
11
+ },
12
+ );
@@ -0,0 +1,15 @@
1
+ import { createParamDecorator, ExecutionContext } from '@nestjs/common';
2
+
3
+ import { getMultipartRequest } from '../multipart/request';
4
+ import { StorageFile } from '../storage/storage';
5
+
6
+ export const UploadedFiles = createParamDecorator(
7
+ async (
8
+ _data: any,
9
+ ctx: ExecutionContext,
10
+ ): Promise<Record<string, StorageFile[]> | StorageFile[] | undefined> => {
11
+ const req = getMultipartRequest(ctx.switchToHttp());
12
+
13
+ return req?.storageFiles;
14
+ },
15
+ );
@@ -0,0 +1,22 @@
1
+ import fs from 'node:fs/promises';
2
+ import { extname } from 'node:path';
3
+
4
+ import { randomBytes } from '../crypto';
5
+
6
+ export const pathExists = async (path: string) => {
7
+ try {
8
+ await fs.stat(path);
9
+ } catch (err) {
10
+ return false;
11
+ }
12
+
13
+ return true;
14
+ };
15
+
16
+ export const getUniqueFilename = async (filename: string) => {
17
+ const buffer = await randomBytes(16);
18
+
19
+ const ext = extname(filename);
20
+
21
+ return buffer.toString('hex') + ext;
22
+ };
@@ -0,0 +1,4 @@
1
+ export * from "./interceptors";
2
+ export * from "./decorators";
3
+ export * from "./storage";
4
+ export * from "./multipart";
@@ -0,0 +1,46 @@
1
+ import { Observable, tap } from 'rxjs';
2
+ import {
3
+ CallHandler,
4
+ ExecutionContext,
5
+ mixin,
6
+ NestInterceptor,
7
+ Type,
8
+ } from '@nestjs/common';
9
+
10
+ import { getMultipartRequest } from '../multipart/request';
11
+ import { transformUploadOptions, UploadOptions } from '../multipart/options';
12
+ import { handleMultipartAnyFiles } from '../multipart/handlers/any-files';
13
+
14
+ 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(
25
+ context: ExecutionContext,
26
+ next: CallHandler,
27
+ ): Promise<Observable<any>> {
28
+ const ctx = context.switchToHttp();
29
+ const req = getMultipartRequest(ctx);
30
+
31
+ const { body, files, remove } = await handleMultipartAnyFiles(
32
+ req,
33
+ this.options,
34
+ );
35
+
36
+ req.body = body;
37
+ req.storageFiles = files;
38
+
39
+ return next.handle().pipe(tap(remove));
40
+ }
41
+ }
42
+
43
+ const Interceptor = mixin(MixinInterceptor);
44
+
45
+ return Interceptor;
46
+ }
@@ -0,0 +1,56 @@
1
+ import { Observable, tap } from 'rxjs';
2
+ import {
3
+ CallHandler,
4
+ ExecutionContext,
5
+ mixin,
6
+ NestInterceptor,
7
+ Type,
8
+ } from '@nestjs/common';
9
+
10
+ import { getMultipartRequest } from '../multipart/request';
11
+ import { transformUploadOptions, UploadOptions } from '../multipart/options';
12
+ import {
13
+ handleMultipartFileFields,
14
+ UploadField,
15
+ UploadFieldMapEntry,
16
+ uploadFieldsToMap,
17
+ } from '../multipart/handlers/file-fields';
18
+
19
+ export function FileFieldsInterceptor(
20
+ 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(
34
+ context: ExecutionContext,
35
+ next: CallHandler,
36
+ ): Promise<Observable<any>> {
37
+ const ctx = context.switchToHttp();
38
+ const req = getMultipartRequest(ctx);
39
+
40
+ const { body, files, remove } = await handleMultipartFileFields(
41
+ req,
42
+ this.fieldsMap,
43
+ this.options,
44
+ );
45
+
46
+ req.body = body;
47
+ req.storageFiles = files;
48
+
49
+ return next.handle().pipe(tap(remove));
50
+ }
51
+ }
52
+
53
+ const Interceptor = mixin(MixinInterceptor);
54
+
55
+ return Interceptor;
56
+ }
@@ -0,0 +1,48 @@
1
+ import { Observable, tap } from 'rxjs';
2
+ import {
3
+ CallHandler,
4
+ ExecutionContext,
5
+ mixin,
6
+ NestInterceptor,
7
+ Type,
8
+ } from '@nestjs/common';
9
+
10
+ import { getMultipartRequest } from '../multipart/request';
11
+ import { transformUploadOptions, UploadOptions } from '../multipart/options';
12
+ import { handleMultipartSingleFile } from '../multipart/handlers/single-file';
13
+
14
+ export function FileInterceptor(
15
+ 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(
26
+ context: ExecutionContext,
27
+ next: CallHandler,
28
+ ): Promise<Observable<any>> {
29
+ const ctx = context.switchToHttp();
30
+ const req = getMultipartRequest(ctx);
31
+
32
+ const { file, body, remove } = await handleMultipartSingleFile(
33
+ req,
34
+ fieldname,
35
+ this.options,
36
+ );
37
+
38
+ req.body = body;
39
+ req.storageFile = file;
40
+
41
+ return next.handle().pipe(tap(remove));
42
+ }
43
+ }
44
+
45
+ const Interceptor = mixin(MixinInterceptor);
46
+
47
+ return Interceptor;
48
+ }
@@ -0,0 +1,50 @@
1
+ import { Observable, tap } from 'rxjs';
2
+ import {
3
+ CallHandler,
4
+ ExecutionContext,
5
+ mixin,
6
+ NestInterceptor,
7
+ Type,
8
+ } from '@nestjs/common';
9
+
10
+ import { getMultipartRequest } from '../multipart/request';
11
+ import { transformUploadOptions, UploadOptions } from '../multipart/options';
12
+ import { handleMultipartMultipleFiles } from '../multipart/handlers/multiple-files';
13
+
14
+ export function FilesInterceptor(
15
+ fieldname: string,
16
+ 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(
27
+ context: ExecutionContext,
28
+ next: CallHandler,
29
+ ): Promise<Observable<any>> {
30
+ const ctx = context.switchToHttp();
31
+ const req = getMultipartRequest(ctx);
32
+
33
+ const { body, files, remove } = await handleMultipartMultipleFiles(
34
+ req,
35
+ fieldname,
36
+ maxCount,
37
+ this.options,
38
+ );
39
+
40
+ req.body = body;
41
+ req.storageFiles = files;
42
+
43
+ return next.handle().pipe(tap(remove));
44
+ }
45
+ }
46
+
47
+ const Interceptor = mixin(MixinInterceptor);
48
+
49
+ return Interceptor;
50
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./file-fields-interceptor";
2
+ export * from "./file-interceptor";
3
+ export * from "./any-files-interceptor";
4
+ export * from "./files-interceptor";
@@ -0,0 +1,25 @@
1
+ import {
2
+ BadRequestException,
3
+ HttpException,
4
+ PayloadTooLargeException,
5
+ } from '@nestjs/common';
6
+
7
+ export const transformException = (err: Error | undefined) => {
8
+ if (!err || err instanceof HttpException) {
9
+ return err;
10
+ }
11
+
12
+ const code: string = (err as any).code;
13
+
14
+ switch (code) {
15
+ case 'REQ_FILE_TOO_LARGE':
16
+ return new PayloadTooLargeException();
17
+ case 'PARTS_LIMIT':
18
+ case 'FILES_LIMIT':
19
+ case 'PROTO_VIOLATION':
20
+ case 'INVALID_MULTIPART_CONTENT_TYPE':
21
+ return new BadRequestException(err.message);
22
+ }
23
+
24
+ return err;
25
+ };
@@ -0,0 +1,18 @@
1
+ import { Readable } from 'stream';
2
+ import { Storage, StorageFile } from '../storage';
3
+
4
+ export type MultipartFile = Omit<File[], 'file'> & {
5
+ value?: any;
6
+ file: Readable & { truncated?: boolean };
7
+ };
8
+
9
+ export const removeStorageFiles = async (
10
+ storage: Storage,
11
+ files?: (StorageFile | undefined)[],
12
+ force?: boolean,
13
+ ) => {
14
+ if (files == null) return;
15
+ await Promise.all(
16
+ files.map((file) => file && storage.removeFile(file, force)),
17
+ );
18
+ };
@@ -0,0 +1,38 @@
1
+ import { BadRequestException } from '@nestjs/common';
2
+ import { UploadOptions } from '.';
3
+
4
+ import { DiskStorageFile, MemoryStorageFile, StorageFile } from '../storage';
5
+ import { HonoRequest } from 'hono';
6
+
7
+ export type UploadFilterFile =
8
+ | DiskStorageFile
9
+ | MemoryStorageFile
10
+ | StorageFile;
11
+
12
+ export type UploadFilterHandler = (
13
+ req: HonoRequest,
14
+ file: UploadFilterFile,
15
+ ) => Promise<boolean | string> | boolean | string;
16
+
17
+ export const filterUpload = async (
18
+ uploadOptions: UploadOptions,
19
+ req: HonoRequest,
20
+ file: UploadFilterFile,
21
+ ): Promise<boolean> => {
22
+ if (uploadOptions.filter == null) {
23
+ return true;
24
+ }
25
+
26
+ try {
27
+ const res = await uploadOptions.filter(req, file);
28
+
29
+ if (typeof res === 'string') {
30
+ throw new BadRequestException(res);
31
+ }
32
+
33
+ return res;
34
+ } catch (error) {
35
+ await uploadOptions.storage!.removeFile(file, true);
36
+ throw error;
37
+ }
38
+ };
@@ -0,0 +1,39 @@
1
+ import { UploadOptions } from '../options';
2
+ import { StorageFile } from '../../storage';
3
+ import { THonoRequest, getParts } from '../request';
4
+ import { removeStorageFiles } from '../file';
5
+ import { filterUpload } from '../filter';
6
+
7
+ export const handleMultipartAnyFiles = async (
8
+ req: THonoRequest,
9
+ options: UploadOptions,
10
+ ) => {
11
+ const parts = await getParts(req, options);
12
+
13
+ const body: Record<string, any> = {};
14
+
15
+ const files: StorageFile[] = [];
16
+
17
+ const removeFiles = async (error?: boolean) => {
18
+ return await removeStorageFiles(options.storage!, files, error);
19
+ };
20
+
21
+ try {
22
+ for await (const [partFieldName, part] of Object.entries(parts)) {
23
+ if (!(part instanceof File)) {
24
+ body[partFieldName] = part;
25
+ continue;
26
+ }
27
+ const file = await options.storage!.handleFile(part, req, partFieldName);
28
+
29
+ if (await filterUpload(options, req, file)) {
30
+ files.push(file);
31
+ }
32
+ }
33
+ } catch (error) {
34
+ await removeFiles(true);
35
+ throw error;
36
+ }
37
+
38
+ return { body, files, remove: () => removeFiles() };
39
+ };
@@ -0,0 +1,89 @@
1
+ import { BadRequestException } from '@nestjs/common';
2
+
3
+ import { UploadOptions } from '../options';
4
+ import { StorageFile } from '../../storage/storage';
5
+ import { THonoRequest, getParts } from '../request';
6
+ import { removeStorageFiles } from '../file';
7
+ import { filterUpload } from '../filter';
8
+ import { HonoRequest } from 'hono';
9
+
10
+ export interface UploadField {
11
+ /**
12
+ * Field name
13
+ */
14
+ name: string;
15
+ /**
16
+ * Max number of files in this field
17
+ */
18
+ maxCount?: number;
19
+ }
20
+
21
+ export type UploadFieldMapEntry = Required<Pick<UploadField, 'maxCount'>>;
22
+
23
+ export const uploadFieldsToMap = (uploadFields: UploadField[]) => {
24
+ const map = new Map<string, UploadFieldMapEntry>();
25
+
26
+ uploadFields.forEach(({ name, ...opts }) => {
27
+ map.set(name, { maxCount: 1, ...opts });
28
+ });
29
+
30
+ return map;
31
+ };
32
+
33
+ export const handleMultipartFileFields = async (
34
+ req: THonoRequest,
35
+ fieldsMap: Map<string, UploadFieldMapEntry>,
36
+ options: UploadOptions,
37
+ ) => {
38
+ const parts = await getParts(req, options);
39
+ const body: Record<string, any> = {};
40
+
41
+ const files: Record<string, StorageFile[]> = {};
42
+
43
+ const removeFiles = async (error?: boolean) => {
44
+ const allFiles = ([] as StorageFile[]).concat(...Object.values(files));
45
+ return await removeStorageFiles(options.storage!, allFiles, error);
46
+ };
47
+
48
+ try {
49
+ for await (const [fieldName, part] of Object.entries(parts)) {
50
+ if (!(part instanceof File)) {
51
+ body[fieldName] = part;
52
+ continue;
53
+ }
54
+
55
+ const fieldOptions = fieldsMap.get(fieldName);
56
+
57
+ if (fieldOptions == null) {
58
+ throw new BadRequestException(
59
+ `Field ${fieldName} doesn't accept files`,
60
+ );
61
+ }
62
+
63
+ if (files[fieldName] == null) {
64
+ files[fieldName] = [];
65
+ }
66
+
67
+ if (files[fieldName].length + 1 > fieldOptions.maxCount) {
68
+ throw new BadRequestException(
69
+ `Field ${fieldName} accepts max ${fieldOptions.maxCount} files`,
70
+ );
71
+ }
72
+
73
+ const file = await options.storage!.handleFile(part, req, fieldName);
74
+
75
+ if (await filterUpload(options, req, file)) {
76
+ files[fieldName].push(file);
77
+ }
78
+ }
79
+ } catch (error) {
80
+ await removeFiles(true);
81
+ throw error;
82
+ }
83
+
84
+ return {
85
+ body,
86
+ files,
87
+ remove: () => removeFiles(),
88
+ };
89
+ };
@@ -0,0 +1 @@
1
+ export { UploadField } from "./file-fields";