arkos 2.0.0-next.13 → 2.0.0-next.16

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 (246) hide show
  1. package/README.md +144 -145
  2. package/cli.js +1 -0
  3. package/dist/cjs/app.js +7 -0
  4. package/dist/cjs/app.js.map +1 -1
  5. package/dist/cjs/exports/error-handler/index.js +15 -0
  6. package/dist/cjs/exports/error-handler/index.js.map +1 -1
  7. package/dist/cjs/modules/auth/auth.router.js +3 -0
  8. package/dist/cjs/modules/auth/auth.router.js.map +1 -1
  9. package/dist/cjs/modules/auth/auth.service.js +2 -0
  10. package/dist/cjs/modules/auth/auth.service.js.map +1 -1
  11. package/dist/cjs/modules/base/base.controller.js +15 -3
  12. package/dist/cjs/modules/base/base.controller.js.map +1 -1
  13. package/dist/cjs/modules/base/base.middlewares.js +19 -12
  14. package/dist/cjs/modules/base/base.middlewares.js.map +1 -1
  15. package/dist/cjs/modules/base/base.service.js +5 -1
  16. package/dist/cjs/modules/base/base.service.js.map +1 -1
  17. package/dist/cjs/modules/base/utils/helpers/base.service.helpers.js +9 -0
  18. package/dist/cjs/modules/base/utils/helpers/base.service.helpers.js.map +1 -1
  19. package/dist/cjs/modules/error-handler/error-handler.controller.js +25 -42
  20. package/dist/cjs/modules/error-handler/error-handler.controller.js.map +1 -1
  21. package/dist/cjs/modules/error-handler/utils/app-error.js +0 -1
  22. package/dist/cjs/modules/error-handler/utils/app-error.js.map +1 -1
  23. package/dist/cjs/modules/error-handler/utils/error-handler.helpers.js +8 -9
  24. package/dist/cjs/modules/error-handler/utils/error-handler.helpers.js.map +1 -1
  25. package/dist/cjs/modules/error-handler/utils/errors.js +158 -0
  26. package/dist/cjs/modules/error-handler/utils/errors.js.map +1 -0
  27. package/dist/cjs/modules/error-handler/utils/multer-error-handler.js +39 -0
  28. package/dist/cjs/modules/error-handler/utils/multer-error-handler.js.map +1 -0
  29. package/dist/cjs/modules/file-upload/file-upload.controller.js +10 -14
  30. package/dist/cjs/modules/file-upload/file-upload.controller.js.map +1 -1
  31. package/dist/cjs/modules/file-upload/file-upload.router.js +2 -0
  32. package/dist/cjs/modules/file-upload/file-upload.router.js.map +1 -1
  33. package/dist/cjs/modules/swagger/swagger.router.js +8 -2
  34. package/dist/cjs/modules/swagger/swagger.router.js.map +1 -1
  35. package/dist/cjs/modules/swagger/utils/get-open-api-login-html.js +18 -0
  36. package/dist/cjs/modules/swagger/utils/get-open-api-login-html.js.map +1 -1
  37. package/dist/cjs/modules/swagger/utils/helpers/get-swagger-default-configs.js +5 -5
  38. package/dist/cjs/modules/swagger/utils/helpers/get-swagger-default-configs.js.map +1 -1
  39. package/dist/cjs/modules/swagger/utils/helpers/openapi-schema-converter.js +1 -1
  40. package/dist/cjs/modules/swagger/utils/helpers/openapi-schema-converter.js.map +1 -1
  41. package/dist/cjs/types/arkos-prisma-input.js.map +1 -1
  42. package/dist/cjs/types/index.js.map +1 -1
  43. package/dist/cjs/types/new-arkos-config.js.map +1 -1
  44. package/dist/cjs/types/router-config.js.map +1 -1
  45. package/dist/cjs/utils/arkos-router/arkos-router-openapi-manager.js +86 -28
  46. package/dist/cjs/utils/arkos-router/arkos-router-openapi-manager.js.map +1 -1
  47. package/dist/cjs/utils/arkos-router/index.js +11 -7
  48. package/dist/cjs/utils/arkos-router/index.js.map +1 -1
  49. package/dist/cjs/utils/arkos-router/types/index.js.map +1 -1
  50. package/dist/cjs/utils/arkos-router/types/upload-config.js.map +1 -1
  51. package/dist/cjs/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js +34 -28
  52. package/dist/cjs/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js.map +1 -1
  53. package/dist/cjs/utils/arkos-router/utils/helpers/index.js +9 -6
  54. package/dist/cjs/utils/arkos-router/utils/helpers/index.js.map +1 -1
  55. package/dist/cjs/utils/arkos-router/utils/helpers/upload-manager.js +334 -77
  56. package/dist/cjs/utils/arkos-router/utils/helpers/upload-manager.js.map +1 -1
  57. package/dist/cjs/utils/bundler.js.map +1 -1
  58. package/dist/cjs/utils/cli/build.js +2 -3
  59. package/dist/cjs/utils/cli/build.js.map +1 -1
  60. package/dist/cjs/utils/cli/dev.js +11 -6
  61. package/dist/cjs/utils/cli/dev.js.map +1 -1
  62. package/dist/cjs/utils/cli/export-auth-action.js +5 -4
  63. package/dist/cjs/utils/cli/export-auth-action.js.map +1 -1
  64. package/dist/cjs/utils/cli/generate.js +6 -8
  65. package/dist/cjs/utils/cli/generate.js.map +1 -1
  66. package/dist/cjs/utils/cli/index.js +22 -19
  67. package/dist/cjs/utils/cli/index.js.map +1 -1
  68. package/dist/cjs/utils/cli/start.js +4 -2
  69. package/dist/cjs/utils/cli/start.js.map +1 -1
  70. package/dist/cjs/utils/cli/utils/cli.helpers.js +1 -1
  71. package/dist/cjs/utils/cli/utils/template-generator/templates/generate-controller-template.js +19 -7
  72. package/dist/cjs/utils/cli/utils/template-generator/templates/generate-controller-template.js.map +1 -1
  73. package/dist/cjs/utils/cli/utils/template-generator/templates/generate-multiple-components.js +7 -6
  74. package/dist/cjs/utils/cli/utils/template-generator/templates/generate-multiple-components.js.map +1 -1
  75. package/dist/cjs/utils/cli/utils/template-generator/templates/policy-template.js +4 -4
  76. package/dist/cjs/utils/cli/utils/template-generator/templates/policy-template.js.map +1 -1
  77. package/dist/cjs/utils/cli/utils/template-generators.js +0 -6
  78. package/dist/cjs/utils/cli/utils/template-generators.js.map +1 -1
  79. package/dist/cjs/utils/define-config.js +5 -0
  80. package/dist/cjs/utils/define-config.js.map +1 -1
  81. package/dist/cjs/utils/dotenv.helpers.js +0 -6
  82. package/dist/cjs/utils/dotenv.helpers.js.map +1 -1
  83. package/dist/cjs/utils/features/api.features.js +23 -5
  84. package/dist/cjs/utils/features/api.features.js.map +1 -1
  85. package/dist/cjs/utils/helpers/arkos-config.helpers.js +22 -2
  86. package/dist/cjs/utils/helpers/arkos-config.helpers.js.map +1 -1
  87. package/dist/cjs/utils/helpers/exit-error.js +1 -0
  88. package/dist/cjs/utils/helpers/exit-error.js.map +1 -1
  89. package/dist/cjs/utils/helpers/fs.helpers.js +25 -24
  90. package/dist/cjs/utils/helpers/fs.helpers.js.map +1 -1
  91. package/dist/cjs/utils/helpers/global.helpers.js +3 -2
  92. package/dist/cjs/utils/helpers/global.helpers.js.map +1 -1
  93. package/dist/cjs/utils/helpers/prisma.helpers.js +4 -5
  94. package/dist/cjs/utils/helpers/prisma.helpers.js.map +1 -1
  95. package/dist/cjs/utils/helpers/url-helpers.js +14 -0
  96. package/dist/cjs/utils/helpers/url-helpers.js.map +1 -0
  97. package/dist/cjs/utils/initialize-app.js +35 -6
  98. package/dist/cjs/utils/initialize-app.js.map +1 -1
  99. package/dist/cjs/utils/prisma/prisma-json-schema-generator.js +12 -6
  100. package/dist/cjs/utils/prisma/prisma-json-schema-generator.js.map +1 -1
  101. package/dist/cjs/utils/prisma/prisma-schema-parser.js +10 -3
  102. package/dist/cjs/utils/prisma/prisma-schema-parser.js.map +1 -1
  103. package/dist/cjs/utils/setup-app.js +58 -41
  104. package/dist/cjs/utils/setup-app.js.map +1 -1
  105. package/dist/esm/app.js +6 -0
  106. package/dist/esm/app.js.map +1 -1
  107. package/dist/esm/exports/error-handler/index.js +1 -0
  108. package/dist/esm/exports/error-handler/index.js.map +1 -1
  109. package/dist/esm/modules/auth/auth.router.js +3 -0
  110. package/dist/esm/modules/auth/auth.router.js.map +1 -1
  111. package/dist/esm/modules/auth/auth.service.js +2 -0
  112. package/dist/esm/modules/auth/auth.service.js.map +1 -1
  113. package/dist/esm/modules/base/base.controller.js +15 -3
  114. package/dist/esm/modules/base/base.controller.js.map +1 -1
  115. package/dist/esm/modules/base/base.middlewares.js +19 -12
  116. package/dist/esm/modules/base/base.middlewares.js.map +1 -1
  117. package/dist/esm/modules/base/base.service.js +5 -1
  118. package/dist/esm/modules/base/base.service.js.map +1 -1
  119. package/dist/esm/modules/base/utils/helpers/base.service.helpers.js +9 -0
  120. package/dist/esm/modules/base/utils/helpers/base.service.helpers.js.map +1 -1
  121. package/dist/esm/modules/error-handler/error-handler.controller.js +22 -42
  122. package/dist/esm/modules/error-handler/error-handler.controller.js.map +1 -1
  123. package/dist/esm/modules/error-handler/utils/app-error.js +0 -1
  124. package/dist/esm/modules/error-handler/utils/app-error.js.map +1 -1
  125. package/dist/esm/modules/error-handler/utils/error-handler.helpers.js +8 -9
  126. package/dist/esm/modules/error-handler/utils/error-handler.helpers.js.map +1 -1
  127. package/dist/esm/modules/error-handler/utils/errors.js +127 -0
  128. package/dist/esm/modules/error-handler/utils/errors.js.map +1 -0
  129. package/dist/esm/modules/error-handler/utils/multer-error-handler.js +34 -0
  130. package/dist/esm/modules/error-handler/utils/multer-error-handler.js.map +1 -0
  131. package/dist/esm/modules/file-upload/file-upload.controller.js +10 -14
  132. package/dist/esm/modules/file-upload/file-upload.controller.js.map +1 -1
  133. package/dist/esm/modules/file-upload/file-upload.router.js +2 -0
  134. package/dist/esm/modules/file-upload/file-upload.router.js.map +1 -1
  135. package/dist/esm/modules/swagger/swagger.router.js +8 -2
  136. package/dist/esm/modules/swagger/swagger.router.js.map +1 -1
  137. package/dist/esm/modules/swagger/utils/get-open-api-login-html.js +18 -0
  138. package/dist/esm/modules/swagger/utils/get-open-api-login-html.js.map +1 -1
  139. package/dist/esm/modules/swagger/utils/helpers/get-swagger-default-configs.js +5 -5
  140. package/dist/esm/modules/swagger/utils/helpers/get-swagger-default-configs.js.map +1 -1
  141. package/dist/esm/modules/swagger/utils/helpers/openapi-schema-converter.js +1 -1
  142. package/dist/esm/modules/swagger/utils/helpers/openapi-schema-converter.js.map +1 -1
  143. package/dist/esm/types/arkos-prisma-input.js.map +1 -1
  144. package/dist/esm/types/index.js.map +1 -1
  145. package/dist/esm/types/new-arkos-config.js.map +1 -1
  146. package/dist/esm/types/router-config.js.map +1 -1
  147. package/dist/esm/utils/arkos-router/arkos-router-openapi-manager.js +86 -28
  148. package/dist/esm/utils/arkos-router/arkos-router-openapi-manager.js.map +1 -1
  149. package/dist/esm/utils/arkos-router/index.js +11 -7
  150. package/dist/esm/utils/arkos-router/index.js.map +1 -1
  151. package/dist/esm/utils/arkos-router/types/index.js.map +1 -1
  152. package/dist/esm/utils/arkos-router/types/upload-config.js.map +1 -1
  153. package/dist/esm/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js +34 -28
  154. package/dist/esm/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.js.map +1 -1
  155. package/dist/esm/utils/arkos-router/utils/helpers/index.js +9 -6
  156. package/dist/esm/utils/arkos-router/utils/helpers/index.js.map +1 -1
  157. package/dist/esm/utils/arkos-router/utils/helpers/upload-manager.js +334 -77
  158. package/dist/esm/utils/arkos-router/utils/helpers/upload-manager.js.map +1 -1
  159. package/dist/esm/utils/bundler.js.map +1 -1
  160. package/dist/esm/utils/cli/build.js +3 -4
  161. package/dist/esm/utils/cli/build.js.map +1 -1
  162. package/dist/esm/utils/cli/dev.js +12 -7
  163. package/dist/esm/utils/cli/dev.js.map +1 -1
  164. package/dist/esm/utils/cli/export-auth-action.js +5 -4
  165. package/dist/esm/utils/cli/export-auth-action.js.map +1 -1
  166. package/dist/esm/utils/cli/generate.js +6 -8
  167. package/dist/esm/utils/cli/generate.js.map +1 -1
  168. package/dist/esm/utils/cli/index.js +22 -19
  169. package/dist/esm/utils/cli/index.js.map +1 -1
  170. package/dist/esm/utils/cli/start.js +4 -2
  171. package/dist/esm/utils/cli/start.js.map +1 -1
  172. package/dist/esm/utils/cli/utils/cli.helpers.js +1 -1
  173. package/dist/esm/utils/cli/utils/template-generator/templates/generate-controller-template.js +16 -7
  174. package/dist/esm/utils/cli/utils/template-generator/templates/generate-controller-template.js.map +1 -1
  175. package/dist/esm/utils/cli/utils/template-generator/templates/generate-multiple-components.js +7 -6
  176. package/dist/esm/utils/cli/utils/template-generator/templates/generate-multiple-components.js.map +1 -1
  177. package/dist/esm/utils/cli/utils/template-generator/templates/policy-template.js +4 -4
  178. package/dist/esm/utils/cli/utils/template-generator/templates/policy-template.js.map +1 -1
  179. package/dist/esm/utils/cli/utils/template-generators.js +0 -6
  180. package/dist/esm/utils/cli/utils/template-generators.js.map +1 -1
  181. package/dist/esm/utils/define-config.js +5 -0
  182. package/dist/esm/utils/define-config.js.map +1 -1
  183. package/dist/esm/utils/dotenv.helpers.js +0 -6
  184. package/dist/esm/utils/dotenv.helpers.js.map +1 -1
  185. package/dist/esm/utils/features/api.features.js +23 -5
  186. package/dist/esm/utils/features/api.features.js.map +1 -1
  187. package/dist/esm/utils/helpers/arkos-config.helpers.js +20 -2
  188. package/dist/esm/utils/helpers/arkos-config.helpers.js.map +1 -1
  189. package/dist/esm/utils/helpers/exit-error.js +1 -0
  190. package/dist/esm/utils/helpers/exit-error.js.map +1 -1
  191. package/dist/esm/utils/helpers/fs.helpers.js +25 -24
  192. package/dist/esm/utils/helpers/fs.helpers.js.map +1 -1
  193. package/dist/esm/utils/helpers/global.helpers.js +1 -1
  194. package/dist/esm/utils/helpers/global.helpers.js.map +1 -1
  195. package/dist/esm/utils/helpers/prisma.helpers.js +4 -5
  196. package/dist/esm/utils/helpers/prisma.helpers.js.map +1 -1
  197. package/dist/esm/utils/helpers/url-helpers.js +11 -0
  198. package/dist/esm/utils/helpers/url-helpers.js.map +1 -0
  199. package/dist/esm/utils/initialize-app.js +35 -6
  200. package/dist/esm/utils/initialize-app.js.map +1 -1
  201. package/dist/esm/utils/prisma/prisma-json-schema-generator.js +12 -6
  202. package/dist/esm/utils/prisma/prisma-json-schema-generator.js.map +1 -1
  203. package/dist/esm/utils/prisma/prisma-schema-parser.js +10 -3
  204. package/dist/esm/utils/prisma/prisma-schema-parser.js.map +1 -1
  205. package/dist/esm/utils/setup-app.js +59 -42
  206. package/dist/esm/utils/setup-app.js.map +1 -1
  207. package/dist/types/app.d.ts +5 -6
  208. package/dist/types/exports/error-handler/index.d.ts +1 -0
  209. package/dist/types/modules/auth/auth.service.d.ts +2 -6
  210. package/dist/types/modules/base/base.service.d.ts +2 -1
  211. package/dist/types/modules/error-handler/utils/app-error.d.ts +0 -2
  212. package/dist/types/modules/error-handler/utils/error-handler.helpers.d.ts +1 -1
  213. package/dist/types/modules/error-handler/utils/errors.d.ts +176 -0
  214. package/dist/types/modules/error-handler/utils/multer-error-handler.d.ts +7 -0
  215. package/dist/types/modules/file-upload/file-upload.controller.d.ts +0 -1
  216. package/dist/types/modules/swagger/utils/helpers/get-swagger-default-configs.d.ts +48 -2
  217. package/dist/types/types/arkos-prisma-input.d.ts +3 -2
  218. package/dist/types/types/index.d.ts +0 -21
  219. package/dist/types/types/new-arkos-config.d.ts +183 -14
  220. package/dist/types/types/router-config.d.ts +1 -1
  221. package/dist/types/utils/arkos-router/arkos-router-openapi-manager.d.ts +14 -1
  222. package/dist/types/utils/arkos-router/index.d.ts +76 -8
  223. package/dist/types/utils/arkos-router/types/index.d.ts +19 -6
  224. package/dist/types/utils/arkos-router/types/upload-config.d.ts +63 -7
  225. package/dist/types/utils/arkos-router/utils/helpers/apply-arkos-router-proxy.d.ts +1 -1
  226. package/dist/types/utils/arkos-router/utils/helpers/index.d.ts +2 -0
  227. package/dist/types/utils/arkos-router/utils/helpers/upload-manager.d.ts +0 -36
  228. package/dist/types/utils/bundler.d.ts +1 -1
  229. package/dist/types/utils/cli/generate.d.ts +0 -1
  230. package/dist/types/utils/cli/start.d.ts +1 -1
  231. package/dist/types/utils/helpers/arkos-config.helpers.d.ts +2 -0
  232. package/dist/types/utils/helpers/fs.helpers.d.ts +1 -1
  233. package/dist/types/utils/helpers/global.helpers.d.ts +1 -0
  234. package/dist/types/utils/helpers/url-helpers.d.ts +1 -0
  235. package/dist/types/utils/prisma/prisma-schema-parser.d.ts +1 -0
  236. package/package.json +15 -15
  237. package/dist/cjs/utils/cli/utils/template-generator/templates/route-hook.template.js +0 -39
  238. package/dist/cjs/utils/cli/utils/template-generator/templates/route-hook.template.js.map +0 -1
  239. package/dist/cjs/utils/cli/utils/template-generator/templates/service-hook.template.js +0 -32
  240. package/dist/cjs/utils/cli/utils/template-generator/templates/service-hook.template.js.map +0 -1
  241. package/dist/esm/utils/cli/utils/template-generator/templates/route-hook.template.js +0 -36
  242. package/dist/esm/utils/cli/utils/template-generator/templates/route-hook.template.js.map +0 -1
  243. package/dist/esm/utils/cli/utils/template-generator/templates/service-hook.template.js +0 -29
  244. package/dist/esm/utils/cli/utils/template-generator/templates/service-hook.template.js.map +0 -1
  245. package/dist/types/utils/cli/utils/template-generator/templates/route-hook.template.d.ts +0 -2
  246. package/dist/types/utils/cli/utils/template-generator/templates/service-hook.template.d.ts +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"arkos-prisma-input.js","sourceRoot":"","sources":["../../../src/types/arkos-prisma-input.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Helper type to exclude properties from T that exist in U\n * Used internally by XOR to create mutually exclusive types\n */\ntype Without<T, U> = {\n [P in Exclude<keyof T, keyof U>]?: never;\n};\n/**\n * XOR (Exclusive OR) type for mutually exclusive union types\n * Ensures that properties from T and U cannot be mixed together\n * @see https://stackoverflow.com/questions/42123407/does-typescript-support-mutually-exclusive-types\n */\ntype XOR<T, U> = T extends object\n ? U extends object\n ? (Without<T, U> & U) | (Without<U, T> & T)\n : U\n : T;\ntype Unpack<T> = T;\n/**\n * Checks if a field is an array relation (one-to-many or many-to-many)\n * Identified by the presence of createMany property\n */\nexport type IsArrayRelation<T> =\n Exclude<T, undefined> extends never\n ? false\n : Exclude<T, undefined> extends { createMany?: any }\n ? true\n : false;\n/**\n * Checks if a field is an object relation (one-to-one or many-to-one)\n * Identified by the presence of relation operations without being an array\n */\nexport type IsObjectRelation<T> =\n Exclude<T, undefined> extends Array<any>\n ? false\n : Exclude<T, undefined> extends\n | {\n create?: any;\n }\n | {\n connect?: any;\n }\n | {\n connectOrCreate?: any;\n }\n | {\n update?: any;\n }\n | {\n delete?: any;\n }\n | {\n disconnect?: any;\n }\n ? true\n : false;\ntype ExtractCreateTypeArray<T> =\n Exclude<T, undefined> extends {\n create?: infer C;\n }\n ? Extract<C, Array<any>> extends Array<infer U>\n ? U extends Array<infer I>\n ? (Omit<I, \"OR\" | \"AND\" | \"NOT\"> & {\n apiAction?: \"create\";\n })[]\n : (Omit<U, \"OR\" | \"AND\" | \"NOT\"> & {\n apiAction?: \"create\";\n })[]\n : never\n : never;\ntype ExtractConnectTypeArray<\n T,\n A extends\n | \"connect\"\n | \"delete\"\n | \"update\"\n | \"disconnect\"\n | \"deleteMany\"\n | \"set\",\n> =\n Exclude<T, undefined> extends {\n [k in A]?: infer C;\n }\n ? Extract<C, Array<any>> extends Array<infer U>\n ? (Omit<U, \"OR\" | \"AND\" | \"NOT\"> & {\n apiAction?: A;\n })[]\n : never\n : never;\ntype ExtractUpdateTypeArray<T> =\n Exclude<T, undefined> extends Array<infer Item>\n ? Item extends {\n update?: infer U;\n }\n ? U extends Array<infer UpdateItem>\n ? UpdateItem extends {\n where: infer W;\n data: infer D;\n }\n ? ((W & D) & {\n apiAction?: \"update\";\n })[]\n : never\n : U extends {\n where: infer W;\n data: infer D;\n }\n ? ((W & D) & {\n apiAction?: \"update\";\n })[]\n : never\n : never\n : never;\ntype ExtractCreateTypeObject<T> =\n Exclude<T, undefined> extends {\n create?: infer C;\n }\n ? Exclude<\n Extract<Exclude<C, undefined>, object>,\n Array<any>\n > extends infer Obj\n ? Obj extends object\n ? Omit<Obj, \"OR\" | \"AND\" | \"NOT\"> & {\n apiAction?: \"create\";\n }\n : never\n : never\n : never;\ntype ExtractConnectTypeObject<\n T,\n A extends \"connect\" | \"delete\" | \"update\" | \"disconnect\",\n> =\n Exclude<T, undefined> extends {\n [k in A]?: infer C;\n }\n ? Exclude<\n Extract<Exclude<C, undefined>, object>,\n Array<any>\n > extends infer Obj\n ? Obj extends object\n ? Omit<Obj, \"OR\" | \"AND\" | \"NOT\"> & {\n apiAction?: A;\n }\n : never\n : never\n : never;\ntype ExtractUpdateTypeObject<T> =\n Exclude<T, undefined> extends {\n update?: infer U;\n }\n ? U extends {\n where: infer W;\n data: infer D;\n }\n ? (W & D) & {\n apiAction?: \"update\";\n }\n : Exclude<Extract<U, object>, Array<any>> & {\n apiAction?: \"update\";\n }\n : never;\ntype FlattenArrayRelation<T> =\n | (ExtractCreateTypeArray<T> extends never\n ? never\n : FlattenRelations<ExtractCreateTypeArray<T>>)\n | (ExtractConnectTypeArray<T, \"connect\"> extends never\n ? never\n : FlattenRelations<ExtractConnectTypeArray<T, \"connect\">>)\n | (ExtractUpdateTypeArray<T> extends never\n ? never\n : FlattenRelations<ExtractUpdateTypeArray<T>>)\n | (Exclude<T, undefined> extends Array<infer Item>\n ? Item extends {\n delete?: any;\n }\n ? FlattenRelations<ExtractConnectTypeArray<T, \"delete\">> & {\n apiAction: \"delete\";\n }\n : never\n : never)\n | (Exclude<T, undefined> extends Array<infer Item>\n ? Item extends {\n disconnect?: any;\n }\n ? FlattenRelations<ExtractConnectTypeArray<T, \"disconnect\">> & {\n apiAction: \"disconnect\";\n }\n : never\n : never)\n | (Exclude<T, undefined> extends Array<infer Item>\n ? Item extends {\n set?: infer S;\n }\n ? Unpack<S> & {\n apiAction?: \"set\";\n }\n : never\n : never)\n | (Exclude<T, undefined> extends Array<infer Item>\n ? Item extends {\n deleteMany?: any;\n }\n ? FlattenRelations<ExtractConnectTypeArray<T, \"deleteMany\">> & {\n apiAction: \"deleteMany\";\n }\n : never\n : never);\ntype FlattenObjectRelation<T> =\n | (ExtractCreateTypeObject<T> extends never\n ? never\n : FlattenRelations<ExtractCreateTypeObject<T>>)\n | (ExtractConnectTypeObject<T, \"connect\"> extends never\n ? never\n : FlattenRelations<ExtractConnectTypeObject<T, \"connect\">>)\n | (ExtractUpdateTypeObject<T> extends never\n ? never\n : FlattenRelations<ExtractUpdateTypeObject<T>>)\n | (Exclude<T, undefined> extends {\n delete?: any;\n }\n ? FlattenRelations<ExtractConnectTypeObject<T, \"delete\">> & {\n apiAction: \"delete\";\n }\n : never)\n | (Exclude<T, undefined> extends {\n disconnect?: any;\n }\n ? FlattenRelations<ExtractConnectTypeObject<T, \"disconnect\">> & {\n apiAction: \"disconnect\";\n }\n : never)\n | (Exclude<T, undefined> extends {\n set?: infer S;\n }\n ? Unpack<S> & {\n apiAction?: \"set\";\n }\n : never);\ntype StripPrismaFilters<T> = T extends\n | {\n equals?: any;\n }\n | {\n in?: any;\n }\n | {\n notIn?: any;\n }\n | {\n lt?: any;\n }\n | {\n lte?: any;\n }\n | {\n gt?: any;\n }\n | {\n gte?: any;\n }\n | {\n AND?: any;\n }\n | {\n OR?: any;\n }\n | {\n NOT?: any;\n }\n ? never\n : T;\ntype FlattenRelations<T> = {\n [K in keyof T]: IsArrayRelation<T[K]> extends true\n ? FlattenArrayRelation<T[K]>\n : IsObjectRelation<T[K]> extends true\n ? XOR<FlattenObjectRelation<T[K]>, T[K]>\n : StripPrismaFilters<T[K]> extends never\n ? never\n : T[K] extends object\n ? T[K] extends Date | null | undefined\n ? T[K]\n : FlattenRelations<StripPrismaFilters<T[K]>>\n : StripPrismaFilters<T[K]>;\n};\n/**\n * Flattens Prisma relation inputs into a simpler, developer-friendly format\n *\n * Transforms Prisma's nested relation format:\n * ```typescript\n * { posts: { create: [...], connect: [...], update: [...] } }\n * ```\n *\n * Into a flattened format with optional apiAction discriminators:\n * ```typescript\n * { posts: [\n * { title: \"New Post\" }, // auto-detected as create\n * { id: 1 }, // auto-detected as connect\n * { id: 2, title: \"Updated\", apiAction: \"update\" }\n * ]}\n * ```\n *\n * @see {@link https://wwww.arkosjs.com/docs/reference/arkos-prisma-input}\n * @template T - The Prisma input type (e.g., Prisma.UserCreateInput)\n * @returns A flattened version of the input type with simplified relation handling\n */\nexport type ArkosPrismaInput<T> = FlattenRelations<T>;\n"]}
1
+ {"version":3,"file":"arkos-prisma-input.js","sourceRoot":"","sources":["../../../src/types/arkos-prisma-input.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Helper type to exclude properties from T that exist in U\n * Used internally by XOR to create mutually exclusive types\n */\ntype Without<T, U> = {\n [P in Exclude<keyof T, keyof U>]?: never;\n};\n/**\n * XOR (Exclusive OR) type for mutually exclusive union types\n * Ensures that properties from T and U cannot be mixed together\n * @see https://stackoverflow.com/questions/42123407/does-typescript-support-mutually-exclusive-types\n */\ntype XOR<T, U> = T extends object\n ? U extends object\n ? (Without<T, U> & U) | (Without<U, T> & T)\n : U\n : T;\ntype Unpack<T> = T;\n/**\n * Checks if a field is an array relation (one-to-many or many-to-many)\n * Identified by the presence of createMany property\n */\nexport type IsArrayRelation<T> =\n Exclude<T, undefined> extends never\n ? false\n : Exclude<T, undefined> extends { createMany?: any }\n ? true\n : false;\n/**\n * Checks if a field is an object relation (one-to-one or many-to-one)\n * Identified by the presence of relation operations without being an array\n */\nexport type IsObjectRelation<T> =\n Exclude<T, undefined> extends Array<any>\n ? false\n : Exclude<T, undefined> extends\n | {\n create?: any;\n }\n | {\n connect?: any;\n }\n | {\n connectOrCreate?: any;\n }\n | {\n update?: any;\n }\n | {\n delete?: any;\n }\n | {\n disconnect?: any;\n }\n ? true\n : false;\ntype ExtractCreateTypeArray<T> =\n Exclude<T, undefined> extends {\n create?: infer C;\n }\n ? Extract<C, Array<any>> extends Array<infer U>\n ? U extends Array<infer I>\n ? (Omit<I, \"OR\" | \"AND\" | \"NOT\"> & {\n apiAction?: \"create\";\n })[]\n : (Omit<U, \"OR\" | \"AND\" | \"NOT\"> & {\n apiAction?: \"create\";\n })[]\n : never\n : never;\ntype ExtractConnectTypeArray<\n T,\n A extends\n | \"connect\"\n | \"delete\"\n | \"update\"\n | \"disconnect\"\n | \"deleteMany\"\n | \"set\",\n> =\n Exclude<T, undefined> extends {\n [k in A]?: infer C;\n }\n ? Extract<C, Array<any>> extends Array<infer U>\n ? (Omit<U, \"OR\" | \"AND\" | \"NOT\"> & {\n apiAction?: A;\n })[]\n : never\n : never;\ntype ExtractUpdateTypeArray<T> =\n Exclude<T, undefined> extends Array<infer Item>\n ? Item extends {\n update?: infer U;\n }\n ? U extends Array<infer UpdateItem>\n ? UpdateItem extends {\n where: infer W;\n data: infer D;\n }\n ? ((W & D) & {\n apiAction?: \"update\";\n })[]\n : never\n : U extends {\n where: infer W;\n data: infer D;\n }\n ? ((W & D) & {\n apiAction?: \"update\";\n })[]\n : never\n : never\n : never;\ntype ExtractCreateTypeObject<T> =\n Exclude<T, undefined> extends {\n create?: infer C;\n }\n ? Exclude<\n Extract<Exclude<C, undefined>, object>,\n Array<any>\n > extends infer Obj\n ? Obj extends object\n ? Omit<Obj, \"OR\" | \"AND\" | \"NOT\"> & {\n apiAction?: \"create\";\n }\n : never\n : never\n : never;\ntype ExtractConnectTypeObject<\n T,\n A extends \"connect\" | \"delete\" | \"update\" | \"disconnect\",\n> =\n Exclude<T, undefined> extends {\n [k in A]?: infer C;\n }\n ? Exclude<\n Extract<Exclude<C, undefined>, object>,\n Array<any>\n > extends infer Obj\n ? Obj extends object\n ? Omit<Obj, \"OR\" | \"AND\" | \"NOT\"> & {\n apiAction?: A;\n }\n : never\n : never\n : never;\ntype ExtractUpdateTypeObject<T> =\n Exclude<T, undefined> extends {\n update?: infer U;\n }\n ? U extends {\n where: infer W;\n data: infer D;\n }\n ? (W & D) & {\n apiAction?: \"update\";\n }\n : Exclude<Extract<U, object>, Array<any>> & {\n apiAction?: \"update\";\n }\n : never;\ntype FlattenArrayRelation<T> =\n | (ExtractCreateTypeArray<T> extends never\n ? never\n : FlattenRelations<ExtractCreateTypeArray<T>>)\n | (ExtractConnectTypeArray<T, \"connect\"> extends never\n ? never\n : FlattenRelations<ExtractConnectTypeArray<T, \"connect\">>)\n | (ExtractUpdateTypeArray<T> extends never\n ? never\n : FlattenRelations<ExtractUpdateTypeArray<T>>)\n | (Exclude<T, undefined> extends Array<infer Item>\n ? Item extends {\n delete?: any;\n }\n ? FlattenRelations<ExtractConnectTypeArray<T, \"delete\">> & {\n apiAction: \"delete\";\n }\n : never\n : never)\n | (Exclude<T, undefined> extends Array<infer Item>\n ? Item extends {\n disconnect?: any;\n }\n ? FlattenRelations<ExtractConnectTypeArray<T, \"disconnect\">> & {\n apiAction: \"disconnect\";\n }\n : never\n : never)\n | (Exclude<T, undefined> extends Array<infer Item>\n ? Item extends {\n set?: infer S;\n }\n ? Unpack<S> & {\n apiAction?: \"set\";\n }\n : never\n : never)\n | (Exclude<T, undefined> extends Array<infer Item>\n ? Item extends {\n deleteMany?: any;\n }\n ? FlattenRelations<ExtractConnectTypeArray<T, \"deleteMany\">> & {\n apiAction: \"deleteMany\";\n }\n : never\n : never);\ntype FlattenObjectRelation<T> =\n | (ExtractCreateTypeObject<T> extends never\n ? never\n : FlattenRelations<ExtractCreateTypeObject<T>>)\n | (ExtractConnectTypeObject<T, \"connect\"> extends never\n ? never\n : FlattenRelations<ExtractConnectTypeObject<T, \"connect\">>)\n | (ExtractUpdateTypeObject<T> extends never\n ? never\n : FlattenRelations<ExtractUpdateTypeObject<T>>)\n | (Exclude<T, undefined> extends {\n delete?: any;\n }\n ? FlattenRelations<ExtractConnectTypeObject<T, \"delete\">> & {\n apiAction: \"delete\";\n }\n : never)\n | (Exclude<T, undefined> extends {\n disconnect?: any;\n }\n ? FlattenRelations<ExtractConnectTypeObject<T, \"disconnect\">> & {\n apiAction: \"disconnect\";\n }\n : never)\n | (Exclude<T, undefined> extends {\n set?: infer S;\n }\n ? Unpack<S> & {\n apiAction?: \"set\";\n }\n : never);\ntype StripPrismaFilters<T> = T extends\n | { equals?: any }\n | { in?: any }\n | { notIn?: any }\n | { lt?: any }\n | { lte?: any }\n | { gt?: any }\n | { gte?: any }\n | { AND?: any }\n | { OR?: any }\n | { NOT?: any }\n ? Omit<\n T,\n | \"equals\"\n | \"in\"\n | \"notIn\"\n | \"lt\"\n | \"lte\"\n | \"gt\"\n | \"gte\"\n | \"AND\"\n | \"OR\"\n | \"NOT\"\n >\n : T;\n\ntype StripToScalar<T> = T extends\n | string\n | number\n | boolean\n | Date\n | null\n | undefined\n ? T\n : never;\n\ntype FlattenRelations<T> = {\n [K in keyof T]: IsArrayRelation<T[K]> extends true\n ? FlattenArrayRelation<T[K]> | undefined\n : IsObjectRelation<T[K]> extends true\n ? XOR<FlattenObjectRelation<T[K]> | undefined, T[K]>\n : StripPrismaFilters<T[K]> extends never\n ? never\n : T[K] extends object\n ? T[K] extends Date | null | undefined\n ? T[K]\n : FlattenRelations<StripPrismaFilters<T[K]>> | undefined\n : StripToScalar<T[K]> extends never\n ? StripPrismaFilters<T[K]>\n : StripToScalar<T[K]>;\n};\n/**\n * Flattens Prisma relation inputs into a simpler, developer-friendly format\n *\n * Transforms Prisma's nested relation format:\n * ```typescript\n * { posts: { create: [...], connect: [...], update: [...] } }\n * ```\n *\n * Into a flattened format with optional apiAction discriminators:\n * ```typescript\n * { posts: [\n * { title: \"New Post\" }, // auto-detected as create\n * { id: 1 }, // auto-detected as connect\n * { id: 2, title: \"Updated\", apiAction: \"update\" }\n * ]}\n * ```\n *\n * @see {@link https://wwww.arkosjs.com/docs/reference/arkos-prisma-input}\n * @template T - The Prisma input type (e.g., Prisma.UserCreateInput)\n * @returns A flattened version of the input type with simplified relation handling\n */\nexport type ArkosPrismaInput<T> = FlattenRelations<T>;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"","sourcesContent":["import { NextFunction, Response, Request } from \"express\";\nimport { PrismaModels } from \"../generated\";\n\n/**\n * Type definition for authentication-related Prisma query operations\n * @template T - The Prisma model delegate type\n */\nexport type AuthPrismaQueryOptions<T extends Record<string, any>> = {\n // User profile endpoints\n /**\n * Options for retrieving the current authenticated user's profile\n */\n getMe?: Partial<Parameters<T[\"findUnique\"]>[0]>;\n /**\n * Options for updating the current authenticated user's profile\n */\n updateMe?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for soft deleting or deactivating the current authenticated user's account\n */\n deleteMe?: Partial<Parameters<T[\"update\"]>[0]>;\n // Authentication endpoints\n /**\n * Options for user login authentication queries\n */\n login?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n /**\n * Options for user registration and account creation\n */\n signup?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * Options for updating the current authenticated user's password\n */\n updatePassword?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for finding multiple auth actions\n */\n findManyAuthAction?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Options for finding a single auth action\n */\n findOneAuthAction?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n};\n\n/**\n * Base Prisma query options for standard CRUD operations\n * @template T - The Prisma model delegate type\n */\ntype BasePrismaQueryOptions<T extends Record<string, any>> = {\n /**\n * @deprecated Use `global` instead for general query options\n */\n queryOptions?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Global query options that can be used for all operations\n * Replaces the deprecated queryOptions\n */\n global?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * General find options for findMany and findOne operations\n */\n find?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * General create options for createOne and createMany operations\n */\n create?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * General update options for updateOne and updateMany operations\n */\n update?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * General delete options for deleteOne and deleteMany operations\n */\n delete?: Partial<Parameters<T[\"delete\"]>[0]>;\n /**\n * General save options for createOne, createMany, updateOne, updateMany operations\n */\n save?:\n | Partial<Parameters<T[\"create\"]>[0]>\n | Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Save options for single record operations (createOne, updateOne)\n */\n saveOne?:\n | Partial<Parameters<T[\"create\"]>[0]>\n | Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Save options for multiple record operations (createMany, updateMany)\n */\n saveMany?:\n | Partial<Parameters<T[\"createMany\"]>[0]>\n | Partial<Parameters<T[\"updateMany\"]>[0]>;\n /**\n * Options for finding a single record (first match)\n */\n findOne?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n /**\n * Options for finding multiple records\n */\n findMany?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Options for creating a single record\n */\n createOne?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * Options for creating multiple records\n */\n createMany?: Partial<Parameters<T[\"createMany\"]>[0]>;\n /**\n * Options for updating a single record\n */\n updateOne?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for updating multiple records\n */\n updateMany?: Partial<Parameters<T[\"updateMany\"]>[0]>;\n /**\n * Options for deleting a single record\n */\n deleteOne?: Partial<Parameters<T[\"delete\"]>[0]>;\n /**\n * Options for deleting multiple records\n */\n deleteMany?: Partial<Parameters<T[\"deleteMany\"]>[0]>;\n};\n\n/**\n * Type definition for Prisma query operations with flexible options\n * Conditionally provides auth-specific options when ModelName is \"auth\"\n * @template T - The Prisma model delegate type\n * @template ModelName - The model name (defaults to string for standard models)\n */\nexport type PrismaQueryOptions<\n T extends Record<string, any>,\n ModelName extends string = string,\n> = ModelName extends \"auth\"\n ? AuthPrismaQueryOptions<T>\n : BasePrismaQueryOptions<T>;\n\nexport interface BaseUser extends Record<string, any> {\n id: string;\n isSuperUser: boolean;\n password: string;\n passwordChangedAt?: Date;\n deletedSelfAccountAt: Date;\n isActive: boolean;\n}\n\ntype UserModelPayload =\n PrismaModels<{}> extends { user: infer U }\n ? U extends { GetPayload: infer P }\n ? P\n : never\n : never;\n\nexport type User = UserModelPayload extends never ? BaseUser : UserModelPayload;\n\nexport type UserRole = User extends { roles: infer R extends any[] }\n ? R[number]\n : User extends { role: infer R }\n ? R\n : string;\n\nexport interface ArkosRequest<\n P extends Record<string, any> = any,\n ResBody = any,\n ReqBody = any,\n Query extends Record<string, any> = any,\n> extends Request<P, ResBody, ReqBody, Query> {\n /**\n * Request signals used to control Arkos's built-in request handling pipeline.\n *\n * @since v1.6.0-beta\n */\n signals?: {\n /**\n * When set to `true` in a `before` hook, Arkos skips its built-in logic for the current pipeline step (e.g. CRUD, authentication, authorization).\n * Automatically reset to `false` after the step completes.\n *\n * @example\n * ```ts\n * before: (req, res, next) => {\n * req.user = myCustomAuth(req);\n * req.signals.skip = true;\n * next();\n * }\n * ```\n */\n skip?: boolean;\n };\n /**\n * Authenticated user\n */\n user?: User;\n /**\n * Single uploaded file, populated when using `multer.single()`\n */\n file?: Express.Multer.File;\n /**\n * Uploaded files, populated when using `multer.array()` or `multer.fields()`.\n *\n */\n files?: Express.Multer.File[] | Record<string, Express.Multer.File[]>;\n\n /**\n * Fields to include in relational queries\n */\n relationFields?: Record<string, boolean>;\n\n /**\n * Prisma include options for related data\n */\n include?: Record<string, any>;\n\n /**\n * Data to be sent in the response\n */\n responseData?: Record<string, any> | null;\n\n /**\n * Additional context data\n */\n additionalData?: Record<string, any> | null;\n\n /**\n * HTTP status code for the response\n */\n responseStatus?: number;\n\n /**\n * Typed request body\n */\n body: ReqBody;\n\n /**\n * Prisma query options (where, orderBy, select, etc.)\n */\n prismaQueryOptions?: Record<string, any>;\n\n /**\n * Typed query parameters\n */\n query: Query;\n\n /**\n * JWT token used in authentication process\n */\n accessToken?: string;\n\n /**\n * Query parameters after being handled and transformed by middleware\n */\n transformedQuery?: Record<string, any>;\n\n /**\n * Processed filters from APIFeatures.filters\n */\n filters?: Record<string, any>;\n\n /**\n * Name of the Prisma model being queried\n */\n modelName?: string;\n}\n\nexport interface ArkosResponse<\n ResBody = any,\n Locals extends Record<string, any> = Record<string, any>,\n> extends Response<ResBody, Locals> {}\n\nexport interface ArkosNextFunction extends NextFunction {}\n\nexport type ArkosRequestHandler<\n P extends Record<string, any> = any,\n ResBody = any,\n ReqBody = any,\n ReqQuery extends Record<string, any> = any,\n Locals extends Record<string, any> = Record<string, any>,\n> = (\n req: ArkosRequest<P, ResBody, ReqBody, ReqQuery>,\n res: ArkosResponse<ResBody, Locals>,\n next: ArkosNextFunction\n) => void | Promise<void>;\n\nexport type ArkosErrorRequestHandler<\n P extends Record<string, any> = any,\n ResBody = any,\n ReqBody = any,\n ReqQuery extends Record<string, any> = any,\n Locals extends Record<string, any> = Record<string, any>,\n> = (\n err: any,\n req: ArkosRequest<P, ResBody, ReqBody, ReqQuery>,\n res: ArkosResponse<ResBody, Locals>,\n next: ArkosNextFunction\n) => void | Promise<void>;\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"","sourcesContent":["import { NextFunction, Response, Request } from \"express\";\nimport { PrismaModels } from \"../generated\";\n\n/**\n * Type definition for authentication-related Prisma query operations\n * @template T - The Prisma model delegate type\n */\nexport type AuthPrismaQueryOptions<T extends Record<string, any>> = {\n // User profile endpoints\n /**\n * Options for retrieving the current authenticated user's profile\n */\n getMe?: Partial<Parameters<T[\"findUnique\"]>[0]>;\n /**\n * Options for updating the current authenticated user's profile\n */\n updateMe?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for soft deleting or deactivating the current authenticated user's account\n */\n deleteMe?: Partial<Parameters<T[\"update\"]>[0]>;\n // Authentication endpoints\n /**\n * Options for user login authentication queries\n */\n login?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n /**\n * Options for user registration and account creation\n */\n signup?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * Options for updating the current authenticated user's password\n */\n updatePassword?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for finding multiple auth actions\n */\n findManyAuthAction?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Options for finding a single auth action\n */\n findOneAuthAction?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n};\n\n/**\n * Base Prisma query options for standard CRUD operations\n * @template T - The Prisma model delegate type\n */\ntype BasePrismaQueryOptions<T extends Record<string, any>> = {\n /**\n * @deprecated Use `global` instead for general query options\n */\n queryOptions?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Global query options that can be used for all operations\n * Replaces the deprecated queryOptions\n */\n global?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * General find options for findMany and findOne operations\n */\n find?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * General create options for createOne and createMany operations\n */\n create?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * General update options for updateOne and updateMany operations\n */\n update?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * General delete options for deleteOne and deleteMany operations\n */\n delete?: Partial<Parameters<T[\"delete\"]>[0]>;\n /**\n * General save options for createOne, createMany, updateOne, updateMany operations\n */\n save?:\n | Partial<Parameters<T[\"create\"]>[0]>\n | Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Save options for single record operations (createOne, updateOne)\n */\n saveOne?:\n | Partial<Parameters<T[\"create\"]>[0]>\n | Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Save options for multiple record operations (createMany, updateMany)\n */\n saveMany?:\n | Partial<Parameters<T[\"createMany\"]>[0]>\n | Partial<Parameters<T[\"updateMany\"]>[0]>;\n /**\n * Options for finding a single record (first match)\n */\n findOne?: Partial<Parameters<T[\"findFirst\"]>[0]>;\n /**\n * Options for finding multiple records\n */\n findMany?: Partial<Parameters<T[\"findMany\"]>[0]>;\n /**\n * Options for creating a single record\n */\n createOne?: Partial<Parameters<T[\"create\"]>[0]>;\n /**\n * Options for creating multiple records\n */\n createMany?: Partial<Parameters<T[\"createMany\"]>[0]>;\n /**\n * Options for updating a single record\n */\n updateOne?: Partial<Parameters<T[\"update\"]>[0]>;\n /**\n * Options for updating multiple records\n */\n updateMany?: Partial<Parameters<T[\"updateMany\"]>[0]>;\n /**\n * Options for deleting a single record\n */\n deleteOne?: Partial<Parameters<T[\"delete\"]>[0]>;\n /**\n * Options for deleting multiple records\n */\n deleteMany?: Partial<Parameters<T[\"deleteMany\"]>[0]>;\n};\n\n/**\n * Type definition for Prisma query operations with flexible options\n * Conditionally provides auth-specific options when ModelName is \"auth\"\n * @template T - The Prisma model delegate type\n * @template ModelName - The model name (defaults to string for standard models)\n */\nexport type PrismaQueryOptions<\n T extends Record<string, any>,\n ModelName extends string = string,\n> = ModelName extends \"auth\"\n ? AuthPrismaQueryOptions<T>\n : BasePrismaQueryOptions<T>;\n\nexport interface BaseUser extends Record<string, any> {\n id: string;\n isSuperUser: boolean;\n password: string;\n passwordChangedAt?: Date;\n deletedSelfAccountAt: Date;\n isActive: boolean;\n}\n\ntype UserModelPayload =\n PrismaModels<{}> extends { user: infer U }\n ? U extends { GetPayload: infer P }\n ? P\n : never\n : never;\n\nexport type User = UserModelPayload extends never ? BaseUser : UserModelPayload;\n\nexport type UserRole = User extends { roles: infer R extends any[] }\n ? R[number]\n : User extends { role: infer R }\n ? R\n : string;\n\nexport interface ArkosRequest<\n P extends Record<string, any> = any,\n ResBody = any,\n ReqBody = any,\n Query extends Record<string, any> = any,\n> extends Request<P, ResBody, ReqBody, Query> {\n // /**\n // * Request signals used to control Arkos's built-in request handling pipeline.\n // *\n // * @since v1.6.0-beta\n // */\n // signals?: {\n // /**\n // * When set to `true` in a `before` hook, Arkos skips its built-in logic for the current pipeline step (e.g. CRUD, authentication, authorization).\n // * Automatically reset to `false` after the step completes.\n // *\n // * @example\n // * ```ts\n // * before: (req, res, next) => {\n // * req.user = myCustomAuth(req);\n // * req.signals.skip = true;\n // * next();\n // * }\n // * ```\n // */\n // skip?: boolean;\n // };\n /**\n * Authenticated user\n */\n user?: User;\n /**\n * Single uploaded file, populated when using `multer.single()`\n */\n file?: Express.Multer.File;\n /**\n * Uploaded files, populated when using `multer.array()` or `multer.fields()`.\n *\n */\n files?: Express.Multer.File[] | Record<string, Express.Multer.File[]>;\n\n /**\n * Fields to include in relational queries\n */\n relationFields?: Record<string, boolean>;\n\n /**\n * Prisma include options for related data\n */\n include?: Record<string, any>;\n\n /**\n * Data to be sent in the response\n */\n responseData?: Record<string, any> | null;\n\n /**\n * Additional context data\n */\n additionalData?: Record<string, any> | null;\n\n /**\n * HTTP status code for the response\n */\n responseStatus?: number;\n\n /**\n * Typed request body\n */\n body: ReqBody;\n\n /**\n * Prisma query options (where, orderBy, select, etc.)\n */\n prismaQueryOptions?: Record<string, any>;\n\n /**\n * Typed query parameters\n */\n query: Query;\n\n /**\n * JWT token used in authentication process\n */\n accessToken?: string;\n\n /**\n * Query parameters after being handled and transformed by middleware\n */\n transformedQuery?: Record<string, any>;\n\n /**\n * Processed filters from APIFeatures.filters\n */\n filters?: Record<string, any>;\n\n /**\n * Name of the Prisma model being queried\n */\n modelName?: string;\n}\n\nexport interface ArkosResponse<\n ResBody = any,\n Locals extends Record<string, any> = Record<string, any>,\n> extends Response<ResBody, Locals> {}\n\nexport interface ArkosNextFunction extends NextFunction {}\n\nexport type ArkosRequestHandler<\n P extends Record<string, any> = any,\n ResBody = any,\n ReqBody = any,\n ReqQuery extends Record<string, any> = any,\n Locals extends Record<string, any> = Record<string, any>,\n> = (\n req: ArkosRequest<P, ResBody, ReqBody, ReqQuery>,\n res: ArkosResponse<ResBody, Locals>,\n next: ArkosNextFunction\n) => void | Promise<void>;\n\nexport type ArkosErrorRequestHandler<\n P extends Record<string, any> = any,\n ResBody = any,\n ReqBody = any,\n ReqQuery extends Record<string, any> = any,\n Locals extends Record<string, any> = Record<string, any>,\n> = (\n err: any,\n req: ArkosRequest<P, ResBody, ReqBody, ReqQuery>,\n res: ArkosResponse<ResBody, Locals>,\n next: ArkosNextFunction\n) => void | Promise<void>;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"new-arkos-config.js","sourceRoot":"","sources":["../../../src/types/new-arkos-config.ts"],"names":[],"mappings":"","sourcesContent":["import cors from \"cors\";\nimport express from \"express\";\nimport { Options as RateLimitOptions } from \"express-rate-limit\";\nimport cookieParser from \"cookie-parser\";\nimport compression from \"compression\";\nimport { Options as QueryParserOptions } from \"../utils/helpers/query-parser.helpers\";\nimport { ValidatorOptions } from \"class-validator\";\nimport { MsDuration } from \"../modules/auth/utils/helpers/auth.controller.helpers\";\nimport { OpenAPIV3 } from \"openapi-types\";\nimport type { ApiReferenceConfiguration } from \"@scalar/express-api-reference\" with { \"resolution-mode\": \"import\" };\nimport nodemailer from \"nodemailer\";\nimport { ArkosRequestHandler } from \".\";\nimport { PrismaClient } from \"../generated\";\nimport {\n AuthenticateHookHandler,\n AuthenticateAfterHookHandler,\n AuthenticateErrorHookHandler,\n AuthorizeHookHandler,\n AuthorizeAfterHookHandler,\n AuthorizeErrorHookHandler,\n} from \"./arkos-config/utils\";\n\n/**\n * Defines the initial configs of the api to be loaded at startup when arkos.init() is called.\n */\nexport type ArkosConfig = {\n /**\n * The global prefixer for the whole application\n *\n * @default \"/api\"\n */\n readonly globalPrefix?: string;\n /**\n * Allows to configure request configs\n */\n request?: {\n /**\n * Allows to configure request parameters\n */\n parameters?: {\n /**\n * Toggles allowing `VERY DANGEROUS` request paramateres under `req.query` for passing prisma query options.\n *\n * See more\n */\n allowDangerousPrismaQueryOptions?: boolean;\n };\n };\n /** Message you would like to send, as Json and 200 response when\n * ```curl\n * GET /api\n * ```\n *\n * ```json\n * { \"message\": \"Welcome to YourAppName\" }\n * ```\n *\n * default message is: Welcome to our Rest API generated by Arkos, find more about Arkos at www.arkosjs.com.\n *\n *\n * */\n welcomeMessage?: string;\n /**\n * Port where the application will run, can be set in 3 ways:\n *\n * 1. default is 8000\n * 2. PORT under environment variables (Lower precedence)\n * 3. this config option (Higher precedence)\n */\n port?: number | undefined;\n /**\n * Allows to listen on a different host than localhost only\n */\n host?: string;\n /**\n * Defines authentication related configurations, by default is undefined.\n *\n * See [www.arkosjs.com/docs/core-concepts/authentication/setup](https://www.arkosjs.com/docs/core-concepts/authentication/setup) for details.\n */\n authentication?: {\n /**\n * Lifecycle hooks for the built-in authentication and authorization pipeline.\n *\n * These hooks only apply to **auto-generated Arkos routes**. On custom routes using\n * `authService.authenticate` directly, chain them manually as standard middlewares.\n *\n * Hooks run as standard Express middlewares — call `next()` to continue or\n * `next(error)` to abort and forward to the global error handler.\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/authentication/hooks}\n */\n hooks?: {\n authenticate?: {\n /**\n * Runs before JWT extraction and verification.\n *\n * @example\n * ```ts\n * before: ({ req, skip, action, resource, rule }) => {\n * req.authContext = { startedAt: Date.now() };\n * }\n * ```\n *\n * @example Skip core logic entirely (e.g. custom auth)\n * ```ts\n * before: ({ req, skip, action, resource, rule }) => {\n * req.user = myCustomAuth(req);\n * skip();\n * }\n * ```\n */\n before?: AuthenticateHookHandler | AuthenticateHookHandler[];\n\n /**\n * Runs after `req.user` has been set.\n *\n * @example\n * ```ts\n * after: ({ req }) => {\n * if (!req.user.hasChangedPassword) {\n * throw new AppError(\"Password change required.\", 403, \"PasswordChangeRequired\");\n * }\n * }\n * ```\n */\n after?: AuthenticateAfterHookHandler | AuthenticateAfterHookHandler[];\n\n /**\n * Runs when authentication throws — invalid token, expired token, user not found, etc.\n * Throw to forward to the global error handler, or call `skip()` to suppress and jump to `after` hooks.\n *\n * @example\n * ```ts\n * onError: ({ req, error, skip, action, resource, rule }) => {\n * console.warn(`Auth failed:`, error);\n * throw error;\n * }\n * ```\n *\n * @example Suppress error and continue\n * ```ts\n * onError: ({ req, skip, action, resource, rule }) => {\n * req.user = guestUser;\n * skip();\n * }\n * ```\n */\n onError?: AuthenticateErrorHookHandler | AuthenticateErrorHookHandler[];\n };\n\n authorize?: {\n /**\n * Runs before the role/permission check.\n *\n * @example\n * ```ts\n * before: ({ req }) => {\n * if (req.headers[\"x-elevated-access\"] === process.env.ELEVATION_KEY) {\n * req.user.role = \"admin\";\n * }\n * }\n * ```\n *\n * @example Skip permission check entirely\n * ```ts\n * before: ({ req, skip, action, resource, rule }) => {\n * req.user.role = myCustomRoleResolver(req);\n * skip();\n * }\n * ```\n */\n before?: AuthorizeHookHandler | AuthorizeHookHandler[];\n\n /**\n * Runs after the permission check passes.\n *\n * @example\n * ```ts\n * after: ({ req }) => {\n * auditLog.record({ userId: req.user.id, path: req.path });\n * }\n * ```\n */\n after?: AuthorizeAfterHookHandler | AuthorizeAfterHookHandler[];\n\n /**\n * Runs when the user lacks sufficient permissions (403).\n * Throw to forward to the global error handler, or call `skip()` to suppress and jump to `after` hooks.\n *\n * @example\n * ```ts\n * onError: ({ req, error, action, resource, rule }) => {\n * auditLog.record({ userId: req.user?.id, reason: \"insufficient_permissions\" });\n * throw error;\n * }\n * ```\n *\n * @example Suppress error and continue\n * ```ts\n * onError: ({ req, skip, action, resource, rule }) => {\n * req.user.role = \"guest\";\n * skip();\n * }\n * ```\n */\n onError?: AuthorizeErrorHookHandler | AuthorizeErrorHookHandler[];\n };\n };\n enabled?: boolean;\n /**\n * Defines whether to use Static or Dynamic Role-Based Acess Control\n *\n * Visit [www.arkosjs.com/docs/core-concepts/authentication/setup](https://www.arkosjs.com/docs/core-concepts/authentication/setup) for more details.\n */\n mode: \"static\" | \"dynamic\";\n /**\n * Defines auth login related configurations to customize the api.\n */\n login?: {\n /**\n * Defines the field that will be used as username by the built-in auth system, by default arkos will look for the field \"username\" in your model User, hence when making login for example you must send:\n *\n * ```json\n * {\n * \"username\": \"johndoe\",\n * \"password\": \"somePassword123\"\n * }\n * ```\n *\n * **Note:** You can also modify the usernameField on the fly by passing it to the request query parameters. example:\n *\n * ```curl\n * POST /api/auth/login?usernameField=email\n * ```\n *\n * See more at [www.arkosjs.com/docs/core-concepts/authentication/setup#login-with-different-fileds](https://www.arkosjs.com/docs/core-concepts/authentication/setup#login-with-different-fileds)\n *\n * By specifing here another field for username, for example passing \"email\", \"companyCode\" or something else your json will be like:\n *\n * **Example with email**\n *\n * ```json\n * {\n * \"email\": \"john.doe@example.com\",\n * \"password\": \"somePassword123\"\n * }\n * ```\n */\n allowedUsernames?: string[];\n /** Defines wether to send the access token in response after login or only send as cookie, defeault is both.*/\n sendAccessTokenThrough?: \"cookie-only\" | \"response-only\" | \"both\";\n };\n /**\n * Specifies the regex pattern used by the authentication system to enforce password strength requirements.\n *\n * **Important**: If using validation libraries like Zod or class-validator, this will be completely overwritten.\n *\n * **Default**: ```/^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d).+$/``` - Ensures the password contains at least one uppercase letter, one lowercase letter, and one numeric digit.\n *\n * **message**: (Optional) A custom error message to display when the password does not meet the required strength criteria.\n * @deprecated will stop working on v2.0\n */\n passwordValidation?: { regex: RegExp; message?: string };\n /**\n * Allows to specify the request rate limit for all authentication endpoints but `/api/users/me`.\n * \n * #### Default\n *{\n windowMs: 5000,\n limit: 10,\n standardHeaders: \"draft-7\",\n legacyHeaders: false,\n }\n * \n * Passing an object not overriding all the default options will only\n * cause it to be deepmerged and not actually replace with empty fields\n * \n *@see This is are the options used on the `express-rate-limit` npm package used on epxress. read more about [https://www.npmjs.com/package/express-rate-limit](https://www.npmjs.com/package/express-rate-limit)\n */\n rateLimit?: Partial<RateLimitOptions>;\n /**\n * JWT (JSON Web Token) authentication configuration.\n *\n * You can override these values directly in code, or use environment variables:\n *\n * - `JWT_SECRET`: Secret used to sign and verify JWT tokens.\n * - `JWT_EXPIRES_IN`: Duration string or number indicating when the token should expire (e.g. \"30d\", 3600).\n * - `JWT_COOKIE_SECURE`: Whether the cookie is sent only over HTTPS. Default: `true` in production.\n * - `JWT_COOKIE_HTTP_ONLY`: Whether the cookie is HTTP-only. Default: `true`.\n * - `JWT_COOKIE_SAME_SITE`: Can be \"lax\", \"strict\", or \"none\". Defaults to \"lax\" in dev, \"none\" in prod.\n *\n *@see Values passed here take precedence over environment variables.\n */\n jwt?: {\n /** Secret key used for signing and verifying JWT tokens */\n secret?: string;\n /**\n * Duration after which the JWT token expires.\n * Accepts either a duration string (e.g. \"30d\", \"1h\") or a number in milliseconds.\n * Defaults to \"30d\" if not provided.\n */\n expiresIn?: MsDuration | number;\n\n /**\n * Configuration for the JWT cookie sent to the client\n */\n cookie?: {\n /**\n * Whether the cookie should be marked as secure (sent only over HTTPS).\n * Defaults to `true` in production and `false` in development.\n */\n secure?: boolean;\n\n /**\n * Whether the cookie should be marked as HTTP-only.\n * Default is `true` to prevent access via JavaScript.\n */\n httpOnly?: boolean;\n\n /**\n * Controls the SameSite attribute of the cookie.\n * Defaults to \"none\" in production and \"lax\" in development.\n * Options: \"lax\" | \"strict\" | \"none\"\n */\n sameSite?: \"lax\" | \"strict\" | \"none\";\n };\n };\n };\n /** Allows to customize and toggle the built-in validation, by default it is set to `false`. If true is passed it will use validation with the default resolver set to `class-validator` if you intend to change the resolver to `zod` do the following:\n *\n *```ts\n * // src/app.ts\n * import arkos from 'arkos'\n *\n * arkos.init({\n * validation: {\n * resolver: \"zod\"\n * }\n * })\n * ```\n *\n * @See [www.arkosjs.com/docs/guides/validation/setup](https://www.arkosjs.com/docs/guides/validation/setup) for more details.\n */\n validation?: {\n /**\n * Defines whether to use strict request validation, it means in every request using `ArkosRouter()` you must pass the validation options with all options (e.g: query, params, body, etc.).\n *\n * **How It Works:**\n * - If it is true, Arkos will require all the options a stated above on the routes and if you don't pass it will throw an error.\n * **What if you don't want to pass a validator to some options?**\n * - You will need to pass `undefined` to the validator option (see example below), this way Arkos will throw an error if something is passed to `req.query` if you passed undefined as validator into `validation.query`\n *\n * ```ts\n * import { ArkosRouter } from \"arkos\"\n *\n * const router = ArkosRouter()\n *\n * router.get({\n * route: \"/api/posts\",\n * validation: {\n * query: undefined\n * }\n * })\n *\n * ```\n *\n * @since 1.4.0-beta\n */\n strict?: boolean;\n } & (\n | {\n resolver: \"class-validator\";\n /**\n * ValidatorOptions to used while validating request data.\n *\n * **Default**:\n * ```ts\n * {\n * whitelist: true\n * forbidNonWhitelisted: true\n * }\n * ```\n */\n validationOptions?: ValidatorOptions;\n }\n | {\n resolver: \"zod\";\n /**\n * @since v1.5.0-beta\n */\n validationOptions?: {\n /**\n * Throws an error for know whitelisted fields\n *\n * @default true\n */\n forbidNonWhitelisted?: boolean;\n };\n }\n );\n /**\n * Defines file upload configurations\n *\n * See [www.arkosjs.com/docs/core-concepts/file-upload#costum-configurations](https://www.arkosjs.com/docs/core-concepts/file-upload#costum-configurations)\n */\n fileUpload?: {\n /**\n * Defiens the base file upload directory, default is set to /uploads (on root directory)\n *\n * When setting up a path dir always now that root directory will be the starting reference.\n *\n * #### Example\n * passing `../my-arkos-uploaded-files`\n *\n * Will save uploaded files one level outside the root dir inside `my-arkos-uploaded-files`\n *\n * NB: You must be aware of permissions on your server to acess files outside your project directory.\n *\n */\n baseUploadDir?: string;\n /**\n * Changes the default `/api/uploads` base route for accessing file upload route.\n *\n * #### IMPORTANT\n * Changing this will not affect the `baseUploadDir` folder. You can\n * pass here `/api/files/my-user-files` and `baseUploadDir` be `/uploaded-files`.\n *\n */\n baseRoute?: string;\n /**\n * Defines options for `express.static(somePath, someOptions)`\n *\n * #### Default:\n *\n * ```ts\n *{\n maxAge: \"1y\",\n etag: true,\n lastModified: true,\n dotfiles: \"ignore\",\n fallthrough: true,\n index: false,\n cacheControl: true,\n }\n * ```\n * \n * By passing your custom options have in mind that it\n * will be deepmerged with the default.\n * \n * Visit [https://expressjs.com/en/4x/api.html#express.static](https://expressjs.com/en/4x/api.html#express.static) for more understanding.\n * \n */\n expressStatic?: Parameters<typeof express.static>[1];\n /**\n * Defines upload restrictions for each file type: image, video, document or other.\n *\n * #### Important:\n * Passing an object without overriding everything will only cause it\n * to be deepmerged with the default options.\n *\n * See [www.arkosjs.com/docs/reference/default-supported-upload-files](https://www.arkosjs.com/docs/reference/default-supported-upload-files) for detailed explanation about default values.\n * ```\n */\n restrictions?: {\n images?: {\n maxCount?: number;\n maxSize?: number;\n supportedFilesRegex?: RegExp;\n };\n videos?: {\n maxCount?: number;\n maxSize?: number;\n supportedFilesRegex?: RegExp;\n };\n documents?: {\n maxCount?: number;\n maxSize?: number;\n supportedFilesRegex?: RegExp;\n };\n files?: {\n maxCount?: number;\n maxSize?: number;\n supportedFilesRegex?: RegExp;\n };\n };\n };\n /**\n * Defines express middlewares configurations\n */\n middlewares?: {\n /**\n * Allows to define options for npm package compression\n * Nothing is passed by default.\n *\n * See [www.npmjs.com/package/compression](https://www.npmjs.com/package/compression) for further details.\n */\n compression?: false | compression.CompressionOptions | ArkosRequestHandler;\n /**\n * Allows to specify the request rate limit for all endpoints.\n * \n * #### Default\n *```ts\n *{\n windowMs: 60 * 1000,\n limit: 1000,\n standardHeaders: \"draft-7\",\n legacyHeaders: false,\n }\n ```\n * \n * Passing an object not overriding all the default options will only\n * cause it to be deepmerged and not actually replace with empty fields\n * \n * This is are the options used on the `express-rate-limit` npm package used on epxress. read more about [https://www.npmjs.com/package/express-rate-limit](https://www.npmjs.com/package/express-rate-limit)\n */\n rateLimit?: false | Partial<RateLimitOptions> | ArkosRequestHandler;\n /**\n * Configuration for CORS (Cross-Origin Resource Sharing).\n *\n * @property {string | string[] | \"all\"} [allowedOrigins] - List of allowed origins. If set to `\"all\"`, all origins are accepted.\n * @property {import('cors').CorsOptions} [options] - Additional CORS options passed directly to the `cors` middleware.\n * @property {import('cors').CorsOptionsDelegate} [customHandler] - A custom middleware function that overrides the default behavior.\n *\n * @remarks\n * If `customHandler` is provided, both `allowedOrigins` and `options` will be ignored in favor of the custom logic.\n *\n * See https://www.npmjs.com/package/cors\n */\n cors?:\n | false\n | {\n /**\n * Defines allowed origins to acess the API.\n */\n allowedOrigins?: string | string[] | \"*\";\n options?: cors.CorsOptions;\n /**\n * If you would like to override the entire middleware\n *\n * see\n */\n customHandler?: cors.CorsOptionsDelegate;\n }\n | ArkosRequestHandler;\n /**\n * Defines options for the built-in express.json() middleware\n * Nothing is passed by default.\n */\n expressJson?:\n | false\n | Parameters<typeof express.json>[0]\n | ArkosRequestHandler;\n /**\n * Allows to pass paremeters to cookieParser from npm package cookie-parser\n * Nothing is passed by default.\n *\n * See [www.npmjs.com/package/cookie-parser](https://www.npmjs.com/package/cookie-parser) for further details.\n */\n cookieParser?:\n | false\n | Parameters<typeof cookieParser>\n | ArkosRequestHandler;\n /**\n * Options to define how query must be parsed.\n *\n * #### for example:\n * ```\n * GET /api/product?saleId=null\n * ```\n *\n * Normally would parsed to { saleId: \"null\" } so query parser\n * trough setting option `parseNull` will transform { saleId: null }\n * \n * #### Default:\n * \n * {\n parseNull: true,\n parseUndefined: true,\n parseBoolean: true,\n parseNumber: true,\n }\n * \n * parseNumber may convert fields that are string but you only passed\n * numbers to query pay attention to this.\n * \n * Soon a feature to converted the query to the end prisma type will be added.\n */\n queryParser?: false | QueryParserOptions | ArkosRequestHandler;\n /**\n * Configuration for request logger middleware.\n *\n * Logs incoming HTTP requests with details such as method, URL, status code, and response time.\n * Useful for debugging and monitoring API traffic.\n */\n requestLogger?: false | ArkosRequestHandler;\n /**\n * Configuration for global error handler middleware.\n *\n * Catches and processes errors thrown in route handlers and other middlewares.\n * Provides a centralized way to format error responses and log errors.\n */\n errorHandler?: false | express.ErrorRequestHandler;\n };\n /**\n * Defines express/arkos routers configurations\n */\n routers?: {\n /**\n * Strict mode configuration for routing security\n *\n * @default false\n * - all CRUD + Auth (if using auth) endpoits are enabled and avialable by default.\n *\n * When enabled:\n * - If `true`: All CRUD endpoints start disabled and must be explicitly enabled\n * in each model's router configuration\n * - If `'no-bulk'`: Bulk operations (createMany, updateMany, deleteMany) are disabled\n * by default, while individual operations can be enabled per model\n *\n * This provides enhanced security by ensuring no routes are accidentally exposed.\n * Use this in production environments to follow the principle of least privilege.\n *\n * See documentation: https://www.arkosjs.com/docs/guide/security#strict-mode\n */\n strict?: boolean | \"no-bulk\";\n /**\n * Replace the default welcome endpoint handler\n * @param req Express request object\n * @param res Express response object\n * @param next Express next function\n */\n welcomeRoute?: false | ArkosRequestHandler;\n };\n /**\n * Allows to configure email configurations for sending emails through `emailService`\n *\n * See [www.arkosjs.com/docs/guides/email-service](https://www.arkosjs.com/docs/guides/email-service)\n */\n email?: {\n /**\n * Email name to used like:\n *\n * John Doe\\<john.doe@gmail.com>\n */\n name?: string;\n /**\n * Your email provider url\n */\n host: string;\n /**\n * Email provider SMTP port, Default is `465`\n */\n port?: number;\n /**\n * If smtp connection must be secure, Default is `true`\n */\n secure?: boolean;\n /**\n * Used to authenticate in your smtp server\n */\n auth: {\n /**\n * Email used for auth as well as sending emails\n */\n user: string;\n /**\n * Your SMTP password\n */\n pass: string;\n };\n } & Parameters<typeof nodemailer.createTransport>[0];\n /**\n * Defines Swagger and OpenApi specifications for auto generating swagger documentation UI using whether it is Prisma Schemas, Class-validator DTOs, Zod Schemas or JSON-Schemas.\n *\n * **Important**: Is worth mentioning that this works alongside `@scalar/express-api-reference` npm package, you define it's ApiReferenceConfiguration under ``. also consider checking the package documentation at []\n *\n * **Usage**\n *\n * ```ts\n * // src/app.ts\n *\n * import arkos from \"arkos\"\n *\n * arkos.init({\n * // other configs\n * swagger: {\n * mode: \"zod\",\n * options: {\n * defintion: {\n * info: {\n * openapi: \"3.0.0\",\n * title: \"API Generated By Arkos.js\",\n * description: \"This API was automatically generated by Arkos.js read more about at www.arkosjs.com\"\n * }\n * }\n * }\n * }\n * })\n * ```\n * @see {@link https://www.arkosjs.com/docs/guides/open-api-documentation/setup}\n */\n swagger?: {\n /**\n * By default Arkos will disable API Documentation when the project is built `npm run build`, it does not matter what node environment is set. If you want to use it even after the `arkos build` command just set this to `true`.\n * */\n enableAfterBuild?: boolean;\n /**\n * Whether to require superUser authentication to access docs in production.\n * Default: true after build\n */\n authenticate?: boolean;\n /**\n * Endpoint where the Swagger UI will be available.\n *\n * @default \"/api/api-docs\"\n */\n endpoint?: string;\n /**\n * Allows `Arkos.js` to fallback to prisma schema and use them as json schema for defining request body and response data\n * when a given zod Schema or class-validator Class is not found to be transformed to json schema.\n *\n * @default false\n */\n strict?: boolean;\n /**\n * Defines your swagger configurations\n */\n options?: {\n /**\n * Swagger definition according to OpenAPI Specification.\n */\n definition?: {\n /**\n * OpenAPI version.\n *\n * @default \"3.0.0\"\n */\n openapi?: string;\n\n /**\n * Information about your API.\n */\n info?: {\n /**\n * Title of the API documentation.\n *\n *\n * @example \"My API\"\n *\n * @default \"API Generated By Arkos.js\"\n */\n title?: string;\n\n /**\n * Version of the API.\n *\n * @example \"1.0.0\"\n */\n version?: string;\n\n /**\n * Description of the API.\n *\n * @default \"This API was automatically generated by Arkos.js read more about at www.arkosjs.com\"\n */\n description?: string;\n };\n\n /**\n * Server configurations for the API.\n *\n * @default [{ url: \"http://localhost:8000\", description: \"Development server\" }]\n *\n * This can be overridden automatically by Arkos based on CLI, .env, or `arkos.init()`.\n */\n servers?: {\n /**\n * Base URL of the server.\n *\n * @example \"http://localhost:8000\"\n */\n url: string;\n\n /**\n * Human-readable description of the server.\n *\n * @example \"Development Server\"\n */\n description?: string;\n }[];\n /**\n * Allows adding more paths for your OpenAPI documentation\n *\n * */\n paths?: OpenAPIV3.PathsObject;\n /**\n * (Optional) Additional metadata such as terms of service, contact, or license.\n *\n * See: https://swagger.io/specification/#infoObject\n */\n termsOfService?: string;\n contact?: {\n name?: string;\n url?: string;\n email?: string;\n };\n license?: {\n name: string;\n url?: string;\n };\n\n /**\n * Tags to group and describe endpoints.\n */\n tags?: {\n name: string;\n description?: string;\n }[];\n\n /**\n * Security definitions (e.g., Bearer Auth).\n */\n components?: {\n securitySchemes?: Record<string, any>;\n schemas?: Record<string, any>;\n };\n\n /**\n * Global security requirements.\n */\n security?: Array<Record<string, string[]>>;\n };\n\n /**\n * Glob patterns defining where Swagger should look for API route definitions and comments.\n *\n * @default \n * ```ts\n * [\"./src/routers/*.router.{ts,js}\", \"./src/modules/**\\/*.router.{ts,js}\"]\n ```\n *\n * Adjust depending on TypeScript or JavaScript usage.\n */\n apis?: string[];\n\n /**\n * Enables deep linking in the Swagger UI.\n *\n * @default true\n */\n deepLinking?: boolean;\n\n /**\n * Enable/disable the \"Try it out\" button globally.\n *\n * @default true\n */\n tryItOutEnabled?: boolean;\n\n /**\n * Whether to persist authorization data across page reloads.\n *\n * @default false\n */\n persistAuthorization?: boolean;\n };\n /**\n * Custom `@scalar/express-api-reference` package options.\n *\n * @see {@link https://guides.scalar.com/scalar/scalar-api-references/integrations/express}\n */\n scalarApiReferenceConfiguration?: Partial<ApiReferenceConfiguration>;\n };\n /**\n * Helps in debugging some of the variables values that are used inside arkos from dynamic loaded components towhat is used into the generated api.\n *\n */\n debugging?: {\n /**\n * Controls debugging over HTTP request level\n */\n requests?: {\n level?: 0 | 1 | 2 | 3;\n filter?: (\n | \"Query\"\n | \"Body\"\n | \"Params\"\n | \"TransformedQuery\"\n | \"ServiceArgs\"\n | \"PrismaFinalQueryArgs\"\n )[];\n };\n };\n /**\n * Defines Prisma-related configurations for Arkos to communicate with your database.\n */\n prisma: {\n /**\n * Your PrismaClient instance. Required for Arkos to communicate with your database.\n *\n * @example\n * ```ts\n * import { PrismaClient } from \"@prisma/client\";\n *\n * const prisma = new PrismaClient();\n *\n * export default defineConfig({\n * prisma: { instance: prisma },\n * });\n * ```\n */\n instance: PrismaClient;\n };\n};\n"]}
1
+ {"version":3,"file":"new-arkos-config.js","sourceRoot":"","sources":["../../../src/types/new-arkos-config.ts"],"names":[],"mappings":"","sourcesContent":["import cors from \"cors\";\nimport express, { CookieOptions } from \"express\";\nimport { Options as RateLimitOptions } from \"express-rate-limit\";\nimport cookieParser from \"cookie-parser\";\nimport compression from \"compression\";\nimport { Options as QueryParserOptions } from \"../utils/helpers/query-parser.helpers\";\nimport { ValidatorOptions } from \"class-validator\";\nimport { MsDuration } from \"../modules/auth/utils/helpers/auth.controller.helpers\";\nimport { OpenAPIV3 } from \"openapi-types\";\nimport type { ApiReferenceConfiguration } from \"@scalar/express-api-reference\" with { \"resolution-mode\": \"import\" };\nimport nodemailer from \"nodemailer\";\nimport { ArkosRequestHandler } from \".\";\nimport { PrismaClient } from \"../generated\";\nimport {\n AuthenticateHookHandler,\n AuthenticateAfterHookHandler,\n AuthenticateErrorHookHandler,\n AuthorizeHookHandler,\n AuthorizeAfterHookHandler,\n AuthorizeErrorHookHandler,\n} from \"./arkos-config/utils\";\n\n/**\n * Defines the initial configs of the api to be loaded at startup when arkos.init() is called.\n */\nexport type ArkosConfig = {\n /**\n * Configuration for resolving your Arkos application's source files at runtime.\n *\n * @since 1.6.1-canary.2\n *\n */\n source?: {\n /**\n * The entry point file of your Arkos application, resolved at runtime.\n *\n * This should point to the file where `app.listen()` or `app.listen(server)`\n * is called to start the HTTP server.\n *\n * Supports both TypeScript and JavaScript projects.\n *\n * @type {string}\n *\n * @default \"src/app.ts\" (TypeScript) | \"src/app.js\" (JavaScript)\n *\n * @since 1.6.1-canary.2\n *\n * @example\n * ```ts\n * // TypeScript project\n * entryPoint: \"src/app.ts\"\n *\n * // JavaScript project\n * entryPoint: \"src/app.js\"\n *\n * // Custom path\n * entryPoint: \"src/server/main.ts\"\n * ```\n */\n entryPoint?: string;\n };\n /**\n * The global prefixer for the whole application\n *\n * @default \"/api\"\n */\n readonly globalPrefix?: string;\n /**\n * Allows to configure request configs\n */\n request?: {\n /**\n * Allows to configure request parameters\n */\n parameters?: {\n /**\n * Toggles allowing `VERY DANGEROUS` request paramateres under `req.query` for passing prisma query options.\n *\n * See more\n */\n allowDangerousPrismaQueryOptions?: boolean;\n };\n };\n /** Message you would like to send, as Json and 200 response when\n * ```curl\n * GET /api\n * ```\n *\n * ```json\n * { \"message\": \"Welcome to YourAppName\" }\n * ```\n *\n * default message is: Welcome to our Rest API generated by Arkos, find more about Arkos at www.arkosjs.com.\n *\n *\n * */\n welcomeMessage?: string;\n /**\n * Port where the application will run, can be set in 3 ways:\n *\n * 1. default is 8000\n * 2. PORT under environment variables (Lower precedence)\n * 3. this config option (Higher precedence)\n */\n port?: number | undefined;\n /**\n * Allows to listen on a different host than localhost only\n */\n host?: string;\n /**\n * Defines authentication related configurations, by default is undefined.\n *\n * See [www.arkosjs.com/docs/core-concepts/authentication/setup](https://www.arkosjs.com/docs/core-concepts/authentication/setup) for details.\n */\n authentication?: {\n /**\n * Lifecycle hooks for the built-in authentication and authorization pipeline.\n *\n * These hooks only apply to **auto-generated Arkos routes**. On custom routes using\n * `authService.authenticate` directly, chain them manually as standard middlewares.\n *\n * Hooks run as standard Express middlewares — call `next()` to continue or\n * `next(error)` to abort and forward to the global error handler.\n *\n * @see {@link https://www.arkosjs.com/docs/core-concepts/authentication/hooks}\n */\n hooks?: {\n authenticate?: {\n /**\n * Runs before JWT extraction and verification.\n *\n * @example\n * ```ts\n * before: ({ req, skip, action, resource, rule }) => {\n * req.authContext = { startedAt: Date.now() };\n * }\n * ```\n *\n * @example Skip core logic entirely (e.g. custom auth)\n * ```ts\n * before: ({ req, skip, action, resource, rule }) => {\n * req.user = myCustomAuth(req);\n * skip();\n * }\n * ```\n */\n before?: AuthenticateHookHandler | AuthenticateHookHandler[];\n\n /**\n * Runs after `req.user` has been set.\n *\n * @example\n * ```ts\n * after: ({ req }) => {\n * if (!req.user.hasChangedPassword) {\n * throw new AppError(\"Password change required.\", 403, \"PasswordChangeRequired\");\n * }\n * }\n * ```\n */\n after?: AuthenticateAfterHookHandler | AuthenticateAfterHookHandler[];\n\n /**\n * Runs when authentication throws — invalid token, expired token, user not found, etc.\n * Throw to forward to the global error handler, or call `skip()` to suppress and jump to `after` hooks.\n *\n * @example\n * ```ts\n * onError: ({ req, error, skip, action, resource, rule }) => {\n * console.warn(`Auth failed:`, error);\n * throw error;\n * }\n * ```\n *\n * @example Suppress error and continue\n * ```ts\n * onError: ({ req, skip, action, resource, rule }) => {\n * req.user = guestUser;\n * skip();\n * }\n * ```\n */\n onError?: AuthenticateErrorHookHandler | AuthenticateErrorHookHandler[];\n };\n\n authorize?: {\n /**\n * Runs before the role/permission check.\n *\n * @example\n * ```ts\n * before: ({ req }) => {\n * if (req.headers[\"x-elevated-access\"] === process.env.ELEVATION_KEY) {\n * req.user.role = \"admin\";\n * }\n * }\n * ```\n *\n * @example Skip permission check entirely\n * ```ts\n * before: ({ req, skip, action, resource, rule }) => {\n * req.user.role = myCustomRoleResolver(req);\n * skip();\n * }\n * ```\n */\n before?: AuthorizeHookHandler | AuthorizeHookHandler[];\n\n /**\n * Runs after the permission check passes.\n *\n * @example\n * ```ts\n * after: ({ req }) => {\n * auditLog.record({ userId: req.user.id, path: req.path });\n * }\n * ```\n */\n after?: AuthorizeAfterHookHandler | AuthorizeAfterHookHandler[];\n\n /**\n * Runs when the user lacks sufficient permissions (403).\n * Throw to forward to the global error handler, or call `skip()` to suppress and jump to `after` hooks.\n *\n * @example\n * ```ts\n * onError: ({ req, error, action, resource, rule }) => {\n * auditLog.record({ userId: req.user?.id, reason: \"insufficient_permissions\" });\n * throw error;\n * }\n * ```\n *\n * @example Suppress error and continue\n * ```ts\n * onError: ({ req, skip, action, resource, rule }) => {\n * req.user.role = \"guest\";\n * skip();\n * }\n * ```\n */\n onError?: AuthorizeErrorHookHandler | AuthorizeErrorHookHandler[];\n };\n };\n enabled?: boolean;\n /**\n * Defines whether to use Static or Dynamic Role-Based Acess Control\n *\n * Visit [www.arkosjs.com/docs/core-concepts/authentication/setup](https://www.arkosjs.com/docs/core-concepts/authentication/setup) for more details.\n */\n mode: \"static\" | \"dynamic\";\n /**\n * Defines auth login related configurations to customize the api.\n */\n login?: {\n /**\n * Defines the field that will be used as username by the built-in auth system, by default arkos will look for the field \"username\" in your model User, hence when making login for example you must send:\n *\n * ```json\n * {\n * \"username\": \"johndoe\",\n * \"password\": \"somePassword123\"\n * }\n * ```\n *\n * **Note:** You can also modify the usernameField on the fly by passing it to the request query parameters. example:\n *\n * ```curl\n * POST /api/auth/login?usernameField=email\n * ```\n *\n * See more at [www.arkosjs.com/docs/core-concepts/authentication/setup#login-with-different-fileds](https://www.arkosjs.com/docs/core-concepts/authentication/setup#login-with-different-fileds)\n *\n * By specifing here another field for username, for example passing \"email\", \"companyCode\" or something else your json will be like:\n *\n * **Example with email**\n *\n * ```json\n * {\n * \"email\": \"john.doe@example.com\",\n * \"password\": \"somePassword123\"\n * }\n * ```\n */\n allowedUsernames?: string[];\n /** Defines wether to send the access token in response after login or only send as cookie, defeault is both.*/\n sendAccessTokenThrough?: \"cookie-only\" | \"response-only\" | \"both\";\n };\n /**\n * Specifies the regex pattern used by the authentication system to enforce password strength requirements.\n *\n * **Important**: If using validation libraries like Zod or class-validator, this will be completely overwritten.\n *\n * **Default**: ```/^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d).+$/``` - Ensures the password contains at least one uppercase letter, one lowercase letter, and one numeric digit.\n *\n * **message**: (Optional) A custom error message to display when the password does not meet the required strength criteria.\n * @deprecated will stop working on v2.0\n */\n passwordValidation?: { regex: RegExp; message?: string };\n /**\n * Allows to specify the request rate limit for all authentication endpoints but `/api/users/me`.\n * \n * #### Default\n *{\n windowMs: 5000,\n limit: 10,\n standardHeaders: \"draft-7\",\n legacyHeaders: false,\n }\n * \n * Passing an object not overriding all the default options will only\n * cause it to be deepmerged and not actually replace with empty fields\n * \n *@see This is are the options used on the `express-rate-limit` npm package used on epxress. read more about [https://www.npmjs.com/package/express-rate-limit](https://www.npmjs.com/package/express-rate-limit)\n */\n rateLimit?: Partial<RateLimitOptions>;\n /**\n * JWT (JSON Web Token) authentication configuration.\n *\n * You can override these values directly in code, or use environment variables:\n *\n * - `JWT_SECRET`: Secret used to sign and verify JWT tokens.\n * - `JWT_EXPIRES_IN`: Duration string or number indicating when the token should expire (e.g. \"30d\", 3600).\n * - `JWT_COOKIE_SECURE`: Whether the cookie is sent only over HTTPS. Default: `true` in production.\n * - `JWT_COOKIE_HTTP_ONLY`: Whether the cookie is HTTP-only. Default: `true`.\n * - `JWT_COOKIE_SAME_SITE`: Can be \"lax\", \"strict\", or \"none\". Defaults to \"lax\" in dev, \"none\" in prod.\n *\n *@see Values passed here take precedence over environment variables.\n */\n jwt?: {\n /** Secret key used for signing and verifying JWT tokens */\n secret?: string;\n /**\n * Duration after which the JWT token expires.\n * Accepts either a duration string (e.g. \"30d\", \"1h\") or a number in milliseconds.\n * Defaults to \"30d\" if not provided.\n */\n expiresIn?: MsDuration | number;\n /**\n * Configuration for the JWT cookie sent to the client\n */\n cookie?: {\n /**\n * Whether the cookie should be marked as secure (sent only over HTTPS).\n * Defaults to `true` in production and `false` in development.\n *\n * @env `JWT_COOKIE_SECURE`\n */\n secure?: boolean;\n /**\n * Whether the cookie should be marked as HTTP-only.\n * Default is `true` to prevent access via JavaScript.\n *\n * @env `JWT_COOKIE_HTTP_ONLY`\n */\n httpOnly?: boolean;\n /**\n * Controls the SameSite attribute of the cookie.\n * Defaults to \"none\" in production and \"lax\" in development.\n * Options: \"lax\" | \"strict\" | \"none\"\n *\n * @env `JWT_COOKIE_SAME_SITE`\n */\n sameSite?: \"lax\" | \"strict\" | \"none\";\n /**\n * Expiry date of the cookie in GMT. If not specified (undefined), creates a session cookie.\n *\n * @default `now() + authentication.jwt.expireIn | JWT_EXPIRES_IN`\n *\n * @since 1.5.11-beta\n */\n expires?: Date | undefined;\n /**\n * Domain for the cookie. Use a leading dot (e.g. `.example.com`) to include all subdomains.\n *\n * @env `JWT_COOKIE_DOMAIN`\n *\n * @since 1.5.11-beta\n */\n domain?: string | undefined;\n } & Omit<\n CookieOptions,\n \"secure\" | \"httpOnly\" | \"sameSite\" | \"expires\" | \"domain\"\n >;\n };\n };\n /** Allows to customize and toggle the built-in validation, by default it is set to `false`. If true is passed it will use validation with the default resolver set to `class-validator` if you intend to change the resolver to `zod` do the following:\n *\n *```ts\n * // src/app.ts\n * import arkos from 'arkos'\n *\n * arkos.init({\n * validation: {\n * resolver: \"zod\"\n * }\n * })\n * ```\n *\n * @See [www.arkosjs.com/docs/guides/validation/setup](https://www.arkosjs.com/docs/guides/validation/setup) for more details.\n */\n validation?: {\n /**\n * Defines whether to use strict request validation, it means in every request using `ArkosRouter()` you must pass the validation options with all options (e.g: query, params, body, etc.).\n *\n * **How It Works:**\n * - If it is true, Arkos will require all the options a stated above on the routes and if you don't pass it will throw an error.\n * **What if you don't want to pass a validator to some options?**\n * - You will need to pass `undefined` to the validator option (see example below), this way Arkos will throw an error if something is passed to `req.query` if you passed undefined as validator into `validation.query`\n *\n * ```ts\n * import { ArkosRouter } from \"arkos\"\n *\n * const router = ArkosRouter()\n *\n * router.get({\n * route: \"/api/posts\",\n * validation: {\n * query: undefined\n * }\n * })\n *\n * ```\n *\n * @since 1.4.0-beta\n */\n strict?: boolean;\n } & (\n | {\n resolver: \"class-validator\";\n /**\n * ValidatorOptions to used while validating request data.\n *\n * **Default**:\n * ```ts\n * {\n * whitelist: true\n * forbidNonWhitelisted: true\n * }\n * ```\n */\n validationOptions?: ValidatorOptions;\n }\n | {\n resolver: \"zod\";\n /**\n * @since v1.5.0-beta\n */\n validationOptions?: {\n /**\n * Throws an error for know whitelisted fields\n *\n * @default true\n */\n forbidNonWhitelisted?: boolean;\n };\n }\n );\n /**\n * Defines file upload configurations\n *\n * See {@link https://www.arkosjs.com/docs/guides/file-handling/file-uploads/setup}\n */\n fileUpload?: {\n /**\n * Disables built-in file upload\n *\n * @since 1.5.11-beta\n */\n enabled?: boolean;\n /**\n * Defiens the base file upload directory, default is set to /uploads (on root directory)\n *\n * When setting up a path dir always now that root directory will be the starting reference.\n *\n * #### Example\n * passing `../my-arkos-uploaded-files`\n *\n * Will save uploaded files one level outside the root dir inside `my-arkos-uploaded-files`\n *\n * NB: You must be aware of permissions on your server to acess files outside your project directory.\n *\n */\n baseUploadDir?: string;\n /**\n * Changes the default `/api/uploads` base route for accessing file upload route.\n *\n * #### IMPORTANT\n * Changing this will not affect the `baseUploadDir` folder. You can\n * pass here `/api/files/my-user-files` and `baseUploadDir` be `/uploaded-files`.\n *\n */\n baseRoute?: string;\n /**\n * Defines options for `express.static(somePath, someOptions)`\n *\n * #### Default:\n *\n * ```ts\n *{\n maxAge: \"1y\",\n etag: true,\n lastModified: true,\n dotfiles: \"ignore\",\n fallthrough: true,\n index: false,\n cacheControl: true,\n }\n * ```\n * \n * By passing your custom options have in mind that it\n * will be deepmerged with the default.\n * \n * Visit [https://expressjs.com/en/4x/api.html#express.static](https://expressjs.com/en/4x/api.html#express.static) for more understanding.\n * \n */\n expressStatic?: Parameters<typeof express.static>[1];\n /**\n * Defines upload restrictions for each file type: image, video, document or other.\n *\n * #### Important:\n * Passing an object without overriding everything will only cause it\n * to be deepmerged with the default options.\n *\n * See [www.arkosjs.com/docs/reference/default-supported-upload-files](https://www.arkosjs.com/docs/reference/default-supported-upload-files) for detailed explanation about default values.\n * ```\n */\n restrictions?: {\n images?: {\n maxCount?: number;\n maxSize?: number;\n supportedFilesRegex?: RegExp;\n };\n videos?: {\n maxCount?: number;\n maxSize?: number;\n supportedFilesRegex?: RegExp;\n };\n documents?: {\n maxCount?: number;\n maxSize?: number;\n supportedFilesRegex?: RegExp;\n };\n files?: {\n maxCount?: number;\n maxSize?: number;\n supportedFilesRegex?: RegExp;\n };\n };\n };\n /**\n * Defines express middlewares configurations\n */\n middlewares?: {\n /**\n * Allows to define options for npm package compression\n * Nothing is passed by default.\n *\n * See [www.npmjs.com/package/compression](https://www.npmjs.com/package/compression) for further details.\n */\n compression?: false | compression.CompressionOptions | ArkosRequestHandler;\n /**\n * Allows to specify the request rate limit for all endpoints.\n * \n * #### Default\n *```ts\n *{\n windowMs: 60 * 1000,\n limit: 1000,\n standardHeaders: \"draft-7\",\n legacyHeaders: false,\n }\n ```\n * \n * Passing an object not overriding all the default options will only\n * cause it to be deepmerged and not actually replace with empty fields\n * \n * This is are the options used on the `express-rate-limit` npm package used on epxress. read more about [https://www.npmjs.com/package/express-rate-limit](https://www.npmjs.com/package/express-rate-limit)\n */\n rateLimit?: false | Partial<RateLimitOptions> | ArkosRequestHandler;\n /**\n * Configuration for CORS (Cross-Origin Resource Sharing).\n *\n * Accepts:\n * - `false` — disables CORS middleware entirely.\n * - `cors.CorsOptions` — passed directly to the `cors` middleware.\n * - `cors.CorsOptionsDelegate` — a delegate function passed directly to the `cors` middleware.\n * - `ArkosRequestHandler` — a full Express middleware that replaces the cors middleware entirely.\n * - An object with deprecated `allowedOrigins`, `options`, and `customHandler` properties.\n *\n * In development, defaults to `origin: true, credentials: true`.\n * In production, defaults to `origin: \"*\"` (equivalent to plain `cors()`).\n *\n * See https://www.npmjs.com/package/cors\n */\n cors?:\n | false\n | cors.CorsOptions\n | cors.CorsOptionsDelegate\n | {\n /**\n * Defines allowed origins to access the API.\n *\n * @deprecated Use `cors: { origin: string | string[] }` (cors.CorsOptions) directly instead.\n */\n allowedOrigins?: string | string[] | \"*\" | true;\n /**\n * Additional cors options.\n *\n * @deprecated Pass cors.CorsOptions directly instead: `cors: { origin: \"...\", credentials: true }`.\n */\n options?: cors.CorsOptions;\n /**\n * If you would like to override the entire middleware.\n *\n * @deprecated Pass the handler directly instead: `cors: myCorsHandler`.\n */\n customHandler?: cors.CorsOptionsDelegate;\n }\n | ArkosRequestHandler;\n /**\n * Defines options for the built-in express.json() middleware\n * Nothing is passed by default.\n */\n expressJson?:\n | false\n | Parameters<typeof express.json>[0]\n | ArkosRequestHandler;\n /**\n * Allows to pass paremeters to cookieParser from npm package cookie-parser\n * Nothing is passed by default.\n *\n * See [www.npmjs.com/package/cookie-parser](https://www.npmjs.com/package/cookie-parser) for further details.\n */\n cookieParser?:\n | false\n | {\n secret?: string | string[];\n options?: Parameters<typeof cookieParser>[1];\n }\n | ArkosRequestHandler;\n /**\n * Options to define how query must be parsed.\n *\n * #### for example:\n * ```\n * GET /api/product?saleId=null\n * ```\n *\n * Normally would parsed to { saleId: \"null\" } so query parser\n * trough setting option `parseNull` will transform { saleId: null }\n * \n * #### Default:\n * \n * {\n parseNull: true,\n parseUndefined: true,\n parseBoolean: true,\n parseNumber: true,\n }\n * \n * parseNumber may convert fields that are string but you only passed\n * numbers to query pay attention to this.\n * \n * Soon a feature to converted the query to the end prisma type will be added.\n */\n queryParser?: false | QueryParserOptions | ArkosRequestHandler;\n /**\n * Configuration for request logger middleware.\n *\n * Logs incoming HTTP requests with details such as method, URL, status code, and response time.\n * Useful for debugging and monitoring API traffic.\n */\n requestLogger?: false | ArkosRequestHandler;\n /**\n * Configuration for global error handler middleware.\n *\n * Catches and processes errors thrown in route handlers and other middlewares.\n * Provides a centralized way to format error responses and log errors.\n */\n errorHandler?: false | express.ErrorRequestHandler;\n };\n /**\n * Defines express/arkos routers configurations\n */\n routers?: {\n /**\n * Strict mode configuration for routing security\n *\n * @default false\n * - all CRUD + Auth (if using auth) endpoits are enabled and avialable by default.\n *\n * When enabled:\n * - If `true`: All CRUD endpoints start disabled and must be explicitly enabled\n * in each model's router configuration\n * - If `'no-bulk'`: Bulk operations (createMany, updateMany, deleteMany) are disabled\n * by default, while individual operations can be enabled per model\n *\n * This provides enhanced security by ensuring no routes are accidentally exposed.\n * Use this in production environments to follow the principle of least privilege.\n *\n * See documentation: https://www.arkosjs.com/docs/guide/security#strict-mode\n */\n strict?: boolean | \"no-bulk\";\n /**\n * Replace the default welcome endpoint handler\n * @param req Express request object\n * @param res Express response object\n * @param next Express next function\n */\n welcomeRoute?: false | ArkosRequestHandler;\n };\n /**\n * Allows to configure email configurations for sending emails through `emailService`\n *\n * See [www.arkosjs.com/docs/guides/email-service](https://www.arkosjs.com/docs/guides/email-service)\n */\n email?: {\n /**\n * Email name to used like:\n *\n * John Doe\\<john.doe@gmail.com>\n */\n name?: string;\n /**\n * Your email provider url\n */\n host: string;\n /**\n * Email provider SMTP port, Default is `465`\n */\n port?: number;\n /**\n * If smtp connection must be secure, Default is `true`\n */\n secure?: boolean;\n /**\n * Used to authenticate in your smtp server\n */\n auth: {\n /**\n * Email used for auth as well as sending emails\n */\n user: string;\n /**\n * Your SMTP password\n */\n pass: string;\n };\n } & Parameters<typeof nodemailer.createTransport>[0];\n /**\n * Defines Swagger and OpenApi specifications for auto generating swagger documentation UI using whether it is Prisma Schemas, Class-validator DTOs, Zod Schemas or JSON-Schemas.\n *\n * **Important**: Is worth mentioning that this works alongside `@scalar/express-api-reference` npm package, you define it's ApiReferenceConfiguration under ``. also consider checking the package documentation at []\n *\n * **Usage**\n *\n * ```ts\n * // src/app.ts\n *\n * import arkos from \"arkos\"\n *\n * arkos.init({\n * // other configs\n * swagger: {\n * mode: \"zod\",\n * options: {\n * defintion: {\n * info: {\n * openapi: \"3.0.0\",\n * title: \"API Generated By Arkos.js\",\n * description: \"This API was automatically generated by Arkos.js read more about at www.arkosjs.com\"\n * }\n * }\n * }\n * }\n * })\n * ```\n * @see {@link https://www.arkosjs.com/docs/guides/open-api-documentation/setup}\n */\n swagger?: {\n /**\n * By default Arkos will disable API Documentation when the project is built `npm run build`, it does not matter what node environment is set. If you want to use it even after the `arkos build` command just set this to `true`.\n * */\n enableAfterBuild?: boolean;\n /**\n * Whether to require superUser authentication to access docs in production.\n * Default: true after build\n */\n authenticate?: boolean;\n /**\n * Endpoint where the Swagger UI will be available.\n *\n * @default \"/api/api-docs\"\n */\n endpoint?: string;\n /**\n * Allows `Arkos.js` to fallback to prisma schema and use them as json schema for defining request body and response data\n * when a given zod Schema or class-validator Class is not found to be transformed to json schema.\n *\n * @default false\n */\n strict?: boolean;\n /**\n * Defines your swagger configurations\n */\n options?: {\n /**\n * Swagger definition according to OpenAPI Specification.\n */\n definition?: {\n /**\n * OpenAPI version.\n *\n * @default \"3.0.0\"\n */\n openapi?: string;\n\n /**\n * Information about your API.\n */\n info?: {\n /**\n * Title of the API documentation.\n *\n *\n * @example \"My API\"\n *\n * @default \"API Generated By Arkos.js\"\n */\n title?: string;\n\n /**\n * Version of the API.\n *\n * @example \"1.0.0\"\n */\n version?: string;\n\n /**\n * Description of the API.\n *\n * @default \"This API was automatically generated by Arkos.js read more about at www.arkosjs.com\"\n */\n description?: string;\n };\n\n /**\n * Server configurations for the API.\n *\n * @default [{ url: \"http://localhost:8000\", description: \"Development server\" }]\n *\n * This can be overridden automatically by Arkos based on CLI, .env, or `arkos.init()`.\n */\n servers?: {\n /**\n * Base URL of the server.\n *\n * @example \"http://localhost:8000\"\n */\n url: string;\n\n /**\n * Human-readable description of the server.\n *\n * @example \"Development Server\"\n */\n description?: string;\n }[];\n /**\n * Allows adding more paths for your OpenAPI documentation\n *\n * */\n paths?: OpenAPIV3.PathsObject;\n /**\n * (Optional) Additional metadata such as terms of service, contact, or license.\n *\n * See: https://swagger.io/specification/#infoObject\n */\n termsOfService?: string;\n contact?: {\n name?: string;\n url?: string;\n email?: string;\n };\n license?: {\n name: string;\n url?: string;\n };\n\n /**\n * Tags to group and describe endpoints.\n */\n tags?: {\n name: string;\n description?: string;\n }[];\n\n /**\n * Security definitions (e.g., Bearer Auth).\n */\n components?: {\n securitySchemes?: Record<string, any>;\n schemas?: Record<string, any>;\n };\n\n /**\n * Global security requirements.\n */\n security?: Array<Record<string, string[]>>;\n };\n\n /**\n * Glob patterns defining where Swagger should look for API route definitions and comments.\n *\n * @default \n * ```ts\n * [\"./src/routers/*.router.{ts,js}\", \"./src/modules/**\\/*.router.{ts,js}\"]\n ```\n *\n * Adjust depending on TypeScript or JavaScript usage.\n */\n apis?: string[];\n\n /**\n * Enables deep linking in the Swagger UI.\n *\n * @default true\n */\n deepLinking?: boolean;\n\n /**\n * Enable/disable the \"Try it out\" button globally.\n *\n * @default true\n */\n tryItOutEnabled?: boolean;\n\n /**\n * Whether to persist authorization data across page reloads.\n *\n * @default false\n */\n persistAuthorization?: boolean;\n };\n /**\n * Custom `@scalar/express-api-reference` package options.\n *\n * @see {@link https://guides.scalar.com/scalar/scalar-api-references/integrations/express}\n */\n scalarApiReferenceConfiguration?: Partial<ApiReferenceConfiguration>;\n };\n /**\n * Helps in debugging some of the variables values that are used inside arkos from dynamic loaded components towhat is used into the generated api.\n *\n */\n debugging?: {\n /**\n * Controls debugging over HTTP request level\n */\n requests?: {\n level?: 0 | 1 | 2 | 3;\n filter?: (\n | \"Query\"\n | \"Body\"\n | \"Params\"\n | \"TransformedQuery\"\n | \"ServiceArgs\"\n | \"PrismaFinalQueryArgs\"\n )[];\n };\n };\n /**\n * Defines Prisma-related configurations for Arkos to communicate with your database.\n */\n prisma: {\n /**\n * Your PrismaClient instance. Required for Arkos to communicate with your database.\n *\n * @example\n * ```ts\n * import { PrismaClient } from \"@prisma/client\";\n *\n * const prisma = new PrismaClient();\n *\n * export default defineConfig({\n * prisma: { instance: prisma },\n * });\n * ```\n */\n instance: PrismaClient;\n };\n /**\n * Allows to suppress specific warnings emitted by Arkos at startup or runtime.\n *\n * @since 1.5.10-beta\n */\n warnings?: {\n /**\n * Suppresses specific warning messages.\n */\n suppress?: {\n /**\n * Suppresses Prisma-related warnings.\n */\n prisma?: {\n /**\n * Suppresses the warning emitted when no Prisma instance is found.\n */\n noInstanceFound?: boolean;\n /**\n * Suppresses the warning emitted when no Prisma schema is found.\n */\n noSchemaFound?: boolean;\n };\n };\n };\n /**\n * Defines static file serving configurations.\n *\n * Arkos will automatically serve files from the configured folder using `express.static`.\n * If the folder does not exist at startup, a warning will be emitted.\n *\n * **Note:** The static files route is **not** prefixed with the `globalPrefix`.\n *\n * @since 1.7.0-canary.16\n *\n * @example\n * ```ts\n * import { defineConfig } from \"arkos\"\n *\n * export default defineConfig({\n * staticFiles: {\n * folder: \"assets\",\n * prefix: \"/static\",\n * }\n * }) */\n staticFiles?: {\n /**\n * Whether to enable static file serving.\n *\n * Set to `false` to disable static file serving entirely and suppress\n * the warning when the folder is not found.\n *\n * @default true\n */\n enabled?: boolean;\n\n /**\n * The folder to serve static files from, relative to the project root.\n *\n * @default \"public\"\n */\n folder?: string;\n\n /**\n * The URL path prefix under which static files will be served.\n *\n * **Note:** This is not affected by `globalPrefix`.\n *\n * @default \"/\"\n *\n * @example \"/static\" // files served at /static/image.png\n */\n prefix?: string;\n\n /**\n * Options passed directly to `express.static()`.\n *\n * By passing custom options, they will be deep merged with the defaults.\n *\n * #### Default:\n * ```ts\n * {\n * maxAge: \"1y\",\n * etag: true,\n * lastModified: true,\n * dotfiles: \"ignore\",\n * fallthrough: true,\n * index: false,\n * cacheControl: true,\n * }\n * ```\n *\n * @see {@link https://expressjs.com/en/4x/api.html#express.static}\n */\n expressStatic?: Parameters<typeof express.static>[1];\n };\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"router-config.js","sourceRoot":"","sources":["../../../src/types/router-config.ts"],"names":[],"mappings":"","sourcesContent":["import { ArkosRouteConfig } from \"../exports\";\n\nexport type RouterEndpoint =\n | \"createOne\"\n | \"findOne\"\n | \"updateOne\"\n | \"deleteOne\"\n | \"findMany\"\n | \"createMany\"\n | \"updateMany\"\n | \"deleteMany\";\n\nexport type AuthRouterEndpoint =\n | \"getMe\"\n | \"updateMe\"\n | \"deleteMe\"\n | \"login\"\n | \"logout\"\n | \"signup\"\n | \"updatePassword\"\n | \"findManyAuthAction\"\n | \"findOneAuthAction\";\n\nexport type FileUploadRouterEndpoint =\n | \"findFile\"\n | \"uploadFile\"\n | \"updateFile\"\n | \"deleteFile\";\n\ntype BaseRouterConfig = {\n /**\n * Backward compatibility (prior 1.4.0-beta) - disables/enables endpoints\n *\n * prefer to rather to use the following:\n *\n * ```ts\n * export const config = {\n * findMany: {\n * disabled: true\n * }\n * }\n * ```\n */\n disable?:\n | boolean\n | {\n [K in RouterEndpoint]?: boolean;\n };\n} & {\n [K in RouterEndpoint]?: Omit<ArkosRouteConfig, \"path\">;\n};\n\ntype AuthRouterConfig = {\n /**\n * Backward compatibility (prior 1.4.0-beta) - disables/enables endpoints\n *\n * prefer to rather to use the following:\n *\n * ```ts\n * export const config = {\n * getMe: {\n * disabled: true\n * }\n * }\n * ```\n */\n disable?:\n | boolean\n | {\n [K in AuthRouterEndpoint]?: boolean;\n };\n} & {\n [K in AuthRouterEndpoint]?: Omit<ArkosRouteConfig, \"path\">;\n};\n\ntype FileUploadRouterConfig = {\n /**\n * Backward compatibility (prior 1.4.0-beta) - disables/enables endpoints\n *\n * prefer to rather to use the following:\n *\n * ```ts\n * export const config = {\n * deleteFile: {\n * disabled: true\n * }\n * }\n * ```\n */\n disable?:\n | boolean\n | {\n [K in FileUploadRouterEndpoint]?: boolean;\n };\n} & {\n [K in FileUploadRouterEndpoint]?: Omit<ArkosRouteConfig, \"path\" | \"uploads\">;\n};\n\n/**\n * @deprecated use RouteHook instead\n */\nexport type RouterConfig<T extends string = string> = T extends \"auth\"\n ? AuthRouterConfig\n : T extends \"file-upload\"\n ? FileUploadRouterConfig\n : BaseRouterConfig;\n\n/**\n * Represents a Route Hook configuration for Arkos auto-generated routes.\n *\n * Route Hooks allow you to customize built-in routes (e.g. CRUD, auth, file upload)\n * without modifying the route definitions themselves. Each key in the hook maps\n * to a specific operation and accepts the same configuration object used by ArkosRouter.\n *\n * @template T - The hook type:\n * - `\"auth\"` → Uses {@link AuthRouterConfig} for authentication routes\n * - `\"file-upload\"` → Uses {@link FileUploadRouterConfig} for file upload routes\n * - `string` (default) → Uses {@link BaseRouterConfig} for standard model routes\n *\n * @example\n * ```ts\n * export const hook: RouteHook = {\n * findMany: { authentication: false },\n * createOne: { authentication: true },\n * deleteOne: { disabled: true },\n * };\n * ```\n *\n * @example\n * ```ts\n * export const hook: RouteHook<\"auth\"> = {\n * login: { rateLimit: { windowMs: 15 * 60_000, max: 10 } },\n * signup: { disabled: true },\n * };\n * ```\n *\n * @example\n * ```ts\n * export const hook: RouteHook<\"file-upload\"> = {\n * uploadFile: { authentication: true },\n * deleteFile: { disabled: true },\n * };\n * ```\n *\n * @remarks\n * - This replaces the deprecated `RouterConfig` export (since v1.6.0-beta).\n * - The hook must be exported as `export const hook` inside a `*.router.ts` file.\n * - Each property corresponds to a predefined route operation depending on the hook type.\n *\n * @since v1.6.0-beta\n */\nexport type RouteHook<T extends string = string> = T extends \"auth\"\n ? AuthRouterConfig\n : T extends \"file-upload\"\n ? FileUploadRouterConfig\n : BaseRouterConfig;\n"]}
1
+ {"version":3,"file":"router-config.js","sourceRoot":"","sources":["../../../src/types/router-config.ts"],"names":[],"mappings":"","sourcesContent":["import { ArkosRouteConfig } from \"../exports\";\n\nexport type RouterEndpoint =\n | \"createOne\"\n | \"findOne\"\n | \"updateOne\"\n | \"deleteOne\"\n | \"findMany\"\n | \"createMany\"\n | \"updateMany\"\n | \"deleteMany\";\n\nexport type AuthRouterEndpoint =\n | \"getMe\"\n | \"updateMe\"\n | \"deleteMe\"\n | \"login\"\n | \"logout\"\n | \"signup\"\n | \"updatePassword\"\n | \"findManyAuthAction\"\n | \"findOneAuthAction\";\n\nexport type FileUploadRouterEndpoint =\n | \"findFile\"\n | \"uploadFile\"\n | \"updateFile\"\n | \"deleteFile\";\n\ntype BaseRouterConfig = {\n /**\n * Backward compatibility (prior 1.4.0-beta) - disables/enables endpoints\n *\n * prefer to rather to use the following:\n *\n * ```ts\n * export const config = {\n * findMany: {\n * disabled: true\n * }\n * }\n * ```\n */\n disable?:\n | boolean\n | {\n [K in RouterEndpoint]?: boolean;\n };\n} & {\n [K in RouterEndpoint]?: Omit<ArkosRouteConfig, \"path\">;\n};\n\ntype AuthRouterConfig = {\n /**\n * Backward compatibility (prior 1.4.0-beta) - disables/enables endpoints\n *\n * prefer to rather to use the following:\n *\n * ```ts\n * export const config = {\n * getMe: {\n * disabled: true\n * }\n * }\n * ```\n */\n disable?:\n | boolean\n | {\n [K in AuthRouterEndpoint]?: boolean;\n };\n} & {\n [K in AuthRouterEndpoint]?: Omit<ArkosRouteConfig, \"path\">;\n};\n\ntype FileUploadRouterConfig = {\n /**\n * Backward compatibility (prior 1.4.0-beta) - disables/enables endpoints\n *\n * prefer to rather to use the following:\n *\n * ```ts\n * export const config = {\n * deleteFile: {\n * disabled: true\n * }\n * }\n * ```\n */\n disable?:\n | boolean\n | {\n [K in FileUploadRouterEndpoint]?: boolean;\n };\n} & {\n [K in FileUploadRouterEndpoint]?: Omit<ArkosRouteConfig, \"path\" | \"uploads\">;\n};\n\n/**\n * @deprecated use 'import { RouteHook } from \"arkos\"' instead\n */\nexport type RouterConfig<T extends string = string> = T extends \"auth\"\n ? AuthRouterConfig\n : T extends \"file-upload\"\n ? FileUploadRouterConfig\n : BaseRouterConfig;\n\n/**\n * Represents a Route Hook configuration for Arkos auto-generated routes.\n *\n * Route Hooks allow you to customize built-in routes (e.g. CRUD, auth, file upload)\n * without modifying the route definitions themselves. Each key in the hook maps\n * to a specific operation and accepts the same configuration object used by ArkosRouter.\n *\n * @template T - The hook type:\n * - `\"auth\"` → Uses {@link AuthRouterConfig} for authentication routes\n * - `\"file-upload\"` → Uses {@link FileUploadRouterConfig} for file upload routes\n * - `string` (default) → Uses {@link BaseRouterConfig} for standard model routes\n *\n * @example\n * ```ts\n * export const hook: RouteHook = {\n * findMany: { authentication: false },\n * createOne: { authentication: true },\n * deleteOne: { disabled: true },\n * };\n * ```\n *\n * @example\n * ```ts\n * export const hook: RouteHook<\"auth\"> = {\n * login: { rateLimit: { windowMs: 15 * 60_000, max: 10 } },\n * signup: { disabled: true },\n * };\n * ```\n *\n * @example\n * ```ts\n * export const hook: RouteHook<\"file-upload\"> = {\n * uploadFile: { authentication: true },\n * deleteFile: { disabled: true },\n * };\n * ```\n *\n * @remarks\n * - This replaces the deprecated `RouterConfig` export (since v1.6.0-beta).\n * - The hook must be exported as `export const hook` inside a `*.router.ts` file.\n * - Each property corresponds to a predefined route operation depending on the hook type.\n *\n * @since v1.6.0-beta\n */\nexport type RouteHook<T extends string = string> = T extends \"auth\"\n ? AuthRouterConfig\n : T extends \"file-upload\"\n ? FileUploadRouterConfig\n : BaseRouterConfig;\n"]}
@@ -1,5 +1,8 @@
1
1
  import deepmerge from "../helpers/deepmerge.helper.js";
2
2
  class ArkosRouterOpenAPIManager {
3
+ resolveSchemaFieldName(name) {
4
+ return name.replace(/\[\]/g, "[0]");
5
+ }
3
6
  addUploadFields(uploadConfig, existingSchema = {}) {
4
7
  const uploadSchema = {
5
8
  type: "object",
@@ -7,48 +10,51 @@ class ArkosRouterOpenAPIManager {
7
10
  required: [],
8
11
  };
9
12
  if (uploadConfig.type === "single") {
10
- uploadSchema.properties[uploadConfig.field] = {
13
+ const schemaKey = this.resolveSchemaFieldName(uploadConfig.field);
14
+ uploadSchema.properties[schemaKey] = {
11
15
  type: "string",
12
16
  format: "binary",
13
17
  ...(uploadConfig.maxSize && {
14
18
  description: `Max size: ${uploadConfig.maxSize} bytes`,
15
19
  }),
20
+ ...(uploadConfig.description && {
21
+ description: uploadConfig.description,
22
+ }),
16
23
  };
17
- if (uploadConfig.required) {
18
- uploadSchema.required.push(uploadConfig.field);
24
+ if (uploadConfig.required !== false) {
25
+ uploadSchema.required.push(schemaKey);
19
26
  }
20
27
  }
21
28
  else if (uploadConfig.type === "array") {
22
- uploadSchema.properties[uploadConfig.field] = {
29
+ const schemaKey = this.resolveSchemaFieldName(uploadConfig.field);
30
+ uploadSchema.properties[schemaKey] = {
23
31
  type: "array",
24
32
  items: {
25
33
  type: "string",
26
34
  format: "binary",
27
35
  },
28
36
  ...(uploadConfig.maxCount && { maxItems: uploadConfig.maxCount }),
37
+ ...(uploadConfig.minCount && { minItems: uploadConfig.minCount }),
29
38
  ...(uploadConfig.maxSize && {
30
39
  description: `Max size per file: ${uploadConfig.maxSize} bytes`,
31
40
  }),
41
+ ...(uploadConfig.description && {
42
+ description: uploadConfig.description,
43
+ }),
32
44
  };
33
- if (uploadConfig.required) {
34
- uploadSchema.required.push(uploadConfig.field);
45
+ if (uploadConfig.required !== false) {
46
+ uploadSchema.required.push(schemaKey);
35
47
  }
36
48
  }
37
49
  else if (uploadConfig.type === "fields") {
38
50
  for (const field of uploadConfig.fields) {
39
- uploadSchema.properties[field.name] = {
40
- type: "array",
41
- items: {
42
- type: "string",
43
- format: "binary",
44
- },
45
- ...(field.maxCount && { maxItems: field.maxCount }),
46
- ...(uploadConfig.maxSize && {
47
- description: `Max size per file: ${uploadConfig.maxSize} bytes`,
48
- }),
49
- };
50
- if (uploadConfig.required) {
51
- uploadSchema.required.push(field.name);
51
+ uploadSchema.properties[this.resolveSchemaFieldName(field.name)] =
52
+ this.buildFieldSchema(field, uploadConfig);
53
+ const isRequired = field.type === undefined
54
+ ? uploadConfig.required !== false
55
+ : field.required !== false;
56
+ if (isRequired) {
57
+ uploadSchema.required.push(this.resolveSchemaFieldName(field.name));
52
58
  }
53
59
  }
54
60
  }
@@ -56,6 +62,45 @@ class ArkosRouterOpenAPIManager {
56
62
  delete uploadSchema.required;
57
63
  return deepmerge(existingSchema, uploadSchema);
58
64
  }
65
+ buildFieldSchema(field, config) {
66
+ if (field.type === "single") {
67
+ return {
68
+ type: "string",
69
+ format: "binary",
70
+ ...(field.maxSize &&
71
+ !config.maxSize && {
72
+ description: `Max size: ${field.maxSize} bytes`,
73
+ }),
74
+ ...(config.maxSize &&
75
+ !field.maxSize && {
76
+ description: `Max size: ${config.maxSize} bytes`,
77
+ }),
78
+ ...(field.description && { description: field.description }),
79
+ };
80
+ }
81
+ return {
82
+ type: "array",
83
+ items: {
84
+ type: "string",
85
+ format: "binary",
86
+ },
87
+ ...(field.maxCount && { maxItems: field.maxCount }),
88
+ ...(field.type === "array" &&
89
+ field.minCount && { minItems: field.minCount }),
90
+ ...((field.maxSize &&
91
+ !config.maxSize && {
92
+ description: `Max size per file: ${field.maxSize} bytes`,
93
+ }) ||
94
+ (config.maxSize &&
95
+ !field.maxSize && {
96
+ description: `Max size per file: ${config.maxSize} bytes`,
97
+ })),
98
+ ...(field.type === "array" &&
99
+ field.description && {
100
+ description: field.description,
101
+ }),
102
+ };
103
+ }
59
104
  validateMultipartFormDocs(userDefinedMultipartSchema, routePath, uploadConfig) {
60
105
  const errors = [];
61
106
  const properties = userDefinedMultipartSchema?.properties || {};
@@ -64,28 +109,41 @@ class ArkosRouterOpenAPIManager {
64
109
  if (uploadConfig?.type === "single") {
65
110
  expectedFields.push({
66
111
  name: uploadConfig.field,
67
- required: uploadConfig.required || false,
112
+ required: uploadConfig.required !== false,
68
113
  expectedType: "single",
69
114
  });
70
115
  }
71
116
  else if (uploadConfig?.type === "array") {
72
117
  expectedFields.push({
73
118
  name: uploadConfig.field,
74
- required: uploadConfig.required || false,
119
+ required: uploadConfig.required !== false,
75
120
  expectedType: "array",
76
121
  });
77
122
  }
78
123
  else if (uploadConfig?.type === "fields") {
79
124
  for (const field of uploadConfig.fields) {
80
- expectedFields.push({
81
- name: field.name,
82
- required: uploadConfig.required || false,
83
- expectedType: "array",
84
- });
125
+ if (!("type" in field)) {
126
+ expectedFields.push({
127
+ name: field.name,
128
+ required: uploadConfig.required ===
129
+ undefined
130
+ ? true
131
+ : uploadConfig
132
+ .required,
133
+ expectedType: "array",
134
+ });
135
+ }
136
+ else if (field.type)
137
+ expectedFields.push({
138
+ name: field.name,
139
+ required: field.type === undefined ? true : field.required !== false,
140
+ expectedType: field.type ?? "array",
141
+ });
85
142
  }
86
143
  }
87
144
  for (const { name, required, expectedType } of expectedFields) {
88
- const fieldSchema = properties[name];
145
+ const schemaKey = this.resolveSchemaFieldName(name);
146
+ const fieldSchema = properties[schemaKey];
89
147
  if (!fieldSchema) {
90
148
  errors.push(`Missing upload field '${name}' in multipart/form-data schema`);
91
149
  continue;
@@ -105,7 +163,7 @@ class ArkosRouterOpenAPIManager {
105
163
  fieldSchema.items.format !== "binary")
106
164
  errors.push(`Upload field '${name}' must have items with type 'string' and format 'binary'`);
107
165
  }
108
- const isMarkedRequired = requiredFields.includes(name);
166
+ const isMarkedRequired = requiredFields.includes(schemaKey);
109
167
  if (required && !isMarkedRequired)
110
168
  errors.push(`Upload field '${name}' is required in config but not marked as required in schema`);
111
169
  if (!required && isMarkedRequired)
@@ -1 +1 @@
1
- {"version":3,"file":"arkos-router-openapi-manager.js","sourceRoot":"","sources":["../../../../src/utils/arkos-router/arkos-router-openapi-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { OpenAPIV3 } from \"openapi-types\";\nimport deepmerge from \"../helpers/deepmerge.helper\";\nimport { UploadConfig } from \"./types/upload-config\";\n\nclass ArkosRouterOpenAPIManager {\n /**\n * Generates OpenAPI schema for file upload fields in multipart/form-data requests.\n * Converts upload configuration into OpenAPI-compliant schema and merges with existing body schema.\n *\n * @param {UploadConfig} uploadConfig - The upload configuration from config.experimental.uploads\n * @param {any} existingSchema - Existing JSON schema from config.validation.body (optional)\n * @returns {{ schema: any }} OpenAPI schema object for multipart/form-data content type\n *\n * @example\n * // Single file upload\n * addUploadFields({ type: 'single', field: 'avatar', maxSize: 5242880 })\n * // Returns: { schema: { type: 'object', properties: { avatar: { type: 'string', format: 'binary' } } } }\n *\n * @example\n * // Array file upload\n * addUploadFields({ type: 'array', field: 'gallery', maxCount: 10 })\n *\n * @example\n * // Multiple fields upload\n * addUploadFields({ type: 'fields', fields: [{ name: 'avatar', maxCount: 1 }, { name: 'resume', maxCount: 1 }] })\n */\n addUploadFields(\n uploadConfig: UploadConfig,\n existingSchema: OpenAPIV3.SchemaObject = {}\n ): OpenAPIV3.SchemaObject {\n const uploadSchema: any = {\n type: \"object\",\n properties: {},\n required: [],\n };\n\n if (uploadConfig.type === \"single\") {\n uploadSchema.properties[uploadConfig.field] = {\n type: \"string\",\n format: \"binary\",\n ...(uploadConfig.maxSize && {\n description: `Max size: ${uploadConfig.maxSize} bytes`,\n }),\n };\n if (uploadConfig.required) {\n uploadSchema.required.push(uploadConfig.field);\n }\n } else if (uploadConfig.type === \"array\") {\n uploadSchema.properties[uploadConfig.field] = {\n type: \"array\",\n items: {\n type: \"string\",\n format: \"binary\",\n },\n ...(uploadConfig.maxCount && { maxItems: uploadConfig.maxCount }),\n ...(uploadConfig.maxSize && {\n description: `Max size per file: ${uploadConfig.maxSize} bytes`,\n }),\n };\n if (uploadConfig.required) {\n uploadSchema.required.push(uploadConfig.field);\n }\n } else if (uploadConfig.type === \"fields\") {\n for (const field of uploadConfig.fields) {\n uploadSchema.properties[field.name] = {\n type: \"array\",\n items: {\n type: \"string\",\n format: \"binary\",\n },\n ...(field.maxCount && { maxItems: field.maxCount }),\n ...(uploadConfig.maxSize && {\n description: `Max size per file: ${uploadConfig.maxSize} bytes`,\n }),\n };\n if (uploadConfig.required) {\n uploadSchema.required.push(field.name);\n }\n }\n }\n\n // Clean up empty required array\n if (uploadSchema.required.length === 0) delete uploadSchema.required;\n\n return deepmerge(existingSchema as any, uploadSchema);\n }\n\n /**\n * Validates that a user-defined multipart/form-data schema includes all required upload fields\n * with correct types, formats, and required flags.\n *\n * @param {any} userDefinedMultipartSchema - The schema object from openapi.requestBody.content['multipart/form-data'].schema\n * @param {UploadConfig} uploadConfig - The upload configuration from config.experimental.uploads\n * @param {string} routePath - The route path for error context\n * @throws {Error} If upload fields are missing or incorrectly defined\n *\n * @example\n * validateMultipartFormDocs(\n * { type: 'object', properties: { avatar: { type: 'string', format: 'binary' } } },\n * { type: 'single', field: 'avatar', required: true },\n * '/users/:id/avatar'\n * )\n */\n validateMultipartFormDocs(\n userDefinedMultipartSchema: any,\n routePath: string,\n uploadConfig?: UploadConfig\n ): void {\n const errors: string[] = [];\n const properties = userDefinedMultipartSchema?.properties || {};\n const requiredFields = userDefinedMultipartSchema?.required || [];\n\n const expectedFields: Array<{\n name: string;\n required: boolean;\n expectedType: \"single\" | \"array\";\n }> = [];\n\n if (uploadConfig?.type === \"single\") {\n expectedFields.push({\n name: uploadConfig.field,\n required: uploadConfig.required || false,\n expectedType: \"single\",\n });\n } else if (uploadConfig?.type === \"array\") {\n expectedFields.push({\n name: uploadConfig.field,\n required: uploadConfig.required || false,\n expectedType: \"array\",\n });\n } else if (uploadConfig?.type === \"fields\") {\n for (const field of uploadConfig.fields) {\n expectedFields.push({\n name: field.name,\n required: uploadConfig.required || false,\n expectedType: \"array\",\n });\n }\n }\n\n for (const { name, required, expectedType } of expectedFields) {\n const fieldSchema = properties[name];\n\n if (!fieldSchema) {\n errors.push(\n `Missing upload field '${name}' in multipart/form-data schema`\n );\n continue;\n }\n\n if (expectedType === \"single\") {\n if (fieldSchema.type !== \"string\")\n errors.push(\n `Upload field '${name}' must have type 'string', got '${fieldSchema.type}'`\n );\n\n if (fieldSchema.format !== \"binary\")\n errors.push(\n `Upload field '${name}' must have format 'binary', got '${fieldSchema.format || \"undefined\"}'`\n );\n } else if (expectedType === \"array\") {\n if (fieldSchema.type !== \"array\") {\n errors.push(\n `Upload field '${name}' must have type 'array', got '${fieldSchema.type}'`\n );\n } else if (\n !fieldSchema.items ||\n fieldSchema.items.type !== \"string\" ||\n fieldSchema.items.format !== \"binary\"\n )\n errors.push(\n `Upload field '${name}' must have items with type 'string' and format 'binary'`\n );\n }\n\n const isMarkedRequired = requiredFields.includes(name);\n if (required && !isMarkedRequired)\n errors.push(\n `Upload field '${name}' is required in config but not marked as required in schema`\n );\n\n if (!required && isMarkedRequired)\n errors.push(\n `Upload field '${name}' is not required in config but marked as required in schema`\n );\n }\n\n if (errors.length > 0) {\n throw new Error(\n `ValidationError: Invalid multipart/form-data schema for route '${routePath}':\\n${errors.map((e) => ` - ${e}`).join(\"\\n\")}`\n );\n }\n }\n}\n\nconst arkosRouterOpenApiManager = new ArkosRouterOpenAPIManager();\n\nexport default arkosRouterOpenApiManager;\n"]}
1
+ {"version":3,"file":"arkos-router-openapi-manager.js","sourceRoot":"","sources":["../../../../src/utils/arkos-router/arkos-router-openapi-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { OpenAPIV3 } from \"openapi-types\";\nimport deepmerge from \"../helpers/deepmerge.helper\";\nimport {\n ArkosRouterBaseUploadConfig,\n UploadConfig,\n UploadConfigFieldEntry,\n} from \"./types/upload-config\";\n\nclass ArkosRouterOpenAPIManager {\n private resolveSchemaFieldName(name: string): string {\n return name.replace(/\\[\\]/g, \"[0]\");\n }\n /**\n * Generates OpenAPI schema for file upload fields in multipart/form-data requests.\n * Converts upload configuration into OpenAPI-compliant schema and merges with existing body schema.\n *\n * @param {UploadConfig} uploadConfig - The upload configuration from config.experimental.uploads\n * @param {any} existingSchema - Existing JSON schema from config.validation.body (optional)\n * @returns {{ schema: any }} OpenAPI schema object for multipart/form-data content type\n *\n * @example\n * // Single file upload\n * addUploadFields({ type: 'single', field: 'avatar', maxSize: 5242880 })\n * // Returns: { schema: { type: 'object', properties: { avatar: { type: 'string', format: 'binary' } } } }\n *\n * @example\n * // Array file upload\n * addUploadFields({ type: 'array', field: 'gallery', maxCount: 10 })\n *\n * @example\n * // Multiple fields upload\n * addUploadFields({\n * type: 'fields',\n * fields: [\n * { name: 'avatar', type: 'single', uploadDir: 'images' },\n * { name: 'gallery', type: 'array', maxCount: 6, uploadDir: 'gallery' },\n * { name: 'banners[][images]', type: 'array', maxCount: 5, uploadDir: 'banners' }\n * ]\n * })\n */\n addUploadFields(\n uploadConfig: UploadConfig,\n existingSchema: OpenAPIV3.SchemaObject = {}\n ): OpenAPIV3.SchemaObject {\n const uploadSchema: any = {\n type: \"object\",\n properties: {},\n required: [],\n };\n\n if (uploadConfig.type === \"single\") {\n const schemaKey = this.resolveSchemaFieldName(uploadConfig.field);\n uploadSchema.properties[schemaKey] = {\n type: \"string\",\n format: \"binary\",\n ...(uploadConfig.maxSize && {\n description: `Max size: ${uploadConfig.maxSize} bytes`,\n }),\n ...(uploadConfig.description && {\n description: uploadConfig.description,\n }),\n };\n if (uploadConfig.required !== false) {\n uploadSchema.required.push(schemaKey);\n }\n } else if (uploadConfig.type === \"array\") {\n const schemaKey = this.resolveSchemaFieldName(uploadConfig.field);\n uploadSchema.properties[schemaKey] = {\n type: \"array\",\n items: {\n type: \"string\",\n format: \"binary\",\n },\n ...(uploadConfig.maxCount && { maxItems: uploadConfig.maxCount }),\n ...(uploadConfig.minCount && { minItems: uploadConfig.minCount }),\n ...(uploadConfig.maxSize && {\n description: `Max size per file: ${uploadConfig.maxSize} bytes`,\n }),\n ...(uploadConfig.description && {\n description: uploadConfig.description,\n }),\n };\n if (uploadConfig.required !== false) {\n uploadSchema.required.push(schemaKey);\n }\n } else if (uploadConfig.type === \"fields\") {\n for (const field of uploadConfig.fields) {\n uploadSchema.properties[this.resolveSchemaFieldName(field.name)] =\n this.buildFieldSchema(field, uploadConfig);\n\n // legacy shape has no type and no required — default to required\n const isRequired =\n (field as any).type === undefined\n ? (uploadConfig as any).required !== false\n : (field as any).required !== false;\n\n if (isRequired) {\n uploadSchema.required.push(this.resolveSchemaFieldName(field.name));\n }\n }\n }\n\n // Clean up empty required array\n if (uploadSchema.required.length === 0) delete uploadSchema.required;\n\n return deepmerge(existingSchema as any, uploadSchema);\n }\n\n /**\n * Builds the OpenAPI property schema for a single field entry.\n * Legacy entries (no type) are treated as array.\n */\n private buildFieldSchema(\n field: UploadConfigFieldEntry,\n config: ArkosRouterBaseUploadConfig\n ): object {\n if (field.type === \"single\") {\n return {\n type: \"string\",\n format: \"binary\",\n ...(field.maxSize &&\n !config.maxSize && {\n description: `Max size: ${field.maxSize} bytes`,\n }),\n ...(config.maxSize &&\n !field.maxSize && {\n description: `Max size: ${config.maxSize} bytes`,\n }),\n ...(field.description && { description: field.description }),\n };\n }\n\n // type === \"array\" or legacy (no type) — both produce array schema\n return {\n type: \"array\",\n items: {\n type: \"string\",\n format: \"binary\",\n },\n ...(field.maxCount && { maxItems: field.maxCount }),\n ...(field.type === \"array\" &&\n field.minCount && { minItems: field.minCount }),\n ...((field.maxSize &&\n !config.maxSize && {\n description: `Max size per file: ${field.maxSize} bytes`,\n }) ||\n (config.maxSize &&\n !field.maxSize && {\n description: `Max size per file: ${config.maxSize} bytes`,\n })),\n ...(field.type === \"array\" &&\n field.description && {\n description: field.description,\n }),\n };\n }\n\n /**\n * Validates that a user-defined multipart/form-data schema includes all required upload fields\n * with correct types, formats, and required flags.\n *\n * @param {any} userDefinedMultipartSchema - The schema object from openapi.requestBody.content['multipart/form-data'].schema\n * @param {UploadConfig} uploadConfig - The upload configuration from config.experimental.uploads\n * @param {string} routePath - The route path for error context\n * @throws {Error} If upload fields are missing or incorrectly defined\n *\n * @example\n * validateMultipartFormDocs(\n * { type: 'object', properties: { avatar: { type: 'string', format: 'binary' } } },\n * { type: 'single', field: 'avatar', required: true },\n * '/users/:id/avatar'\n * )\n */\n validateMultipartFormDocs(\n userDefinedMultipartSchema: any,\n routePath: string,\n uploadConfig?: UploadConfig\n ): void {\n const errors: string[] = [];\n const properties = userDefinedMultipartSchema?.properties || {};\n const requiredFields = userDefinedMultipartSchema?.required || [];\n\n const expectedFields: Array<{\n name: string;\n required: boolean;\n expectedType: \"single\" | \"array\";\n }> = [];\n\n if (uploadConfig?.type === \"single\") {\n expectedFields.push({\n name: uploadConfig.field,\n required: uploadConfig.required !== false,\n expectedType: \"single\",\n });\n } else if (uploadConfig?.type === \"array\") {\n expectedFields.push({\n name: uploadConfig.field,\n required: uploadConfig.required !== false,\n expectedType: \"array\",\n });\n } else if (uploadConfig?.type === \"fields\") {\n for (const field of uploadConfig.fields) {\n if (!(\"type\" in field)) {\n expectedFields.push({\n name: field.name,\n // legacy shape has no type and no required — default to required\n required:\n (uploadConfig as ArkosRouterBaseUploadConfig).required ===\n undefined\n ? true\n : ((uploadConfig as ArkosRouterBaseUploadConfig)\n .required as boolean),\n expectedType: \"array\",\n });\n } else if (field.type)\n expectedFields.push({\n name: field.name,\n required:\n field.type === undefined ? true : field.required !== false,\n expectedType: field.type ?? \"array\",\n });\n }\n }\n\n for (const { name, required, expectedType } of expectedFields) {\n const schemaKey = this.resolveSchemaFieldName(name);\n const fieldSchema = properties[schemaKey];\n\n if (!fieldSchema) {\n errors.push(\n `Missing upload field '${name}' in multipart/form-data schema`\n );\n continue;\n }\n\n if (expectedType === \"single\") {\n if (fieldSchema.type !== \"string\")\n errors.push(\n `Upload field '${name}' must have type 'string', got '${fieldSchema.type}'`\n );\n\n if (fieldSchema.format !== \"binary\")\n errors.push(\n `Upload field '${name}' must have format 'binary', got '${fieldSchema.format || \"undefined\"}'`\n );\n } else if (expectedType === \"array\") {\n if (fieldSchema.type !== \"array\") {\n errors.push(\n `Upload field '${name}' must have type 'array', got '${fieldSchema.type}'`\n );\n } else if (\n !fieldSchema.items ||\n fieldSchema.items.type !== \"string\" ||\n fieldSchema.items.format !== \"binary\"\n )\n errors.push(\n `Upload field '${name}' must have items with type 'string' and format 'binary'`\n );\n }\n\n const isMarkedRequired = requiredFields.includes(schemaKey);\n if (required && !isMarkedRequired)\n errors.push(\n `Upload field '${name}' is required in config but not marked as required in schema`\n );\n\n if (!required && isMarkedRequired)\n errors.push(\n `Upload field '${name}' is not required in config but marked as required in schema`\n );\n }\n\n if (errors.length > 0) {\n throw new Error(\n `ValidationError: Invalid multipart/form-data schema for route '${routePath}':\\n${errors.map((e) => ` - ${e}`).join(\"\\n\")}`\n );\n }\n }\n}\n\nconst arkosRouterOpenApiManager = new ArkosRouterOpenAPIManager();\n\nexport default arkosRouterOpenApiManager;\n"]}
@@ -10,12 +10,13 @@ export default function ArkosRouter(options) {
10
10
  const router = Router(options);
11
11
  return applyArkosRouterProxy(router, options);
12
12
  }
13
+ const hasDuplicatedPath = (path) => /^(\/.+)\1/.test(path);
13
14
  export function generateOpenAPIFromApp(app) {
14
15
  const routes = extractArkosRoutes(app);
15
16
  const arkosConfig = getArkosConfig();
16
17
  let paths = {};
17
- routes.forEach(({ path, method, config }) => {
18
- if (config?.experimental?.openapi === false)
18
+ routes.forEach(({ path, method, config, routeOptions }) => {
19
+ if (config?.experimental?.openapi === false || hasDuplicatedPath(path))
19
20
  return;
20
21
  const originalPath = path;
21
22
  const pathParatemersFromRoutePath = extractPathParams(path);
@@ -94,7 +95,12 @@ export function generateOpenAPIFromApp(app) {
94
95
  ...convertedOpenAPI,
95
96
  summary: openapi?.summary || `${path}`,
96
97
  description: openapi?.description || `${method} ${path}`,
97
- tags: openapi?.tags || ["Defaults"],
98
+ servers: openapi?.servers || routeOptions?.openapi?.servers || undefined,
99
+ security: openapi?.security || routeOptions?.openapi?.security || undefined,
100
+ externalDocs: openapi?.externalDocs ||
101
+ routeOptions?.openapi?.externalDocs ||
102
+ undefined,
103
+ tags: openapi?.tags || routeOptions?.openapi?.tags || ["Defaults"],
98
104
  operationId: openapi.operationId || `${method.toLowerCase()}:${path}`,
99
105
  parameters: allParameters,
100
106
  ...(!convertedOpenAPI.requestBody &&
@@ -117,15 +123,13 @@ export function generateOpenAPIFromApp(app) {
117
123
  })(),
118
124
  },
119
125
  }),
120
- ...(convertedOpenAPI?.requestBody?.content?.["application/json"]
121
- ?.schema &&
122
- !multipartFormSchema &&
126
+ ...(!multipartFormSchema &&
123
127
  !config?.validation?.body &&
124
128
  hasUploadFields && {
125
129
  requestBody: {
126
130
  content: (() => {
127
131
  const schema = convertedOpenAPI?.requestBody?.content?.["application/json"]
128
- ?.schema;
132
+ ?.schema || {};
129
133
  return {
130
134
  "multipart/form-data": {
131
135
  schema: openApiSchemaConverter.flattenSchema(arkosRouterOpenApiManager.addUploadFields(config?.experimental?.uploads || {}, schema)),